In the below module, ideally cnt, width & start should be inout port, instead of output port.
But I tried with those ports as output ports and still I am able to run it without any error. So can inout and output ports be used interchangeably in Verilog?
If no, then what is the exact criteria, where inout port must be used (output port can't be used in that case)?
module (clk, rst, cnt, start, width, signal);
input clk, rst, signal;
output reg [11:0] cnt, width;
output reg start;
always @(posedge clk or negedge rst)
begin
if(~rst)
begin
cnt <= 0;
start = 0;
width <= 'h271;
end
else
begin
if(signal)
begin
width <= (start) ? width : 'h271;
start = 1;
end
cnt <= (start) ? (cnt + 1) : cnt;
end
end
endmodule
Note - I know, that with inout ports, I need to modify the code, as inout ports can't be of reg type. But I am here asking about just type of ports only.
Port direction is basically advisory in Verilog, and this hasn't changed in SystemVerilog. This is a historical isue, and is related to how Verilog XL (the first Verilog simulator) did port collapsing; basically, everything is an inout. when the '95 LRM was written this existing behaviour was basically documented. In 1364-2005 this appears in 12.3.8 as
A port that is declared as input (output) but used as an output (input) or inout may be coerced to inout. If not
coerced to inout, a warning has to be issued.
In practice, everything ends up as an inout
, and you may or may not get a warning. So, you can do pretty much anything in a simulator, but a linter or a synthesiser should pick up any logical connection errors for you (if it doesn't, it's pretty useless). There are other specific non-direction rules in the following sections - input
and inout
ports have to be of net
type, and so on.
There are differences in output
and inout
ports:
You can't read and write inout
port simultaneously, hence kept 'Z
for reading.
inout
port can never be of type reg
. It must be of wire
type.
There should be a signal which decides that whether the given port is an input
or output
.
In this module, you must have a w_r
signal which functions as follows:
// w_r = 1 => output port
// w_r = 0 => input port
input w_r;
inout cnt;
reg write_cnt;
reg read_cnt;
// wire read_cnt;
assign cnt = w_r ? write_cnt : 1'bz; // driving logic for cnt
// inside some always block
read_cnt <= cnt;
write_cnt <= some_data;
Since the inout
signal is wire, it must be driven by continuous assignment statements.
Referring to this part:
So can inout and output ports be used interchangeably in Verilog?
The answer is that it is not encouraged to use them interchangeably. Since for output port, you can use reg
type alone.
From synthesis point of view, the inout
port can have tri-state drivers or a Mux as follows: (Note that this results can differ for synthesis tools which I am not sure about.):
For more information refer to Bidirectional port assignment and Bidirectional I/O Pins forum question.
Simulators don't care about port directions. Simulation tools always flatten out the module hierarchy and all that matters is that they can connect the two port signals together. They do not check that the flow of data is actually going in the specified direction. Unfortunately, what is required by the standard and what is implemented in a tool does not always match up.
Sometimes, a user will have code that "works" in one tool but not in another tool with stronger error checking. The user finds it is easier to make their tool vendor remove the error check than to have to go back and fix their code. Some most simulators have removed any checks to enforce port direction.
The rule about not declaring variables data types used inout ports remains mostly intact, but many tools allow constants to be connected to an inout port.