• 异步FIFO的verilog实现与简单验证(调试成功)


    最近在写一个异步FIFO的时候,从网上找了许多资料,文章都写的相当不错,只是附在后面的代码都多多少少有些小错误。

    于是自己写了一个调试成功的代码,放上来供大家参考。

    非原创 原理参考下面:

    原文 https://www.cnblogs.com/SYoong/p/6110328.html

    上代码:

     1 module Asyn_FIFO_tb;
     2 
     3     parameter WIDTH = 8;
     4 
     5     reg clk_wr;
     6     reg clk_rd;
     7     reg rst_n_rd;
     8     reg rst_n_wr;
     9 
    10     reg  [WIDTH-1:0] data_wr;
    11     reg  wr_en;
    12     wire wr_full;
    13 
    14     wire [WIDTH-1:0] data_rd;
    15     reg  rd_en;
    16     wire rd_empty;
    17 
    18 
    19     Asyn_FIFO fifo_inst(
    20     .clk_wr(clk_wr), 
    21     .rst_n_rd(rst_n_rd),
    22     .rst_n_wr(rst_n_wr),
    23     .wr_en(wr_en), 
    24     .data_wr(data_wr), 
    25     .clk_rd(clk_rd), 
    26     .rd_en(rd_en), 
    27     .data_rd(data_rd), 
    28     .rd_empty(rd_empty), 
    29     .wr_full(wr_full)
    30     );
    31     
    32     initial begin
    33         rst_n_rd = 0;
    34         rst_n_wr = 0;
    35         clk_wr = 0;
    36         clk_rd = 0;
    37         wr_en = 0;
    38         rd_en = 0;
    39         
    40         #20
    41         rst_n_rd = 1;
    42         rst_n_wr = 1;
    43         
    44         #80
    45         wr_en = 1;
    46         rd_en = 0;
    47         
    48         #10000
    49         wr_en = 0;
    50         rd_en = 1;
    51     end
    52 
    53     always #10 clk_wr = ~clk_wr;
    54     always #20 clk_rd = ~clk_rd;
    55     
    56 /*     always @(posedge clk_rd)
    57         rd_en <= ($random) % 2;
    58 
    59     always @(posedge clk_wr)
    60         wr_en <= ($random) % 2; */
    61     
    62     always @(posedge clk_wr)
    63         data_wr <= ($random) % 256;
    64     
    65 endmodule
    Asyn_FIFO_tb.v
     1 module Asyn_FIFO
     2 #(
     3     parameter WIDTH = 8,
     4     parameter DEPTH = 4
     5 )
     6 (
     7     input  clk_wr,
     8     input  clk_rd,
     9     input  rst_n_rd,
    10     input  rst_n_wr,
    11     input  wr_en,
    12     input  rd_en,
    13     input  [WIDTH-1:0] data_wr,
    14     output [WIDTH-1:0] data_rd,
    15     output reg rd_empty,
    16     output reg wr_full
    17 );
    18 
    19     //defination
    20     reg  [WIDTH-1 : 0] mem [0 : (1<<DEPTH)-1];        //2^DEPTH numbers
    21     reg  [DEPTH   : 0] wp, rp;
    22     reg  [DEPTH   : 0] wr1_rp, wr2_rp, rd1_wp, rd2_wp;
    23     reg  [DEPTH   : 0] wbin, rbin;
    24 
    25 
    26     wire [DEPTH-1 : 0] waddr, raddr;
    27     wire [DEPTH   : 0] wbin_next, rbin_next;        //bincode
    28     wire [DEPTH   : 0] wgray_next, rgray_next;        //graycode
    29     
    30     wire rd_empty_val, wr_full_val;
    31     
    32     //output
    33     assign data_rd = (rd_en && !rd_empty) ? mem[raddr] : 0;        //clear "xx" state
    34 
    35     //input
    36     always@(posedge clk_wr)
    37         if(wr_en && !wr_full)
    38             mem[waddr] <= data_wr;
    39 
    40 /*----------generate waddr and raddr-------------------------*/
    41     //gen raddr and read gray code
    42     always@(posedge clk_rd or negedge rst_n_rd)
    43         if(!rst_n_rd)
    44             {rbin, rp} <= 0;
    45         else
    46             {rbin, rp} <= {rbin_next, rgray_next};
    47 
    48     assign raddr = rbin[DEPTH-1 : 0];
    49     assign rbin_next = rbin + (rd_en & ~rd_empty);
    50     assign rgray_next = rbin_next ^ (rbin_next >> 1);
    51 
    52     //gen waddr and write gray code
    53     always@(posedge clk_wr or negedge rst_n_wr)
    54         if(!rst_n_wr)
    55             {wbin, wp} <= 0;
    56         else
    57             {wbin, wp} <= {wbin_next, wgray_next};
    58 
    59     assign waddr = wbin[DEPTH-1 : 0];
    60     assign wbin_next = wbin + (wr_en & ~wr_full);
    61     assign wgray_next = wbin_next ^ (wbin_next >> 1);
    62 
    63 /*---------------synchro rp and wp--------------------------*/
    64     //synchro rp
    65     always@(posedge clk_wr or negedge rst_n_wr)
    66         if(!rst_n_wr)
    67             {wr2_rp, wr1_rp} <= 0;
    68         else
    69             {wr2_rp, wr1_rp} <= {wr1_rp, rp}; //delay two clock
    70 
    71     //synchro wp
    72     always@(posedge clk_rd or negedge rst_n_rd)
    73         if(!rst_n_rd)
    74             {rd2_wp, rd1_wp} <= 0;
    75         else
    76             {rd2_wp, rd1_wp} <= {rd1_wp, wp};
    77 
    78 /*---------------empty and full flags--------------------------*/
    79     //gen rd_empty
    80     assign rd_empty_val = (rd2_wp == rgray_next);
    81     always@(posedge clk_rd or negedge rst_n_rd)
    82         if(!rst_n_rd)
    83             rd_empty <= 1'b1;
    84         else
    85             rd_empty <= rd_empty_val;
    86 
    87     //gen wr_full, two high bit do not equal
    88     assign wr_full_val = ({~wr2_rp[DEPTH : DEPTH-1], wr2_rp[DEPTH-2 : 0]} == wgray_next);
    89     always@(posedge clk_wr or negedge rst_n_wr)
    90         if(!rst_n_wr)
    91             wr_full <= 1'b0;
    92         else
    93             wr_full <= wr_full_val;
    94 
    95 endmodule
    Asyn_FIFO.v

    注意wire、reg类型的赋值。

  • 相关阅读:
    WM_MOUSEWHEEL消息的处理
    Delphi之TStrings和TStringLists类[转]
    使用mysqladmin命令修改Mysql密码
    AP_发票与预付款核销时预付款带税码
    ORACLE EBS AP发票到付款的数据流
    .关于货币大写的探索
    Oracle SQL 空值排序(Nulls)
    实现主从关系Form中汇总行金额/数量
    巧妙的查看FORM中的 LOV查询语句
    供应商接口的使用
  • 原文地址:https://www.cnblogs.com/HolmeXin/p/9448626.html
Copyright © 2020-2023  润新知