Menu Close

自建同步时钟,数据等宽FIFO IP 方法

在实际的FPGA开发项目中,可能会用到一些常见的IP 核, 例如 PLL,MMCM, 双端口RAM, FIFO等等。一般来说,可以使用Xilinx ISE, Vivado , Altera Quartus 等IDE 集成软件, 通过创建厂家给出的一些IP 核 来完成工作中一些需求。如果Xilinx, Altera 等厂家没有提供需要的IP 核 , 或者是他们提供的IP核 不能满足用户的特定需求,这时工程师就需要自主创建一些IP 核,来满足 客户工程的需要了。

FPGA厂家一般会提供标准的FIFO IP 核的, 无论是Xilinx, Altera 还是其他公司。 但有时编写的Verilog 代码 不知道会在什么样的FPGA使用, 有可能是xilinx, 也有可能是Altera ,或者是其他公司的FPGA。本文介绍一种FIFO IP 核的创建方法,因为 Verilog 语言是通用的, 所以通过Verilog 语言自建的IP 的适用范围会更加宽广,即使是准备生产芯片(ASIC 等,不再使用FPGA芯片),Verilog 也是非常方便被导入到生产环节的(不必一定需要工厂提供相对应的IP了)。

这种自建的FIFO IP 会在很多Verilog 工程中被应用,这样用户发布的代码往往不需要修改, 就可以在不同公司的平台上使用。

本文中自建的IP 是一个同步时钟的FIFO, 并且FIFO写入数据的宽度和数据读出的宽度相等。

 

参考代码:


 

接口介绍:


 

由于使用了参数化设计, 所以这个FIFO IP 存储深度是可以被用户配置的。 同时写入和读出的数据宽度, 用户也是可以配置的。

 

这里的代码讲解都是以 ADDR_WIDTH = 3, DATA_WIDTH = 8 进行讲解的。其他情况,对代码的理解也是相似的。

 

FIFO 数据结构定义


 

FIFO 相关的参数定义


 

FIFO 读写 相关的操作


这里,我们会发现,在计算FIFO counter 时 ,不论写地址 是否 小于 读地址 ,只要 写地址 – 读 地址 , prt_diff 的结果都是正确的(1 – 7 ) , 只有 0 ,8 这两个值需要看当前FIFO是空 还是满 才能判断。

写地址计数器


当wr_en 写FIFO信号有效, FIFO 又不是为满时, wr_vld 有效; 这时 写地址 + 1

 

写数据到存储空间


当wr_en 写FIFO信号有效, FIFO又不是为满时, wr_vld 有效; 这时 写数据到相应的地址空间中。

 

读地址计数器


当rd_en 写FIFO 信号有效, FIFO又不是为空时, rd_vld 有效; 这时 读地址 + 1

 

满足读写不同时发生的最后一次操作


从FIFO 读出的数据有效标志


当rd_en 有效, 同时 FIFO不为 空, 这时输出的数据是有效的。

 

仿真代码:


 

仿真波形

reset 过后,FIFO counter 为0;fifo_rd 可以连续读, 只要是valid, 输出的fifo_dout 都是有效的。empty 时, valid 为 0, 输出的 fifo_dout 无效。

 

 

FIFO full 时, io_count = 8; 当 full = 0 时, 又可以继续写FIFO 了。

 

当k = 256 时, 表示 valid 出现过256 次, 这和FIFO写入的 数值个数 一直, 到此, FIFO写 256 个数据, FIFO读 256 个数据 完毕。

 

总结

到此, 同步FIFO设计完成了。

自建的FIFO的优点是不需要 Xilinx , Altera 或者其他公司的IP, Verilog 代码可以快速移植, 甚至生产。甚至可以根据自己的要求,设计FIFO输入,输出格式。

目前这个FIFO的缺点是 只能使用同步时钟(写时钟和读时钟是一致的),写数据宽度 和 读数据的宽度必须一致的。 当然,用户掌握了自建IP 的方法, 也可以解决这些问题的。

 

Posted in FPGA, FPGA 教材教案, IP开发, RISC-V IPcore设计, RISC-V架构, Verilog, 教材与教案, 文章, 编程语言