跳到主要内容
SystemVerilog

Class 实用示例

SystemVerilog面向对象编程实用示例

SV class 面向对象

Class 实用示例

示例1:基础transaction

class transaction;
    // 属性
    logic [31:0] addr;
    logic [31:0] data;
    logic        wr;      // 1=写, 0=读

    // 构造函数
    function new(input logic [31:0] a = 0, 
                 input logic [31:0] d = 0, 
                 input logic        w = 1);
        addr = a;
        data = d;
        wr   = w;
    endfunction

    // 显示方法
    function void display();
        $display("wr=%b, addr=%h, data=%h", wr, addr, data);
    endfunction
endclass

// 使用
transaction txn;
initial begin
    txn = new(32'h100, 32'hABCD, 1);  // 写操作
    txn.display();
    
    txn = new(32'h200, 0, 0);         // 读操作
    txn.display();
end

示例2:继承 - 基础与扩展transaction

// 基础transaction
class base_transaction;
    logic [31:0] addr;
    logic        wr;

    function new(input logic [31:0] a = 0, input logic w = 0);
        addr = a;
        wr   = w;
    endfunction

    function void display();
        $display("wr=%b, addr=%h", wr, addr);
    endfunction
endclass

// 扩展transaction(增加data字段)
class ext_transaction extends base_transaction;
    logic [31:0] data;

    function new(input logic [31:0] a = 0, 
                 input logic [31:0] d = 0, 
                 input logic w = 0);
        super.new(a, w);  // 调用父类
        data = d;
    endfunction

    // 重写display
    function void display();
        $display("wr=%b, addr=%h, data=%h", wr, addr, data);
    endfunction
endclass

// 使用
ext_transaction ext_txn;
initial begin
    ext_txn = new(32'h100, 32'hDEAD_BEEF, 1);
    ext_txn.display();
end

示例3:随机化 - 带约束的transaction

class rand_transaction;
    rand logic [31:0] addr;
    rand logic [31:0] data;
    rand logic        wr;
    randc bit [7:0]   id;     // 循环不重复

    // 地址约束:0x000~0x0FF
    constraint c_addr {
        addr inside {[32'h0000:32'h00FF]};
    }

    // 数据约束:不能为0
    constraint c_data {
        data != 0;
    }

    // 写操作时数据范围
    constraint c_wr_data {
        if (wr)
            data inside {[32'h0000:32'h0000_FFFF]};
    }
endclass

// 使用
rand_transaction txn;
initial begin
    txn = new();
    repeat(5) begin
        assert(txn.randomize())
            $display("id=%0d, wr=%b, addr=%h, data=%h", 
                     txn.id, txn.wr, txn.addr, txn.data);
    end
end

示例4:队列 - 存储多个transaction

class transaction_queue;
    transaction queue[$];  // 队列存储transaction

    // 入队
    function void push(transaction txn);
        queue.push_back(txn);
    endfunction

    // 出队
    function transaction pop();
        return queue.pop_front();
    endfunction

    // 显示所有
    function void display_all();
        foreach(queue[i])
            $display("[%0d] %h", i, queue[i].addr);
    endfunction
endclass

// 使用
transaction_queue tq;
transaction txn;

initial begin
    tq = new();
    
    // 添加多个transaction
    repeat(5) begin
        txn = new($urandom_range(0, 255), $urandom);
        tq.push(txn);
    end
    
    tq.display_all();
end

示例5:driver - 驱动DUT

class driver;
    virtual axi_if vif;  // 虚接口连接DUT

    function new(virtual axi_if vif);
        this.vif = vif;  // this.访问成员变量
    endfunction

    // 写操作
    task write(input logic [31:0] addr, input logic [31:0] data);
        @(posedge vif.clk);
        vif.awvalid <= 1;
        vif.awaddr  <= addr;
        @(posedge vif.clk);
        vif.wvalid  <= 1;
        vif.wdata   <= data;
        @(posedge vif.clk);
        vif.wvalid  <= 0;
        vif.awvalid <= 0;
    endtask

    // 读操作
    task read(input logic [31:0] addr, output logic [31:0] data);
        @(posedge vif.clk);
        vif.arvalid <= 1;
        vif.araddr  <= addr;
        @(posedge vif.clk);
        vif.arvalid <= 0;
        @(posedge vif.rvalid);
        data = vif.rdata;
    endtask
endclass

// 使用
driver drv;
initial begin
    drv = new(vif);  // 传入接口
    drv.write(32'h100, 32'hDEAD_BEEF);
end

示例6:monitor - 采集DUT信号

class monitor;
    virtual axi_if vif;
    transaction txn;

    function new(virtual axi_if vif);
        this.vif = vif;
    endfunction

    // 监测写操作
    task run();
        forever begin
            @(posedge vif.clk);
            if (vif.awvalid && vif.awready) begin
                txn = new(vif.awaddr, vif.wdata, 1);
                $display("Monitor: %h", txn.addr);
            end
        end
    endtask
endclass

// 使用
monitor mon;
initial begin
    mon = new(vif);
    mon.run();
end

示例7:scoreboard - 比较结果

class scoreboard;
    int pass_count = 0;
    int fail_count = 0;

    // 比较预期和实际
    function void check(input logic [31:0] expected, 
                        input logic [31:0] actual);
        if (expected === actual) begin
            $display("PASS: %h == %h", expected, actual);
            pass_count++;
        end else begin
            $display("FAIL: %h != %h", expected, actual);
            fail_count++;
        end
    endfunction

    // 显示统计
    function void report();
        $display("Pass: %0d, Fail: %0d", pass_count, fail_count);
    endfunction
endclass

示例8:parameterized class - 参数化类

// 通用FIFO类,位宽可配置
class fifo #(parameter WIDTH = 8, DEPTH = 16);
    logic [WIDTH-1:0] queue[$];

    function void push(input logic [WIDTH-1:0] data);
        if (queue.size() < DEPTH)
            queue.push_back(data);
        else
            $error("FIFO full");
    endfunction

    function logic [WIDTH-1:0] pop();
        if (queue.size() > 0)
            return queue.pop_front();
        else
            $error("FIFO empty");
    endfunction

    function int size();
        return queue.size();
    endfunction
endclass

// 使用
fifo #(8, 16)   fifo8;    // 8位宽,深度16
fifo #(32, 64)  fifo32;   // 32位宽,深度64

initial begin
    fifo8 = new();
    fifo8.push(8'hAA);
    fifo8.push(8'hBB);
end

最后更新: 2026-07-15