728x90
1. Title
Full TestBench in System Verilog
2. Category
"System Verilog", "BASYS3", "VIVADO"
3. Key Concepts
Monitor, Scoreboard
4. Setup
https://verificationguide.com/systemverilog -examples/systemverilog-testbench-example-memory/
모니터(monitor), 스코어보드(scoreboard)를 추가적으로 구현하여 Full TestBench를 구현한다.
5. Code Review
module register(
input logic clk, reset,
input logic [31:0] d,
output logic [31:0] q
);
always_ff @( posedge clk, posedge reset ) begin
if(reset) begin
q <= 0;
end else begin
q <= d;
end
end
endmodule
interface reg_interface;
bit clk, reset;
logic [31:0] d;
logic [31:0] q;
endinterface //reg_interface
class transaction;
rand logic [31:0] data;
logic [31:0] out;
task display(string name);
$display("[%s] data: %x, out: %x", name, data, out);
endtask
endclass //transaction
class generator;
transaction trans;
mailbox #(transaction) gen2drv_mbx;
event gen_next_event;
function new(mailbox#(transaction) gen2drv_mbx, event gen_next_event);
this.gen2drv_mbx = gen2drv_mbx;
this.gen_next_event = gen_next_event;
endfunction
task run(int count);
repeat(count) begin
trans = new();
trans.randomize();
gen2drv_mbx.put(trans);
trans.display("GEN");
@(gen_next_event);
end
endtask
endclass //generator
class driver;
transaction trans;
mailbox #(transaction) gen2drv_mbx;
virtual reg_interface reg_interface;
event mon_next_event;
function new(virtual reg_interface reg_interface, mailbox #(transaction) gen2drv_mbx, event mon_next_event);
this.reg_interface = reg_interface;
this.gen2drv_mbx = gen2drv_mbx;
this.mon_next_event = mon_next_event;
endfunction
task reset();
reg_interface.d <= 0;
reg_interface.reset <= 1;
repeat(5) begin
@(posedge reg_interface.clk);
end
reg_interface.reset <= 0;
endtask
task run();
forever begin
#1;
gen2drv_mbx.get(trans);
reg_interface.d = trans.data;
trans.display("DRV");
@(posedge reg_interface.clk);
-> mon_next_event;
end
endtask
endclass //driver
class monitor;
virtual reg_interface reg_interface;
mailbox #(transaction) mon2scb_mbx;
transaction trans;
event mon_next_event;
function new(virtual reg_interface reg_interface, mailbox #(transaction) mon2scb_mbx, event mon_next_event);
this.reg_interface = reg_interface;
this.mon2scb_mbx = mon2scb_mbx;
this.mon_next_event = mon_next_event;
endfunction //new()
task run();
forever begin
@(mon_next_event);
trans = new();
trans.data = reg_interface.d;
@(posedge reg_interface.clk);
#1;
trans.out = reg_interface.q;
mon2scb_mbx.put(trans);
trans.display("MON");
end
endtask
endclass //monitor
class scoreboard;
mailbox #(transaction) mon2scb_mbx;
transaction trans;
event gen_next_event;
int total_count, pass_count, fail_count;
function new(mailbox #(transaction) mon2scb_mbx, event gen_next_event);
this.mon2scb_mbx = mon2scb_mbx;
this.gen_next_event = gen_next_event;
total_count = 0;
pass_count = 0;
fail_count = 0;
endfunction //new()
task run ();
forever begin
mon2scb_mbx.get(trans);
trans.display("SCB");
if(trans.data == trans.out) begin
$display("--> PASS !1 %x == %x", trans.data, trans.out);
pass_count++;
end else begin
$display("--> FAIL !1 %x == %x", trans.data, trans.out);
fail_count++;
end
total_count++;
-> gen_next_event;
end
endtask
endclass //scoreboard
class environment;
generator generator;
driver driver;
monitor monitor;
scoreboard scoreboard;
mailbox #(transaction) gen2drv_mbx;
mailbox #(transaction) mon2scb_mbx;
event gen_next_event;
event mon_next_event;
function new(virtual reg_interface reg_interface);
gen2drv_mbx = new();
mon2scb_mbx = new();
generator = new(gen2drv_mbx, gen_next_event);
driver = new(reg_interface, gen2drv_mbx, mon_next_event);
monitor = new(reg_interface, mon2scb_mbx, mon_next_event);
scoreboard = new(mon2scb_mbx, gen_next_event);
endfunction //new()
task report();
$display("===============================================");
$display("=============== FINAL REPORT =================");
$display(" TOTAL TEST : %d ", scoreboard.total_count);
$display("===============================================");
$display(" PASS TEST : %d ", scoreboard.pass_count);
$display(" FAIL TEST : %d ", scoreboard.fail_count);
$display("===============================================");
$display("===============================================");
$display("===============================================");
#10
$finish;
endtask
task pre_run();
driver.reset();
endtask
task run();
fork
generator.run(10000);
driver.run();
monitor.run();
scoreboard.run();
join_any
endtask
task run_test();
pre_run();
run();
endtask
endclass //environment
6. Testing and Debugging
* Testing Tools: VIVADO, Modelsim
module tb_register(
);
reg_interface reg_interface();
environment env;
register DUT(
.clk(reg_interface.clk), .reset(reg_interface.reset),
.d(reg_interface.d),
.q(reg_interface.q)
);
always
#5 reg_interface.clk = ~reg_interface.clk;
initial begin
reg_interface.clk = 0;
env = new(reg_interface);
env.pre_run();
env.run();
env.report();
end
endmodule
728x90
'AI SOC COURSE > SYSTEM VERILOG (CPU 설계)' 카테고리의 다른 글
CPU Course Review - 08. RAM (0) | 2025.02.12 |
---|---|
CPU Course Review - 07. Register (0) | 2025.02.11 |
CPU Course Review - 05. Accumulator (0 ~ 9) (0) | 2025.02.10 |
CPU Course Review - 04. Counter (0 ~ 9) (0) | 2025.02.10 |
CPU Course Review - 03. CPU Overview (0) | 2025.02.10 |