I have the following Verilog modules, which I'm simulating with Icarus Verilog. It seems that the ternary operator doesn't work, or has a bug:
main module (i2c_app_tb.v)
`timescale 1ns/100ps
module i2c_app_tb;
wire t1;
wire [7:0] t2;
reg rst = 0;
reg clk = 0;
pullup(t1);
pullupdown_t1 pt1(t1, t2, rst, clk);
always #5 clk <= ~clk;
initial begin
$dumpfile("i2c_app_tb.vcd");
$dumpvars(1, i2c_app_tb);
rst <= 1;
#20 rst <= 0;
#300;
$finish;
end
wire _i0_reg;
assign _i0_reg = pt1.i0_reg;
endmodule
pullupdown_t1.v
module pullupdown_t1 (
inout wire i0,
inout wire [7:0] i1,
input rst,
input clk
);
reg i0_reg;
always @ (posedge clk or posedge rst) begin
if (rst) begin
i0_reg <= 0;
end else begin
i0_reg <= (i0_reg == 0 ? (1'bz) : 0);
end
end
assign i0 = i0_reg;
endmodule
When I simulate the above, I get:
However, if I replace
i0_reg <= (i0_reg == 0 ? (1'bz) : 0);
by
if (i0_reg == 0) begin
i0_reg <= 1'bz;
end else begin
i0_reg <= 0;
end
(which is equivalent), I get:
Am I missing something? Is this a bug?
-
\$\begingroup\$ Check the data types — not every type supports ‘z’ which is defined as not driven. Only a tri-state signal path can physically support the z state. \$\endgroup\$MarkU– MarkU2021年12月30日 22:26:32 +00:00Commented Dec 30, 2021 at 22:26
1 Answer 1
If you want to use the ternary (conditional) operator, you can use case equality (===
) instead of logical equality (==
):
i0_reg <= (i0_reg === 0 ? (1'bz) : 0);
Refer to IEEE Std 1800-2017, section 11.4.5 Equality operators.
The behavior you observed is not a bug and it is not specific to iverilog
; it is observed on other simulators as well.
In your original ternary code, when i0_reg
has the value 1'bz
, then the expression i0_reg == 0
evaluates to 1'bx
, and i0_reg
is assigned the value 1'bx
.