一直在做xilinx FPGA,最近学习了fifo的使用,看了一些前辈写的博客,现在总结一下。本文附完整代码,手把手教程,保证看完本文一定能把fifo跑通!
开发软件:ISE14.5
仿真软件:Modelsim SE 10.1a
开发语言:verilog
一.整个工程的结构
一个顶层的.v文件,里面包含一个fifo的ip核,文档结构如下
二.设计流程
1.建立工程,可以取名为fifo,这里选用了xc7k325t-2ffg900的FPGA芯片
2.先生成一个fifo 核,取名为fifo
3.接下来就是最重要的fifo各参数的设置,照着图片设置(很多配置不是必要的,但本文为了详细讲解,就多设置了几项)
注:上图写入位宽为8,写深度为256,读取宽度为4,读深度为512(自动计算出来)
注:上图Full Threshold Assert Value设置为200,是指当写入深度达到200时,prog_full(接下里会遇到)置位;Empty Threshold Assert Value设置为10,是指当读取深度小于10时,prog_full置位。
注:上图中,由于写深度为256,读深度为512,故写计数wr_data_count设置为8位,读计数rd_data_count设置为9位(系统自动设置)
注:上图为最后一步,点generate生成IP核。
4.新建一个.v文档,取名FIFO_top,将以下代码输入。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 10:11:28 09/18/2015
// Design Name:
// Module Name: FIFO_top
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module FIFO_top(
input clk,rst,
output wire[3:0] dout
);
wire clk_50M_wire;
wire [7:0] din_wire;
wire valid,wr_ack;
wire overflow,underflow;
wire almost_empty,almost_full;
wire [8:0] rd_data_count;
wire [7:0] wr_data_count;
wire prog_full,prog_empty;
wire wr_en,rd_en;
wire full,empty;
//二分频电路
//100M为读时钟,50M为写时钟
reg clk_50M;
assign clk_50M_wire = clk_50M;
always @(posedge clk or posedge rst)
begin
if(rst)
clk_50M <= 0;
else
clk_50M <= ~clk_50M;
end
///
///
reg[2:0] cnt;
assign wr_en = (full==0 && rd_en==0 && cnt==5)? 1 : 0;//非满时写,且满后就不再写了,即便之后数据被读取导致非满
assign rd_en = (empty==0 && wr_en==0) ? 1 : 0;//写时不读取,写完再读取
reg [7:0] din;
assign din_wire = din;
always @(posedge clk_50M or posedge rst)
begin
if(rst)
begin
din <= 1;
end
else
begin
if(wr_en)
din <= din + 1;
else
din <= din;
end
end
always @(posedge clk_50M or posedge rst)
if(rst)
cnt <= 0;
else
begin
if(cnt == 3’d5)
cnt <= cnt;
else
cnt <= cnt + 1;
end
fifo FIFO (
.rst(rst), // input rst
.wr_clk(clk_50M_wire), // input wr_clk
.rd_clk(clk), // input rd_clk
.din(din_wire), // input [7 : 0] din
.wr_en(wr_en), // input wr_en
.rd_en(rd_en), // input rd_en
.dout(dout), // output [3 : 0] dout
.full(full), // output full
.almost_full(almost_full), // output almost_full
.wr_ack(wr_ack), // output wr_ack
.overflow(overflow), // output overflow
.empty(empty), // output empty
.almost_empty(almost_empty), // output almost_empty
.valid(valid), // output valid
.underflow(underflow), // output underflow
.rd_data_count(rd_data_count), // output [8 : 0] rd_data_count
.wr_data_count(wr_data_count), // output [7 : 0] wr_data_count
.prog_full(prog_full), // output prog_full
.prog_empty(prog_empty) // output prog_empty
);
endmodule
5.然后再建一个Verilog Test Fixture文档,进行仿真,代码如下
`timescale 1ns / 1ps
// Company:
// Engineer:
//
// Create Date: 11:18:08 09/18/2015
// Design Name: FIFO_top
// Module Name: E:/ise_design/fifo_design/test_fifo.v
// Project Name: fifo_design
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: FIFO_top
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
module test_fifo;
// Inputs
reg clk;
reg rst;
// Outputs
wire [3:0] dout;
// Instantiate the Unit Under Test (UUT)
FIFO_top uut (
.clk(clk),
.rst(rst),
.dout(dout)
);
// parameter PERIOD = 10;
initial begin
// Initialize Inputs
clk = 1’b0;
rst = 1'b0;
//
// // Wait 100 ns for global reset to finish
#100;
rst = 1’b1;
#100;
rst = 1’b0;
// Add stimulus here
end
always
begin
clk = 1'b0;
#5;
clk = 1'b1;
#5;
end
endmodule
6.综合后开始仿真,仿真结果如下图所示
注:上图显示写数据正常,从1开始加,累加到255
注:上图显示读数据正常