npx claudepluginhub codejunkie99/gateflow-plugin --plugin gateflowThis skill is limited to using the following tools:
Professional verification patterns for SystemVerilog testbenches.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Professional verification patterns for SystemVerilog testbenches.
┌─────────────────────────────────────────┐
│ Test Layer │ ← Test scenarios
├─────────────────────────────────────────┤
│ Environment Layer │ ← Agent coordination
├──────────────┬──────────────────────────┤
│ Agent │ Agent │ ← Protocol-specific
│ ┌────────┐ │ ┌────────┐ │
│ │ Driver │ │ │Monitor │ │
│ └────────┘ │ └────────┘ │
│ ┌────────┐ │ ┌────────┐ │
│ │Sequencer│ │ │Scoreboard│ │
│ └────────┘ │ └────────┘ │
├──────────────┴──────────────────────────┤
│ Interface Layer │ ← Signal abstraction
├─────────────────────────────────────────┤
│ DUT │
└─────────────────────────────────────────┘
module tb_dut;
// Clock and reset
logic clk = 0;
logic rst_n = 0;
always #5 clk = ~clk;
// DUT signals
logic [7:0] data_in, data_out;
logic valid_in, valid_out;
// DUT instance
dut u_dut (.*);
// Test
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, tb_dut);
// Reset
rst_n = 0;
repeat(5) @(posedge clk);
rst_n = 1;
// Stimulus + Check
for (int i = 0; i < 100; i++) begin
@(posedge clk);
data_in <= $urandom();
valid_in <= 1;
@(posedge clk);
valid_in <= 0;
// Wait for output
wait(valid_out);
check_result(data_in, data_out);
end
$display("TEST PASSED");
$finish;
end
// Checker
function void check_result(input [7:0] expected, input [7:0] actual);
assert(actual == expected)
else $error("Mismatch: expected %0h, got %0h", expected, actual);
endfunction
endmodule
class Transaction;
rand bit [31:0] addr;
rand bit [31:0] data;
rand bit [3:0] burst_len;
rand bit write;
// Constraints
constraint c_aligned { addr[1:0] == 2'b00; }
constraint c_burst { burst_len inside {1, 4, 8, 16}; }
// Copy
function Transaction copy();
Transaction t = new();
t.addr = this.addr;
t.data = this.data;
t.burst_len = this.burst_len;
t.write = this.write;
return t;
endfunction
// Display
function void display(string prefix = "");
$display("%s addr=%08h data=%08h burst=%0d %s",
prefix, addr, data, burst_len, write ? "WR" : "RD");
endfunction
endclass
class Driver;
virtual bus_if.master vif;
mailbox #(Transaction) mbx;
function new(virtual bus_if.master vif, mailbox #(Transaction) mbx);
this.vif = vif;
this.mbx = mbx;
endfunction
task run();
Transaction t;
forever begin
mbx.get(t);
drive(t);
end
endtask
task drive(Transaction t);
@(posedge vif.clk);
vif.addr <= t.addr;
vif.data <= t.data;
vif.valid <= 1;
@(posedge vif.clk);
while (!vif.ready) @(posedge vif.clk);
vif.valid <= 0;
endtask
endclass
class Monitor;
virtual bus_if.monitor vif;
mailbox #(Transaction) mbx; // To scoreboard
function new(virtual bus_if.monitor vif, mailbox #(Transaction) mbx);
this.vif = vif;
this.mbx = mbx;
endfunction
task run();
Transaction t;
forever begin
@(posedge vif.clk);
if (vif.valid && vif.ready) begin
t = new();
t.addr = vif.addr;
t.data = vif.data;
mbx.put(t);
end
end
endtask
endclass
class Scoreboard;
mailbox #(Transaction) expected_mbx;
mailbox #(Transaction) actual_mbx;
int pass_count, fail_count;
function new(mailbox #(Transaction) expected_mbx, mailbox #(Transaction) actual_mbx);
this.expected_mbx = expected_mbx;
this.actual_mbx = actual_mbx;
endfunction
task run();
Transaction expected, actual;
forever begin
expected_mbx.get(expected);
actual_mbx.get(actual);
compare(expected, actual);
end
endtask
function void compare(Transaction expected, Transaction actual);
if (expected.data == actual.data) begin
pass_count++;
end else begin
fail_count++;
$error("MISMATCH: expected=%08h actual=%08h", expected.data, actual.data);
end
endfunction
function void report();
$display("=============================");
$display("Scoreboard: PASS=%0d FAIL=%0d", pass_count, fail_count);
$display("=============================");
endfunction
endclass
class Transaction;
rand bit [31:0] addr;
rand bit [7:0] data;
// Base constraint
constraint c_valid_addr { addr < 32'h1000_0000; }
// Can be overridden in extended class
constraint c_mode { soft data > 0; }
endclass
class ErrorTransaction extends Transaction;
// Override to inject errors
constraint c_mode { data == 0; }
endclass
class Packet;
rand bit [1:0] pkt_type;
constraint c_type_dist {
pkt_type dist {
0 := 60, // 60% normal
1 := 30, // 30% error
2 := 10 // 10% special
};
}
endclass
class Packet;
rand bit [7:0] length;
rand bit [7:0] payload[];
constraint c_size {
payload.size() == length;
length inside {[1:64]};
solve length before payload;
}
endclass
class Coverage;
Transaction t;
covergroup cg_trans @(posedge clk);
// Coverpoints
cp_addr: coverpoint t.addr[31:28] {
bins low = {[0:3]};
bins mid = {[4:11]};
bins high = {[12:15]};
}
cp_write: coverpoint t.write;
cp_burst: coverpoint t.burst_len {
bins single = {1};
bins burst4 = {4};
bins burst8 = {8};
bins burst16 = {16};
illegal_bins bad = default;
}
// Cross coverage
cross_addr_write: cross cp_addr, cp_write;
endgroup
function new();
cg_trans = new();
endfunction
function void sample(Transaction t);
this.t = t;
cg_trans.sample();
endfunction
endclass
| Coverage Type | Target |
|---|---|
| Line | >95% |
| Branch | >90% |
| FSM State | 100% |
| FSM Transition | >95% |
| Functional | >98% |
// Parallel - wait for all
fork
driver.run();
monitor.run();
scoreboard.run();
join
// Parallel - wait for any (with cleanup)
fork
driver.run();
monitor.run();
timeout_check();
join_any
disable fork;
// Parallel - don't wait
fork
background_task();
join_none
task run_with_timeout(int cycles);
fork
begin
run_test();
end
begin
repeat(cycles) @(posedge clk);
$error("TIMEOUT after %0d cycles", cycles);
$finish;
end
join_any
disable fork;
endtask
interface axi_if #(
parameter int ADDR_W = 32,
parameter int DATA_W = 32
) (
input logic clk,
input logic rst_n
);
logic [ADDR_W-1:0] awaddr;
logic [DATA_W-1:0] wdata;
logic awvalid, awready;
logic wvalid, wready;
logic [1:0] bresp;
logic bvalid, bready;
modport master (
output awaddr, awvalid, wdata, wvalid, bready,
input awready, wready, bresp, bvalid
);
modport slave (
input awaddr, awvalid, wdata, wvalid, bready,
output awready, wready, bresp, bvalid
);
modport monitor (
input awaddr, awvalid, awready, wdata, wvalid, wready,
bresp, bvalid, bready
);
// Clocking block for TB
clocking cb @(posedge clk);
default input #1 output #1;
output awaddr, awvalid, wdata, wvalid, bready;
input awready, wready, bresp, bvalid;
endclocking
endinterface
class Agent;
virtual axi_if vif;
function new(virtual axi_if vif);
this.vif = vif;
endfunction
endclass
// In interface or bind module
property p_valid_stable;
@(posedge clk) disable iff (!rst_n)
valid && !ready |=> valid && $stable(data);
endproperty
assert property (p_valid_stable) else $error("Valid dropped before ready");
property p_handshake;
@(posedge clk) disable iff (!rst_n)
valid |-> ##[1:100] ready;
endproperty
assert property (p_handshake) else $error("No ready within 100 cycles");
virtual class BaseTest;
Environment env;
function new(Environment env);
this.env = env;
endfunction
pure virtual task run();
task pre_test();
env.reset();
endtask
task post_test();
env.report();
endtask
endclass
class SmokeTest extends BaseTest;
virtual task run();
Transaction t = new();
repeat(10) begin
assert(t.randomize());
env.driver_mbx.put(t);
end
endtask
endclass
[SystemVerilog for Verification, 3rd ed. — Spear/Tumbush]
|url: https://picture.iczhiku.com/resource/eetop/wYIEDKFRorpoPvvV.pdf
|relevant: Ch 5 (OOP), Ch 6 (Rand), Ch 7 (Threads), Ch 8 (Advanced OOP), Ch 9 (Coverage), Ch 11 (Complete TB)