SystemVerilog Verification – Mini Project
Verification plan creation
Stimulus/checker separation
Random + directed blend
Regression and debug workflow
Concept and setup
Understand what you will build
Day 30 — Integrated FIFO Verification Mini-Project
Simulation status (28 Oct 2026): run_regression.sh passes on Verilator 5.052: 4 scenario runs and 10 seeded runs, with no errors. Icarus Verilog 12 cannot compile the interface modports, so the script now uses Verilator. Details: Week 6 validation record (VALIDATION.md).
Files: fifo_interface.sv, fifo_dut.sv, tb_fifo_project.sv, run_regression.sh, verification_plan.md, LABS.md.
Run on Linux with Verilator 5 installed: bash run_regression.sh. A compile failure is reported as BLOCKED, never as PASS.
The source is a self-checking, non-UVM testbench with transaction stimulus, driver, scoreboard, reference model, directed/boundary/error/random scenarios and ten reproducible seeds. The XLS Day 30 lab inventory is included for later sign-off.
Architecture
Follow the verification data flow
Worked source
Study the supplied implementation
fifo_dut.sv
`timescale 1ns/1ps
module fifo_dut #(parameter DEPTH=4)(fifo_if.dut bus);
logic [7:0] mem[0:DEPTH-1];
integer head=0,tail=0,count=0;
assign bus.full = (count==DEPTH);
assign bus.empty = (count==0);
// Contract: when full, a write is rejected even if read is also requested;
// when empty, a read is rejected even if write is also requested.
always @(posedge bus.clk) begin : fifo_step
bit accept_w,accept_r;
if (!bus.rst_n) begin
head <= 0; tail <= 0; count <= 0;
bus.rd_data <= 0;
bus.overflow <= 0; bus.underflow <= 0;
end else begin
accept_w = bus.wr_en && (count<DEPTH);
accept_r = bus.rd_en && (count>0);
bus.overflow <= bus.wr_en && !accept_w;
bus.underflow <= bus.rd_en && !accept_r;
if (accept_w) begin
mem[tail] <= bus.wr_data;
tail <= (tail+1)%DEPTH;
end
if (accept_r) begin
bus.rd_data <= mem[head];
head <= (head+1)%DEPTH;
end
case ({accept_w,accept_r})
2'b10: count <= count+1;
2'b01: count <= count-1;
default: count <= count;
endcase
end
end
endmodule
fifo_interface.sv
`timescale 1ns/1ps
interface fifo_if(input logic clk);
logic rst_n=0, wr_en=0, rd_en=0;
logic [7:0] wr_data=0, rd_data;
logic full, empty, overflow, underflow;
modport dut(input clk,rst_n,wr_en,rd_en,wr_data,
output rd_data,full,empty,overflow,underflow);
modport tb(input clk,rd_data,full,empty,overflow,underflow,
output rst_n,wr_en,rd_en,wr_data);
endinterface
tb_fifo_project.sv
`timescale 1ns/1ps
// Self-checking, non-UVM FIFO verification mini-project.
// Generator -> driver -> DUT/interface -> monitor -> reference-model/scoreboard.
module tb_fifo_project;
localparam DEPTH=4;
logic clk=0;
always #5 clk=~clk;
fifo_if bus(clk);
fifo_dut #(.DEPTH(DEPTH)) dut(bus);
int seed=1,mode=0,checks=0,errors=0,cycles=0;
int unsigned rng;
byte unsigned model[0:DEPTH-1];
integer model_head=0,model_tail=0,model_count=0;
logic [7:0] expected_rd=0;
bit expected_overflow=0,expected_underflow=0;
// Local deterministic PRNG makes a 10-seed regression reproducible.
function automatic int unsigned next_random();
rng=(rng*32'd1664525)+32'd1013904223;
return rng;
endfunction
// Reference model predicts behavior from pre-clock inputs and queue state.
task automatic predict(input bit reset_n,input bit wr,input bit rd,input byte unsigned data);
bit aw,ar;
if (!reset_n) begin
model_head=0;model_tail=0;model_count=0;
expected_rd=0;expected_overflow=0;expected_underflow=0;
end else begin
aw=wr && (model_count<DEPTH);
ar=rd && (model_count>0);
expected_overflow=wr && !aw;
expected_underflow=rd && !ar;
if (aw) begin
model[model_tail]=data;
model_tail=(model_tail+1)%DEPTH;
end
if (ar) begin
expected_rd=model[model_head];
model_head=(model_head+1)%DEPTH;
end
if (aw && !ar) model_count++;
if (ar && !aw) model_count--;
end
endtask
// Driver controls signals before active edge; monitor checks after NBA updates.
task automatic step(input bit reset_n,input bit wr,input bit rd,input byte unsigned data);
@(negedge clk);
bus.rst_n=reset_n;bus.wr_en=wr;bus.rd_en=rd;bus.wr_data=data;
predict(reset_n,wr,rd,data);
@(posedge clk);
#1;
cycles++;
if (bus.full !== (model_count==DEPTH) ||
bus.empty !== (model_count==0) ||
bus.rd_data !== expected_rd ||
bus.overflow !== expected_overflow ||
bus.underflow !== expected_underflow) begin
$display("FAIL seed=%0d mode=%0d cycle=%0d count=%0d wr=%0b rd=%0b data=%0h got(rd=%0h full=%0b empty=%0b ov=%0b un=%0b) expected(rd=%0h full=%0b empty=%0b ov=%0b un=%0b)",
seed,mode,cycles,model_count,wr,rd,data,bus.rd_data,bus.full,bus.empty,bus.overflow,bus.underflow,
expected_rd,(model_count==DEPTH),(model_count==0),expected_overflow,expected_underflow);
errors++;
$fatal(1,"scoreboard mismatch");
end
checks++;
endtask
task automatic reset_fifo();
step(0,0,0,0);
step(1,0,0,0);
endtask
task automatic directed();
reset_fifo();
step(1,1,0,8'h11);
step(1,1,0,8'h22);
step(1,0,1,0);
step(1,0,1,0);
step(1,0,0,0);
endtask
task automatic boundary();
reset_fifo();
for(int i=0;i<DEPTH;i++) step(1,1,0,byte'(i+1));
step(1,1,0,8'h99); // full overflow
step(1,1,1,8'h77); // full: write rejected, read accepted
step(1,1,1,8'h66); // simultaneous accepted
for(int i=0;i<DEPTH;i++) step(1,0,1,0);
step(1,0,1,0); // empty underflow
step(1,1,1,8'h33); // empty: write accepted, read rejected
step(1,0,1,0);
endtask
task automatic error_tests();
reset_fifo();
step(1,0,1,0); // underflow
for(int i=0;i<DEPTH;i++) step(1,1,0,byte'(i));
step(1,1,0,8'hff); // overflow
step(0,1,1,8'hff); // reset takes precedence
step(1,0,1,0); // underflow after reset
endtask
task automatic random_tests(input int count);
int unsigned x;
reset_fifo();
for(int i=0;i<count;i++) begin
x=next_random();
step(1,x[0],x[8],byte'(x>>16));
end
endtask
initial begin
if (!$value$plusargs("SEED=%d",seed)) seed=1;
if (!$value$plusargs("MODE=%d",mode)) mode=0;
rng=seed;
case(mode)
1: directed();
2: boundary();
3: error_tests();
4: random_tests(300);
0: begin directed();boundary();error_tests();random_tests(300);end
default: $fatal(1,"invalid MODE (0=all 1=directed 2=boundary 3=error 4=random)");
endcase
if(errors!=0) $fatal(1,"errors=%0d",errors);
$display("DAY30_PASS seed=%0d mode=%0d checks=%0d cycles=%0d errors=%0d",seed,mode,checks,cycles,errors);
$finish;
end
initial begin
#1000000;
$fatal(1,"watchdog timeout");
end
endmodule
Guided and independent work
Complete the lab checklist
Day 30 — XLS-derived lab checklist
- [ ] Lab 1: Verification plan — Code and demonstrate verification plan with simulation evidence; document observations or debug result.
- [ ] Lab 2: Interface — Code and demonstrate interface with simulation evidence; document observations or debug result.
- [ ] Lab 3: Transaction — Code and demonstrate transaction with simulation evidence; document observations or debug result.
- [ ] Lab 4: Generator — Code and demonstrate generator with simulation evidence; document observations or debug result.
- [ ] Lab 5: Driver — Code and demonstrate driver with simulation evidence; document observations or debug result.
- [ ] Lab 6: Monitor — Code and demonstrate monitor with simulation evidence; document observations or debug result.
- [ ] Lab 7: Scoreboard — Code and demonstrate scoreboard with simulation evidence; document observations or debug result.
- [ ] Lab 8: Reference model — Code and demonstrate reference model with simulation evidence; document observations or debug result.
- [ ] Lab 9: Directed test — Code and demonstrate directed test with simulation evidence; document observations or debug result.
- [ ] Lab 10: Random test — Code and demonstrate random test with simulation evidence; document observations or debug result.
- [ ] Lab 11: Boundary test — Code and demonstrate boundary test with simulation evidence; document observations or debug result.
- [ ] Lab 12: Error test — Code and demonstrate error test with simulation evidence; document observations or debug result.
- [ ] Lab 13: 10-seed regression — Code and demonstrate 10-seed regression with simulation evidence; document observations or debug result.
- [ ] Lab 14: Failure triage — Code and demonstrate failure triage with simulation evidence; document observations or debug result.
- [ ] Lab 15: Architecture review — Code and demonstrate architecture review with simulation evidence; document observations or debug result.
The supplied project runs on Verilator 5.052 (run_regression.sh); each lab still needs your own evidence.
Assignment and evidence
Demonstrate the required engineering outcome
Debug assignment
Week-6 practical assessment
Peer review of architecture and code
Submission evidence
- Source files
- README with commands and environment
- Lab evidence log and screenshots if applicable
- Debug observations and outstanding issues
Review rubric
- Source and design
- 35
- Functional checks
- 30
- Debug and explanation
- 20
- Reproducibility
- 15
Personal evidence
This lesson is public; no account is needed to study it.
Knowledge check
Confirm the verification concepts
The scored check is being prepared.