> 文章列表 > 用移位寄存器实现同步FIFO,带空满判断

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

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

用移位寄存器实现同步FIFO

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


 解题思路

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

always @(posedge clk)beginif(!rstn)counter <= 'd0;else if(push && pop)counter <= counter;else if(push)counter <= counter + 1'b1;else if(pop)counter <= counter - 1'b1;
endassign empty = (counter == 'd0);
assign full  = (counter == DEPTH);

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

always @(posedge clk)beginif(!rstn)pop_data <= 'd;else if(push && pop)beginfifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};pop_data <= fifo_mem[DEPTH-counter];endelse if(push)beginfifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};endelse if(pop)beginpop_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)beginif(!rstn)pop_data <= 'd;else if(push && pop)beginfifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};pop_data <= fifo_mem[DEPTH-counter];endelse if(push)beginfifo_mem <= {push_data,fifo_mem[DEPTH-1:1]};endelse if(pop)beginpop_data <= fifo_mem[DEPTH-counter];end
endalways @(posedge clk)beginif(!rstn)counter <= 'd0;else if(push && pop)counter <= counter;else if(push)counter <= counter + 1'b1;else if(pop)counter <= counter - 1'b1;
endassign 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 beginforever #5 clk = ~clk;
endinitial beginclk  =  1'b0;rstn =  1'b0;pop  =  1'b0;push = 1'b0;push_data =  32'd0;#10rstn =  1'b1;#16repeat(8)begin#10 push =  1'b1;push_data = $random%32;end#10push = 1'b0;repeat(8)begin#10pop =  1'b1;end#10pop =  1'b0;repeat(3)begin#10pop  = 1'b0;push =  1'b1;push_data = $random() % 10'd32;#10push = 1'b0;pop  = 1'b1;end#10pop = 1'b0;push = 1'b1;push_data = $random() % 10'd32;repeat(4)begin#10pop  = 1'b1;push = 1'b1;push_data = $random() % 10'd32;end#10pop = 1'b0;push = 1'b0;#50$finish();
endinitial begin$fsdbDumpfile("shift_fifo.fsdb");$fsdbDumpvars(0);
endshift_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次。


波形图