Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

verilog

inout

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.

like image 763
FatherOfNations Avatar asked Dec 01 '16 04:12

FatherOfNations


2 Answers

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
like image 112
Karan Shah Avatar answered Sep 27 '22 18:09

Karan Shah


As you say, this isn't a Verilog question, it's a logic design question.

You need to implement a tri-state driver to drive DQ:

assign DQ = WE ? 8'bz : HWDATA;

(assuming WE is 1'b0 when you are doing a write).

In general I would avoid tri-state logic inside an IC/FPGA, because not only is there the obvious problem when more than one driver drives a bus, it is also a problem if nothing drives the bus (some gates get floating inputs). There are also further problems in IC design. However, presumably you have not choice in this case; presumably you did not design module async. (If you did - take out the inout.)

like image 34
Matthew Taylor Avatar answered Sep 27 '22 16:09

Matthew Taylor