同步fifo设计

目录

1 双端口RAM设计

1.1 FIFO中的数据存储

1.2 双端口RAM的verilog实现

2 同步FIFO设计

2.1 FIFO空满信号的产生

2.2 同步FIFO的verilog实现


1 双端口RAM设计

1.1 FIFO中的数据存储

大量数据的存放不是使用reg,而是使用mem去存储。

fifo使用双端口RAM存储数据:即输入端口和输出端口是独立的。

1.2 双端口RAM的verilog实现

下面为双端口RAM的verilog实现:

module dual_port_ram#(
    parameter DEPTH = 16,
    parameter WIDTH = 8
)(
    input                               wclk    ,
    input                               wenc    ,
    input           [$clog2(DEPTH)-1:0] waddr   ,
    input           [WIDTH-1:0]         wdata   ,

    input                               rclk    ,
    input                               renc    ,
    input           [$clog2(DEPTH)-1:0] raddr   ,
    output  reg     [WIDTH-1:0]         rdata   
);

reg [WIDTH-1:0] ram_mem [0:DEPTH-1];

always_ff@(posedge wclk)begin
    if(wenc)
        ram_mem[waddr] <= wdata;
end

always_ff@(posedge rclk)begin
    if(renc)
        rdata <= ram_mem[raddr];
end


endmodule

下面为双端口RAM的testbench:(是使用vcs进行仿真的,如果使用vivado或者其他工具仿真的话,稍微修改下就好~)

`timescale 1ns/1ps

module tb_dual_port_ram();

parameter DEPTH = 16;
parameter WIDTH = 8;


reg                               wclk    ;
reg                               wenc    ;
reg           [$clog2(DEPTH)-1:0] waddr   ;
reg           [WIDTH-1:0]         wdata   ;
reg                               rclk    ;
reg                               renc    ;
reg           [$clog2(DEPTH)-1:0]  raddr   ;
wire     [WIDTH-1:0]                rdata;  


initial begin
    wclk = 0;
    forever #10 wclk = ~wclk;
end

initial begin
    rclk = 0;
    forever #10 rclk = ~rclk;
end

initial begin
    wenc = 0;
    waddr = 0;
    wdata = 0;
    renc = 0;
    raddr = 0;


    #40;
    wenc = 1;

    
    repeat(16)begin
        waddr = waddr + 1;
        wdata = wdata + 1;
        #20;
    end


    #40;
    renc = 1;
    repeat(16)begin
        raddr = raddr + 1;
        #20;
    end
end


dual_port_ram#(
    .DEPTH(DEPTH),
    .WIDTH(WIDTH)
)u_dual_port_ram(
    .wclk    (wclk    ),
    .wenc    (wenc    ),
    .waddr   (waddr   ),
    .wdata   (wdata   ),
    .rclk    (rclk    ),
    .renc    (renc    ),
    .raddr   (raddr   ),
    .rdata   (rdata   )
);



initial begin
    $fsdbDumpfile("tb_dual_port_ram.fsdb");
    $fsdbDumpvars(0);
    $fsdbDumpMDA(0,tb_dual_port_ram);

    #1000;
    $finish;
end


endmodule


2 同步FIFO设计

2.1 FIFO空满信号的产生

FIFO的原则:empty不能读,full不能写

FIFO设计的关键就是设计emptyfull信号

空满信号的产生通常用两种方法:

方法一:直接比较读写指针,(读写指针追赶的一个过程)

指针表示将要读取数据的地址

写指针表示将要写入数据的地址

操作使得读写指针相等

信号的产生:fifo_full=(read_ptr == write_ptr+1) && write

操作使得读写指针相等

信号的产生:fifo_empty=(write_ptr == read_ptr +1) && read

方法二:使用counter计数器来进行比较

写操作时,counter+1

读操作时,counter-1

读写同时进行的时候,counter不变

比较counterram的深度来产生空满信号

本次设计使用方法二实现

2.2 同步FIFO的verilog实现

 

下面为同步FIFO的verilog代码: 

module sync_fifo#(
    parameter   DEPTH  =   16,
    parameter   WIDTH   =   8
    )(
    input               clk     ,
    input               rst_n   ,

    input               winc    ,
    input   [WIDTH-1:0] wdata   ,

    input               rinc    ,
    input   [WIDTH-1:0] rdata   ,

    output              wfull   ,
    output              rempty              
);

reg [$clog2(DEPTH)-1:0]    write_ptr;
reg [$clog2(DEPTH)-1:0]    read_ptr;
wire wen_vld;
wire ren_vld;

reg [$clog2(DEPTH):0]      data_count;

//generate write pointer
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        write_ptr <= 0;    
    end
    else if(winc && !wfull)begin
        write_ptr <= write_ptr + 1;
    end
end 

//generate read pointer
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        read_ptr <= 0;
    else if(rinc && !rempty)begin
        read_ptr <= read_ptr + 1;
    end
end

//generate data counter
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        data_count <= 0;
    else if(winc && !wfull && !rinc)
        data_count <= data_count + 1;
    else if(rinc && !rempty && !winc)
        data_count <= data_count - 1;
end

//generate full && empty
assign wfull = (data_count == DEPTH) ? 1 : 0;
assign rempty = (data_count == 0) ? 1 : 0;



assign wen_vld = winc && (!wfull);
assign ren_vld = rinc && (!rempty);

dual_port_ram#(
    .DEPTH(DEPTH),
    .WIDTH(WIDTH)
)u_dual_port_ram(
    .wclk    (clk           ),
    .wenc    (wen_vld       ),
    .waddr   (write_ptr     ),
    .wdata   (wdata         ),
    .rclk    (clk           ),
    .renc    (ren_vld       ),
    .raddr   (read_ptr      ),
    .rdata   (rdata         )
);

endmodule

 下面为同步FIFO的testbench:(是使用vcs进行仿真的,如果使用vivado或者其他工具仿真的话,稍微修改下就好~)

`timescale 1ns/1ps

module tb_sync_fifo();

parameter DEPTH = 16;
parameter WIDTH = 8;

reg               clk     ;
reg               rst_n   ;
reg               winc    ;
reg   [WIDTH-1:0] wdata   ;
reg               rinc    ;
wire   [WIDTH-1:0]rdata   ;
wire              wfull   ;
wire              rempty  ;

initial begin
    clk = 0;
    forever #10 clk = ~clk;
end
initial begin
    rst_n = 0;
    #1000;
	rst_n = 1;
end

initial begin

		winc = 0;
        rinc = 0;
		#1000;

		#200;
		winc = 1;
		#4000;
		winc = 0;
	

		#2000;
		winc = 1;
		#4000;
		winc = 0;	
		
		#4000;
        $finish;
	end
	
always @(posedge clk or negedge rst_n)
if(!rst_n)
	wdata <= 16'd0;
else if(winc && ~wfull)
	wdata <= $random%256;

always @(posedge clk or negedge rst_n)
if(!rst_n)
	rinc <= 1'b0;
else if(~rempty)
	rinc <= 1'b1;
else 
	rinc <= 1'b0;


sync_fifo#(
    .DEPTH(DEPTH),
    .WIDTH(WIDTH)
    )u_sync_fifo(
    .clk     (clk     ),
    .rst_n   (rst_n   ),
    .winc    (winc    ),
    .wdata   (wdata   ),
    .rinc    (rinc    ),
    .rdata   (rdata   ),
    .wfull   (wfull   ),
    .rempty  (rempty  )            
);


initial begin
    $fsdbDumpfile("tb_sync_fifo.fsdb");
    $fsdbDumpvars(0);
    $fsdbDumpMDA(0,tb_sync_fifo);

    #100000;
    $finish;
end


endmodule

参考博客:

同步fifo设计_IamSarah的博客-CSDN博客_同步fifo设计

两种同步FIFO的设计方法(计数器、扩展位)_SD.ZHAI的博客-CSDN博客_同步fifo设计

GitHub - DeamonYang/FPGA_SYNC_ASYNC_FIFO: FPGA 同步FIFO与异步FIFO

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值