[하만]세미콘 아카데미/verilog

0521 num.sv

내머리속은이런걸로 2024. 7. 9. 17:42

system verilog test bench

 

 

 


num.sv

`timescale 1ns / 1ps

module num (
    input clk,
    input reset,
    input  [15:0] num_in,
    output [15:0] num_out
);

    reg [15:0] num_reg, num_next;

    assign num_out = num_reg;

    // register
    always @(posedge clk, posedge reset) begin
        if (reset) begin
            num_reg <= 0;
        end else begin
            num_reg <= num_next;
        end
    end

    // next state
    always @(*) begin
        num_next = num_in;
    end

endmodule

 

 

tb_num.sv

`timescale 1ns / 1ps

interface num_intf;
    logic clk;
    logic reset;
    logic [15:0] num_in;
    logic [15:0] num_out;
endinterface //num_intf

class transaction;
    rand logic [15:0] num_in;
    logic [15:0] num_out;

    task display(string name);
        $display("[%s] num_in : %d, num_out : %d", name, num_in, num_out);        
    endtask //display
endclass    // transaction

class generator;
    transaction tr;
    mailbox #(transaction) gen2drv_mbox;
    event genNextEvent;

    function new();
        tr = new();
    endfunction

    task run();
        repeat(10) begin
            assert (tr.randomize()) 
            else   $error("tr.randomize() error!");
            gen2drv_mbox.put(tr);
            tr.display("GEN");
            @(genNextEvent);
        end
        
    endtask

endclass //generator

class driver;
    virtual num_intf num_intf;
    mailbox #(transaction) gen2drv_mbox;
    transaction tr;
    event monNextEvent;

    function new(virtual num_intf num_intf);
        this.num_intf = num_intf;
    endfunction

    task reset();
        num_intf.num_in <= 0;
        num_intf.reset <= 1'b1;
        repeat (5) @(posedge num_intf.clk);
        num_intf.reset <= 1'b0;
    endtask //reset

    task run();
        forever begin
            gen2drv_mbox.get(tr);
            num_intf.num_in <= tr.num_in;
            @(posedge num_intf.clk);
            num_intf.num_out <= tr.num_out;
            tr.display("DRV");
            @(posedge num_intf.clk);
            -> monNextEvent;
        end
    endtask //run

endclass //driver

class monitor;
    virtual num_intf num_intf;
    mailbox #(transaction) mon2scb_mbox;
    transaction tr;
    event monNextEvent;

    function new(virtual num_intf num_intf);
        this.num_intf = num_intf;
        tr = new();
    endfunction //new()

    task run();
        forever begin
            @(monNextEvent);
            tr.num_in = num_intf.num_in;
            tr.num_out = num_intf.num_out;
            mon2scb_mbox.put(tr);
            tr.display("MON");
        end
    endtask //run
endclass //monitor

class scoreboard;
    transaction tr;
    mailbox #(transaction) mon2scb_mbox;
    event genNextEvent;

    int total_cnt, pass_cnt, fail_cnt;

    function new();
        total_cnt = 0;
        pass_cnt = 0;
        fail_cnt = 0;
    endfunction //new()

    task run();
        forever begin
            mon2scb_mbox.get(tr);
            tr.display("SCB");
            if (tr.num_in == tr.num_out) begin
                $display(" --> PASS! %d = %d", tr.num_in, tr.num_out);
                pass_cnt++;
            end else begin
                $display(" --> FAIL! %d = %d", tr.num_in, tr.num_out);
                fail_cnt++;
            end
            total_cnt++;
            ->genNextEvent;
        end
    endtask //run
endclass //scoreboard

module tb_num();

    num_intf num_intf(); // make really num interface
    generator gen;
    driver drv;
    monitor mon;
    scoreboard scb;

    event genNextEvent;
    event monNextEvent;

    mailbox #(transaction) gen2drv_mbox;
    mailbox #(transaction) mon2scb_mbox;

    num dut(
        .clk(num_intf.clk),
        .reset(num_intf.reset),
        .num_in(num_intf.num_in),
        .num_out(num_intf.num_out)
    );

    always #5 num_intf.clk = ~num_intf.clk;

    initial begin
        num_intf.clk = 1'b0;
        num_intf.reset = 1'b1;
    end

    initial begin
        gen2drv_mbox = new();
        mon2scb_mbox = new();

        gen = new();
        drv = new(num_intf);
        mon = new(num_intf);
        scb = new();

        // Event
        gen.genNextEvent = genNextEvent;
        drv.monNextEvent = monNextEvent;
        mon.monNextEvent = monNextEvent;
        scb.genNextEvent = genNextEvent;

        // MailBox
        gen.gen2drv_mbox = gen2drv_mbox;
        drv.gen2drv_mbox = gen2drv_mbox;
        mon.mon2scb_mbox = mon2scb_mbox;
        scb.mon2scb_mbox = mon2scb_mbox;

        drv.reset();

        fork
            gen.run();
            drv.run();
            mon.run();
            scb.run();
        join_any

        $display("=======================================");
        $display("            Final Report");
        $display("=======================================");
        $display ("Total Test   : %d", scb.total_cnt);
        $display ("Pass Counter : %d", scb.pass_cnt);
        $display ("Fail Counter : %d", scb.fail_cnt);
        $display("=======================================");
        $display("       test bench is finished!");
        $display("=======================================");
        #10 $finish;
    end
endmodule

 

simulation

'[하만]세미콘 아카데미 > verilog' 카테고리의 다른 글

0522 RAM SystemVerilog verification  (0) 2024.07.09
0522 32bit register.sv  (0) 2024.07.09
0521 system verilog, adder.sv  (0) 2024.07.09
0520 uart_led  (0) 2024.07.09
0520 oversampling, uart  (0) 2024.06.22