[Solved] Help getting bidirectional pins (inout) to work (BX)


I am trying to get the simple single-port RAM example below to work, but somehow writes seem to always result in all zeroes being read from the data_bus pins. Any help with what could be wrong would be greatly appreciated!

`default_nettype none

module single_port_sync_ram
( 	input 		clk,
        input [1:0] addr,
        inout [3:0] data,
        input       we,
        input       oe

reg [3:0]        tmp_data;
reg [3:0]        mem [4];

initial begin
    mem[0] = 'h1;
    mem[1] = 'h2;
    mem[2] = 'h3;
    mem[3] = 'h4;

always @ (posedge clk) begin
    if (!oe & we)
        mem[addr] <= data;

always @ (posedge clk) begin
    if (oe & !we)
        tmp_data <= mem[addr];

assign data = (oe & !we) ? tmp_data : 4'bz;

module Top(input CLK,
        // addr0, addr1, we, oe
        input PIN_14, input PIN_15, input PIN_16, input PIN_17,
        // data bus
        inout PIN_10, inout PIN_11, inout PIN_12, inout PIN_13);

wire [3:0]    data_bus = {PIN_13, PIN_12, PIN_11, PIN_10};
wire [1:0]    addr = {PIN_15, PIN_14};
single_port_sync_ram  U1(.clk(CLK), .addr(addr), .data(data_bus), .we(PIN_16), .oe(PIN_17));


Full example with Makefile: https://github.com/kalj/fpga-uart/tree/simple-ram

My test setup (note 10k pull ups on all data pins and 10k pull downs on OE and WE):



if as I assume you are using the open source toolchain you might want to explicitly instantiate the ports and not use verilog tristate logic

SB_IO #(
    .PULLUP(1'b 0)
) iobuf_mybuf (


I found that in the single_port_sync_ram module, I had to change

reg [3:0] mem [4];

reg [3:0] mem [3:0];

to get the memory array to be correctly created. Try that.


Thanks for the answers! It turned out the error was somewhere else in my test setup, and now it works.
Though I am happy I got introduced to that SB_IO construct. I hadn’t seen those kinds of verilog before and it in some sense is simpler than my verilog code.