Testbenches, simulation, and proving your design works
Verification typically takes 60-70% of project time!
module counter_tb;
// Testbench signals
reg clk;
reg rst_n;
reg enable;
wire [3:0] count;
// Instantiate DUT
counter4 dut (
.clk (clk),
.rst_n (rst_n),
.enable (enable),
.count (count)
);
// Clock generation
initial clk = 0;
always #5 clk = ~clk; // 100MHz (10ns period)
// Stimulus
initial begin
// Initialize
rst_n = 0;
enable = 0;
// Reset
#20;
rst_n = 1;
// Enable counting
#10;
enable = 1;
// Let it count
#200;
// Disable
enable = 0;
#50;
// End simulation
$display("Test completed!");
$finish;
end
// Monitor
initial begin
$monitor("Time=%0t rst_n=%b enable=%b count=%d",
$time, rst_n, enable, count);
end
// Waveform dump (for viewing in waveform viewer)
initial begin
$dumpfile("counter.vcd");
$dumpvars(0, counter_tb);
end
endmodule
module adder_tb;
reg [7:0] a, b;
reg cin;
wire [7:0] sum;
wire cout;
// Expected values
reg [8:0] expected;
integer errors;
// DUT
adder8 dut (
.a(a), .b(b), .cin(cin),
.sum(sum), .cout(cout)
);
initial begin
errors = 0;
// Test all combinations (exhaustive for small designs)
for (a = 0; a < 256; a = a + 1) begin
for (b = 0; b < 256; b = b + 1) begin
for (cin = 0; cin < 2; cin = cin + 1) begin
#1; // Wait for combinational logic
expected = a + b + cin;
if ({cout, sum} !== expected) begin
$display("ERROR: a=%d b=%d cin=%d, got %d, expected %d",
a, b, cin, {cout, sum}, expected);
errors = errors + 1;
end
end
end
end
// Report
if (errors == 0)
$display("TEST PASSED!");
else
$display("TEST FAILED with %d errors", errors);
$finish;
end
endmodule
// Method 1: Initial + always
initial clk = 0;
always #5 clk = ~clk;
// Method 2: Forever loop
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// Method 3: Parameterized
parameter CLK_PERIOD = 10;
initial clk = 0;
always #(CLK_PERIOD/2) clk = ~clk;
// Reset generation
initial begin
rst_n = 0;
repeat(5) @(posedge clk); // Hold reset for 5 clocks
rst_n = 1;
end
// Task: Can have delays, multiple outputs
task write_data;
input [7:0] data;
input [3:0] addr;
begin
@(posedge clk);
wr_en <= 1;
wr_addr <= addr;
wr_data <= data;
@(posedge clk);
wr_en <= 0;
end
endtask
// Usage
initial begin
write_data(8'hAB, 4'h0);
write_data(8'hCD, 4'h1);
end
// Function: No delays, single output
function [7:0] expected_result;
input [7:0] a, b;
begin
expected_result = a ^ b; // XOR for example
end
endfunction
// Display and monitoring
$display("Value = %d", value); // Print once
$monitor("clk=%b data=%h", clk, data); // Print on change
$strobe("At end of timestep: %d", x); // Print at end of timestep
// Time
$time // Current simulation time (integer)
$realtime // Current simulation time (real)
// File I/O
integer fd;
fd = $fopen("output.txt", "w");
$fdisplay(fd, "Data: %h", data);
$fclose(fd);
// Waveform
$dumpfile("waves.vcd");
$dumpvars(0, testbench); // Dump all signals
// Control
$finish; // End simulation
$stop; // Pause simulation (for debugging)
// Immediate assertion
always @(posedge clk) begin
assert (count < 16) else $error("Count overflow!");
end
// Concurrent assertions
// Check that valid is followed by ready within 5 cycles
property valid_handshake;
@(posedge clk) valid |-> ##[1:5] ready;
endproperty
assert property (valid_handshake)
else $error("Handshake timeout!");
// Cover property (for coverage)
cover property (@(posedge clk) state == ERROR);
Measures how much of your design was exercised:
| Type | What It Measures |
|---|---|
| Line Coverage | Which lines executed |
| Branch Coverage | Which if/else branches taken |
| Toggle Coverage | Which signals toggled 0→1 and 1→0 |
| FSM Coverage | Which states visited, transitions taken |
| Condition Coverage | Boolean sub-expressions |
// Basic random
initial begin
repeat(1000) begin
data = $random; // 32-bit random
addr = $urandom_range(0, 255); // Range 0-255
#10;
check_result();
end
end
// Constrained random (SystemVerilog)
class Transaction;
rand bit [7:0] addr;
rand bit [31:0] data;
constraint valid_addr { addr < 100; }
constraint aligned { data[1:0] == 0; }
endclass
Transaction t = new();
t.randomize();
| Item | Description |
|---|---|
| ✓ Clock generation | Correct frequency |
| ✓ Reset sequence | Proper initialization |
| ✓ Stimulus | Cover normal and edge cases |
| ✓ Self-checking | Compare with expected values |
| ✓ Error reporting | Clear pass/fail indication |
| ✓ Timeout | Prevent infinite simulation |
| ✓ Waveform dump | For debugging |
| Concept | Key Point |
|---|---|
| Testbench | Stimulus + DUT + Checker |
| Self-checking | Compare actual vs expected |
| Tasks | Reusable stimulus sequences |
| Assertions | Check design properties |
| Coverage | Measure test completeness |
You've completed the Digital Design Blog Series!
You now have a solid foundation in digital design concepts.
← Back to All Articles