SystemVerilog Testbench - Example - 2
SystemVerilog Testbench - Example - 2
Verilog
Testbench
Example
SystemVerilog Testbench Example 2
Design
This Verilog module named "switch" is designed to handle two sets of address and data pairs
based on a specified condition. Here's a brief explanation of the design:
- Parameters:
- `ADDR_WIDTH`: Specifies the width of the address bus.
- `DATA_WIDTH`: Specifies the width of the data bus.
- `ADDR_DIV`: Represents a dividing value for determining the condition.
- Inputs:
- `clk`: Clock input.
- `rstn`: Active-low asynchronous reset.
- `vld`: Valid signal indicating a valid input condition.
- `addr`: Address input.
- `data`: Data input.
- Outputs:
- `addr_a`: Address output for condition met.
- `data_a`: Data output for condition met.
- `addr_b`: Address output for condition not met.
- `data_b`: Data output for condition not met.
- Behavior:
- On the positive edge of the clock (`posedge clk`), the module processes the input data.
- During a reset condition (`!rstn`), all outputs are set to zero.
- If the valid signal (`vld`) is active, the module checks whether the address is within the specified
range (`0` to `ADDR_DIV`).
- If true, it assigns the input address and data to `addr_a` and `data_a`, respectively. `addr_b`
and `data_b` are set to zero.
- If false, it assigns the input address and data to `addr_b` and `data_b`, respectively. `addr_a`
and `data_a` are set to zero.
This design effectively separates input data into two sets based on the condition specified by the
dividing value `ADDR_DIV`. The outputs `addr_a`, `data_a`, `addr_b`, and `data_b` represent the
results of this conditional separation.
module switch #
(
parameter ADDR_WIDTH = 8,
parameter DATA_WIDTH = 16,
parameter ADDR_DIV = 8'h3F
)
(
input clk,
input rstn,
input vld,
input [ADDR_WIDTH-1:0] addr,
input [DATA_WIDTH-1:0] data,
output reg [ADDR_WIDTH-1:0] addr_a,
output reg [DATA_WIDTH-1:0] data_a,
output reg [ADDR_WIDTH-1:0] addr_b,
output reg [DATA_WIDTH-1:0] data_b
);
always @(posedge clk) begin
if (!rstn) begin
addr_a <= 0;
data_a <= 0;
addr_b <= 0;
data_b <= 0;
end
else begin
if (vld) begin
if (addr >= 0 && addr <= ADDR_DIV) begin
addr_a <= addr;
data_a <= data;
addr_b <= 0;
data_b <= 0;
end
else begin
addr_a <= 0;
data_a <= 0;
addr_b <= addr;
data_b <= data;
end
end
end
end
endmodule
Interface
Transaction Object
task run();
for (int i = 0; i < num; i++) begin
switch_item item = new;
item.randomize();
$display("T=%0t [Generator] Loop:%0d/%0d create next item", $time, i +
1, num);
drv_mbx.put(item);
@(drv_done);
end
$display("T=%0t [Generator] Done generation of %0d items", $time, num);
endtask
endclass
Driver
task run();
$display("T=%0t [Driver] starting ...", $time);
@(posedge vif.clk);
function new();
sema4 = new(1);
endfunction
task run();
$display("T=%0t [Monitor] starting ...", $time);
function new();
d0 = new;
m0 = new;
g0 = new;
s0 = new;
drv_mbx = new();
scb_mbx = new();
d0.drv_mbx = drv_mbx;
g0.drv_mbx = drv_mbx;
m0.scb_mbx = scb_mbx;
s0.scb_mbx = scb_mbx;
d0.drv_done = drv_done;
g0.drv_done = drv_done;
endfunction
task run();
forever begin
switch_item item;
scb_mbx.get(item);
function new();
e0 = new;
endfunction
task run();
e0.run();
endtask
endclass
Testbench TOP
switch_if _if(clk);
switch u0(
.clk(clk),
.rstn(_if.rstn),
.addr(_if.addr),
.data(_if.data),
.vld(_if.vld),
.addr_a(_if.addr_a),
.data_a(_if.data_a),
.addr_b(_if.addr_b),
.data_b(_if.data_b)
);
test t0;
initial begin
{clk, _if.rstn} <= 0;
// Apply reset and start stimulus
#20 _if.rstn <= 1;
t0 = new;
t0.e0.vif = _if;
t0.run();
// Because multiple components and clock are running
// in the background, we need to call $finish explicitly
#50 $finish;
end