赞
踩
FIFO(First In First Out,即先入先出),是一种数据缓冲器,用来实现数据先入先出的读写方式。与 ROM 或 RAM 的按地址读写方式不同,FIFO 的读写遵循“先进先出”的原则,即数据按顺序写入 FIFO,先被写入的数据同样在读取的时候先被读出,所以FIFO存储器没有地址线。FIFO 有一个写端口和一个读端口外部无需使用者控制地址,使用方便。
FIFO存储器主要是作为缓存,应用在同步时钟系统和异步时钟系统中,在很多的设计中都会使用,后面实例中如:多比特数据做跨时钟域的转换、前后带宽不同步等都用到了FIFO。FIFO 根据读写时钟是否相同,分为SCFIFO(同步FIFO)和 DCFIFO(异步FIFO),SCFIFO 的读写为同一时钟,应用在同步时钟系统中; DCFIFO 的读写时钟不同,应用在异步时钟系统中。
下面来看一下同步fifo的配置:
① 框中我们输入IP核的命名, 后面实例化IP 的时候都是使用的该名字,这里所取的名字最好是和该 IP 核相关,因为本节我们主要讲解同步 fifo,给该 IP 核取名为scfifo_256x8,让人一看名字就知道我们调用的 scfifo 是 256 个深度 8 位宽的。
② 框是选中 FIFO 的接口类型, 这里我们按默认选择“Native” 即可。
③ 框是选中 FIFO 的类型, 以及使用什么资源来实现。 这里我们选择“Common Clock Block RAM”使用块 RAM 来实现同步 FIFO;其中 Common Clock 表示是同步 FIFO,Block RAM 表示的是块 RAM 资源。
①框中是对模式的选择,这里我们选择标准 FIFO(Standard FIF0) 即可。
② 框中可设置存储数据的位宽和深度, 其中“Write Width”是设置写数据位宽,这里我们设置为 8 位; “Write Depth” 是设置数据深度,这里我们设置为 256; “Read Width”是设置读数据位宽,这里我们设置为 8 位;“Read Depth”为读数据深度,该选项会根据我们设置的读写位宽及写数据深度自动设置。
③ 框是对复位信号创建的设置, 大家可根据自己的设计需求进行选择是否创建, 这里我们按默认勾选, 进行创建。设置完之后切换到“Status Flags”页面。
①框中可勾选生成 FIFO 几乎满(Almost Full Flag) ,几乎空(Almost Empty Flag) 输
出信号;也就是说若勾选了这两个信号,当 FIFO 存储数据快满或者快空的时候,该信号就有效。这里大家可根据自己的实际需求进行勾选,这里我们选择都不勾选。
② 左框中可勾选生成写确认标志信号,用于报告写操作成功。 若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
② 右框中可勾选生成溢出标志信号; 该标志信号可以指示 FIFO 内存储数据是否溢出,可以指示上一次写操作何时失败。若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
③左 框中可勾选生成指示输出总线上数据何时有效的有效标志信号。 若勾选后可以配置
为高电平有效或低电平有,这里我们选择不勾选。
③右框中可勾选生成下溢标志信号;该标志信号可以指示 FIFO 内存储数据空了,可以指示上一次的读请求何时失败。 若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
这些选项可以根据自己的设计需求进行勾选,这里我们按默认都不勾选,直接切换到“Data Counts”页面。
可勾选“Data Count”生成 FIFO 内剩余个数输出信号, 该输出信号可根据自己设计是否需要进行生成,默认是不生成,这里我们勾选进行生成该信号。设置完之后切换到“summary”页面。
然后点击OK。
生成IP之后就可以将我们的同步fifo IP例化到我们的新建的同步fifo工程进行一个tb文件的编写。
- module scfifo(
- input sys_clk , //
- input sys_rst_n , //
- input [7:0] din , //写数据
- input wr_en , //写使能
- input rd_en , //读使能
- output [7:0] dout , //读数据
- output full , //fifo满标志信号,高有效
- output empty , //fifo空标志信号,高有效
- output [7:0] data_count //fifo存在的数据个数
- );
-
-
- scfifo_256x8 scfifo_256x8_inst (
- .clk(sys_clk), // input wire clk
- .srst(~sys_rst_n), // input wire srst
- .din(din), // input wire [7 : 0] din
- .wr_en(wr_en), // input wire wr_en
- .rd_en(rd_en), // input wire rd_en
- .dout(dout), // output wire [7 : 0] dout
- .full(full), // output wire full
- .empty(empty), // output wire empty
- .data_count(data_count) // output wire [7 : 0] data_count
- );
-
- endmodule
下面是 Testbench 仿真测试文件,和 SCFIFO 的仿真一样,我们也需要给输入信号测试激励, pi_flag 每 4 个时钟周期且没有读请求时产生一个数据有效标志信号也作为 FIFO 的写请求信号,因为需要 pi_data 伴随着 pi_flag 一起产生,所以每当 pi_data 检测到 pi_flag 标志信号有效时就自加 1,其值从 0~255 循环变化,这样我们就可以在 pi_flag 标志信号有效时将 pi_data 写入到 FIFO 中。而 FIFO 的读请求信号 rd_en 当 FIFO 的满标志信号 full 有效时拉高,当 FIFO 的空标志信号 empty 有效时拉低。
SCFIFO 可以同时进行读写操作,但本例我们没有让 SCFIFO 同时进行读写,当我们真正使用 SCFIFO IP 核时一定要保证 FIFO 不被写满也不被读空。
- `timescale 1ns / 1ns
- module tb_scfifo();
-
- //reg define
- reg sys_clk ; //系统时钟
- reg [7:0] pi_data ; //写数据
- reg wr_en ; //写使能
- reg rd_en ; //读使能
- reg sys_rst_n ; //系统复位
- reg [1:0] cnt_baud ; //计数器
-
- //wire define
- wire [7:0] po_data ; //读数据
- wire empty ; //读空标志信号
- wire full ; //写满标志信号
- wire [7:0] data_count ; //数据计数器
-
-
- initial begin
- sys_clk = 1'b1;
- sys_rst_n <= 1'b0;
- #201
- sys_rst_n <= 1'b1;
- end
-
- always #10 sys_clk <= ~sys_clk;
-
- //数据读写之间产生一个间隔
- always@(posedge sys_clk or negedge sys_rst_n) begin
- if(!sys_rst_n)
- cnt_baud <= 2'd0;
- else if(&cnt_baud == 2'd1) //累计满清零
- cnt_baud <= 2'd0;
- else
- cnt_baud <= cnt_baud + 2'd1;
- end
-
- //写使能信号,也是fifo的写请求信号
- always@(posedge sys_clk or negedge sys_rst_n) begin
- if(!sys_rst_n)
- wr_en <= 1'b0;
- //每四个周期且没有读使能没有产生一个读使能信号
- else if(cnt_baud == 2'd0 && rd_en == 1'b0)
- wr_en <= 1'b1;
- else
- wr_en <= 1'b0;
- end
-
- //写数据模块,向fifo写入256个数据
- always@(posedge sys_clk or negedge sys_rst_n) begin
- if(!sys_rst_n)
- pi_data <= 8'd0;
- else if(pi_data == 8'd255 && wr_en == 1'd1)
- pi_data <= 8'd0;
- else if(wr_en == 1'b1)
- pi_data <= pi_data + 1'b1;
- end
-
- //fifo读请求信号
- always@(posedge sys_clk or negedge sys_rst_n) begin
- if(!sys_rst_n)
- rd_en <= 1'b0;
- //当fifo中的数据被读空时,停止读取fifo中的数据
- else if(empty == 1'b1)
- rd_en <= 1'b0;
- //当fifo中的数据被写满时,停止往fifo中写入数据
- else if(full == 1'b1)
- rd_en <= 1'b1;
- end
- scfifo scfifo_inst(
- .sys_clk (sys_clk),
- .sys_rst_n (sys_rst_n),
-
- .din (pi_data) , //写数据
- .wr_en (wr_en), //写使能
- .rd_en (rd_en), //读使能
-
- .dout (po_data), //读数据
- .full (full), //fifo满标志信号,高有效
- .empty (empty), //fifo空标志信号,高有效
- .data_count (data_count) //fifo存在的数据个数
- );
-
- endmodule
仿真结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。