赞
踩
FIFO的英文全称为First In First Out,即先进先出。FPGA使用的FIFO一般指的是对数据的存储具有先进先出的特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即所谓的跨时钟域信号传递(发送和接收不是同一个时钟)。
它与FPGA内部的RAM和ROM的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像RAM和ROM那样可以由地址线决定读取或写入某个指定的地址
先做同步时钟(单时钟FIFO)情况下
设置FIFO的位宽,即传输数据的位宽,深度为传输128字节的数据,选择单时钟FIFO
设置引脚
full为数据满时的标志信号,empty为空数据标志信号,usedw[]为剩余的可用数据量;
almost empty/almost full 将满/将空 标志信号,当剩余数据量将满/将空时,对应信号拉高;
Asynchronous clear 异步清零;
Synchronous clear同步清零;
一般使用异步清零。
选择读请求信号的类型,此处选择正常模式的FIFO,即数据在读请求发出后有效;
选择存储的数据类型,此处以自动Auto为例。
不需要用更多空间换取最大的性能,但需要电能保护。
仍然生成.v文件
再创建一个前写模式s_fifo_ah.v,存储数据256字节,选择另一种模式,在读请求之前数据有效,生成.v文件。
打开生成的inst文件
将其复制到test_ip文件里,并修改端口连接信息
- module test_ip (
- input rst_n,
- input clk,
- input [7:0] no_data ,
- input no_rdreq ,
- input no_wrreq ,
- output [7:0] no_q ,
- input [7:0] ah_data ,
- input ah_rdreq ,
- input ah_wrreq ,
- output [7:0] ah_q
- );
-
- wire no_empty ;
- wire no_full ;
- wire [6:0] no_usedw ;
-
- wire ah_empty ;
- wire ah_full ;
- wire [7:0] ah_usedw ;
-
-
- s_fifo s_fifo_inst (
- .aclr ( ~rst_n ),
- .clock ( clk ),
- .data ( no_data ),
- .rdreq ( no_rdreq ),
- .wrreq ( no_wrreq ),
- .empty ( no_empty ),
- .full ( no_full ),
- .q ( no_q ),
- .usedw ( no_usedw )
- );
-
- s_fifo_ah s_fifo_ah_inst (
- .aclr ( ~rst_n ),
- .clock ( clk ),
- .data ( ah_data ),
- .rdreq ( ah_rdreq ),
- .wrreq ( ah_wrreq ),
- .empty ( ah_empty ),
- .full ( ah_full ),
- .q ( ah_q ),
- .usedw ( ah_usedw )
- );
-
- endmodule

- `timescale 1ns/1ps
- module test_tb();
- reg rst_n ;
- reg clk ;
-
- reg [7:0] no_data ;
- reg no_rdreq ;
- reg no_wrreq ;
- wire [7:0] no_q ;
-
- reg [7:0] ah_data ;
- reg ah_rdreq ;
- reg ah_wrreq ;
- wire [7:0] ah_q ;
-
-
- parameter CYCLE = 20;
-
- test_ip u_test_ip (
- .rst_n ( rst_n ),
- .clk ( clk ),
- .no_data (no_data ),
- .no_rdreq (no_rdreq ),
- .no_wrreq (no_wrreq ),
- .no_q (no_q ),
- .ah_data (ah_data ),
- .ah_rdreq (ah_rdreq ),
- .ah_wrreq (ah_wrreq ),
- .ah_q (ah_q )
- );
-
- integer i ;
-
- initial begin
- clk = 1'b1;
- rst_n = 1'b1;
- #(2*CYCLE);
- #5;
-
- rst_n = 1'b0;
- no_data = 0 ;//复位给定信号初值
- no_rdreq = 0 ;
- no_wrreq = 0 ;
-
- ah_data = 0 ;
- ah_rdreq = 0 ;
- ah_wrreq = 0 ;
-
-
- #(5*CYCLE);
- rst_n = 1'b1;//复位释放
- #(CYCLE*10);//延迟10个时钟是为了打开时钟锁得到稳定的时钟信号
-
- //写数据
- for(i=0;i<32;i=i+1) begin
- no_wrreq = 1'b1 ;
- no_data = i + 1 ;//data给1到64
-
- ah_wrreq = 1'b1 ;
- ah_data = i + 1 ;
- #(CYCLE) ;//保证一个时钟周期写写完一个数据
- end
- no_wrreq = 1'b0 ;//写完数据拉低
- ah_wrreq = 1'b0 ;
- #(5*CYCLE) ;
-
- //读数据
- for (i=0;i<16;i=i+1) begin
- no_rdreq = 1'b1 ;
- ah_rdreq = 1'b1 ;//写数据读地址
- #(CYCLE*2) ;//保证一个是时钟周期读完一个数据
- end //这个for循环,内部三行代码,在时钟上升沿到来时且读请求拉高时读一个数据,持续两个时钟周期读2个数据,相当于执行依次循环读2个数据,for循环要经历16次,所以循环内读了32个数据
- no_rdreq = 1'b0 ;
- ah_rdreq = 1'b0 ; //读完数据拉低
- #(20*CYCLE) ;
-
- $stop;
- end
-
- always #(CYCLE/2) clk = ~clk ;//50M
- endmodule

test.do文件(修改自己的对应文件路径)
- vlib work
- vmap work work
-
- #编译testbench文件
- vlog test_tb.v
- #编译 设计文件
- vlog ../ip/s_fifo.v
- vlog ../ip/s_fifo_ah.v
- vlog ../rtl/test_ip.v
-
- vlog altera_mf.v
-
-
- #指定仿真顶层
- vsim -novopt work.test_tb
- #添加信号到波形窗
- add wave -position insertpoint sim:/test_tb//*
-
- run -all

另外,由于正常模式和前写模式fifo生成的ip文件里没有用到eccstatus端口,需要注释掉
全局:
先分析正常模式下,
上图定位出可以看出,写写请求拉高时有了第一个数据,而当在下一个始终上升沿时,此时已经有了数据,空数据标志拉低(它是在数据写入的同时拉低,表明可能是组合逻辑),可用数据量为1,q端无变化。
然后观察读数据波形:
当读请求拉高时,在下一个时钟上升沿读出数据1,之前写入了32个数据,读出1个数后,剩余可用数据量为31个
到最后读完时,输出32个数据,剩余可用数据为0,与此同时空信号标志拉高,数据读完后读请求拉低。
然后分析前写模式:
对比两种模式下,正常模式是在读请求拉高后才有数据,而前写模式fifo在读请求拉高之前就已经输出了一个数据,并知道拉高之后再输出第二个数据。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。