SystemVerilog probes · 101cVivado: unverified
an always_latch whose gate (s < sw) and data (sw < 16'd1791) come from the same inputs, so both change at once (seed 7 of test/fuzz, shrunk)
Vivado: unverified. The open-source chain: it builds a bitstream, and the netlist check fails.
| stage | today |
|---|---|
| rtl, simulation | pass |
| synth, synthesis | pass |
| netlist, the netlist | fail |
| bit, the bitstream | pass |
What does Vivado do with it?
Unverified. UG901 v2023.2 Ch.5 Latches (p.84) describes the LDCE Vivado builds and does not say what Vivado does when a latch's gate and data change together; no Vivado log
What does the open-source chain do with it?
a documented silent wrong: the bitstream builds and the build warns at the always_latch line: 'design.sv:4: warning [latch-hazard]: always_latch builds a latch for led (an LDCE cell, as Vivado builds it, UG901 Ch.5 Latches), and a latch has no clock: when its gate (s < sw) closes in the same instant its data changes, the board keeps the old value or takes the new one depending on which wire is faster, where the simulation always keeps the old one; dewfpga sim cannot show that race. Fix: if a register was meant, write always_ff @(posedge clk) with the gate as its enable: if (s < sw) led <= ...; keep always_latch only when the gate is held steady while the data changes.'; rtl: PASS (iverilog keeps the old led at the step sw 16'h2bdc -> 16'h0000); netlist: 'FAIL: step 1: sw=0000 led=0001, expected 0000 (the gate closed as the data changed)' (the LDCE took the new data as the gate closed); bit: 'pnr ok: 22 LUT, 1 FF, no clocked paths, timing not applicable'
Which error pages explain the messages?
- latch-hazard: An always_latch whose gate and data come from the same inputs: when both change at once the board races, where the simulation keeps the old value; the build goes on with the warning.
What is the probe's code?
From test/sv/101c_always_latch_race.
design.sv
module top(input logic [15:0] sw, output logic [15:0] led);
logic [1:0] s;
assign s = {sw[1] ^ sw[0], sw[0] ^ sw[1]};
always_latch if (s < sw) led = {15'b0, (sw < 16'd1791)};
endmodule
tb.sv
module tb;
reg clk = 1'b0;
reg btnC = 1'b0, btnU = 1'b0, btnD = 1'b0, btnL = 1'b0, btnR = 1'b0;
reg [15:0] sw = 16'h0000;
wire [15:0] led; wire [6:0] seg; wire dp; wire [3:0] an;
task tick; begin #5 clk = 1'b1; #5 clk = 1'b0; end endtask
initial begin #200000 $display("FAIL: timeout"); $finish; end
top dut(.sw(sw), .led(led));
initial begin
// the gate (s < sw) is open at 16'h2bdc; at 16'h0000 it closes in the same instant the data (sw < 1791) changes
sw = 16'h2bdc; #1
if (!(led === 16'h0000)) begin $display("FAIL: step 0: sw=2bdc led=%h, expected 0000", led); $finish; end
sw = 16'h0000; #1
if (!(led === 16'h0000)) begin $display("FAIL: step 1: sw=0000 led=%h, expected 0000 (the gate closed as the data changed)", led); $finish; end
sw = 16'h2bdc; #1
if (!(led === 16'h0000)) begin $display("FAIL: step 2: sw=2bdc led=%h, expected 0000", led); $finish; end
sw = 16'h0100; #1
if (!(led === 16'h0001)) begin $display("FAIL: step 3: sw=0100 led=%h, expected 0001", led); $finish; end
$display("PASS"); $finish;
end
endmodule
previous: the same always_latch next to a foreach loop (43_foreach_loop), so the design is read with yosys-slang
next: a .* connection whose port (N bits, N = 8) and signal (4 bits) widths differ