对上篇文章【ahb_bus设计】设计的ahb_connect进行testbench仿真。其实就是在testbench中模拟master和slave的行为。
由于控制信号HBURST和HSIZE的原因,使得AHB总线传输的方式是多样的。假定HSIZE=3’b010,即32bits传输。剩下就是考虑HBURST的事了。
当然,从上篇文章结尾对HBURST的补充说明表不难看出,当处于single传输(即HBURST=3’b000)或者INCR传输(即HBURST=3’b001)时,HSIZE才有意义,这时候需要指定单次传输位宽;而其他几种BURST模式实际上根据地址的递增或回环已经指定了传输位宽,比如说HBURST=3’b011即INCR4模式和HBURST=3’b001 + HSIZE=3’b010是一样的,都是INCR模式单次传输32bits。
为了简单起见,只对single、INCR和WRAP4进行学习(即单次传输32位,其他位宽同理的)。本次学习内容有两个:
①:对HBUSREQ进行仿真,即验证master申请总线的逻辑;
②:进行master1对总线进行single模式读、写数据操作仿真。
注:由于本人coding level太低,testbench编写能力较差(且写的慢,因为一直在改bug),代码可能不优,仅做记录学习使用,后续INCR、WRAP的验证也会分开分享。
1.对HBUSREQ逻辑仿真
采用了最笨的方法,穷举法。
下图为仿真波形图
逻辑比较简单,先是master1、2同时申请总线,master1申请到了,体现优先级;然后是master1申请到了之后master2来抢占,失败;最后是master1抢占master2的总线,也失败。
2.Single模式读写
单次读写模式就是说每次只传输一个数据,传输完了就结束。由于slave有可能没有做好数据交换的准备,通过HREADY来告诉主机能不能交换数据。所以又分为无等待读写和有等待的读写。
从前一篇文章分析,时序图也不难理解,先是申请总线,申请到了就发送地址寻址slave,然后发送控制信号,最后是写/读的数据,时序图来源于互联网
a. 无等待的单传输
b. 有等待的单传输
先对ahb_connect模块中,master写操作逻辑功能进行验证,就相当于模拟一个master进行操作,看时序是否正确,tb代码如下
逻辑比较简单,就不赘述了。
下面对仿真图进行分析
T1时刻,master1得到总线授权(HGRANTx1 = 1’b1);作为得到授权的第一个上升沿,发送地址信号(HADDRx1)寻址slave,这里是0x5000_0001,以及之前提到的控制信号(HTRANS、HBURST、HSIZE、HWRITE);
T2时刻,发送数据,HWDATA = 32’h0000_04e6;同时因为T1发的地址没有slave与其对应,所以slave的HSELx都为低;
T3时刻,没有寻址到slave,所以slave接收到的数据SRDATA = 32’hx;同时开始下一次HADDR以及控制信号发送;流水线就体现出来了;
T4时刻,slave1被选中,且HREADY1为1’b1,无等待写数据;
T5时刻,数据传输完成,同时开启下一次传输,发送HADDR以及控制信号;
T6时刻,寻址到slave2,写数据HWDATA1,但是HREADY为1’b0,等待;
T7,继续等待,
T8,HREADY为高了,开始传输。
读数据一样的
反思总结:
Testbench编写能力有待提高(所以设计还是要懂验证的啊啊啊啊),刚学会task的使用;另外所有的信号都是在边沿变化,看起来不是很明显,是不是适当延时会好点。