verilog 实现异步fifo

理论知识参考

异步FIFO_Verilog实现_verilog实现异步fifo_Crazzy_M的博客-CSDN博客

代码

/*
位宽8bit, 位深8
*/
module async_fifo#(
    parameter FIFO_DEPTH = 8,
    parameter FIFO_WIDTH = 8
)
(
    input       rst_n,
    input       wr_clk,
    input       wr_en,
    input [FIFO_WIDTH - 1:0] din,

    input    rd_clk,
    input    rd_en,
    
    output reg [FIFO_WIDTH - 1:0] dout,
    output     wire    full,
    output     wire    empty
);

reg [FIFO_WIDTH - 1:0] mem [FIFO_DEPTH - 1:0];

//地址的位数要满足fifo的位深
wire [2:0] wr_addr;
wire [2:0] rd_addr;

//指针的位数和格雷码的位数要比地址位数大1位
reg [3:0] wr_addr_ptr;
reg [3:0] rd_addr_ptr;

wire [3:0] wr_gray;
reg [3:0] wr_gray1;
reg [3:0] wr_gray2;

wire [3:0] rd_gray;
reg [3:0] rd_gray1;
reg [3:0] rd_gray2;


assign wr_addr = wr_addr_ptr;
assign rd_addr = rd_addr_ptr;

//二进制转格雷码
assign wr_gray = (wr_addr_ptr >> 1) ^ wr_addr_ptr;
assign rd_gray = (rd_addr_ptr >> 1) ^ rd_addr_ptr;

//判断异步FIFO空的条件:读写地址(格雷码)完全相同
assign empty = rd_gray == wr_gray2 ? 1'b1 :1'b0;

//判断异步FIFO满的条件:读写地址(格雷码)的高2位不同,其余位均相同
assign full = ((wr_gray[3:2] != rd_gray2[3:2]) && (wr_gray[1:0] == rd_gray2[1:0])) ? 1'b1 : 1'b0;


//写
always @(posedge wr_clk) begin
    if(wr_en && ~full)
        mem[wr_addr] <= din;
    else 
        mem[wr_addr] <= mem[wr_addr];
end

always @(posedge wr_clk or negedge rst_n) begin
    if(!rst_n)
		wr_addr_ptr <= 0;
	else if(wr_en && ~full)
		wr_addr_ptr <= wr_addr_ptr + 1'b1;
	else 
		wr_addr_ptr <= wr_addr_ptr; 
end

//读
always@ (posedge rd_clk or negedge rst_n)
	if(!rst_n)
		rd_addr_ptr <= 0;
	else if(rd_en && ~empty)
		rd_addr_ptr <= rd_addr_ptr + 1'b1;
	else
		rd_addr_ptr <= rd_addr_ptr;
		
always@ (posedge rd_clk or negedge rst_n)
	if(!rst_n)
		dout <= 11;
	else if(rd_en && ~empty)
		dout <= mem[rd_addr];
	else 
		dout <= 11;


//读地址格雷码同步到写时钟域
always @(posedge wr_clk or negedge rst_n)
	if(!rst_n) begin
		rd_gray1 <= 0;
		rd_gray2 <= 0;
	end
	else begin
		rd_gray1 <= rd_gray;
		rd_gray2 <= rd_gray1;
	end

//写地址格雷码同步到读时钟域
always@ (posedge rd_clk or negedge rst_n)
	if(!rst_n) begin
		wr_gray1 <= 0;
		wr_gray2 <= 0;
	end
	else begin
		wr_gray1 <= wr_gray;
		wr_gray2 <= wr_gray1;
	end

endmodule

 

testbench

`timescale 1ns/1ps

module fifo_tb ();
	reg rst_n;
	reg [7:0] data_in;
	reg wr_clk;
	reg rd_clk;
	reg wr_en;
	reg rd_en;
	wire [7:0]data_out;
	wire full;
	wire empty;

	async_fifo fifo(
	.wr_clk(wr_clk),//写时钟
	.rd_clk(rd_clk),//读时钟
	.rst_n(rst_n),//复位信号
	.wr_en(wr_en),//写使能
	.rd_en(rd_en),//读使能
	.din(data_in),//写入的数据
	.dout(data_out),//读出的数据
	.empty(empty),//读空信号
	.full(full)//写满信号
	);
	
	initial wr_clk = 0;//产生写时钟
	always #10 wr_clk = ~wr_clk;

	initial rd_clk = 0;//产生读时钟
	always #30 rd_clk = ~rd_clk;

	always@(posedge wr_clk or negedge rst_n)//产生写入的数据
		if(!rst_n)
			data_in <= 0;
		else if (wr_en) begin
			data_in <= data_in + 1'b1;
		end
		else
			data_in <= data_in;
    initial begin
        rst_n = 0;
        wr_en = 0;
        rd_en = 0;
        #200;
        rst_n = 1;
        wr_en = 1;
        #200;
        rd_en = 1;
		#200
		wr_en = 0;
		#1100
        rd_en = 0;
        #20000;
        $stop; 
    end
	
		
	
	
endmodule
 

觉得还不错请点赞,有建议请留言^_^

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

eachanm

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

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

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

打赏作者

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

抵扣说明:

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

余额充值