SystemVerilog probes · 31bVivado: supported

registers on the falling edge with no start value: a counter with a synchronous set (FDSE_1) and a bit with an asynchronous preset (FDPE_1), both reset from two switches

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 v2023.2 Ch.5 'Flip-Flops, Registers, and Latches' (p.81): Vivado synthesis recognizes registers with 'Rising or falling-edge clocks', 'Asynchronous Set/Reset' and 'Synchronous Set/Reset'

What does the open-source chain do with it?

every stage passes: yosys maps the counter to FDSE_1 and the preset bit to FDPE_1; since #34 the Makefile sets their INIT to 1 before write_json (setundef -one -params; before, INIT x), the value nextpnr programs, so the netlist starts both at 1 and equals the RTL started at 1 (the resets are built from two switches, so the bench does not press them first). Since #5 the pnr line names the clock by its port, 'pnr ok: 11 LUT, 5 FF, clk' '(PASS at 100.00 MHz)' (before #5 a cut internal name ending in slice$...C, the net after abc9)

What is the probe's code?

From test/sv/31b_negedge_set.

design.sv

// registers clocked on the falling edge, with no start value: a counter with a synchronous set and a bit with
// an asynchronous preset. Both resets are built from two switches, so the power-up state shows until they are used
module top(input logic clk, input logic [15:0] sw, output logic [15:0] led);
  logic [3:0] q;
  logic p;
  wire pre = sw[13] & sw[12];
  always_ff @(negedge clk)
    if (sw[15] & sw[14]) q <= 4'hf;
    else                 q <= q + 4'd1;
  always_ff @(negedge clk, posedge pre)
    if (pre) p <= 1'b1;
    else     p <= sw[0];
  assign led = {11'd0, p, q};
endmodule

tb.sv

module tb;
  logic clk = 1; logic [15:0] sw = 0; logic [15:0] led;
  top dut(.clk(clk), .sw(sw), .led(led));
  always #5 clk = ~clk;                               // falling edges at 5, 15, 25, ...
  integer i, bad = 0;
  initial begin
    sw = 16'hc000; @(posedge clk); #1;               // no edge yet: nothing set
    @(negedge clk); #1 if (led[3:0] !== 4'hf) begin bad++; $display("FAIL: the set on the falling edge: led=%h", led); end
    sw = 16'h0000;
    for (i = 1; i <= 20; i++) begin
      @(posedge clk); #1 if (led[3:0] !== 4'(15 + i - 1)) begin bad++; if (bad < 4) $display("FAIL: the rising edge moved q: led=%h", led); end
      @(negedge clk); #1 if (led[3:0] !== 4'(15 + i)) begin bad++; if (bad < 4) $display("FAIL: after %0d falling edges led=%h", i, led); end
    end
    sw = 16'h3000; #1 if (led[4] !== 1'b1) begin bad++; $display("FAIL: the preset, before any edge: led=%h", led); end
    sw = 16'h0000; @(negedge clk); #1 if (led[4] !== 1'b0) begin bad++; $display("FAIL: p follows sw[0] on the falling edge: led=%h", led); end
    sw = 16'h0001; @(posedge clk); #1 if (led[4] !== 1'b0) begin bad++; $display("FAIL: p moved on a rising edge: led=%h", led); end
    @(negedge clk); #1 if (led[4] !== 1'b1) begin bad++; $display("FAIL: p follows sw[0] on the falling edge: led=%h", led); end
    if (bad == 0) $display("PASS"); else $display("FAIL: %0d checks", bad);
    $finish;
  end
endmodule

previous: sync active-high reset, async active-low reset (negedge rst_n), async set to a nonzero constant
next: clock divider making a derived clock (always_ff @(posedge slow)) + 4-digit 7-seg multiplexing + hex ROM via case