用移位寄存器实现同步FIFO,带空满判断

文章介绍了如何利用移位寄存器和计数器实现一个同步FIFO,包括空满状态的判断和数据的读写操作。在FIFO满时阻止写入,空时阻止读出,通过push和pop信号控制数据的进出,并提供了Verilog代码示例进行说明。
摘要由CSDN通过智能技术生成

用移位寄存器实现同步FIFO

        如图所示,同步FIFO带有push信号和pop信号,push代表往队列里面压入一个数据,pop代表往队列外面排出一个数据。


 解题思路

        同步FIFO的空满判断用一个计数器来判断,收到push信号计数器加1,收到pop信号时计数器减1,考虑同时push和pop的情况计数器不变,当计数器为0时,输出空,当计数器为DEPTH时,输出满。FIFO给出空满信号,空时不能读,满时不能写。具体代码如下:

always @(posedge clk)begin
    if(!rstn)
        counter <= 'd0;
    else if(push && pop)
        counter <= counter;
    else if(push)
        counter <= counter + 1'b1;
    else if(pop)
        counter <= counter - 1'b1;
end

assign empty = (counter == 'd0);
assign full  = (counter == DEPTH);

         数据的写入和读出,push数据就直接在移位寄存器的一端,用拼接符号把数据拼接在一起。pop数据输出DEPTH-counter位置的数据,因为我们位拼接是从高位开始拼接的,要注意读出的地址位置。

always @(posedge clk)begin
      if(!rstn)
        pop_data <= 'd;
      else if(push && pop)begin
        fifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};
        pop_data <= fifo_mem[DEPTH-counter];
      end
      else if(push)begin
        fifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};
      end
      else if(pop)begin
        pop_data <= fifo_mem[DEPTH-counter];
      end
end

代码

module shift_reg_fifo#(
    parameter DEPTH  = 8    ,
    parameter DATA_W = 32
)(
    input                      clk          ,
    input                      rstn         ,
    output                     empty        ,
    output                     full         ,

    input                      push         ,
    input      [DATA_W-1:0]    push_data    ,
    input                      pop          ,
    output reg [DATA_W-1:0]    pop_data    
);
reg [DATA_W-1:0] fifo_mem [DEPTH-1:0];
reg [$clog2(DEPTH)+1:0] counter;

always @(posedge clk)begin
      if(!rstn)
        pop_data <= 'd;
      else if(push && pop)begin
        fifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};
        pop_data <= fifo_mem[DEPTH-counter];
      end
      else if(push)begin
        fifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};
      end
      else if(pop)begin
        pop_data <= fifo_mem[DEPTH-counter];
      end
end

always @(posedge clk)begin
    if(!rstn)
        counter <= 'd0;
    else if(push && pop)
        counter <= counter;
    else if(push)
        counter <= counter + 1'b1;
    else if(pop)
        counter <= counter - 1'b1;
end

assign empty = (counter == 'd0);
assign full  = (counter == DEPTH);

endmodule

testbench

`timescale 1ns/1ps
module tb#(
    parameter DEPTH  = 8    ,
    parameter DATA_W = 32   
)();
reg clk,rstn;
wire empty,full;
wire [DATA_W-1:0] pop_data;

reg push,pop;
reg [DATA_W-1:0] push_data;

initial begin
    forever #5 clk = ~clk;
end

initial begin
    clk  =  1'b0;
    rstn =  1'b0;
    pop  =  1'b0;
    push = 1'b0;
    push_data =  32'd0;
    #10
    rstn =  1'b1;
    #16
    repeat(8)begin
        #10 
        push =  1'b1;
        push_data = $random%32;
    end
    #10
    push = 1'b0;
    repeat(8)begin
        #10
        pop =  1'b1;
    end
    #10
    pop =  1'b0;
    repeat(3)begin
        #10
        pop  = 1'b0;
        push =  1'b1;
        push_data = $random() % 10'd32;
        #10
        push = 1'b0;
        pop  = 1'b1;
    end
    #10
    pop = 1'b0;
    push = 1'b1;
    push_data = $random() % 10'd32;
    repeat(4)begin
        #10
        pop  = 1'b1;
        push = 1'b1;
        push_data = $random() % 10'd32;
    end
    #10
    pop = 1'b0;
    push = 1'b0;
    #50
    $finish();
end

initial begin
    $fsdbDumpfile("shift_fifo.fsdb");
    $fsdbDumpvars(0);
end

shift_reg_fifo #(
    .DEPTH  (DEPTH  ),
    .DATA_W (DATA_W )
)u_shift_reg_fifo(
    .clk        (clk        ),
    .rstn       (rstn       ),
    .empty      (empty      ),
    .full       (full       ),

    .push       (push       ),
    .push_data  (push_data  ),
    .pop        (pop        ),
    .pop_data   (pop_data   )
);

endmodule

        仿真部分,在深度为8的情况下,我们分别模拟了写入8个数据到写满,读出8个数据直到读空,接着连续写读3次,然后写入1个数据(保证下一步同时读写时,FIFO不为空,能读出数据)。再同时读写4次。


波形图

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃葱的酸菜鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值