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.
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.
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
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
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With