Closed Noah-S-E closed 5 months ago
This is almost certainly a race in your design.
Have you noticed that Vivado has synthesised a latch for y
and no flip-flops?
This is almost certainly a race in your design. Have you noticed that Vivado has synthesised a latch for
y
and no flip-flops?
Thank you very much for your replyamidst your busy schedule.
To eliminate the latch, I modified the code:
I changed the two instances of for (forvar19 = (1'h0); (forvar19 < (1'h0)); forvar19 = (forvar19 + (1'h1)))
to forvar19 <= 1'h1;
.
The latch disappeared, and the output of both versions was consistent when using iverilog.
However, for the example above where iVerilog simulation results don't match up, when I used Aldec Riviera Pro 2023.04
on edaplayground
for simulation, the results were consistent with Vivado simulation. It seems that these tools handle such latch conditions more effectively.
output only includes the forvar19
https://www.edaplayground.com/x/GxX4
Output wire7
and forvar19
https://www.edaplayground.com/x/Q2iW
I hope that iVerilog can address this issue in the future and become a better simulation tool. Thank you for your contributions to the FPGA field. Best wishes to you.
Icarus Verilog handles latches perfectly well. But if there is a race condition in your design, you can't expect all simulators to give the same result. If you haven't done so already, read the "Scheduling semantics" section in the LRM (IEEE 1364 or IEEE 1800), particularly the "Nondeterminism" and "Race conditions" sub-sections.
Closing as this is not an Icarus Verilog issue.
In the following two code snippets, y is the output wire.
The original design of the two statements generated
syn_vivado.v
after synthesis in Vivado, and I simulated the synthesized code.Theoretically, if all other conditions remain the same, the simulation output in the
forvar19
section should be consistent, meaning that the lower bits ofy
should be the same for theforvar19
value in both cases.However, when I simulated using iverilog, with all other conditions being equal, the two produced different simulation outputs. (both
wire7
andforvar19
I constructed are 2-bit).The left side only includes the
forvar19
output as shown (highlighted in yellow for theforvar19
output section); the right side includes the output with thewire7
signal as shown (highlighted in yellow for theforvar19
output section).Inconsistencies appeared on lines 6, 7, and 14.
Therefore, I used Vivado's simulation tool to simulate the synthesized output of the two statements, and the lower bits of the
forvar19
output were consistent.The left side only includes the
forvar19
output as shown (highlighted in yellow for theforvar19
output section); the right side includes the output with thewire7
signal as shown (highlighted in yellow for theforvar19
output section).Comparing the outputs of the two simulation tools mentioned above, I think that the issue might be caused by adding signal output, leading to abnormal simulation results in iverilog.
My original designs are as follows:
forvar19
:syn_vivado
code is as follows:Output with
wire7
signal:syn_vivado
code is as follows:( STRUCTURAL_NETLIST = "yes" ) module top (y, clk, wire3, wire2, wire1, wire0); output [3:0]y; input [0:0]clk; input [4:0]wire3; input [6:0]wire2; input [2:0]wire1; input [2:0]wire0;
wire \ ;
wire GND_2;
wire VCC_1;
wire forvar190_i_1_n_0;
wire forvar190_i_2_n_0;
wire forvar19__0_i_3_n_0;
wire [2:0]wire0;
wire [2:0]wire0_IBUF;
wire [2:0]wire1;
wire [2:0]wire1_IBUF;
wire [6:0]wire2;
wire [6:0]wire2_IBUF;
wire [4:0]wire3;
wire [1:0]wire3_IBUF;
wire [3:0]y;
wire [3:0]y_OBUF;
wire \y_OBUF[3]_inst_i_2_n_0 ;
wire \y_OBUF[3]_inst_i_3_n_0 ;
wire \y_OBUF[3]_inst_i_4_n_0 ;
GND GND (.G(\ ));
GND GND_1
(.G(GND_2));
VCC VCC
(.P(VCC_1));
( XILINX_LEGACY_PRIM = "LD" )
( XILINX_TRANSFORM_PINMAP = "VCC:GE GND:CLR" )
LDCE #(
.INIT(1'b0))
forvar190
(.CLR(GND_2),
.D(forvar19__0_i_1_n_0),
.G(y_OBUF[3]),
.GE(VCC_1),
.Q(y_OBUF[0]));
LUT6 #(
.INIT(64'hFFFFFFFFFFFF00F1))
forvar190_i_1
(.I0(\y_OBUF[3]_inst_i_3_n_0 ),
.I1(\y_OBUF[3]_inst_i_2_n_0 ),
.I2(wire1_IBUF[0]),
.I3(wire0_IBUF[0]),
.I4(forvar190_i_2_n_0),
.I5(forvar190_i_3_n_0),
.O(forvar190_i_1_n_0));
LUT3 #(
.INIT(8'h14))
forvar190_i_2
(.I0(wire0_IBUF[0]),
.I1(wire0_IBUF[2]),
.I2(wire1_IBUF[2]),
.O(forvar190_i_2_n_0));
( SOFT_HLUTNM = "soft_lutpair0" )
LUT3 #(
.INIT(8'h14))
forvar190_i_3
(.I0(wire0_IBUF[0]),
.I1(wire0_IBUF[1]),
.I2(wire1_IBUF[1]),
.O(forvar19__0_i_3_n_0));
IBUF \wire0_IBUF[0]_inst
(.I(wire0[0]),
.O(wire0_IBUF[0]));
IBUF \wire0_IBUF[1]_inst
(.I(wire0[1]),
.O(wire0_IBUF[1]));
IBUF \wire0_IBUF[2]_inst
(.I(wire0[2]),
.O(wire0_IBUF[2]));
IBUF \wire1_IBUF[0]_inst
(.I(wire1[0]),
.O(wire1_IBUF[0]));
IBUF \wire1_IBUF[1]_inst
(.I(wire1[1]),
.O(wire1_IBUF[1]));
IBUF \wire1_IBUF[2]_inst
(.I(wire1[2]),
.O(wire1_IBUF[2]));
IBUF \wire2_IBUF[0]_inst
(.I(wire2[0]),
.O(wire2_IBUF[0]));
IBUF \wire2_IBUF[1]_inst
(.I(wire2[1]),
.O(wire2_IBUF[1]));
IBUF \wire2_IBUF[2]_inst
(.I(wire2[2]),
.O(wire2_IBUF[2]));
IBUF \wire2_IBUF[3]_inst
(.I(wire2[3]),
.O(wire2_IBUF[3]));
IBUF \wire2_IBUF[4]_inst
(.I(wire2[4]),
.O(wire2_IBUF[4]));
IBUF \wire2_IBUF[5]_inst
(.I(wire2[5]),
.O(wire2_IBUF[5]));
IBUF \wire2_IBUF[6]_inst
(.I(wire2[6]),
.O(wire2_IBUF[6]));
IBUF \wire3_IBUF[0]_inst
(.I(wire3[0]),
.O(wire3_IBUF[0]));
IBUF \wire3_IBUF[1]_inst
(.I(wire3[1]),
.O(wire3_IBUF[1]));
OBUF \y_OBUF[0]_inst
(.I(y_OBUF[0]),
.O(y[0]));
OBUF \y_OBUF[1]_inst
(.I(\ ),
.O(y[1]));
OBUF \y_OBUF[2]_inst
(.I(y_OBUF[2]),
.O(y[2]));
LUT6 #(
.INIT(64'hAAAA3330AAAACCCF))
\y_OBUF[2]_inst_i_1
(.I0(wire3_IBUF[0]),
.I1(wire1_IBUF[0]),
.I2(\y_OBUF[3]_inst_i_2_n_0 ),
.I3(\y_OBUF[3]_inst_i_3_n_0 ),
.I4(wire1_IBUF[2]),
.I5(wire0_IBUF[0]),
.O(y_OBUF[2]));
OBUF \y_OBUF[3]_inst
(.I(y_OBUF[3]),
.O(y[3]));
LUT6 #(
.INIT(64'hAAAAAAAA03FFFC00))
\y_OBUF[3]_inst_i_1
(.I0(wire3_IBUF[1]),
.I1(\y_OBUF[3]_inst_i_2_n_0 ),
.I2(\y_OBUF[3]_inst_i_3_n_0 ),
.I3(\y_OBUF[3]_inst_i_4_n_0 ),
.I4(wire0_IBUF[1]),
.I5(wire1_IBUF[2]),
.O(y_OBUF[3]));
LUT3 #(
.INIT(8'hFE))
\y_OBUF[3]_inst_i_2
(.I0(wire2_IBUF[6]),
.I1(wire2_IBUF[5]),
.I2(wire2_IBUF[0]),
.O(\y_OBUF[3]_inst_i_2_n_0 ));
LUT4 #(
.INIT(16'hFFFE))
\y_OBUF[3]_inst_i_3
(.I0(wire2_IBUF[2]),
.I1(wire2_IBUF[1]),
.I2(wire2_IBUF[4]),
.I3(wire2_IBUF[3]),
.O(\y_OBUF[3]_inst_i_3_n_0 ));
( SOFT_HLUTNM = "soft_lutpair0" )
LUT3 #(
.INIT(8'hD2))
\y_OBUF[3]_inst_i_4
(.I0(wire0_IBUF[0]),
.I1(wire1_IBUF[0]),
.I2(wire1_IBUF[1]),
.O(\y_OBUF[3]_inst_i_4_n_0 ));
endmodule
include "./data/cells_cmos.v"
include "./data/cells_cyclone_v.v"include "./data/cells_verific.v"
include "./data/cells_xilinx_7.v"include "./data/cells_yosys.v"
include "syn_vivado.v"module testbench ; wire [3:0] y; reg [(1'h0):(1'h0)] clk; reg signed [(3'h4):(1'h0)] wire3; reg [(3'h6):(1'h0)] wire2; reg signed [(2'h2):(1'h0)] wire1; reg signed [(2'h2):(1'h0)] wire0; top #() top1 (.y(y), .clk(clk), .wire3(wire3), .wire2(wire2), .wire1(wire1), .wire0(wire0)); initial begin clk = (1'h0); {wire3, wire2, wire1, wire0} = (1'h0);
10 {wire3, wire2, wire1, wire0} = (256'hc8ed17754b580360127ef910e2932082ec2579f7a131db637cc1d86e57c7d0cb);
always
5 clk = (~clk);
always @(posedge clk) $strobe ("%b", y); endmodule
├── 1/ │ ├── data/ │ │ ├── cells_cmos.v │ │ ├── cells_cyclone_v.v │ │ ├── cells_verific.v │ │ ├── cells_xilinx_7.v │ │ ├── README.md │ │ └── cells_yosys.v │ ├── rtl.v │ ├── syn_vivado.v │ ├── vivado.log │ ├── vivado_main │ ├── vivado_testbench.v │ └── vvp_vivado.log ├── 2/ │ ├── data/ │ │ ├── cells_cmos.v │ │ ├── cells_cyclone_v.v │ │ ├── cells_verific.v │ │ ├── cells_xilinx_7.v │ │ ├── README.md │ │ └── cells_yosys.v │ ├── rtl.v │ ├── syn_vivado.v │ ├── vivado.log │ ├── vivado_main │ ├── vivado_testbench.v │ └── vvp_vivado.log