Made corrections; GPIO testbench now passes.
diff --git a/verilog/rtl/README b/verilog/rtl/README
index ec44791..1ac0025 100644
--- a/verilog/rtl/README
+++ b/verilog/rtl/README
@@ -151,7 +151,7 @@
Standard GPIO output configuration:
- mprj_io[6] Tx, UART 110 0 0 0 0 0 0 0 0 0 1
+ mprj_io[6] Tx, UART 110 0 0 0 0 0 0 1 0 0 1
Standard GPIO input configuration:
mprj_io[*] 001 0 0 0 0 0 0 0 0 1 1
diff --git a/verilog/rtl/caravel.v b/verilog/rtl/caravel.v
index cdefe74..c51bef1 100644
--- a/verilog/rtl/caravel.v
+++ b/verilog/rtl/caravel.v
@@ -313,8 +313,8 @@
.mprj_io_loader_clock(mprj_io_loader_clock),
.mprj_io_loader_data(mprj_io_loader_data),
.mgmt_in_data(mgmt_io_in),
- .mgmt_out_data({mgmt_io_nc1, sdo_out, jtag_out}),
.mgmt_outz_data({mgmt_io_in[(`MPRJ_IO_PADS-1):2], mgmt_io_nc2}),
+ .mgmt_out_data({mgmt_io_nc1, sdo_out, jtag_out}),
.mgmt_oeb_data({mgmt_io_nc3, sdo_outenb, jtag_outenb}),
// Mega Project Slave ports (WB MI A)
.mprj_cyc_o(mprj_cyc_o_core),
@@ -361,8 +361,8 @@
.la_data_out(la_data_out_mprj),
.la_oen (la_oen),
// IO Pads
- .io_out(mprj_io_out),
- .io_in (mprj_io_in)
+ .io_in (mprj_io_in),
+ .io_out() // ???
);
wire [`MPRJ_IO_PADS-1:0] gpio_serial_link_shifted;
@@ -375,42 +375,81 @@
// of the shift register, bits are presented in reverse, as the first
// bit in ends up as the last bit of the last I/O pad control block.
+ // There are two types of block; the first two are configured to be
+ // full bidirectional under control of the management Soc (JTAG and
+ // SDO). The rest are configured to be default (input).
+
gpio_control_block #(
- .DM_INIT(3'b010), // Test: All pads set to pull-up
- .OENB_INIT(1'b0) // Test: All pads set to pull-up
- ) gpio_control_inst [`MPRJ_IO_PADS-1:0] (
+ .DM_INIT(3'b110), // Mode = output, strong up/down
+ .OENB_INIT(1'b0) // Enable output signaling from wire
+ ) gpio_control_bidir [1:0] (
// Management Soc-facing signals
.resetn(mprj_io_loader_resetn),
.serial_clock(mprj_io_loader_clock),
- .mgmt_gpio_in(mgmt_io_in),
- .mgmt_gpio_out({mgmt_io_in[(`MPRJ_IO_PADS-1):2], sdo_out, jtag_out}),
- .mgmt_gpio_oeb({{(`MPRJ_IO_PADS-2){1'b1}}, sdo_outenb, jtag_outenb}),
+ .mgmt_gpio_in(mgmt_io_in[1:0]),
+ .mgmt_gpio_out({sdo_out, jtag_out}),
+ .mgmt_gpio_oeb({sdo_outenb, jtag_outenb}),
// Serial data chain for pad configuration
- .serial_data_in(gpio_serial_link_shifted),
- .serial_data_out(gpio_serial_link),
+ .serial_data_in(gpio_serial_link_shifted[1:0]),
+ .serial_data_out(gpio_serial_link[1:0]),
// User-facing signals
- .user_gpio_out(user_io_out),
- .user_gpio_oeb(user_io_oeb),
- .user_gpio_in(user_io_in),
+ .user_gpio_out(user_io_out[1:0]),
+ .user_gpio_oeb(user_io_oeb[1:0]),
+ .user_gpio_in(user_io_in[1:0]),
// Pad-facing signals (Pad GPIOv2)
- .pad_gpio_inenb(mprj_io_inp_dis),
- .pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel),
- .pad_gpio_vtrip_sel(mprj_io_vtrip_sel),
- .pad_gpio_slow_sel(mprj_io_slow_sel),
- .pad_gpio_holdover(mprj_io_holdover),
- .pad_gpio_ana_en(mprj_io_analog_en),
- .pad_gpio_ana_sel(mprj_io_analog_sel),
- .pad_gpio_ana_pol(mprj_io_analog_pol),
- .pad_gpio_dm(mprj_io_dm),
- .pad_gpio_outenb(mprj_io_oeb),
- .pad_gpio_out(mprj_io_out),
- .pad_gpio_in(mprj_io_in)
+ .pad_gpio_inenb(mprj_io_inp_dis[1:0]),
+ .pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[1:0]),
+ .pad_gpio_vtrip_sel(mprj_io_vtrip_sel[1:0]),
+ .pad_gpio_slow_sel(mprj_io_slow_sel[1:0]),
+ .pad_gpio_holdover(mprj_io_holdover[1:0]),
+ .pad_gpio_ana_en(mprj_io_analog_en[1:0]),
+ .pad_gpio_ana_sel(mprj_io_analog_sel[1:0]),
+ .pad_gpio_ana_pol(mprj_io_analog_pol[1:0]),
+ .pad_gpio_dm(mprj_io_dm[5:0]),
+ .pad_gpio_outenb(mprj_io_oeb[1:0]),
+ .pad_gpio_out(mprj_io_out[1:0]),
+ .pad_gpio_in(mprj_io_in[1:0])
+ );
+
+ gpio_control_block gpio_control_in [`MPRJ_IO_PADS-1:2] (
+
+ // Management Soc-facing signals
+
+ .resetn(mprj_io_loader_resetn),
+ .serial_clock(mprj_io_loader_clock),
+
+ .mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-1):2]),
+ .mgmt_gpio_out(mgmt_io_in[(`MPRJ_IO_PADS-1):2]),
+ .mgmt_gpio_oeb(1'b1),
+
+ // Serial data chain for pad configuration
+ .serial_data_in(gpio_serial_link_shifted[(`MPRJ_IO_PADS-1):2]),
+ .serial_data_out(gpio_serial_link[(`MPRJ_IO_PADS-1):2]),
+
+ // User-facing signals
+ .user_gpio_out(user_io_out[(`MPRJ_IO_PADS-1):2]),
+ .user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-1):2]),
+ .user_gpio_in(user_io_in[(`MPRJ_IO_PADS-1):2]),
+
+ // Pad-facing signals (Pad GPIOv2)
+ .pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-1):6]),
+ .pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-1):2]),
+ .pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-1):2])
);
sky130_fd_sc_hvl__lsbufhv2lv levelshift (
diff --git a/verilog/rtl/gpio_control_block.v b/verilog/rtl/gpio_control_block.v
index 5d3adb1..823856b 100644
--- a/verilog/rtl/gpio_control_block.v
+++ b/verilog/rtl/gpio_control_block.v
@@ -183,10 +183,17 @@
/* Implement pad control behavior depending on state of mgmt_ena */
- assign pad_gpio_out = (mgmt_ena) ? mgmt_gpio_out : user_gpio_out;
- assign pad_gpio_outenb = (mgmt_ena) ? mgmt_gpio_oeb : user_gpio_oeb;
-
assign user_gpio_in = (mgmt_ena) ? 1'b0 : pad_gpio_in;
- assign mgmt_gpio_in = (mgmt_ena) ? pad_gpio_in : 1'b0;
+ assign mgmt_gpio_in = (mgmt_ena) ? ((gpio_inenb == 1'b0) ?
+ pad_gpio_in : 1'bz) : 1'b0;
+
+ assign pad_gpio_outenb = (mgmt_ena) ? ((mgmt_gpio_oeb == 1'b1) ? gpio_outenb :
+ 1'b0) : user_gpio_oeb;
+ assign pad_gpio_out = (mgmt_ena) ?
+ ((mgmt_gpio_oeb == 1'b1) ?
+ ((gpio_dm[2:1] == 2'b01) ? ~gpio_dm[0] : mgmt_gpio_out) :
+ mgmt_gpio_out) :
+ user_gpio_out;
+
endmodule
diff --git a/verilog/rtl/mprj_ctrl.v b/verilog/rtl/mprj_ctrl.v
index c002610..035e756 100644
--- a/verilog/rtl/mprj_ctrl.v
+++ b/verilog/rtl/mprj_ctrl.v
@@ -109,8 +109,8 @@
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 [IO_PADS-1:0]; // I/O control, 1 word per gpio pad
- reg [PWR_CTRL_BITS-1:0] pwr_ctrl [PWR_PADS-1:0];// Power control, 1 word per power pad
+ reg [IO_CTRL_BITS-1:0] io_ctrl[IO_PADS-1:0]; // I/O control, 1 word per gpio pad
+ reg [PWR_CTRL_BITS-1:0] pwr_ctrl[PWR_PADS-1:0]; // Power control, 1 word per power pad
reg [IO_PADS-1:0] mgmt_gpio_out; // I/O write data, 1 bit per gpio pad
wire [IO_PADS-1:0] mgmt_gpio_outz; // I/O write data output when input disabled
wire [IO_PADS-1:0] mgmt_gpio_oeb;
@@ -125,12 +125,6 @@
assign xfer_sel = (iomem_addr[7:0] == XFER);
assign io_data_sel = (iomem_addr[7:0] == DATA);
- // Direction of mgmt_gpio_io depends on the value of io_ctrl pad bit 1 (OEB)
- // if OEB = 0 then mgmt_gpio_out --> mgmt_gpio_io; if OEB = 1 then
- // mgmt_gpio_io --> mgmt_gpio_in. mgmt_gpio_in is always a copy of mgmt_gpio_io.
-
- // assign mgmt_gpio_in = mgmt_gpio_io;
-
genvar i;
generate
for (i=0; i<IO_PADS; i=i+1) begin
@@ -138,8 +132,8 @@
// OEB is both tranferred by serial chain and output; that way
// each pad can selectively choose whether to have a dedicated
// signal for OEB, or to use it as a static configuration bit.
- assign mgmt_gpio_oeb[i] = io_ctrl[OEB][i];
- assign mgmt_gpio_outz[i] = (io_ctrl[INP_DIS][i] == 1'b1) ?
+ assign mgmt_gpio_oeb[i] = io_ctrl[i][OEB];
+ assign mgmt_gpio_outz[i] = (io_ctrl[i][INP_DIS] == 1'b1) ?
mgmt_gpio_out[i] : 1'bz;
end
endgenerate