异步fifo设计及验证(Verilog)

目录

一、设计代码

二、testbench代码

三、仿真结果


一、设计代码

//async_fifo.v

`timescale 1ns/1ns
module async_fifo #(
    parameter DATA_WIDTH = 8,
    parameter DATA_DEPTH = 8
)
(
    input wr_clk,
    input wr_rst_n,
    input wr_en,
	input signed [DATA_WIDTH - 1:0] data_in,
	input rd_clk,
	input rd_rst_n,
	input rd_en,
	output reg signed [DATA_WIDTH - 1:0] data_out,
	output empty,
	output full
);

reg [DATA_WIDTH - 1:0] fifo_buffer [DATA_DEPTH - 1:0];
reg [$clog2(DATA_DEPTH):0] wr_ptr, rd_ptr;
reg [$clog2(DATA_DEPTH):0] wr_ptr_g_d1, rd_ptr_g_d1;
reg [$clog2(DATA_DEPTH):0] wr_ptr_g_d2, rd_ptr_g_d2;

wire [$clog2(DATA_DEPTH):0] wr_ptr_g, rd_ptr_g;
wire [$clog2(DATA_DEPTH) - 1:0] wr_ptr_true, rd_ptr_true;

assign wr_ptr_g = wr_ptr ^ (wr_ptr >> 1);
assign rd_ptr_g = rd_ptr ^ (rd_ptr >> 1);

assign wr_ptr_true = wr_ptr[$clog2(DATA_DEPTH) - 1:0];
assign rd_ptr_true = rd_ptr[$clog2(DATA_DEPTH) - 1:0];

//写fifo
always @ (posedge wr_clk or negedge wr_rst_n) begin
	if (!wr_rst_n)
		wr_ptr <= 0;
	else if (!full && wr_en) begin
		wr_ptr <= wr_ptr + 1;
		fifo_buffer[wr_ptr_true] <= data_in;
	end
end

//将读指针同步到写时钟域
always @ (posedge wr_clk or negedge wr_rst_n) begin
	if (!wr_rst_n) begin
		rd_ptr_g_d1 <= 0;
		rd_ptr_g_d2 <= 0;
	end
	else begin	
		rd_ptr_g_d1 <= rd_ptr_g;
		rd_ptr_g_d2 <= rd_ptr_g_d1;
	end
end

//读fifo
always @ (posedge rd_clk or negedge rd_rst_n) begin
	if (!rd_rst_n) begin
		rd_ptr <= 0;
		data_out <= 0;
	end
	else if (!empty && rd_en) begin
		rd_ptr <= rd_ptr + 1;
		data_out <= fifo_buffer[rd_ptr_true];
	end
end

//将写指针同步到读时钟域
always @ (posedge rd_clk or negedge rd_rst_n) begin
	if (!rd_rst_n) begin
		wr_ptr_g_d1 <= 0;
		wr_ptr_g_d2 <= 0;
	end
	else begin	
		wr_ptr_g_d1 <= wr_ptr_g;
		wr_ptr_g_d2 <= wr_ptr_g_d1;
	end
end

//判断读空和写满
assign empty = (wr_ptr_g_d2 == rd_ptr_g) ? 1 : 0;
assign full = (wr_ptr_g == {~(rd_ptr_g_d2[$clog2(DATA_DEPTH) : $clog2(DATA_DEPTH) - 1]),
							rd_ptr_g_d2[$clog2(DATA_DEPTH) - 2 : 0]}) ? 1 : 0;

endmodule

二、testbench代码

使用System Verilog实现testbench,以进行随机验证。SV相关基础可参考:System Verilog基础_qq_42922513的博客-CSDN博客https://blog.csdn.net/qq_42922513/article/details/130984574

//async_fifo_tb.sv

`timescale 1ns/1ns

module async_fifo_tb;
parameter DATA_WIDTH = 8;
parameter DATA_DEPTH = 8;

bit wr_clk;
bit wr_rst_n;
bit wr_en;
bit signed [DATA_WIDTH - 1:0] data_in;

bit rd_clk;
bit rd_rst_n;
bit rd_en;
bit signed [DATA_WIDTH - 1:0] data_out;

bit empty;
bit full;

int error_num;

async_fifo #(
	.DATA_WIDTH(DATA_WIDTH),
	.DATA_DEPTH(DATA_DEPTH)
)
u1(
	.wr_clk(wr_clk),
	.wr_rst_n(wr_rst_n),
	.wr_en(wr_en),
	.data_in(data_in),
    .rd_clk(rd_clk),
	.rd_rst_n(rd_rst_n),
	.rd_en(rd_en),
	.data_out(data_out),
	.empty(empty),
	.full(full)
);

bit signed [DATA_WIDTH - 1:0] fifo_reg [DATA_DEPTH - 1:0];
bit [$clog2(DATA_DEPTH) - 1:0] m, n;
bit signed [DATA_WIDTH - 1:0] data_out_tb;

class packet0;
	rand bit signed [DATA_WIDTH - 1:0] number;
	rand bit wr_en_rand;
	constraint c {number <= 2 ** (DATA_WIDTH - 1) - 1;
				  number >= - ( 2 ** (DATA_WIDTH - 1));
				  wr_en_rand inside {[0:1]};
				  }
endclass

class packet1;
	rand bit rd_en_rand;
	constraint c {rd_en_rand inside {[0:1]};}
endclass

packet0 numb0;
packet1 numb1;

always #15 wr_clk = ~wr_clk;
always #10 rd_clk = ~rd_clk;

initial begin
	numb0 = new();
	numb1 = new();
	rd_clk = 0;
	wr_clk = 0;
	wr_rst_n = 1;
	rd_rst_n = 1;
	m = 0;
	n = 0;
	#3
	wr_rst_n = 0;
	rd_rst_n = 0;
	#20
	wr_rst_n = 1;
	rd_rst_n = 1;
end

initial begin
	repeat (1000) begin
		@(negedge wr_clk) begin
			assert(numb0.randomize());
			data_in <= numb0.number;
			wr_en <= numb0.wr_en_rand;
		end
		@(posedge wr_clk) begin
			if (wr_en && !full) begin
				fifo_reg[m] = data_in;
				m = m + 1;
			end
		end
	end
	#200;
	$display("-------error_num = %0d -------", error_num);
	$stop;
end

initial begin
	repeat (1000) begin
		@(negedge rd_clk) begin
			assert(numb1.randomize());
			rd_en <= numb1.rd_en_rand;
		end
		@(posedge rd_clk) begin
			if (rd_en && !empty) begin
				data_out_tb <= fifo_reg[n];
				if (data_out_tb != data_out) begin
					$display("-------ERROR. A mismatch has occurred -------");
					$display("data_out_tb = %0d; data_out = %0d;", data_out_tb, data_out);
					error_num = error_num + 1;
				end
				n = n + 1;
			end
		end
	end
end


endmodule
		
			

三、仿真结果

工具:Vivado2018.3

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值