Systemverilog中同一时刻连续执行两次task的问题

在写一个driver的过程中,遇到了一个奇怪的问题。driver的drv_transfer函数如下:

 forever begin

       wait(hready);

        repeat(4) begin

               data <= data_q.pop_front;

                @if.driver_cb;

       end

 end

这样写完之后,会出现一个时钟周期,queue被pop两次的情况,因此data的第一个数据就会被覆盖掉,并且这种现象仅仅发生在第一组数据上。出现这种情况的原因在于,hready是一个和时钟同步的信号,hready和时钟的上升沿是同时到来的。当hready拉高时,循环不会被@if.driver_cb阻塞,会继续运行,直到被下一个@if.driver_cb阻塞,因此,在一个时钟周期,queue会被pop两次,当forever不阻塞在wait(hready)时,已经不是上升沿的时钟周期,因此会pop一个数据,进入下一次循环,阻塞在@if.driver_cb,然后再次pop。对第一组数据而言,wait等待的信号成立,也就是hready初始就是高电平,因此不会被wait(hready)阻塞,也不会在某个上升沿不被wait(hready)阻塞,因此,第一组数据会pop两次,而其它的数据仅仅会pop一次。解决这个问题的方法是在pop后面添加#0语句。添加#0语句会将仿真时间推向当前时间的末尾,因此第一次pop就会被@if.driver_cb阻塞。

    systemverilog中的@和wait都是阻塞,但是区别在于一个@是同步阻塞,而wait是异步阻塞。对于被@阻塞的信号,如果触发时没有执行,就会一直阻塞,对于被wait阻塞的信号,只要触发过一次,就不会被阻塞。

    对于systemverilog而言,在同一仿真时刻,不同事件出现由先后顺序的。一个被posedge clk驱动的信号,出现的顺序会晚于posedge clk,因此,如果使用wait(signal)来阻塞程序,会等信号出现之后再继续执行,如果后面还有一个@posedge clk, 程序仍然会被阻塞。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值