ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

FPGA之FIFO详解,读写位宽不同

2022-02-09 22:35:14  阅读:423  来源: 互联网

标签:dout FPGA 读写 练习 FIFO 32bit 模块 时钟


      这篇博客里,通过两个练习来总结在FPGA设计中FIFO读写位宽不同的情况下,我们应该去如何设计时序逻辑,因为在现实工程中FIFO读写位宽不同也是经常出现的情况。

练习1

         设计一个模块包含读写位宽是32bit、读写深度是64的异步时钟FIFO,其中输入数据信号din和输入 数据指示信号din_vld是属于clk_in时钟域的,上游模块会负责写数据到本模块的FIFO中,当本模块FIFO写端口已写入了60个数据,也就是FIFO快要写满溢出的时候,这时上游模块仍有数据要写入FIFO则直接丢弃该数据。下游模块负责从本模块的FIFO中读数据,当下游模块输入rdy信号时表示下游模块已准备好可以接收FIFO中的数据了,这时如果FIFO中有数据,那么就把FIFO中的数据赋值给输出数据信号dout送至下游模块并同时拉高dout_vld输出数据指示信号,其中输出数据信号dout和输出数据指示信号dout_vld则是属于clk_out时钟域的,上游模块din信号的写位宽是32bit,下游模块dout信号的读位宽是8bit,表1为练习1的信号列表。

信号列表

信号名

I/O

位宽

clk_in

I

1

rst_n

I

1

rdy

I

1

din

I

32

din_vld

I

1

clk_out

I

1

dout

O

8

dout_vld

O

1

fifo_empty

O

1

表1 FIFO IP练习1设计中的信号列表

         我们来思考下练习1功能模块的代码设计,其实不同的地方主要在于上游模块的写位宽din是32bit,而下游模块的读位宽dout是8bit,两者位宽是不一致的,同样的方法我们也在Vivado下初始化一个读写位宽是32bit、读写深度是64的异步时钟FIFO,因为FIFO读写位宽都是32bit,所以上游模块直接写入FIFO即可,这里和练习1中的方法完全一样,但是在读取FIFO的时候,又因为下游模块的读位宽是8bit,而一次性从FIFO中读出的数据是32bit,我们就需要用一个cnt计数器去计数拆分32bit的数据,dout再依次去输出从32bit数据拆分来的数据,同时也拉高dout_vld指示信号,如图1所示FIFO IP练习1的代码设计,具体细节笔者就不再赘述了。

       对于FIFO IP练习1的Testbench,其实和FIFO读写位宽相同的设计也大同小异,先模拟上游模块向本模块的写入数据,再模拟输入下游模块准备就绪的rdy信号,这里只补充说明一点,因为FIFO写端口的输入时钟是50Mhz,而读端口的输出时钟是100Mhz,其中上游模块的写位宽din是32bit,下游模块的读位宽dout是8bit,所以给出120个时钟的rdy高电平,大家可以简单计算下,写端口属于clk_in时钟域,120个clk_in应该是120*20ns=2400ns。而读端口属于clk_out时钟域,2400ns就是对应写端口的2400ns/10ns=240个时钟周期,因为下游模块的读位宽是8bit,所以说要输出完32bit*60的数据,需要32bit*60/8bit也就是240个时钟周期,如图2是FIFO IP练习1的输入信号激励设计。

       大家打开Vivado环境,添加好功能文件和测试文件后,启动Modelsim进行仿真,如图3是FIFO IP练习1的仿真结果,可以清楚地观察到当fifo_empty为高时,即FIFO当前已经没有数据了,此时恰好dout输出FIFO中的最后一个数据,且dout_vld被拉高,和我们预期的设计效果完全相符。

图1 FIFO IP练习1的代码设计

图2 FIFO IP练习1的输入信号激励设计

图3 FIFO IP练习1的仿真结果

练习2

      设计一个模块包含读写位宽是32bit、读写深度是64的异步时钟FIFO,其中输入数据信号din和输入数据指示信号din_vld是属于clk_in时钟域的,上游模块会负责写数据到本模块的FIFO中,当本模块FIFO写端口已写入了60个数据,也就是FIFO快要写满溢出的时候,这时上游模块仍有数据要写入FIFO则直接丢弃该数据。下游模块负责从本模块的FIFO中读数据,当下游模块输入rdy信号时表示下游模块已准备好可以接收FIFO中的数据了,这时如果FIFO中有数据,那么就把FIFO中的数据赋值给输出数据信号dout送至下游模块并同时拉高dout_vld输出数据指示信号,其中输出数据信号dout和输出数据指示信号dout_vld则是属于clk_out时钟域的,上游模块din信号的写位宽是8bit,下游模块dout信号的读位宽是32bit,表2为练习2的信号列表。

信号列表

信号名

I/O

位宽

clk_in

I

1

rst_n

I

1

rdy

I

1

din

I

8

din_vld

I

1

clk_out

I

1

dout

O

32

dout_vld

O

1

fifo_empty

O

1

表2 FIFO IP练习2设计中的信号列表

        练习2和练习1一样都是在FIFO相同读写位宽的基础上的延伸扩展,当然Vivado环境下完全支持异步时钟FIFO配置成位宽不同的读写端口,实际工作中也有不少FPGA工程师习惯性去把异步时钟FIFO读写端口根据需求人为配置成位宽不同的,但是笔者还是推荐大家把读写位宽都配置成相同的,这样在程序设计上也更简便不需要再去考虑一些其他因素影响,这里练习1和练习2其实把现实工作中上游模块输入信号din和下游模块输出信号dout的两种可能情况都包括在内了,所以大家实践过这两个练习,在实际项目中完全可以灵活应用,就可以达到二次开发的效果,练习2是输入信号din位宽是32bit,输出信号dout位宽是8bit,所以我们需要对FIFO的输出进行拆分,而练习2相反的是输入信号din位宽是8bit,输出信号dout位宽是32bit,所以我们需要对FIFO的输入进行拼接,练习1和练习2中包含了对数据拼接和拆分的一般性方法,有很强的代表性,如图4所示FIFO IP练习2的代码设计。

        对于FIFO IP练习2的Testbench,其实类似练习1,在练习2中因为FIFO写端口的输入时钟是50Mhz,读端口的输出时钟是100Mhz,这里上游模块的写位宽din是8bit,下游模块的读位宽dout是32bit,所以也给出了240个时钟周期的din_vld信号用以模拟上游模块向本模块写入240个8bit的数据,之后再去给出30个clk_in时钟周期的rdy高电平模拟下游模块读数据,这里30个clk_in是30*20ns=600ns,读端口在clk_out时钟域,600ns就对应读端口的600ns/10ns=60个时钟周期,因为下游模块的读位宽是32bit,所以说要输出完32bit*60的数据,需要60个时钟周期,如图5是FIFO IP练习2的输入信号激励设计。如图6 FIFO IP练习2的仿真结果,大家代入Modelsim下可以观察到和预期的设计效果完全一致。

 

图4 FIFO IP练习2的代码设计

图5 FIFO IP练习2的输入信号激励设计

图6 FIFO IP练习2的仿真结果

标签:dout,FPGA,读写,练习,FIFO,32bit,模块,时钟
来源: https://blog.csdn.net/wandou0511/article/details/122850776

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有