美文网首页
同步fifo设计

同步fifo设计

作者: 喜欢萝莉的逗逼青年 | 来源:发表于2016-08-14 11:18 被阅读459次

    1.同步fifo的功能点


    当fifo写满的时候,输出满标志.
    当fifo读空的时候,输出空标志.
    写满之后不能继续写,即有满标志,禁止向ram写入数据,防止数据混乱.
    读空之后不能继续读,读完所有数据,禁止重复读.
    对于空满标志的判断,设计的思想是,当读指针等于写指针加1,且同时有一个写使能,这样,就认为fifo已满,这是满的临界条件,近乎满。空标志也是同样的原理。

    2.设计代码


     module sync_fifo
        (
         clk                        ,
         reset                    ,
         fifo_wr                    ,
         fifo_rd                    ,
         wr_data                    ,
         rd_data                    ,
         full                      ,
         empty              
         )                        ;
     //*****************************parameter define*********************
     //******************************************************************
    
     parameter WH=8                     ;//ram width
     parameter DH=16                       ;//ram deepth
     parameter AD=4                     ;//ram addr
    
     //*****************************signal define*********************
     //******************************************************************
      input         clk                 ;
      input           reset               ;
      input            fifo_wr              ;
      input         fifo_rd             ;
      input [WH-1:0]   wr_data              ;
    
      output          full                  ;
      output        empty                  ;
      output [WH-1:0] rd_data                ;
    
      reg    [AD-1:0] wr_pts                  ;
      reg    [AD-1:0] rd_pts                  ; 
      reg    [WH-1:0] fifo_ram [DH-1:0]    ;
      wire          valid_wr                ;
      wire          valid_rd                ;
      reg    [WH-1:0]  rd_data              ;
      reg             full                 ;
      reg             empty               ;
    
      reg   [AD-1:0]   wp                   ;//wr_pts gray code
      reg   [AD-1:0]   wp_s               ;//wr_pts+1 gray code
      reg   [AD-1:0]   rp                   ;//rd_pts gray code
      reg   [AD-1:0]   rp_s               ;//rd_pts+1 gray code
    
      wire   [AD-1:0]   wr_pts_s0            ;//wr_pts interal signal
      wire   [AD-1:0]   wr_pts_s1            ;//wr_pts+1 interal signal
      wire  [AD-1:0]   rp_pts_s0            ;//rd_pts interal signal
      wire  [AD-1:0]   rp_pts_s1            ;//rd_pts+1 interal signal
      integer           i                   ;
    //*****************************code brgin*********************
    //*****************************part1:ram************************    
    always@(posedge clk or negedge reset)
      if(!reset)
        rd_data<={WH{1'd0}};
    else if(valid_rd)
        rd_data<=fifo_ram[rd_pts];
    else
        rd_data<={WH{1'd0}};
        
    always@(posedge clk or negedge reset)
    if(!reset)
        begin
        for(i=0;i<DH;i=i+1)
          fifo_ram[i]<=0;
        end
    else if (valid_wr)
          fifo_ram[wr_pts]<=wr_data;
    else
          fifo_ram[wr_pts]<=fifo_ram[wr_pts];
    
    //*****************************part2:full/empty*********************
    //*******************************************************************
    always@(posedge clk or negedge reset)
    if(!reset)
        full<=1'd0;
    else if(fifo_wr&&(rp==wp_s))
        full<=1'd1;
    else 
        full<=full;
        
    always@(posedge clk or negedge reset)
    if(!reset)
        empty<=1'd1;
    else if(fifo_rd&&(wp==rp_s))
        empty<=1'd1;
    else
        empty<=empty;
    
    //*****************************part3:wr/rd*********************
    //*******************************************************************   
    assign  valid_wr=fifo_wr&&(~full);
    assign  valid_rd=fifo_rd&&(~empty);
    
    //******************************part4:wr/rd_pts pro**********************
    //**********************************************************************
    always@(posedge clk or negedge reset)
    if(!reset)
        wr_pts<={AD{1'd0}};
    else if(valid_wr)
        wr_pts<=wr_pts+1;
    else if(wr_pts==15)
        wr_pts<={AD{1'd0}}  ;
    else    
        wr_pts<=wr_pts      ;
        
        
    always@(posedge clk or negedge reset)
    if(!reset)
        rd_pts<={AD{1'd0}};
    else if(valid_rd)
        rd_pts<=rd_pts+1;
    else if(rd_pts==15)
        rd_pts<={AD{1'd0}}  ;
    else    
        rd_pts<=rd_pts      ;
    
    //*********************************part5:b-to-g************************
    //*************************************************************************
    assign wr_pts_s0=wr_pts;
    assign wr_pts_s1=wr_pts+1;
    assign rp_pts_s0=rd_pts;
    assign rp_pts_s1=rd_pts+1;
    
    always@(*)
    begin
        wp[3]=wr_pts_s0[3];
        wp[2]=wr_pts_s0[3]^wr_pts_s0[2];
        wp[1]=wr_pts_s0[2]^wr_pts_s0[1];
        wp[0]=wr_pts_s0[1]^wr_pts_s0[0];
    end
    
    always@(*)
    begin
        wp_s[3]=wr_pts_s1[3];
        wp_s[2]=wr_pts_s1[3]^wr_pts_s1[2];
        wp_s[1]=wr_pts_s1[2]^wr_pts_s1[1];
        wp_s[0]=wr_pts_s1[1]^wr_pts_s1[0];
    end
    always@(*)
    begin
        rp[3]=rp_pts_s0[3];
        rp[2]=rp_pts_s0[3]^rp_pts_s0[2];
        rp[1]=rp_pts_s0[2]^rp_pts_s0[1];
        rp[0]=rp_pts_s0[1]^rp_pts_s0[0];
    end
    
    always@(*)
    begin
        rp_s[3]=rp_pts_s1[3];
        rp_s[2]=rp_pts_s1[3]^rp_pts_s1[2];
        rp_s[1]=rp_pts_s1[2]^rp_pts_s1[1];
        rp_s[0]=rp_pts_s1[1]^rp_pts_s1[0];
    end
     endmodule
    

    难点在于空满标志的判断,代码里对空满标志的判断是一个近乎满,近乎空的状态.

    3.测试波形

    fifo设计要保证写指针追不上读指针 ,读指针追不上写指针;  
    在fifo将写0,将读1的时候,下一拍拉高full,告诉user,fifo已满(近乎满的临界状态,不要在发送写指令了)
    如果user继续发送写指令,则继续输出full标志,同时写指针不再自加,有效的写命令不会生成,user发送过来的数据不会被写入到ram里.
    直到有读指针把full拉低。才可以继续写入数据.   
    
    1.1.png 1.2.png

    相关文章

      网友评论

          本文标题:同步fifo设计

          本文链接:https://www.haomeiwen.com/subject/cryysttx.html