// SPDX-FileCopyrightText: 2020 Efabless Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // SPDX-License-Identifier: Apache-2.0 `default_nettype none module mprj_ctrl_wb #( parameter BASE_ADR = 32'h 2300_0000, parameter XFER = 8'h 00, parameter PWRDATA = 8'h 04, parameter IRQDATA = 8'h 08, parameter IODATA = 8'h 0c, // One word per 32 IOs parameter IOCONFIG = 8'h 24 )( input wb_clk_i, input wb_rst_i, input [31:0] wb_dat_i, input [31:0] wb_adr_i, input [3:0] wb_sel_i, input wb_cyc_i, input wb_stb_i, input wb_we_i, output [31:0] wb_dat_o, output wb_ack_o, // Output is to serial loader output serial_clock, output serial_resetn, output serial_data_out_1, output serial_data_out_2, // Pass state of OEB bit on SDO and JTAG back to the core // so that the function can be overridden for management output output sdo_oenb_state, output jtag_oenb_state, output flash_io2_oenb_state, output flash_io3_oenb_state, // Read/write data to each GPIO pad from management SoC input [`MPRJ_IO_PADS-1:0] mgmt_gpio_in, output [`MPRJ_IO_PADS-1:0] mgmt_gpio_out, output [`MPRJ_IO_PADS-1:0] mgmt_gpio_oeb, // Write data to power controls output [`MPRJ_PWR_PADS-1:0] pwr_ctrl_out, // Enable user project IRQ signals to management SoC output [2:0] user_irq_ena, // External bit-bang controls from the housekeeping SPI input ext_clock, input ext_resetn, input ext_data_1, input ext_data_2, input ext_enable ); wire resetn; wire valid; wire ready; wire [3:0] iomem_we; assign resetn = ~wb_rst_i; assign valid = wb_stb_i && wb_cyc_i; assign iomem_we = wb_sel_i & {4{wb_we_i}}; assign wb_ack_o = ready; mprj_ctrl #( .BASE_ADR(BASE_ADR), .XFER(XFER), .PWRDATA(PWRDATA), .IRQDATA(IRQDATA), .IODATA(IODATA), .IOCONFIG(IOCONFIG) ) mprj_ctrl ( .clk(wb_clk_i), .resetn(resetn), .iomem_addr(wb_adr_i), .iomem_valid(valid), .iomem_wstrb(iomem_we[1:0]), .iomem_wdata(wb_dat_i), .iomem_rdata(wb_dat_o), .iomem_ready(ready), .serial_clock(serial_clock), .serial_resetn(serial_resetn), .serial_data_out_1(serial_data_out_1), .serial_data_out_2(serial_data_out_2), .sdo_oenb_state(sdo_oenb_state), .jtag_oenb_state(jtag_oenb_state), .flash_io2_oenb_state(flash_io2_oenb_state), .flash_io3_oenb_state(flash_io3_oenb_state), // .mgmt_gpio_io(mgmt_gpio_io) .mgmt_gpio_in(mgmt_gpio_in), .mgmt_gpio_out(mgmt_gpio_out), .mgmt_gpio_oeb(mgmt_gpio_oeb), // Write data to power controls .pwr_ctrl_out(pwr_ctrl_out), // Enable user project IRQ signals to management SoC .user_irq_ena(user_irq_ena), // External bit-bang control from housekeeping SPI .ext_clock(ext_clock), .ext_resetn(ext_resetn), .ext_data_1(ext_data_1), .ext_data_2(ext_data_2), .ext_enable(ext_enable) ); endmodule module mprj_ctrl #( parameter BASE_ADR = 32'h 2300_0000, parameter XFER = 8'h 00, parameter PWRDATA = 8'h 04, parameter IRQDATA = 8'h 08, parameter IODATA = 8'h 0c, parameter IOCONFIG = 8'h 24, parameter IO_CTRL_BITS = 13 )( input clk, input resetn, input [31:0] iomem_addr, input iomem_valid, input [1:0] iomem_wstrb, input [31:0] iomem_wdata, output reg [31:0] iomem_rdata, output reg iomem_ready, output serial_clock, output serial_resetn, output serial_data_out_1, output serial_data_out_2, output sdo_oenb_state, output jtag_oenb_state, output flash_io2_oenb_state, output flash_io3_oenb_state, input [`MPRJ_IO_PADS-1:0] mgmt_gpio_in, output [`MPRJ_IO_PADS-1:0] mgmt_gpio_out, output [`MPRJ_IO_PADS-1:0] mgmt_gpio_oeb, output [`MPRJ_PWR_PADS-1:0] pwr_ctrl_out, output [2:0] user_irq_ena, input ext_clock, input ext_resetn, input ext_data_1, input ext_data_2, input ext_enable ); `define IDLE 2'b00 `define START 2'b01 `define XBYTE 2'b10 `define LOAD 2'b11 localparam IO_WORDS = (`MPRJ_IO_PADS % 32 != 0) + (`MPRJ_IO_PADS / 32); localparam IO_BASE_ADR = (BASE_ADR | IOCONFIG); localparam OEB = 1; // Offset of output enable in shift register. localparam INP_DIS = 3; // Offset of input disable in shift register. reg [IO_CTRL_BITS-1:0] io_ctrl[`MPRJ_IO_PADS-1:0]; // I/O control, 1 word per gpio pad reg [`MPRJ_IO_PADS-1:0] mgmt_gpio_out; // I/O write data, 1 bit per gpio pad reg [`MPRJ_PWR_PADS-1:0] pwr_ctrl_out; // Power write data, 1 bit per power pad reg [2:0] user_irq_ena; // Enable user to raise IRQs reg xfer_ctrl; // Transfer control (1 bit) wire [IO_WORDS-1:0] io_data_sel; // wishbone selects wire pwr_data_sel; wire irq_data_sel; wire xfer_sel; wire busy; wire selected; wire [`MPRJ_IO_PADS-1:0] io_ctrl_sel; reg [31:0] iomem_rdata_pre; wire [`MPRJ_IO_PADS-1:0] mgmt_gpio_in; wire sdo_oenb_state, jtag_oenb_state; wire flash_io2_oenb_state, flash_io3_oenb_state; // JTAG and housekeeping SDO are normally controlled by their respective // modules with OEB set to the default 1 value. If configured for an // additional output by setting the OEB bit low, then pass this information // back to the core so that the default signals can be overridden. assign jtag_oenb_state = io_ctrl[0][OEB]; assign sdo_oenb_state = io_ctrl[1][OEB]; // Likewise for the flash_io2 and flash_io3, although they are configured // as input by default. assign flash_io2_oenb_state = io_ctrl[(`MPRJ_IO_PADS)-2][OEB]; assign flash_io3_oenb_state = io_ctrl[(`MPRJ_IO_PADS)-1][OEB]; `define wtop (((i+1)*32 > `MPRJ_IO_PADS) ? `MPRJ_IO_PADS-1 : (i+1)*32-1) `define wbot (i*32) `define rtop (`wtop - `wbot) genvar i; // Assign selection bits per address assign xfer_sel = (iomem_addr[7:0] == XFER); assign pwr_data_sel = (iomem_addr[7:0] == PWRDATA); assign irq_data_sel = (iomem_addr[7:0] == IRQDATA); generate for (i=0; i