最近在学习FIFO,于是将学习成果记录一下。
仿真工具为VCS,并用DVE观测波形。
FIFO 表示先入先出,它是一种存储器结构,被广泛的应用与芯片设计中。FIFO分为同步FIFO和异步FIFO,本次记录同步FIFO的设计和验证。
在同步FIFO中,单一时钟同时用于写入和读取数据操作。FIFO的设计原则:满不能写,空不能读。
以下是FIFO的结构框图:
设计的关键: 如何产生empty和full信号。
方法一:采用一个计数器,当执行一次写操作时,计数器加1,执行一次读操作时,计数器减一。
当计数器为0时,说明FIFO为空,或者计数器为1时,此时正在执行读操作,都说明FIFO为空。此时empty拉高。
当计数器为最大FIFO深度时,说明FIFO为满,或者计数器差一个到最大FIFO深度,而此时正在写操作,都说明FIFO为满,此时full拉高。
在后续会采用另外一种方法来实现FIFO的空满信号的产生。
RTL设计:
1 module sync_fifo #(parameter DATA_WIDTH = 8, 2 DATA_DEPTH = 16, 3 ADDR_WIDTH = 4) 4 ( input wire clk, 5 input wire rst_n, 6 input wire wr_en, 7 input wire[DATA_WIDTH-1:0] wr_data, 8 input wire rd_en, 9 output reg [DATA_WIDTH-1:0] rd_data,10 output reg full,11 output reg empty12 );13 //addr14 reg[ADDR_WIDTH-1:0] wr_addr,rd_addr;15 //memory16 reg[DATA_WIDTH-1:0] mem[DATA_DEPTH-1:0];17 //counter18 reg[ADDR_WIDTH-1:0] count;19 20 wire rd_allow = rd_en && !empty;21 wire wr_allow = wr_en && !full;22 23 24 //empty25 always @(posedge clk or negedge rst_n)26 if (!rst_n)27 empty <= 1'b1;28 else29 empty <= (!wr_en && count[ADDR_WIDTH-1:1]=='b0) && (count[0]==1'b0 || rd_en);30 31 //full32 always @(posedge clk or negedge rst_n)33 if (!rst_n)34 full <= 1'b0;35 else36 full <= (!rd_en && count[ADDR_WIDTH-1:1]=={ADDR_WIDTH-1{1'b1}}) && (count[0]==1'b1 || wr_en);37 38 //rd_addr39 always @(posedge clk or negedge rst_n)40 if (!rst_n)41 rd_addr <= 'd0;42 else if(rd_allow) begin43 rd_data <= mem[rd_addr];44 rd_addr <= rd_addr + 1'b1;45 end46 47 48 //wr_addr49 always @(posedge clk or negedge rst_n)50 if (!rst_n)51 wr_addr <= 'd0;52 else if(wr_allow) begin53 mem[wr_addr] <= wr_data;54 wr_addr <= wr_addr + 1'b1;55 end56 57 always @(posedge clk or negedge rst_n)58 if (!rst_n)59 count <= 'd0;60 else if ( (!rd_allow && wr_allow) || (rd_allow && !wr_allow) ) begin61 if( wr_allow )62 count <= count + 1'b1;63 else 64 count <= count - 1'b1;65 end66 67 endmodule
testbench设计:
1 `timescale 1ns/1ps 2 module sync_fifo_tb; 3 4 parameter DATA_WIDTH = 8, 5 DATA_DEPTH = 16, 6 ADDR_WIDTH = 4, 7 PERIOD = 20; 8 9 10 reg clk,rst_n,wr_en,rd_en;11 reg[DATA_WIDTH-1:0] wr_data;12 wire full,empty;13 wire[DATA_WIDTH-1:0] rd_data;14 15 sync_fifo #(.DATA_WIDTH(DATA_WIDTH),16 .DATA_DEPTH(DATA_DEPTH),17 .ADDR_WIDTH(ADDR_WIDTH)18 )19 sync_fifo_inst( 20 .clk (clk ),21 .rst_n (rst_n ),22 .wr_en (wr_en ),23 .wr_data(wr_data),24 .rd_en (rd_en ),25 .rd_data(rd_data),26 .full (full ),27 .empty (empty )28 );29 30 initial begin31 rst_n = 0;32 clk = 0;33 #534 rst_n = 1;35 end36 37 always #(PERIOD/2) clk=~clk;38 39 initial begin40 wr_en = 0;41 rd_en = 0;42 #543 wr_en = 1;44 #20 wr_data = 8'h0;45 #20 wr_data = 8'h1;46 #20 wr_data = 8'h2;47 #20 wr_data = 8'h3;48 #20 wr_data = 8'h4;49 #20 wr_data = 8'h5;50 #20 wr_data = 8'h6;51 #20 wr_data = 8'h7;52 #20 wr_data = 8'h8;53 #20 wr_data = 8'h9;54 #20 wr_data = 8'hA;55 #20 wr_data = 8'hB;56 #20 wr_data = 8'hC;57 #20 wr_data = 8'hD;58 #20 wr_data = 8'hE;59 #20 wr_data = 8'hF;60 rd_en = 1;61 wr_en = 0;62 #40063 $finish;64 end65 66 endmodule
DVE仿真:
此次记录同步FIFO的设计。