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


#1

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;
end

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

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

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

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));

endmodule

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):


#2

Hi,

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 #(
    .PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
    .PULLUP(1'b 0)
) iobuf_mybuf (
    .PACKAGE_PIN(my_pin),
    .OUTPUT_ENABLE(my_pin_oe),
    .D_OUT_0(data_out)
    .D_IN_0(data_in)
);

#3

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

reg [3:0] mem [4];

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

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


#4

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.