zoukankan      html  css  js  c++  java
  • verilog实现之同步FIFO

       上一节我们实现RAM的相关知识,也对比了RAM和FIFO的区别;FIFO:先进先出数据缓冲器,也是一个端口只读,另一个端口只写。但是FIFO与伪双口RAM的不同,FIFO为先入先出,没有地址线,不能对存储单元寻址;而伪双口RAM两个端口都有地址线,可以对存储单元寻址。但是FIFO内部的存储单元主要是由双口RAM(异步读写来实现的),在verilog 实现之RAM中已经讲过各种各样的RAM的实现。此时就要用双端口的RAM来实现FIFO。

      一、实现双口RAM(异步读写)

        

      1 `timescale 1ns / 1ps
      2 //////////////////////////////////////////////////////////////////////////////////
      3 // Company: 
      4 // Engineer: 
      5 // 
      6 // Create Date: 2020/06/25 20:46:14
      7 // Design Name: 
      8 // Module Name: synram_double_port
      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 synram_double_port #(
     24 parameter DATA_WIDTH = 8,
     25 parameter ADDR_WIDTH = 8,
     26 parameter RAM_DEPTH = 1 << ADDR_WIDTH
     27 )(
     28 input [ADDR_WIDTH - 1 : 0] address_0 , // address_0 Input
     29 inout [DATA_WIDTH-1 : 0] data_0    , // data_0 bi-directional
     30 input cs_0      , // Chip Select
     31 input we_0      , // Write Enable/Read Enable
     32 input oe_0      , // Output Enable
     33 input [ADDR_WIDTH - 1 : 0] address_1 , // address_1 Input
     34 inout [DATA_WIDTH-1 : 0] data_1    , // data_1 bi-directional
     35 input cs_1      , // Chip Select
     36 input we_1      , // Write Enable/Read Enable
     37 input oe_1        // Output Enable
     38 ); 
     39  
     40 //--------------Internal variables---------------- 
     41 reg [DATA_WIDTH-1:0] data_0_out ; 
     42 reg [DATA_WIDTH-1:0] data_1_out ;
     43 reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];
     44  
     45  
     46 //initialization
     47  
     48 // synopsys_translate_off
     49 integer i;
     50 initial begin
     51     for(i=0; i < RAM_DEPTH; i = i + 1) begin
     52         mem[i] = 8'h00;
     53     end
     54 end
     55 // synopsys_translate_on
     56  
     57  
     58 //--------------Code Starts Here------------------ 
     59 // Memory Write Block 
     60 // Write Operation : When we_0 = 1, cs_0 = 1
     61 always @ (address_0 or cs_0 or we_0 or data_0
     62 or address_1 or cs_1 or we_1 or data_1)
     63 begin : MEM_WRITE
     64   if ( cs_0 && we_0 ) begin
     65      mem[address_0] <= data_0;
     66   end 
     67   else if  (cs_1 && we_1) begin
     68      mem[address_1] <= data_1;
     69   end
     70 end
     71  
     72 // Tri-State Buffer control 
     73 // output : When we_0 = 0, oe_0 = 1, cs_0 = 1
     74 assign data_0 = (cs_0 && oe_0 && !we_0) ? data_0_out : 8'bz; 
     75  
     76 // Memory Read Block 
     77 // Read Operation : When we_0 = 0, oe_0 = 1, cs_0 = 1
     78 always @ (address_0 or cs_0 or we_1 or oe_0)
     79 begin : MEM_READ_0
     80   if (cs_0 && !we_0 && oe_0) begin
     81     data_0_out <= mem[address_0]; 
     82   end else begin
     83     data_0_out <= 0; 
     84   end
     85 end 
     86  
     87 //Second Port of RAM
     88 // Tri-State Buffer control 
     89 // output : When we_0 = 0, oe_0 = 1, cs_0 = 1
     90 assign data_1 = (cs_1 && oe_1 && !we_1) ? data_1_out : 8'bz; 
     91 // Memory Read Block 1 
     92 // Read Operation : When we_1 = 0, oe_1 = 1, cs_1 = 1
     93 always @ (address_1 or cs_1 or we_1 or oe_1)
     94 begin : MEM_READ_1
     95   if (cs_1 && !we_1 && oe_1) begin
     96     data_1_out <= mem[address_1]; 
     97   end else begin
     98     data_1_out <= 0; 
     99   end
    100 end
    101  
    102 endmodule
    View Code

      二、对RAM端口的实例化

     1 synram_double_port #(
     2         .DATA_WIDTH(DATA_WIDTH),
     3         .ADDR_WIDTH(ADDR_WIDTH),
     4         .RAM_DEPTH(RAM_DEPTH)
     5     ) inst_synram_double_port (
     6         .address_0 (wr_pointer),
     7         .data_0    (data_in),
     8         .cs_0      (wr_cs),
     9         .we_0      (wr_en),
    10         .oe_0      (1'b0),
    11         .address_1 (rd_pointer),
    12         .data_1    (data_ram),
    13         .cs_1      (rd_cs),
    14         .we_1      (1'b0),
    15         .oe_1      (rd_en)
    16     );

      三、同步FIFO的实现

      同步FIFO的框图:

      同步FIFO读写原理:通常,FIFO是使用旋转指针实现的。 我们可以将FIFO的写入和读取指针称为数据区的头和尾。 最初,FIFO的读写指针将指向相同的位置,吸入所示:这是一个解释FIFO如何使用内存的示例。 这是长度为8的fifo,WP和RP是写指针和读指针指向的位置。 图中的阴影区域填充了数据。使用stutus_cnt记录FIFO RAM中的数据个数,等于0时,给出empty信号,等于RAM_DEPTH时,给出full信号。stutus_cnt写而未满时增加1,读而未空时减1。同时发生读写操作时,stutus_cnt。读写指针宽度与地址宽度相当,地址增加而溢出后,自动变成0。

     从同步FIFO的框图中。我们可以推理出同步FIFO的管脚图,同时这里所说的fifo 没有了地址,是因为用指针代替了地址。剩下的就是看图说话。

       四、实现的代码

    RTL:

      1 `timescale 1ns / 1ps
      2 //////////////////////////////////////////////////////////////////////////////////
      3 // Company: 
      4 // Engineer: 
      5 // 
      6 // Create Date: 2020/06/25 20:42:22
      7 // Design Name: 
      8 // Module Name: syn_fifo
      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 module syn_fifo #(
     23 parameter DATA_WIDTH = 8,
     24 parameter ADDR_WIDTH = 8,
     25 parameter RAM_DEPTH = (1 << ADDR_WIDTH)
     26     )
     27 (
     28     input           wire                     clk            ,
     29     input            wire                     rst          ,
     30     //interfaces    
     31     input             wire                     wr_cs       ,//�--片�信�
     32     input             wire                    rd_cs        ,//�--片�信�
     33     input              wire [DATA_WIDTH-1:0]    data_in        ,//输入数据
     34     input           wire                    rd_en        ,//读是�
     35     input           wire                      wr_en       ,//写使�
     36     output            wire [DATA_WIDTH-1:0]    data_out    ,//数据输出
     37     output            wire                    empty        ,//空标�
     38     output          wire                     full
     39 
     40     );
     41 
     42 //========================================================================
     43 // ################ Define Parameter and Internal signals ################ 
     44 //========================================================================/
     45 reg                [ADDR_WIDTH-1:0]        wr_pointer    ;//写指�
     46 reg                [ADDR_WIDTH-1:0]        rd_pointer    ;
     47 reg                [ADDR_WIDTH:0]            status_cnt    ;//状æ??
     48 reg             [DATA_WIDTH-1:0]        data_out_r    ;//数据计数
     49 wire               [DATA_WIDTH-1:0]        data_ram    ;
     50 
     51 //=============================================================================
     52 //+++++++++++++++++++++++++     Main Code    +++++++++++++++++++++++++++++++
     53 //=============================================================================
     54 
     55 assign     full   =   (status_cnt==RAM_DEPTH)?1'b1 :1'b0 ;
     56 assign     empty  =      (status_cnt==0)?1'b1:1'b0;
     57 
     58 //wr_pointer
     59 always @(posedge clk or posedge rst) begin
     60     if (!rst) begin
     61         wr_pointer  <= 0 ;        
     62     end
     63     else if (wr_cs && wr_en) begin
     64         wr_pointer  <= wr_pointer + 1;
     65     end 
     66 end
     67 
     68 //rd_pointer
     69 always @(posedge clk or posedge rst) begin
     70     if (!rst) begin
     71         rd_pointer   <=   0    ;
     72     end
     73     else if (rd_cs && rd_en) begin
     74         rd_pointer   <= rd_pointer + 1'b1 ;
     75     end
     76 end
     77 //data_out_r
     78 
     79 always @(posedge clk or posedge rst) begin
     80     if (!rst) begin
     81         data_out_r    <=   0 ;
     82         
     83     end
     84     else if (rd_cs && rd_en) begin
     85         data_out_r   <=  data_ram ;
     86     end
     87 end
     88 assign   data_out   =  data_out_r ;
     89 
     90 //status_cnt
     91 always @(posedge clk or posedge rst) begin
     92     if (!rst) begin
     93         
     94         status_cnt   <=   0; //只读不写
     95     end
     96     else if ((rd_cs && rd_en) && !(wr_cs && wr_en) && (status_cnt!=0)) begin
     97         status_cnt     <= status_cnt - 1'b1 ;//只读不写
     98     end
     99     else if(!(rd_cs && rd_en) && (wr_cs && wr_en) && (status_cnt!=RAM_DEPTH))begin
    100         status_cnt     <= status_cnt + 1'b1 ;//只写不读
    101     end
    102 end
    103 
    104 
    105 
    106 synram_double_port #(
    107         .DATA_WIDTH(DATA_WIDTH),
    108         .ADDR_WIDTH(ADDR_WIDTH),
    109         .RAM_DEPTH(RAM_DEPTH)
    110     ) inst_synram_double_port (
    111         .address_0 (wr_pointer),
    112         .data_0    (data_in),
    113         .cs_0      (wr_cs),
    114         .we_0      (wr_en),
    115         .oe_0      (1'b0),
    116         .address_1 (rd_pointer),
    117         .data_1    (data_ram),
    118         .cs_1      (rd_cs),
    119         .we_1      (1'b0),
    120         .oe_1      (rd_en)
    121     );
    122 
    123 endmodule
    View Code

    TB:

      1 `timescale 1ns / 1ps
      2 //////////////////////////////////////////////////////////////////////////////////
      3 // Company: 
      4 // Engineer: 
      5 // 
      6 // Create Date: 2020/06/25 23:12:58
      7 // Design Name: 
      8 // Module Name: syn_fifo_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 
     24 module syn_fifo_tb();
     25 
     26 parameter DATA_WIDTH = 8;
     27 parameter ADDR_WIDTH = 8;
     28 parameter RAM_DEPTH = (1 << ADDR_WIDTH);
     29     
     30 reg clk ;
     31 reg rst ;
     32 reg wr_cs ;
     33 reg rd_cs ;
     34 reg rd_en ;
     35 reg wr_en ;
     36 reg [DATA_WIDTH-1:0] data_in ;
     37 wire full ;
     38 wire empty ;
     39 wire [DATA_WIDTH-1:0] data_out ;
     40 
     41 
     42 initial begin
     43     clk = 0;
     44     forever
     45     #2 clk = ~clk;
     46 
     47 end
     48 
     49 integer i=0;
     50 initial begin
     51 
     52     rst = 0;
     53     wr_cs = 0;
     54     rd_cs = 0;
     55     wr_en = 0;
     56     rd_en = 0;
     57     data_in = 0;
     58     
     59     #8
     60     rst = 1;
     61     //write
     62     wr_cs = 1;
     63     wr_en = 1;
     64     
     65     for(i = 0; i < 256; i = i + 1) begin
     66         @(negedge clk) begin
     67             data_in = data_in + 1;
     68         end
     69         
     70     end
     71     
     72     //read
     73     
     74     //#8
     75     wr_cs = 0;
     76     wr_en = 0;
     77     rd_cs = 1;
     78     rd_en = 1;
     79 
     80 
     81 
     82 
     83 end
     84 
     85 syn_fifo #(
     86     .DATA_WIDTH(DATA_WIDTH),
     87     .ADDR_WIDTH(ADDR_WIDTH),
     88     .RAM_DEPTH(RAM_DEPTH)
     89 ) inst_syn_fifo (
     90     .clk      (clk),
     91     .rst      (rst),
     92     .wr_cs    (wr_cs),
     93     .rd_cs    (rd_cs),
     94     .data_in  (data_in),
     95     .rd_en    (rd_en),
     96     .wr_en    (wr_en),
     97     .data_out (data_out),
     98     .empty    (empty),
     99     .full     (full)
    100     );
    101 
    102     
    103     
    104 endmodule
    View Code
  • 相关阅读:
    NFine框架JqGrid导出选中行为Excel实现方法
    NFine框架全选checkBox列错位
    VS 在文件中查找替换界面死掉。
    WCF各个Service之间共享数据
    Devexpress Winform 使用MVVM
    FontAwesome图标选择器
    Xampp PHPStorm XDebug配置
    SDL 库 无法解析的外部符号 __imp__fprintf
    ffmpeg mp4转yuv
    JAVA环境变量配置
  • 原文地址:https://www.cnblogs.com/lgy-gdeu/p/13197562.html
Copyright © 2011-2022 走看看