美文网首页
同步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设计

    1.同步fifo的功能点 当fifo写满的时候,输出满标志.当fifo读空的时候,输出空标志.写满之后不能继续写,...

  • 公平锁和非公平锁

    AQS内部维护着一个FIFO队列,该队列就是CLH同步队列。CLH同步队列是一个FIFO双向队列,AQS依赖它来完...

  • AQS 源码阅读

    一 简介-API 文档阅读 提供一个基于 FIFO 等待队列实现阻塞锁和相关同步器的基础框架。这个类被设计用于依靠...

  • 异步FIFO设计

    本文首发于个人博客 1.设计目标 设计一个参数可配置的异步FIFO,要求: FIFO深度从4开始在2的幂次方连续可...

  • 异步FIFO的同步问题

    异步FIFO通过比较读写地址进行满空判断,但是读写地址属于不同的时钟域,所以在比较之前需要先将读写地址进行同步处理...

  • 理解ReentrantLock的公平锁和非公平锁

    学习AQS的时候,了解到AQS依赖于内部的FIFO同步队列来完成同步状态的管理,当前线程获取同步状态失败时,同步器...

  • AbstractQueuedSynchronizer

    提供了实现阻塞锁和相关同步器依靠先入先出(FIFO)等待队列(信号量,事件等)的框架. 此类设计对于大多数种类的依...

  • AQS学习笔记

    AQS AbstractQueueSynchronizer 一个帮助实现同步锁功能的框架。底层基于FIFO队列,提...

  • (十九)AQS实现原理(具体例子待总结)

    AbstractQueuedSynchronizer,提供FIFO队列,构建锁或者其他同步组件(信号量、事件等、R...

  • Java并发包基础——AQS源码解析

    AQS AbstractQueuedSynchronizer 提供了一个基于FIFO队列用于构建锁或其他相关同步装...

网友评论

      本文标题:同步fifo设计

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