vivado 仿真ram,rom和fifo

本文详细介绍了在 Vivado 中进行 FIFO、RAM 和 ROM 的仿真的关键概念和注意事项,包括 FIFO 的读延迟、空满标志、数据计数、写入确认信号等,以及 RAM 的双口和单口操作,ROM 的延迟输出特性,并提到了在仿真过程中可能遇到的问题及解决策略。

FIFO、RAM、ROM学习文档

一、FIFO

  1. read latency问题

FIFO有两种读模式,第一种是标准fifo,这种模式下读使能为1之后,要延迟一个时钟周期之后fifo输出的第一个数据才是第一个写入fifo的数据。如下图所示:

蓝色信号为读使能,18为fifo第一个写入的数据。

第二种是first-word fall through, 这种模式下读使能为1之后,不延迟时钟周期。

2.仿真时一直出现问题,full和empty信号一直飘红,后来发现是初始信号full设置的初值问题。

 

图中的full flags reset value开始为1,需要设置为0。

3.data count信号

Data count信号是在写入数据是开始从0开始加1,一直加到写满,加到1023(即写满)后为0,此时开始读的话,从0开始减1,减到1为止。(即读空)后为0。

4.wr_ack信号时wr_en的写入数据状态,成功写入一个数据后为1。即相当于wr_en的一个延时信号

5.valid信号,在standard fifo中,rd_en信号为1的下一个时钟valid为1,在first模式中,rd_en为1,valid为1。即此信号为1时,读出的信号为有效信号。

6.empty和full信号,standard模式写入一个数据后empty由1变为0,或者读完全部数据后由0变为1。almost_empty与almost_full相当于full和empty的展宽信号,在full与empty为1的前一个时钟周期它为1.在full与empty为0的后一个时钟周期它为0。如果是first模式,要写入三个数据后empty才由1变为0,同样的,full信号在standard模式时,数据写到1023后面的0时才变为1,而first模式,在数据写到1022时full就变为1。

7.underflow与overflow信号有图可以看出,当信号写满fifo时,wr_en还为1时,此时overflow为1,同样的,若读空时,rd_en还为1,underflow为1。

这里要注意读写使能的信号给定,不然只给定一个信号的时候,很容易出现full,empty信号出现X的情况。

always @(posedge clk or posedge rst)begin

  if(rst)begin

      wr_en <= 1'b0;

      rd_en <= 1'b0;

  end

  else begin

       if((!full)&(!rd_en))

       begin

           wr_en <= 1'b1;

            rd_en <= 1'b0;

         end

         else if(!empty)begin

          wr_en <= 1'b0;

          rd_en <= 1'b1;

      end

      else begin

         rd_en <= 1'b0;

         end

end 

例如这里初始化和if条件中,wr_en和rd_en都需要给定值。

8.当读写时钟不一样时,即异步fifo时,开始写入数据时,这里设定wr_clk为50MHZ,数据位为10位,rd_clk为100MHZ,数据位为5位,开始写数据时,wr_data_count开始从0累加到1023,同时rd_data_count从0累加到2042(跟着wr_clk,每次累加2)。读信号为1的下一个周期一直到full为0期间,wr_data_count保持1023不变,但在rd为1的下一个周期开始时,rd_data_count已经开始随着rd_clk变化了,每读一个数据,rd_data_count减1。开始读数据后,full信号为0后,wr_data_count开始随着wr_clk自减1。(我也不知道为啥full信号持续时间这么长)

9.prog_full与prog_empty与wr_data_count,rd_data_count有关,当rd_data_count为2(与empty threshold assert value设定的值有关-2)时,prog_empty为1。wr_data_count为1019(与full threshold assert value设定的值有关-2)时,prog_full为1。

二、RAM

  这里实验是使用RAM的真双口ram做的,这里的输入信号和输出信号相差一个时钟,即当din信号给定,地址开始加时,douta或doutb延迟2个时钟周期得到din的值,这里需要注意的问题是A口和B口是共享同一个内存地址的,即addra[0]写入的值,用addrb[0]也可读取出来。

 

第二个实验是用single RAM做的,开始为了验证wea和ena各自的作用,将ena当作读使能的时候有以下结果:

此时dout一直为0,说明写使能无效。

  之后将ena置1,其它不变,可以得到以下结果:

说明ena不是读使能,是整个ram的使能信号,局部放大看:

  可以看出,douta比dina延迟两个时钟,即输出信号有两个时钟的延迟,另外,从图中可以看出wea为0时,只要地址在加,douta就有数据。说明ram读数据是通过地址来读的,只要使能信号为1,地址在加,内存有数据,读数据就有效。

三、ROM

  可以看出,使能信号给出之后,douta数据延迟输出2个时钟,和ram类似。

在实验过程中,coe文件加载不了,原因之一是有中文路径,另外一个原因是深度给的不够,改了路径后成功加载,改了深度后validate通过。

在 FPGA 设计中,RAMROM FIFO IP 核的资源占用情况与多个因素密切相关,包括存储容量、数据位宽、访问模式(单端口/双端口)、是否启用寄存器级控制信号等。以下是对这三种存储结构在 FPGA 中典型资源消耗的概述。 ### RAM 的资源使用 FPGA 中的 RAM 通常分为单端口 RAM 双端口 RAM(DPRAM)。Xilinx Intel(原 Altera)等主流厂商的 FPGA 提供了 Block RAM(BRAM)作为专用硬件资源用于实现较大容量的 RAM 结构。例如: - **Xilinx Spartan-6** 系列中,每个 BRAM 模块可提供 18 Kb 的存储容量,支持单端口或简单双端口模式。 - 若设计需要更大的 DPRAM 容量,则可能需要多个 BRAM 模块进行拼接[^1]。 此外,若设计对速度要求不高且容量较小,也可以使用分布式 RAM(LUT RAM),但其资源消耗较高,因为会占用逻辑单元中的 LUT 资源。 ### ROM 的资源使用 ROM 可以通过 Block RAM 实现,特别是在需要大容量常量表时。例如: - 在 Xilinx FPGA 中,当 ROM 表达式被综合时,工具会自动将其映射到 Block RAM 或 LUT 中。 - 小型 ROM 表格可以使用查找表(LUT)实现,而较大的表格则更适合使用 Block RAM 资源,从而节省逻辑资源[^2]。 ### FIFO 的资源使用 FIFO 是一种特殊的缓冲结构,常用于跨时钟域传输或数据流控制。FIFO IP 核通常基于 Block RAM 或分布式 RAM 实现,并附加读写指针管理逻辑: - 对于同步 FIFO,通常只需一个时钟域下的 RAM 控制逻辑,资源消耗相对较低。 - 异步 FIFO 则需处理跨时钟域的读写操作,因此需要额外的同步电路空满标志生成逻辑,导致资源消耗增加约 20%~30%。 - 在 Xilinx Vivado 中,使用 FIFO Generator IP 可以根据需求选择是否使用 Block RAM、分布式 RAM 或 UltraRAM(在 UltraScale+ 器件中)实现 FIFO,资源使用情况因配置不同而异。 ### 示例代码:使用 Verilog 实现一个简单的同步 FIFO(基于 RAM) ```verilog module sync_fifo #( parameter DATA_WIDTH = 8, parameter ADDR_WIDTH = 4 )( input clk, input rst_n, input wr_en, input rd_en, input [DATA_WIDTH-1:0] din, output reg [DATA_WIDTH-1:0] dout, output full, output empty ); localparam DEPTH = 1 << ADDR_WIDTH; reg [ADDR_WIDTH-1:0] wr_ptr, rd_ptr; reg [DATA_WIDTH-1:0] mem [0:DEPTH-1]; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin wr_ptr <= 0; rd_ptr <= 0; end else begin if (wr_en && !full) mem[wr_ptr] <= din; if (wr_en && !full) wr_ptr <= wr_ptr + 1; if (rd_en && !empty) rd_ptr <= rd_ptr + 1; end end assign full = (wr_ptr == rd_ptr - 1); assign empty = (wr_ptr == rd_ptr); always @(posedge clk or negedge rst_n) begin if (!rst_n) dout <= 0; else if (rd_en && !empty) dout <= mem[rd_ptr]; end endmodule ``` ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值