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.

stagetoday
rtl, simulationpass
synth, synthesispass
netlist, the netlistfail
bit, the bitstreampass

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?

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