UVM驱动无法在连续时钟周期发送数据,求解决方法
问题分析与解决方案
问题根源
你的UVM驱动无法在ready持续为高时逐周期发送事务,核心原因是:
- 驱动
valid后多余等待了一个时钟上升沿,直接浪费了一个周期 - 拉低
valid的时机与握手完成的时钟沿不同步,导致额外的周期消耗
原代码时序(ready=1时):
- 时钟沿1:驱动
valid=1、addr、data - 时钟沿2:无意义等待(无任何操作)
- 时钟沿3:采样到
ready=1,拉低valid=0 - 返回
run_phase获取下一个事务,又要等待下一个时钟沿才能驱动,最终间隔两个周期才发送下一个事务
修正后的驱动代码
virtual task run_phase(uvm_phase phase); forever begin seq_item_port.get_next_item(trans); drive(trans); seq_item_port.item_done; end endtask virtual task drive(packet trans); // 等待时钟上升沿,驱动事务信号 @(posedge vif.mod_p.cb); vif.mod_p.cb.valid <= 'b1; vif.mod_p.cb.addr <= trans.addr; vif.mod_p.cb.data <= trans.data; // 等待DUT的ready信号(在时钟上升沿采样) while(!vif.mod_p.cb.ready) begin @(posedge vif.mod_p.cb); end // 握手完成后,在下一个时钟沿拉低valid(适配多数协议的时序要求) @(posedge vif.mod_p.cb); vif.mod_p.cb.valid <= 'b0; endtask
严格逐周期发送的优化方案
如果协议要求握手完成后立即在下一个时钟沿发送下一个事务,可以进一步调整逻辑,将拉低valid的操作和握手完成放在同一时钟沿,避免额外等待:
virtual task drive(packet trans); // 驱动事务并等待握手 @(posedge vif.mod_p.cb); vif.mod_p.cb.valid <= 'b1; vif.mod_p.cb.addr <= trans.addr; vif.mod_p.cb.data <= trans.data; // 等待ready响应 while(!vif.mod_p.cb.ready) begin @(posedge vif.mod_p.cb); end // 握手完成的同一时钟沿拉低valid,确保下一个事务能在下一周期立即驱动 vif.mod_p.cb.valid <= 'b0; endtask
这种情况下,当ready持续为高时,每个事务仅占用一个时钟周期(驱动并完成握手),下一个事务会在下一个时钟沿立即驱动,实现真正的逐周期发送。
内容的提问来源于stack exchange,提问作者Grace90
相关产品推荐
相关产品推荐

