System verilog 通过任务驱动虚拟接口信号的位片
我试图创建一个任务,负责设置一个向量位,并在一个时钟周期后清除它。我的驾驶员代码附在下面:System verilog 通过任务驱动虚拟接口信号的位片,system-verilog,uvm,System Verilog,Uvm,我试图创建一个任务,负责设置一个向量位,并在一个时钟周期后清除它。我的驾驶员代码附在下面: class my_if_driver extends uvm_driver; `uvm_component_utils(my_if_driver) // Members // UVM stuff virtual my_if_interface vif; function new(string name="my_if_driver", uvm_componen
class my_if_driver extends uvm_driver;
`uvm_component_utils(my_if_driver)
// Members
// UVM stuff
virtual my_if_interface vif;
function new(string name="my_if_driver", uvm_component parent);
super.new(name, parent);
endfunction
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
extern task drive_my_if(my_if_transaction txn);
extern task set_then_clear(ref logic signal);
endclass
function void my_if_driver::build_phase(uvm_phase phase);
endfunction
function void my_if_driver::connect_phase(uvm_phase phase);
endfunction
task my_if_driver::run_phase(uvm_phase phase);
@(posedge vif.resetn);
forever begin
seq_item_port.get_next_item(req);
fork
drive_my_if(req);
join_none
seq_item_port.item_done(req);
end
endtask
// NOTE: each 'command-signal' has bit for each tid (transaction ID)
task my_if_driver::drive_my_if(my_if_transaction txn);
// Wait for delay
repeat (txn.cycle_delay) @(posedge vif.clk);
// Then drive appropriate signal
if (txn.my_if_cmd == my_if_transaction::CMDA) begin
set_then_clear(vif.my_if_cmd_a[txn.tid]);
end
else if (txn.my_if_cmd == my_if_transaction::CMDB) begin
set_then_clear(vif.my_if_cmd_b[txn.tid]);
end
else if (txn.my_if_cmd == my_if_transaction::CMDC) begin
set_then_clear(vif.my_if_cmd_c[txn.tid]);
end
endtask
task my_if_driver::set_then_clear(ref logic signal);
signal <= 1'b1;
@(posedge vif.clk);
signal <= 1'b0;
endtask
如果驱动程序扩展了uvm驱动程序,则将my\u分类;
`uvm_组件_utils(我的if_驱动程序)
//成员
//UVM材料
虚拟my_if_接口vif;
新函数(字符串名称=“我的驱动程序”,uvm\U组件父级);
super.new(名称、父级);
端功能
外部功能无效构建阶段(uvm阶段);
外部功能无效连接相位(uvm相位);
外部任务运行阶段(uvm阶段);
外部任务驱动\我的\如果(我的\如果\事务txn);
外部任务集然后清除(参考逻辑信号);
末级
函数void my_if_驱动程序::构建阶段(uvm_阶段);
端功能
函数void my_if_驱动程序::连接_阶段(uvm_阶段);
端功能
任务my_if_驱动程序::运行阶段(uvm_阶段);
@(posedge vif.resetn);
永远开始
seq_item_port.获取下一个_item(请求);
叉
驾驶我的车如果(需要);
加入
序号项目端口。项目完成(需求);
结束
结束任务
//注意:每个“命令信号”都有每个tid的位(事务ID)
任务my_if_驱动程序::drive_my_if(my_if_事务txn);
//等待延误
重复(txn循环延迟)@(posedge振动时钟);
//然后驱动适当的信号
如果(txn.my\u if\u cmd==my\u if\u事务::CMDA)开始
设置然后清除(vif.my\u if\u cmd\u a[txn.tid]);
结束
else if(txn.my\u if\u cmd==my\u if\u transaction::CMDB)开始
设置然后清除(vif.my\u if\u cmd\u b[txn.tid]);
结束
else if(txn.my\u if\u cmd==my\u if\u transaction::CMDC)开始
设置然后清除(vif.my\u if\u cmd\u c[txn.tid]);
结束
结束任务
任务my_if_驱动程序::设置_然后清除(参考逻辑信号);
信号LRM说
因为通过引用传递的变量可能是自动变量
ref参数不得用于禁止自动执行的任何上下文中
变量
并且不能通过引用传递压缩变量的一位select,只能传递整个变量
如果不为每个cmd编写单独的任务,或者在选择要分配的接口变量的signal任务中编写一个big case语句,那么就没有简单的方法可以做到这一点 LRM说
因为通过引用传递的变量可能是自动变量
ref参数不得用于禁止自动执行的任何上下文中
变量
并且不能通过引用传递压缩变量的一位select,只能传递整个变量
如果不为每个cmd编写单独的任务,或者在选择要分配的接口变量的signal任务中编写一个big case语句,那么就没有简单的方法可以做到这一点 尝试将这两行上的非阻塞分配更改为阻塞。我确实在服务器上尝试了你的代码,并得到另一个错误“Object”this.vif.my_if_cmd_a[txn.tid]”无法通过引用传递。允许的对象类型包括变量、类属性、未打包的结构成员和未打包的数组元素。”(我没有检查此错误是模拟器问题还是SV规则。)根据Dave的回答,这是LRM规则(第13.5.2节)。我选择执行非阻塞的原因是,我希望在所有监视活动之后更新值(目前不使用CB)。请尝试将这两行上的非阻塞分配更改为阻塞。我确实在服务器上尝试了你的代码,并得到另一个错误“Object”this.vif.my_if_cmd_a[txn.tid]”无法通过引用传递。允许的对象类型包括变量、类属性、未打包的结构成员和未打包的数组元素。”(我没有检查此错误是模拟器问题还是SV规则。)根据Dave的回答,这是LRM规则(第13.5.2节)。我选择执行非阻塞的原因是因为我希望在所有监视活动之后更新值(目前不使用CB)。谢谢Dave!我在LRM中看到了这一点,但后来我也看到了这一点,我将您的答案解释为这是可能的,因此我满怀希望:)我将采用“大案例/多假设”路线。谢谢Dave!我在LRM中看到了这一点,但后来我也看到了这一点,我将您的答案解释为这是可能的,因此我满怀希望:)我将采用“大案例/多假设”路线。