SystemVerilog probes · 104Vivado: supported

a 3-state enum FSM with no start value, read by a case and an if before its first reset (led before the first clock edge)

Vivado: supported. The open-source chain: all four stages pass.

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

What does Vivado do with it?

Supported. UG901 v2022.2 Ch.4 p.79: 'FDRE: D flip-flop with Clock Enable and Synchronous Reset', 'FDSE: D flip-flop with Clock Enable and Synchronous Set'; 'To initialize the content of a Register at circuit power-up, specify a default value for the signal during declaration'. What Vivado programs for a register WITHOUT a start value is not in the guide; the start values this row states are nextpnr-xilinx's def_init (xilinx/fasm.cc), checked on the product's own FASM

What does the open-source chain do with it?

every stage prints 'PASS': the Makefile runs setundef -zero -params on the FDRE before write_json, so net.v starts the state register at INIT = 0 as nextpnr programs it, and led is all off before the first edge in RTL, netlist and bitstream alike. Since #35 the register keeps the student's 2-bit codes (FSM_KEEP_AWK sets fsm_encoding none before synth_xilinx: 2 FDRE, measured 'pnr ok: 3 LUT, 2 FF'), so that all-zero start is IDLE and the netlist leaves it at the first edge as the RTL does; between #34 and #35 yosys recoded the enum to three one-hot flip-flops whose all-zero start was none of the three states. Before #34 the netlist stage failed: the FDRE kept INIT x, cells_sim.v started Q at x, the case on it drove every led to x, and the testbench reported the before-the-first-edge check as a failure (expected all off) while rtl, synth and bit passed: a silent wrong

What is the probe's code?

From test/sv/104_fsm_before_first_reset.

design.sv

// a 3-state FSM read before its first reset: the netlist starts a register without a start value as the
// bitstream does (the three one-hot FDRE yosys makes of the enum at 0, which is none of the states), where the RTL has x
module top(input logic clk, input logic btnC, input logic [15:0] sw, output logic [15:0] led);
  typedef enum logic [1:0] {IDLE, RUN, DONE} state_t;
  state_t state, next;
  always_ff @(posedge clk)
    if (btnC) state <= IDLE;
    else      state <= next;
  always_comb
    case (state)
      IDLE:    if (sw[0]) next = RUN; else next = IDLE;
      RUN:     next = DONE;
      DONE:    if (sw[0]) next = DONE; else next = IDLE;
      default: next = IDLE;
    endcase
  always_comb
    if (state == DONE) led = 16'hFFFF;
    else               led = '0;
endmodule

tb.sv

// checks led before any clock edge: the RTL's x state takes the else branch (all off), and so must the
// netlist, which starts the FDRE at 0 as the bitstream does
module tb;
  logic clk = 1'b0, btnC = 1'b0;
  logic [15:0] sw = 16'h0000;
  logic [15:0] led;
  top dut(.clk(clk), .btnC(btnC), .sw(sw), .led(led));
  task tick; begin #5 clk = 1'b1; #5 clk = 1'b0; end endtask
  initial begin #200000 $display("FAIL: timeout"); $finish; end
  initial begin
    #1 if (led !== 16'h0000) begin $display("FAIL: before the first edge led=%b, expected all off", led); $finish; end
    btnC = 1'b1; tick; btnC = 1'b0;
    if (led !== 16'h0000) begin $display("FAIL: after reset led=%b", led); $finish; end
    sw[0] = 1'b1; tick; tick;
    if (led !== 16'hFFFF) begin $display("FAIL: in DONE led=%b", led); $finish; end
    sw[0] = 1'b0; tick;
    if (led !== 16'h0000) begin $display("FAIL: back in IDLE led=%b", led); $finish; end
    $display("PASS"); $finish;
  end
endmodule

previous: a package in its own file (pkg.sv) that design.sv `includes on line 1, 23c's documented fix
next: a 1-bit register set by the reset button (FDSE, no start value) read by an if before its first reset, beside a 16-bit counter (FDRE)