How to write to inout port and read from inout port of the same module?

FatherOfNations picture FatherOfNations · Dec 1, 2016 · Viewed 23.9k times · Source

This is not about actually creating a verilog module with inout ports. There are tons of posts I've found about that.

What I am stuck on is, if I have a blackbox module with an inout port, let's says it's defined like

module blackbox(inout a, in b, in c)

And I want to instantiate it in a different module like

module myModule(input reg inReg, output wire outWire) blackbox(outWire);

How do I also drive the blackbox with the inReg and have it output on the outWire at different times? I don't know of a way to connect one and disconnect the other. This is obviously oversimplified. What I really have is below, but it's more complicated.

module sram_control(
    input wire HCLK,
    input wire [20:0] HADDR,
    input wire HWRITE,
    input wire [1:0] HTRANS,
    input wire [7:0] HWDATA,
    output reg [7:0] HRDATA
    );
parameter IDLE_PHASE = 2'b00;
parameter WRITE_PHASE = 2'b01;
parameter READ_PHASE = 2'b10;

parameter IDLE = 2'b00;
parameter NONSEQ = 2'b10;

parameter READ = 1'b0;
parameter WRITE = 1'b1;

reg current_state, next_state;

wire CE, WE, OE;
reg [20:0] A;
wire [7:0] DQ;
reg [7:0] DQ_tmp1;
wire [7:0] DQ_tmp2;

async the_mem(.CE_b(CE), .WE_b(WE), .OE_b(OE), .A(A), .DQ(DQ));

always @(posedge HCLK) begin
  if(current_state == IDLE_PHASE) begin
        next_state <= HTRANS == NONSEQ? (HWRITE == WRITE? WRITE_PHASE : READ_PHASE) : IDLE_PHASE;   
         A <= HADDR;
  end
    else if(current_state != IDLE_PHASE) begin
        if(HTRANS == NONSEQ) begin
          if(HWRITE == WRITE) begin
            next_state <= WRITE_PHASE;
          end
          else begin 
            next_state <= READ_PHASE;
          end
        end
        else next_state <= IDLE_PHASE;
    end
    // we never get here
    else next_state <= IDLE_PHASE;
end

always@(posedge HCLK) begin
  if(current_state == READ_PHASE) HRDATA <= DQ;
end

assign CE = current_state != IDLE_PHASE? 1 : 0;
assign WE = current_state != IDLE && HWRITE == WRITE? 1 : 0;
assign OE = current_state != IDLE_PHASE? 1 : 0;
always@(posedge HCLK) current_state <= next_state;
endmodule

What I need is a way to assign HWDATA to the async module when I want to write to it, and I need a way to assign the output of the async module to HRDATA when I want to read from the async.

Answer

Karan Shah picture Karan Shah · Dec 4, 2016

For all inout ports, you can read the data at any time. But for driving that net, generally tri state buffers are used. The reason for that is the same net may be shared with multiple modules and since the net is on inout type, to remove conflict of multiple driver, the tri state buffers are used.

enter image description here

For the same above image, here is the code.

assign io = t ? i : 1'bz; // To drive the inout net
assign o = io; // To read from inout net