一种简单的axi2ahb桥的实现

准备走秋招了,感觉除了数字ic设计和验证的理论知识外,项目好像还真没有能拿的出手的Orz,于是弄了个这个,希望设计与验证的两边都能练到。

项目代码在github

先看功能:能将AXI Master的transaction转换为AHB协议发送到AHB slave端口。能正确返回AHB slave的response。AXI部分只支持INCR/WRAP读写操作,(Fixed操作由于没考虑到就没写,其实也不难,但是写完过后我懒得加了);支持outstanding;不支持out of order,retry,split等高级feature。AHB部分则为single传输,支持b2b的single传输。

模块结构如下图:

一种简单的axi2ahb桥的实现_第1张图片

axi2ahb_bridge_top.v:顶层文件,连接各个模块。


axi_controller.v:axi控制器的顶层,连接下面两个模块。


axi2fifo.v:将axi主机发送的数据拆分成一个一个的小块,地址、数据、读写状态、id、size,last一一对应。这个地方主要有两个难点:arlen和awlen如何与ahb协议对应、卷绕突发地址该怎么算。

如果arlen、awlen不为0的话,axi会只发送一个首地址,然后发送一连串的数据。这时我们用两个寄存器a与b,寄存器a在主机第一笔数据来的时候保存当前的len,寄存器b从0开始,遇见一次wvalid自加1,直到加到数据等于len为止。地址的计算就为:首地址+b*(1<

至于卷绕突发,我们需要算出地址上界与下界。

地址下界=start_addr/((1<

如果我们的首地址为56,数据位宽32位(即4byte,size=2),发送4个数据(len=3),那么地址下界就是56/(4*4)*(4*4)=48。

地址上界=地址下界+(1<

算好地址上下界,当地址自加到上界的时候,下一个地址就跳转到下界,然后继续自加。

所有地址切片好后,与对应的数据以及控制信号一起发送到fifo。


fifo2axi.v:接受从ahb返回到fifo的数据,比如rdata,resp,id,读写状态,是否为last,并拼装成axi的格式,这部分主要的难度在于读与写的区分,b channel和r channel数据不要混淆就行,难度不高,看看代码就懂了,就不用细讲了。


fifo_wrapper.v:所有异步fifo的顶层,异步fifo的实现可参考我的这一篇博客:一种简单的异步fifo。每个fifo保存不同的数据与信号,同时要跨时钟域。需要细讲的是id_send_fifo.v和id_resp_fifo.v。第一个fifo除了保存id以外还在最后扩展了一位,用于保存last信号,第二个fifo扩展了两位,倒数第二位保存last,倒数第一位保存读或写。


ahb_controller.v:用于接收fifo的数据,转换成ahb的格式发送到从机,以及接收从机返回的数据,还要返回id,last这些ahb没有的信号给axi。这里难点主要在于单个single和连续single的发送。与axi不同的是,ahb是先发地址,从机回应后再发送数据,所以fifo要先读地址与控制信号,再读数据。同时还要考虑到从机没有ready的情况,用状态机实现,状态机需要考虑的很仔细,比如单个single,连续single,连续single中途从机ready拉低等情况,略微复杂,没考虑清楚有bug的话要调很久。


在验证的时候,要注意WRAP的地址必须满足对齐要求。随机了单笔以及多笔INCR/WRAP数据的读写,全部通过了,好耶!

一种简单的axi2ahb桥的实现_第2张图片

 唯一的error是VIP不知道哪里没设置对报了一个orz还没解决,不过数据全部对上了。

欢迎大家积极留言讨论,如果有bug还请批评指正(๑•̀ㅂ•́)و✧

你可能感兴趣的:(fpga开发,硬件工程)