同步FIFO

FIFO表示先进先出,是一种存储器,要求第一个写入的数据第一个从队列中读出,而同步FIFO表示使用单一时钟来控制写操作和读操作。

这是一个(功能缺失的)FIFO的示意图,写使能时将写数据传入FIFO,在读使能时将内部存储数据传出FIFO。

为满足先进先出的功能,内部需要定义读指针与写指针。代码如下:

module fifo_mem
#(parameter
FIFO_WIDTH = 8,//宽度,是一次读写操作的数据为宽
FIFO_DEPTH = 32,//深度,可以存贮的数据个数
FIFO_PTR   = 5//指针位宽,例如深度为32的FIFO需要的指针宽度为5,因为2的5次方是32
)

(clk,rst_n,wr_en,rd_en,wr_data,rd_data);
    input 		                clk                        ;
    input                       rst_n                      ;
    
    input	                    wr_en                      ;//写操作使能信号,高有效
    input	                    rd_en                      ;//读操作使能信号,高有效
    input    [FIFO_WIDTH-1:0]   wr_data                    ;//输入数据
                                                          
    output   [FIFO_WIDTH-1:0]   rd_data                    ;//输出数据
                                                          
    reg      [FIFO_WIDTH-1:0]  raml[FIFO_DEPTH-1:0]        ;// 寄存器
    reg      [FIFO_WIDTH-1:0]   rd_data                    ;
    reg      [FIFO_PTR-1:0]     wr_ptr,rd_ptr              ;//读写指针,每次读,读指针+1,每次写,写指针+1
    
    
    always@(posedge clk or negedge rst_n) 
    if(!rst_n)//复位信号,对读写指针归零,然后将FIFO内存储数据清零
        begin
            wr_ptr = 0;
            rd_ptr = 0;
            repeat(FIFO_DEPTH)
                begin
                    raml[wr_ptr] = 0;
                    wr_ptr       = wr_ptr+1;
                end
                
        end
        
    else if(wr_en&&!rd_en)	
        begin
            raml[wr_ptr]        <= wr_data;
            wr_ptr              <= wr_ptr+1;
        end                    
                           
    else if(!wr_en&rd_en)	   
        begin                  
            rd_data             <= raml[rd_ptr]; 
            rd_ptr              <= rd_ptr+1;
        end                    
                          
    else if(wr_en&rd_en)	   
        begin                   
            rd_data             <= raml[rd_ptr];
            raml[wr_ptr]        <= wr_data;
            rd_ptr              <= rd_ptr+1;
             wr_ptr             <= wr_ptr+1;
        end
      
endmodule

编写测试模块 

`timescale 1ns/1ns
module  tb #(parameter
FIFO_WIDTH = 8,//宽度,是一次读写操作的数据为宽
FIFO_DEPTH = 32//深度,可以存贮的数据个数
)();

reg 	                clk                     ;
reg                    rst_n                    ;
reg                    wr_en                    ;
reg                    rd_en                    ;
reg [FIFO_WIDTH-1:0]   wr_data   ,wr_data_next  ;
wire[FIFO_WIDTH-1:0]   rd_data                  ;



initial 
    begin
    clk    =     1'b1;
    rst_n  =     1'b0;
    wr_en  =     1'b0;
    rd_en  =     1'b0;
    wr_data=     8'b0;
    wr_data_next=8'b0;
    
        
#20
    rst_n = 1'b1;
#10
    wr_en  =     1'b1;
#5 
    repeat(40)
        begin

            wr_data      = wr_data_next;
#20         wr_data_next = wr_data+1;

        end
    wr_en = 1'b0;
#30    
    rd_en = 1'b1;
    
    
    
    end
always#10 clk = ~clk;

fifo_mem fifo_men_inst
    (
    .clk      (clk     )   ,
    .rst_n    (rst_n   )   ,
                           
    .wr_en    (wr_en   )   ,
    .rd_en    (rd_en   )   ,
    .wr_data  (wr_data )   ,
                          
    .rd_data  (rd_data )   
    );
endmodule

 运行测试模块

 

 

 但是此FIFO存在一下问题:

1:当写空间用完后可以继续写入数据;对应上面第一张图右下角。

2:当数据读取完后可以继续读取数据;对应上面第二张图后半部分。

这两个问题可以在FIFO中加入一个控制模块来解决,此控制模块中有一个计数器,

由于加入了计数模块,FIFO可以输出自己的可写余量、已用容量以及可读可写标志。

 此FIFO的示意图带有control模块,内部有一个计数器,用来计FIFO的可用余量,当计数器为0时,将read_en拉低,stack_empty拉高,当计数器为FIFO的深度时,将write_en拉低和stack_full拉高,此外,FIFO可读可写,将read_end 、write_en、拉高,stack_full、stack_empty拉低 。

编写fifo_control模块

module fifo_control
#(parameter
FIFO_PTR   = 5 ,
FIFO_DEEPTH= 32
)
    
(clk,rst_n,wr_en_in,rd_en_in,wr_en,rd_en,data_value,stack_full,stack_empty);
                                                    
input 		           clk                       ;
input                  rst_n                     ;
                                               
input	               wr_en_in                  ;
input	               rd_en_in                  ;
                       
output                 wr_en                     ;                          
output                 rd_en                     ;
output  [FIFO_PTR-1:0] data_value                ;//已写数据量
output                 stack_full                ;
output                 stack_empty               ;

wire                   wr_en                     ;
wire                   rd_en                     ;
reg     [FIFO_PTR-1:0] data_value                ;
wire                   stack_full,stack_empty    ;

assign stack_full   = (data_value == FIFO_DEEPTH-1)? 1:0;
assign stack_empty  = (data_value == 0)?           1:0;
assign wr_en        = (!stack_full&&wr_en_in)  ?    1:0   ;
assign rd_en        = (!stack_empty&&rd_en_in)?     1:0   ;

always@(posedge clk or negedge rst_n)
    if(!rst_n)
        data_value <= 0;
    else if((wr_en_in&&!rd_en_in&&!stack_full)
             ||(wr_en_in&&rd_en_in&&stack_empty&&!stack_full))//写,不读,数据空间加一
        data_value <= data_value+1;
    else if((!wr_en_in&&rd_en_in&&!stack_empty)
             ||(wr_en_in&&rd_en_in&&!stack_empty&&stack_full))  //不写,读,数据空间减一
        data_value <= data_value-1;   
    else if(wr_en_in&&rd_en_in&&!stack_empty&&!stack_full)  //写,读,数据空间不变
        data_value <= data_value;    
    else
        data_value <= data_value;   
    
endmodule

编写fifo模块

module fifo#(parameter
FIFO_WIDTH = 8,//宽度,是一次读写操作的数据为宽
FIFO_DEPTH = 32,//深度,可以存贮的数据个数
FIFO_PTR   = 5//指针位宽,例如深度为32的FIFO需要的指针宽度为5,因为2的5次方是32
)
(clk,rst_n,wr_en_in,rd_en_in,wr_data,rd_data,data_value,stack_full,stack_empty);

input 		           clk                       ;
input                  rst_n                     ;
input  [FIFO_WIDTH-1:0]wr_data                   ;                                                
input	               wr_en_in                  ;
input	               rd_en_in                  ;
                       
output [FIFO_WIDTH-1:0]rd_data                   ;
output [FIFO_PTR-1:0]  data_value                ;
output                 stack_full                ;
output                 stack_empty               ;

wire                   wr_en,rd_en               ;

fifo_mem fifo_mem_inst
    (
    .clk      (clk     )   ,
    .rst_n    (rst_n   )   ,
                           
    .wr_en    (wr_en   )   ,
    .rd_en    (rd_en   )   ,
    .wr_data  (wr_data )   ,
                          
    .rd_data  (rd_data )   
    );

fifo_control fifo_control_inst
    (
    .clk         (clk         ),
    .rst_n       (rst_n       ),

    .wr_en_in    (wr_en_in    ),
    .rd_en_in    (rd_en_in    ),

    .wr_en       (wr_en       ),
    .rd_en       (rd_en       ),
    .data_value  (data_value  ),
    .stack_full  (stack_full  ),
    .stack_empty (stack_empty )
    );
endmodule



 重新编写测试模块

`timescale 1ns/1ns
module  tb #(parameter
FIFO_WIDTH = 8,//宽度,是一次读写操作的数据为宽
FIFO_DEPTH = 32,//深度,可以存贮的数据个数
FIFO_PTR   = 5//指针位宽,例如深度为32的FIFO需要的指针宽度为5,因为2的5次方是32
)();

reg 	               clk                      ;
reg                    rst_n                    ;
reg                    wr_en_in                 ;
reg                    rd_en_in                 ;
reg [FIFO_WIDTH-1:0]   wr_data   ,wr_data_next  ;
wire[FIFO_WIDTH-1:0]   rd_data                  ;
wire [FIFO_PTR-1:0]    data_value               ;
wire                   stack_full,stack_empty   ;
      
initial 
    begin
    clk    =     1'b1;
    rst_n  =     1'b0;
    wr_en_in  =  1'b0;
    rd_en_in  =  1'b0;
    wr_data=     8'b0;
    wr_data_next=8'b0;
    
        
#20
    rst_n = 1'b1;
#10
    wr_en_in  =     1'b1;
#5 
    repeat(40)
        begin

            wr_data      = wr_data_next;
#20         wr_data_next = wr_data+1;

        end
    wr_en_in = 1'b0;
#30    
    rd_en_in = 1'b1;
    
    
    
    end
always#10 clk = ~clk;

fifo fifo_inst
    (
     .clk            (clk         ),
     .rst_n          (rst_n       ),
     .wr_data        (wr_data     ),
     .wr_en_in       (wr_en_in    ),
     .rd_en_in       (rd_en_in    ),

     .rd_data        (rd_data     ),
     .data_value     (data_value  ),
     .stack_full     (stack_full  ),
     .stack_empty    (stack_empty )
    );


endmodule

测试结果:stack_full成功拉高,数据无法写入

 stack_empty成功拉低,数据无法读出

 由此实现了同步FIFO 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值