求助:在systemverilog的task中只能用阻塞赋值么?
今天突然遇到一个简单的基本问题,但是会导致设计很大的错误。就是在systemverilog的task中使用非阻塞赋值的问题。
我在写一个task,当valid为高的时候,采集总线上的id信号,并根据id去查id对应的transfer,根据该transfer的延时参数来给出ready信号。那么问题来了:
刚开始我是这样写的:
- @(posedge vif.axi_clock iff(vif.axi_rst_n))
- if(vif.rvalid) begin
- id = vif.RID;
- $display("receive r_id=%h @ %t",id,$time);
- ......
- end
然后波形出来一看,有点不对,rvalid是在1550ns时刻拉高,本来应该这个时候就采集到id的,但是打印出来的却是在1570ns的时候才采集到id的值(时钟周期20ns)。所以我就想应该使用"<=",结果ncvlog报错NOAUTO,难道systemverilog的task中不能使用非阻塞赋值么,应该不会吧,应该是我没用对,所以,我想问问各位,这种情况我应该怎么修改我的代码?
小编能否把波形图贴上,不然很难从你的文字知道电路的运行情况。
还有那个错误,是否是你定义id变量不是寄存器变量造成的,因为非阻塞赋值操作只能用于寄存器变量赋值。
id的定义我后来改了呀,改成logic或者reg都不行。
波形图,由于已经改动了很多,问题已经跟开始描述的有些不一样了,(已经把if(vif.rvalid)改成@(posedge vif.rvalid),这样就能按照我要求的时序采数据。)但是还有个不变的问题就是我没办法在task里面使用“<="赋值。我想知道是确实不能使用么?
valid信号应该是在时钟有效沿之后才被驱动拉高的,
如果valid已被clocking block同步的话,作为input,应该是在时钟有效沿之前被采样,
所以被拉高的时候,没有被采到,直到下一个时钟沿
至于你说的task不能用非blocking,我想是可以的,可能是别的什么问题导致的
你看看的你贴的代码的if下的两个语句末的分号,好像不一样
我的个人观点,最近刚接触,欢迎交流
你的vif 的interface里面是否用clocking block 做信号同步,不然就会出现tb 和 dut的信号竞争问题。
另外1570的rising edge sample到 1550的rising edge 驱动assert的valid信号没有错啊?!
1. interface中是已经跟时钟同步了的
2.这个是设计时候想法问题,等发觉到的时候想改已经不容易了。因为我是想把master发出的每个AR传输都存在一个队列中,然后等master收到slave传输的数据的时候,用收到的ID去队列中查找相应的transfer,然后取出transfer中定义的rvalid_to_rready_delay值,用这个值来数时钟,以便产生rready信号。因此只能先sample再drive,没办法做到axi标准里面的在valid与ready同时有效的时候才sample。要改这个问题的话,真的整个架构都要重新推翻了。
马克后看
你在1楼的代码没有问题,把打印去掉即可。根据verilog标准,“id = vif.RID;” 和 “$display("receive r_id=%h @ %t",id,$time);” 都是在active区间执行,但是他们的执行顺序是随机的。这里的$display无论是打印id的新值还是打印id的旧值都是正确的。或者你可以display vif.RID而非id,这样可以确保得到consistent的结果。
一个信号在时刻1被驱动为高,那么一定是在下一个时刻才能被采到,本来就应该是这样子的啊
task里面当然可以用非阻塞赋值了,毫无疑问的。贴你的代码出来,把编译错误贴出来,看看是啥原因
当然不是task里面就一定可以非阻塞赋值,标准里面写的很清楚:It shall be illegal to make nonblocking assignments to automatic variables.如果id是local variable那肯定会报错的
我的意思是说,能不能非阻塞赋值和是不是task没关系,LZ想问是不是在task里面不能用非阻塞赋值,我的意思是,可以。
我估计他犯的错就是你说的这个原因,估计他的task是在class里面定义的,这样定义的id就默认是automatic变量。(class里面的task默认是automatic, module里面的task 默认是static)导致编译错误。
"rvalid是在1550ns时刻拉高,本来应该这个时候就采集到id的"
在1550ns才开始驱动,难道不应该是在下一个周期才能采到么?
task中使用非阻塞赋值的前提是task是静态的,所以这个task要么是在module里要么是在静态class里。我记得是这样的。看看语法手册。
学学~