首页 > 技术文章 > Verilog笔记.6.FIFO

protogenoi 2018-05-03 10:29 原文

FIFO,First In First Out ,是一种先进先出的数据缓存器。

没有外部读写地址线,只能顺序写入数据,顺序的读出数据, 其数据地址由内部读写指针自动加1完成。

不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

 FIFO一般用于不同时钟域之间的数据传输,根据工作的时钟域,分为同步FIFO和异步FIFO。

同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。

异步FIFO是指读写时钟不一致,读写时钟是互相独立的。

同步FIFO

 

 1 `timescale 1ns / 1ps
 2 //////////////////////////////////////////////////////////////////////////////////
 3 // Company: 
 4 // Engineer: 
 5 // 
 6 // Create Date: 2018/05/02 21:34:02
 7 // Design Name: 
 8 // Module Name: FIFO_16bits_16
 9 // Project Name: 
10 // Target Devices: 
11 // Tool Versions: 
12 // Description: synchronous fifo 16bits * 16
13 // 
14 // Dependencies: 
15 // 
16 // Revision:
17 // Revision 0.01 - File Created
18 // Additional Comments:
19 // 
20 //////////////////////////////////////////////////////////////////////////////////
21 `define ADDR_WIDTH   4       //ADDR WIDTH = 4,  
22 `define FIFO_DEPTH   16      //FIFO DEPTH
23 `define FIFO_WIDTH   16      //FIFO WIDTH 16 BITS
24 
25 module myFIFO(
26             input  wire clk,
27             input  wire rst_n,
28             input  wire wr_en,
29             input  wire rd_en,                      //wire write/read enable
30             input  wire [`FIFO_WIDTH:0] buf_in,     // data input to be pushed to buffer 
31             output reg  [`FIFO_WIDTH:0] buf_out,    // port to output the data using pop.
32             output wire buf_empty,
33             output wire buf_full,                   // fifo buffer empty/full indication 
34             output reg  [`ADDR_WIDTH:0] fifo_cnt    // number of data pushed in to buffer,16-> FULL;0-> EMPTY
35             );
36 
37     reg [`ADDR_WIDTH-1:0] rd_ptr,wr_ptr;      //ADDR PTR .INDEX ,CYCLE 0->15->0->15  
38     reg [`FIFO_WIDTH:0] buf_mem[0:`FIFO_DEPTH-1];  
39     reg rst_nr; 
40     //juge full/empty
41     assign buf_empty = (fifo_cnt == 0)?1:0;   
42     assign buf_full  = (fifo_cnt == `FIFO_DEPTH)?1:0;  
43     //Asynchronous reset,synch release
44 //    always @(posedge clk)begin
45 //        rst_nr <= rst_n;
46 //    end
47     //FIFO_CNT  
48     always @(posedge clk or negedge rst_n)begin  
49        if(!rst_n)  
50            fifo_cnt <= 0;  
51        else if((!buf_full&&wr_en)&&(!buf_empty&&rd_en)) //WRTITE & READ ,HOLD  
52            fifo_cnt <= fifo_cnt;  
53        else if(!buf_full && wr_en)          //WRITE-> +1
54            fifo_cnt <= fifo_cnt + 1;  
55        else if(!buf_empty && rd_en)         //READ -> -1
56            fifo_cnt <= fifo_cnt-1;  
57        else   
58            fifo_cnt <= fifo_cnt;  
59     end  
60     //READ
61     always @(posedge clk or negedge rst_n) begin   
62        if(!rst_n)  
63            buf_out <= 0;  
64        if(rd_en && !buf_empty)  
65            buf_out <= buf_mem[rd_ptr];  
66     end  
67     //WRITE 
68     always @(posedge clk) begin  
69        if(wr_en && !buf_full)  
70            buf_mem[wr_ptr] <= buf_in;  
71     end  
72    //wr_ptr & rd_ptr  ,ADDR PTR
73     always @(posedge clk or negedge rst_n) begin  
74        if(!rst_n) begin  
75            wr_ptr <= 0;  
76            rd_ptr <= 0;  
77        end  
78        else begin  
79            if(!buf_full && wr_en)  
80                wr_ptr <= wr_ptr + 1;  
81            if(!buf_empty && rd_en)  
82                rd_ptr <= rd_ptr + 1;  
83        end  
84     end  
85          
86 endmodule

 

testbench

  1 `timescale 1ns / 1ps
  2 //////////////////////////////////////////////////////////////////////////////////
  3 // Company: 
  4 // Engineer: 
  5 // 
  6 // Create Date: 2018/05/02 21:42:06
  7 // Design Name: 
  8 // Module Name: tb
  9 // Project Name: 
 10 // Target Devices: 
 11 // Tool Versions: 
 12 // Description: 
 13 // 
 14 // Dependencies: 
 15 // 
 16 // Revision:
 17 // Revision 0.01 - File Created
 18 // Additional Comments:
 19 // 
 20 //////////////////////////////////////////////////////////////////////////////////
 21 `define ADDR_WIDTH   4      //ADDR WIDTH = 4,  
 22 `define BUF_DEPTH    16     //FIFO DEPTH
 23 `define FIFO_WIDTH   16     //FIFO WIDTH 16 BITS
 24 
 25 module tb;
 26     reg clk,rst_n;  
 27     reg wr_en,rd_en;  
 28     reg [15:0] buf_in;             // data input to be pushed to buffer  
 29     wire [15:0] buf_out;       // port to output the data using pop.  
 30     wire buf_empty,buf_full;  // buffer empty and full indication   
 31     wire [`ADDR_WIDTH-1:0] fifo_cnt;  // number of data pushed in to buffer   
 32       
 33     myFIFO dut(
 34         .clk(clk),
 35         .rst_n(rst_n),
 36         .buf_in(buf_in),
 37         .buf_out(buf_out),
 38         .wr_en(wr_en),
 39         .rd_en(rd_en),
 40         .buf_empty(buf_empty),
 41         .buf_full(buf_full),
 42         .fifo_cnt(fifo_cnt)
 43         );  
 44       
 45     always #10 clk = ~clk;  
 46       
 47     reg [15:0] tempdata = 0;  
 48     initial begin  
 49         clk = 0;  
 50         rst_n = 0;  
 51         wr_en = 0;  
 52         rd_en = 0;  
 53         buf_in = 0;  
 54         #15;  
 55         rst_n = 1;  
 56           
 57         push(1);  
 58         fork  
 59            push(2);  
 60            pop(tempdata);  
 61         join              //push and pop together     
 62         push(10);  
 63         push(20);  
 64         push(30);  
 65         push(40);  
 66         push(50);  
 67         push(60);  
 68         push(70);  
 69         push(80);  
 70         push(90);  
 71         push(100);  
 72         push(110);  
 73         push(120);  
 74         push(130);  
 75         push(140);  
 76         push(150);  
 77         push(160);  
 78         push(170);  
 79         push(180);  
 80         push(190);  
 81   
 82         pop(tempdata);  
 83         push(tempdata);  
 84         
 85         pop(tempdata);  
 86         pop(tempdata);  
 87         pop(tempdata);  
 88         pop(tempdata);  
 89         push(200);  
 90         pop(tempdata);  
 91         push(tempdata); 
 92         pop(tempdata);  
 93         pop(tempdata);  
 94         pop(tempdata);  
 95         pop(tempdata);  
 96         pop(tempdata);  
 97         pop(tempdata);  
 98         pop(tempdata);  
 99         pop(tempdata);  
100         pop(tempdata);  
101         pop(tempdata);  
102         pop(tempdata);  
103         push(5);  
104         pop(tempdata);  
105         pop(tempdata);  
106         pop(tempdata);  
107         pop(tempdata);  
108         pop(tempdata);  
109         pop(tempdata);  
110         pop(tempdata);  
111         pop(tempdata);  
112         pop(tempdata);  
113         pop(tempdata);  
114         pop(tempdata);  
115         pop(tempdata);  
116         pop(tempdata);  
117         pop(tempdata);  
118         pop(tempdata);  
119         
120         #3;
121         rst_n = 0;  
122         #3;  
123         rst_n = 1;  
124         push(1);  
125         fork  
126            push(2);  
127            pop(tempdata);  
128         join              //push and pop together     
129         push(10);  
130         push(20);  
131         push(30); 
132         pop(tempdata);  
133         pop(tempdata);  
134         pop(tempdata); 
135     end  
136       
137     task push (input [7:0] data);  
138         if(buf_full)  
139             $display("---Cannot push %d: Buffer Full---",data);  
140         else begin  
141             $display("Push:%d",data);  
142             buf_in = data;  
143             wr_en = 1;  
144             @(posedge clk);  
145             #5 wr_en = 0;  
146         end  
147     endtask  
148       
149     task pop(output[7:0] data);  
150         if(buf_empty)  
151             $display("---Cannot Pop: Buffer Empty---");  
152         else begin  
153             rd_en = 1;  
154             @(posedge clk);  
155             #3 rd_en = 0;  
156             data = buf_out;  
157             $display("------Poped:%d",data);  
158         end       
159     endtask  
160   
161 endmodule
View Code

在综合是出现错误

 [Synth 8-91] ambiguous clock in event control [:61]

是因为该段没有else语句,于是将该段改为

1 //READ
2     always @(posedge clk or negedge rst_n) begin   
3         if(!rst_n)  
4             buf_out <= 0;
5         else begin  
6         if(rd_en && !buf_empty)  
7             buf_out <= buf_mem[rd_ptr];
8         end  
9     end  

通过。

//********************************************************************************

异步FIFO

参考了很多文章。

直接上代码

 

  1 `timescale 1ns / 1ps
  2 //////////////////////////////////////////////////////////////////////////////////
  3 // Company: 
  4 // Engineer: 
  5 // 
  6 // Create Date: 2018/05/03 13:56:26
  7 // Design Name: 
  8 // Module Name: AsyncFIFO
  9 // Project Name: 
 10 // Target Devices: 
 11 // Tool Versions: 
 12 // Description: asynchronous fifo
 13 // 
 14 // Dependencies: 
 15 // 
 16 // Revision:
 17 // Revision 0.01 - File Created
 18 // Additional Comments:
 19 // 
 20 //////////////////////////////////////////////////////////////////////////////////
 21 
 22 
 23 module AsyncFIFO
 24     #(
 25     parameter fifo_width = 16,
 26     parameter fifo_depth = 16,  // = ((1<<addr_width) -1)
 27     parameter addr_width = 4    
 28     )
 29     (
 30     input  wire wclk,
 31     input  wire rclk,
 32     input  wire wrst_n,
 33     input  wire rrst_n,
 34     input  wire winc,
 35     input  wire rinc,
 36     input  wire [fifo_width-1:0] wdata,
 37     output wire [fifo_width-1:0] rdata,
 38     output reg  wfull,
 39     output reg  rempty
 40     //output reg  [addr_width:0] fifo_cnt 
 41     );
 42     
 43     reg  [addr_width:0] wptr,rptr;
 44     reg  [addr_width:0] rbin,wbin;
 45     reg  [addr_width:0] wq1_rptr,rq1_wptr,wq2_rptr,rq2_wptr; 
 46     reg  [fifo_width-1:0] fifo_mem [0:fifo_depth-1];
 47     wire [addr_width-1:0] waddr,raddr;
 48     wire [addr_width:0]  rgraynext,rbinnext,wgraynext,wbinnext;
 49     wire rempty_val,wfull_val;
 50 //snyc wptr
 51     always @(posedge wclk or negedge wrst_n)  
 52     if(!wrst_n) begin  
 53       {wq2_rptr,wq1_rptr} <= 0;  
 54     end  
 55     else begin  
 56       {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};  
 57     end 
 58 //snyc rptr
 59     always @(posedge wclk or negedge wrst_n)
 60         if (!wrst_n) begin
 61             {rq2_wptr,rq1_wptr} <= 0;
 62         end
 63         else begin
 64             {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
 65         end
 66 //dualRAM
 67     assign rdata = fifo_mem[raddr];
 68     always@(posedge wclk)
 69         if (winc && !wfull) fifo_mem[waddr] <= wdata;
 70 //------------------------rempty & raddr----------------------------
 71     always @(posedge rclk or negedge rrst_n) // GRAYSTYLE-2 pointer
 72         if (!rrst_n) {rbin, rptr} <= 0;
 73         else {rbin, rptr} <= {rbinnext, rgraynext};
 74 // Memory read-address pointer (okay to use binary to address memory)
 75     assign raddr = rbin[addr_width-1:0];
 76     assign rbinnext = rbin + (rinc & ~rempty);
 77     assign rgraynext = (rbinnext>>1) ^ rbinnext;//binary to gray
 78 // FIFO empty when the next rptr == synchronized wptr or on reset
 79     assign rempty_val = (rgraynext == rq2_wptr)?1:0;
 80     always @(posedge rclk or negedge rrst_n)
 81         if (!rrst_n) rempty <= 1'b1;
 82         else rempty <= rempty_val;
 83 //-----------------------wfull & waddr------------------------------
 84     always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointer
 85         if (!wrst_n) {wbin, wptr} <= 0;
 86         else {wbin, wptr} <= {wbinnext, wgraynext};
 87 // Memory write-address pointer (okay to use binary to address memory)
 88     assign waddr = wbin[addr_width-1:0];
 89     assign wbinnext = wbin + (winc & ~wfull);
 90     assign wgraynext = (wbinnext>>1) ^ wbinnext;
 91 //------------------------------------------------------------------  
 92 // Simplified version of the three necessary full-tests:  
 93 // assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) &&  
 94 // (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) &&  
 95 // (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0]));  
 96 //------------------------------------------------------------------  
 97     assign wfull_val = (wgraynext=={~wq2_rptr[addr_width:addr_width-1], wq2_rptr[addr_width-2:0]}); 
 98     always @(posedge wclk or negedge wrst_n)
 99         if (!wrst_n) wfull <= 1'b0;
100         else wfull <= wfull_val;
101                 
102 endmodule

 

测试程序

  1 `timescale 1ns / 1ps
  2 //////////////////////////////////////////////////////////////////////////////////
  3 // Company: 
  4 // Engineer: 
  5 // 
  6 // Create Date: 2018/05/03 16:53:39
  7 // Design Name: 
  8 // Module Name: tb
  9 // Project Name: 
 10 // Target Devices: 
 11 // Tool Versions: 
 12 // Description: 
 13 // 
 14 // Dependencies: 
 15 // 
 16 // Revision:
 17 // Revision 0.01 - File Created
 18 // Additional Comments:
 19 // 
 20 //////////////////////////////////////////////////////////////////////////////////
 21 
 22 
 23 module tb;
 24 //    parameter fifo_width = 16;
 25 //    parameter fifo_depth = 16;  
 26 //    parameter addr_width = 4;
 27     
 28     reg wclk,rclk,wrst_n,rrst_n;  
 29     reg winc,rinc;  
 30     reg [15:0] wdata;               
 31     wire [15:0] rdata;        
 32     wire rempty,wfull; 
 33        
 34     
 35    
 36     AsyncFIFO i1(
 37         .wclk(wclk),
 38         .rclk(rclk),
 39         .wrst_n(wrst_n),
 40         .rrst_n(rrst_n),
 41         .winc(winc),
 42         .rinc(rinc),
 43         .wdata(wdata),
 44         .rdata(rdata),
 45         .wfull(wfull),
 46         .rempty(rempty)
 47         );
 48     always #20 wclk = ~wclk;
 49     always #10 rclk = ~rclk;
 50 
 51     reg [15:0] tempdata;
 52     reg [15:0] data1;
 53     reg [15:0] data2;
 54     initial begin
 55         wclk   = 0;
 56         rclk   = 0;
 57         wrst_n = 0;
 58         rrst_n = 0;
 59         winc   = 0;
 60         rinc   = 0;
 61         wdata  = 0;
 62         data1 = 0;
 63         
 64         #15
 65         fork
 66             wrst_n = 1;
 67             rrst_n = 1;
 68         join
 69         #5
 70                 push(3);
 71                 push(2);
 72                         push(1);  
 73         push(0);  
 74         #20
 75         //pop(tempdata);  
 76                   //push and pop together     
 77         while(1)begin
 78             fork
 79                 wr;
 80                 rd;
 81             join
 82         end
 83         push(10);  
 84         push(20);  
 85         push(30);  
 86         push(40);  
 87         push(50); 
 88         
 89     end 
 90       
 91         task wr;begin
 92             while(!wfull)begin
 93                push(data1);
 94                 data1 =data1+3;
 95             end
 96         end
 97         endtask
 98       
 99       task rd;begin
100         while(!rempty)
101         #15 pop(tempdata);
102         
103         end
104       endtask
105       
106       task push (input [15:0] data);  
107           if(wfull)  
108               $display("---Cannot push %d: Buffer Full---",data);  
109           else begin  
110               $display("Push:%d",data);  
111               wdata = data;  
112               winc = 1;  
113               @(posedge wclk);  
114               #5 winc = 0;  
115           end  
116       endtask  
117         
118       task pop(output[15:0] data);  
119           if(rempty)  
120               $display("---Cannot Pop: Buffer Empty---");  
121           else begin  
122               rinc = 1;  
123               @(posedge rclk);  
124               #3 rinc = 0;  
125               data = rdata;  
126               $display("------Poped:%d",data);  
127           end       
128       endtask  
129     
130        
131 endmodule
View Code

测试算是通过,但还是有点问题。相同再弄了。

 

推荐阅读