errors · bitdewfpga bit, yosys

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.

A warning: the build goes on, with the latch (an LDCE cell) as Vivado would build it. dewfpga bit on a design whose always_latch gate and data both depend on sw:

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. https://nosey-dewdrop.github.io/dewfpga/errors/latch-hazard/

The design that printed it, seed 7 of test/fuzz cut down to six lines:

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

Why does it happen?

A latch is transparent while its gate is open and holds while it is closed; it has no clock edge to order its inputs. Here the gate s < sw and the data sw < 16'd1791 are both functions of sw, so one change of sw moves both. The testbench drives sw from 16'h2bdc to 16'h0000: the gate goes from open to closed and the data from 0 to 1 in the same instant. The RTL simulation evaluates the if once, with the new gate value, sees it closed and keeps led = 0. The netlist's LDCE gets its G and D through LUTs with different delays: D arrives first, G closes a moment later, and the latch takes led = 1. The board does the same, and which one wins depends on the routing, not on the code. 7 of the 27 silent-wrong seeds in 1..500 of test/fuzz were this shape; each becomes equal to its simulation when the latch is made transparent.

The latch warning names a latch nobody asked for (an always_comb that leaves a path unassigned); this one names a latch that was asked for, built right, and still cannot match the simulation. dewfpga sim cannot show the race, because iverilog has no delays on the netlist's wires either.

What is the fix?

Almost always a register was meant. Give it the clock, and the gate as its enable:

always_ff @(posedge clk)
  if (s < sw) led <= {15'b0, (sw < 16'd1791)};

Keep always_latch only when the gate is held steady while the data changes (a bus-hold or an address latch with a setup time its driver respects): then the warning tells you what the design counts on.

Which command prints it?

Which probes in test/sv print this code?

Every probe, with what Vivado does and what each stage does here: the probes, stage by stage.