寄存器模型集成总线UVC的示例

定义了用于验证 MCDF 总线(可能是模块或协议名称)的 UVM 组件,包括数据传输类、序列器、监控器、驱动器和 agent。

class mcdf_bus_trans extends uvm_sequence_item; // 定义 MCDF 总线事务类,继承自 uvm_sequence_item
    rand bit[1:0] cmd; // 事务命令,随机化
    rand bit[7:0] addr; // 事务地址,随机化
    rand bit[31:0] wdata; // 写入数据,随机化
    bit[31:0] rdata; // 读取数据
    `uvm_object_utils_begin(mcdf_bus_trans) // 使用 `uvm_object_utils_begin` 宏定义字段
        ... // 此处省略了字段定义
    `uvm_object_utils_end // 使用 `uvm_object_utils_end` 宏结束字段定义
    
    ... // 此处省略了其他方法定义
endclass

class mcdf_bus_sequencer extends uvm_sequencer; // 定义 MCDF 总线序列器类,继承自 uvm_sequencer
    virtual mcdf_if vif; // 与 MCDF 接口的虚拟接口
    `uvm_component_utils(mcdf_bus_sequencer) // 使用 `uvm_component_utils` 宏定义字段
    ... // 此处省略了其他方法定义
    
    function void build_phase(uvm_phase phase);
        if(!uvm_config_db#(virtual mcdf_if)::get(this, "", "vif", vif)) begin // 从配置数据库获取虚拟接口
         `在这里插入代码片`   `uvm_error("GETVIF", "no virtual interface is assigned") // 如果获取失败则报错
        end
    endfunction
endclass

class mcdf_bus_monitor extends uvm_monitor; // 定义 MCDF 总线监控器类,继承自 uvm_monitor
    virtual mcdf_if vif; // 与 MCDF 接口的虚拟接口
    uvm_analysis_port#(mcdf_bus_trans) ap; // 分析端口,用于发送事务到分析器
    `uvm_component_utils(mcdf_bus_monitor) // 使用 `uvm_component_utils` 宏定义字段
    ... // 此处省略了其他方法定义
    
    function void build_phase(uvm_phase phase);
        if(!uvm_config_db#(virtual mcdf_if)::get(this, "", "vif", vif)) begin // 从配置数据库获取虚拟接口
            `uvm_error("GETVIF", "no virtual interface is assigned") // 如果获取失败则报错
        end
        ap = new("ap", this); // 创建分析端口
    endfunction
    
    task run_phase(uvm_phase phase);
        forever begin // 循环监控事务
            mon_trans();
        end
    endtask
    
    task mon_trans(); // 监控事务任务
        mcdf_bus_trans t;
        @(posedge vif.clk); // 等待时钟上升沿
        if(vif.cmd == `WRITE) begin // 如果是写入操作
            t = new(); // 创建事务对象
            t.cmd = `WRITE;
            t.addr = vif.addr;
            t.wdata = vif.wdata;
            ap.write(t); // 将事务写入分析端口
        end
        else if(vif.cmd == `READ) begin // 如果是读取操作
            t = new(); // 创建事务对象
            t.cmd = `READ;
            t.addr = vif.addr;
            fork // 并行执行读取操作和发送事务
                begin
                    @(posedge vif.clk); // 等待时钟上升沿
                    #10ns; // 延迟 10ns
                    t.rdata = vif.rdata; // 读取数据
                    ap.write(t); // 将事务写入分析端口
                end
            join_none
        end
    endtask
endclass

class mcdf_bus_driver extends uvm_driver; // 定义 MCDF 总线驱动器类,继承自 uvm_driver
    virtual mcdf_if vif; // 与 MCDF 接口的虚拟接口
    `uvm_component_utils(mcdf_bus_driver) // 使用 `uvm_component_utils` 宏定义字段
    ... // 此处省略了其他方法定义
    
    function void build_phase(uvm_phase phase);
        if(!uvm_config_db#(virtual mcdf_if)::get(this, "", "vif", vif)) begin // 从配置数据库获取虚拟接口
            `uvm_error("GETVIF", "no virtual interface is assigned") // 如果获取失败则报错
        end
    endfunction
    
    task run_phase(uvm_phase phase);
        REQ tmp; // 临时变量
        mcdf_bus_trans req, rsp; // 事务对象
        reset_listener(); // 启动复位监听器
        forever begin // 循环驱动事务
            seq_item_port.get_next_item(tmp); // 从序列器获取下一条事务
            void'($cast(req, tmp)); // 将事务转换为 mcdf_bus_trans 类型
            `uvm_info("DRV", $sformatf("got a item \n %s", req.sprint()), UVM_LOW) // 打印信息
            void'($cast(rsp, req.clone())); // 克隆事务
            rsp.set_sequence_id(req.get_sequence_id()); // 设置序列 ID
            rsp.set_transaction_id(req.get_transaction_id()); // 设置事务 ID
            driver_bus(rsp); // 驱动总线
            seq_item_port.item_done(rsp); // 通知序列器事务完成
            `uvm_info("DRV", $sformatf("sent a item \n %s", req.sprint()), UVM_LOW) // 打印信息
        end
    endtask
    
    task reset_listener(); // 复位监听器任务
        fork
            forever begin
                @(negedge vif.rstn) driver_idle(); // 当复位信号有效时进入空闲状态
            end
        join_none
    endtask
    
    task drive_bus(mcdf_bus_trans t); // 驱动总线任务
        case(t.cmd) // 根据命令类型执行不同的驱动操作
            `WRITE: drive_write(t); // 写入操作
            `READ:  drive_read(t); // 读取操作
            `IDLE:  drive_idle(t); // 空闲状态
            default: `uvm_error("DRIVE", "invalid mcdf command type received!") // 非法命令类型,报错
        endcase
    endtask
    
    task drive_write(mcdf_bus_trans t); // 写入驱动任务
        @(posedge vif.clk); // 等待时钟上升沿
        vif.cmd <= t.cmd; // 写入命令
        vif.addr <= t.addr; // 写入地址
        vif.wdata <= t.wdata; // 写入数据
    endtask
    
    task drive_read(mcdf_bus_trans t); // 读取驱动任务
        @(posedge vif.clk); // 等待时钟上升沿
        vif.cmd <= t.cmd; // 写入命令
        vif.addr <= t.addr; // 写入地址
        @(posedge vif.clk); // 等待时钟上升沿
        #10ns; // 延迟 10ns
        t.rdata = vif.rdata; // 读取数据
    endtask
    
    task drive_idle(bit is_sync=0); // 空闲驱动任务
        if(is_sync) @(posedge vif.clk); // 如果是同步操作,则等待时钟上升沿
        @(posedge vif.clk); // 等待时钟上升沿
        vif.cmd <= 'h0; // 写入空闲命令
        vif.addr <= 'h0; // 写入空闲地址
        vif.wdata <= 'h0; // 写入空闲数据
    endtask
endclass

class mcdf_bus_agent extends uvm_agent; // 定义 MCDF 总线 agent 类,继承自 uvm_agent
    mcdf_bus_driver driver; // 驱动器对象
    mcdf_bus_sequencer sequencer; // 序列器对象
    mcdf_bus_monitor monitor; // 监控器对象
    `uvm_component_utils(mcdf_bus_agent) // 使用 `uvm_component_utils` 宏定义字段
    ... // 此处省略了其他方法定义
    
    function void build_phase(uvm_phase phase);
        driver = mcdf_bus_driver::type_id::create("driver", this); // 创建驱动器对象
        sequencer = mcdf_bus_sequencer::type_id::create("sequencer", this); // 创建序列器对象
        monitor = mcdf_bus_monitor::type_id::create("monitor", this); // 创建监控器对象
    endfunction
    
    function void connect_phase(uvm_phase phase);
        driver.seq_item_port.connect(sequencer.seq_item_export); // 将驱动器的 seq_item_port 连接到序列器的 seq_item_export
    endfunction
endclass

代码功能:

mcdf_bus_trans 类定义了 MCDF 总线上的数据传输结构,包括命令、地址、写入数据和读取数据。

mcdf_bus_sequencer 类定义了 MCDF 总线的序列器,负责生成和发送事务。

mcdf_bus_monitor 类定义了 MCDF 总线的监控器,负责捕获总线上的事务并将其发送到分析器。

mcdf_bus_driver 类定义了 MCDF 总线的驱动器,负责将事务发送到 DUT 并接收响应。

mcdf_bus_agent 类定义了 MCDF 总线的 agent,将驱动器、序列器和监控器组合在一起,并进行连接。

代码优势:

使用 UVM 组件,可以方便地创建和管理测试平台。

使用虚拟接口,可以方便地与 DUT 进行交互。

使用分析端口,可以方便地将事务发送到分析器进行分析。

使用随机化,可以方便地生成测试用例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值