SystemVerilog probes · 53Vivado: supported
async reset ORed with a synchronous clear: always_ff @(posedge clk, posedge btnC) if (btnC || btnU) q <= 0;
Vivado: supported. The open-source chain: it stops before a bitstream.
| stage | today |
|---|---|
| rtl, simulation | pass |
| synth, synthesis | fail |
| netlist, the netlist | not run |
| bit, the bitstream | fail |
What does Vivado do with it?
Supported. Vivado 2021.2 logs of a public lab repo (CS-224, the course after CS223): an always_ff @(posedge clk, posedge reset) whose first branch is if (reset || clear): 'INFO: [Synth 8-6155] done synthesizing module '<that module>' (13#1)', 'Synthesis finished with 0 errors, 0 critical warnings and 2 warnings.'; implementation 'write_bitstream completed successfully'
What does the open-source chain do with it?
since #5; rtl: PASS; yosys: 'ERROR: Multiple edge sensitive events found for this signal!', then the CLI names the block and the real cause (before #5 it said two always blocks): 'design.sv:3: ERROR [async-reset-not-alone]: this always block is sensitive to two edges (@(posedge clk, posedge btnC)), so one of them is an asynchronous reset, but its first if does not test that reset alone (a reset ORed with a synchronous clear: if (rst || clear)), so neither reader can tell the reset from the clock. Fix: test the reset alone first and put the synchronous clear in the else: if (btnC) q <= 0; else if (clear) q <= 0; else q <= q + 1;'; yosys-slang: 'design.sv:4:5: error: condition cannot be matched to any signal from the event list'
Which error pages explain the messages?
- async-reset-not-alone: The block has a clock and an asynchronous reset in its sensitivity list, but the first if tests the reset ORed with another signal.
What is the probe's code?
From test/sv/53_async_reset_sync_clear.
design.sv
module top(input logic clk, input logic btnC, input logic btnU, output logic [15:0] led);
logic [3:0] q;
always_ff @(posedge clk, posedge btnC) // btnC: asynchronous reset
if (btnC || btnU) q <= 4'd0; // btnU: a synchronous clear, in the same branch
else q <= q + 4'd1;
assign led = {12'd0, q};
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(.clk(clk), .btnC(btnC), .btnU(btnU), .led(led));
initial begin
#1 btnC = 1; #1 btnC = 0; #1
if (!(led === 16'd0)) begin $display("FAIL: async reset without a clock edge (led=%h)", led); $finish; end
tick; tick; tick;
if (!(led === 16'd3)) begin $display("FAIL: counts 3 (led=%h)", led); $finish; end
btnU = 1; #1
if (!(led === 16'd3)) begin $display("FAIL: btnU waits for the clock (led=%h)", led); $finish; end
tick; btnU = 0;
if (!(led === 16'd0)) begin $display("FAIL: btnU clears on the edge (led=%h)", led); $finish; end
tick; tick; #2 btnC = 1; #1
if (!(led === 16'd0)) begin $display("FAIL: async reset mid-cycle (led=%h)", led); $finish; end
btnC = 0; tick;
if (!(led === 16'd1)) begin $display("FAIL: counts again (led=%h)", led); $finish; end
$display("PASS"); $finish;
end
endmodule
previous: an internal tri bus with two tristate drivers taking turns (the textbook's mux from tristate buffers)
next: a name used before its declaration: assign led[0] = stop; logic stop;