• Verilog笔记.6.FIFO


    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_0] fifo_cnt 
     41     );
     42     
     43     reg  [addr_0] wptr,rptr;
     44     reg  [addr_0] rbin,wbin;
     45     reg  [addr_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_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_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

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

  • 相关阅读:
    linux下删除乱码文件
    linux修改网卡延时、带宽、丢包等
    连接远程系统里的vbox虚拟机
    Linux路由功能
    关于C语言的取整函数
    新博客
    NEU1217之神风堂最少人数 自己在精度上吃了苦头
    sprintf sscanf自己应该会的小点
    【转】妙解亲和数
    redeclared as different kind of symbol
  • 原文地址:https://www.cnblogs.com/protogenoi/p/8981495.html
Copyright © 2020-2023  润新知