异步fifo设计及验证进阶(System Verilog)

目录

一、异步fifo设计文件

二、接口(interface)文件

三、Transaction文件

四、激励发生器(Stimulator)文件

五、测试平台顶层(top)文件

六、仿真结果


一、异步fifo设计文件

//async_fifo.v

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

reg signed [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

二、接口(interface)文件

//fifo_if.sv

`timescale 1ns/1ns

interface fifo_if #(
    parameter DATA_WIDTH = 8,
    parameter DATA_DEPTH = 8
)
(
    input bit wr_clk,
    input bit rd_clk,
    input bit wr_rst_n,
    input bit rd_rst_n
);

logic wr_en, rd_en;
logic empty, full;
logic signed [DATA_WIDTH - 1:0] data_in;
logic signed [DATA_WIDTH - 1:0] data_out;

/*时钟块,用于激励文件*/
//写时钟下降沿
clocking cb_wr_n @ (posedge wr_clk);
    output wr_en, data_in;
endclocking

//写时钟上升沿
clocking cb_wr_p @ (posedge wr_clk);
    input full;
endclocking

//读时钟下降沿
clocking cb_rd_n @ (negedge rd_clk);
    output rd_en;
endclocking

//读时钟上升沿
clocking cb_rd_p @ (posedge rd_clk);
    input data_out, empty;
endclocking

/*modport*/
modport STIMULATOR (clocking cb_wr_n, cb_wr_p, cb_rd_n, cb_rd_p);


endinterface

三、Transaction文件

//Transaction.sv

class Transaction # (parameter DATA_WIDTH = 8);
	rand bit signed [DATA_WIDTH - 1:0] number;
	rand bit wr_en_rand;
	rand bit rd_en_rand;
	constraint c {number <= 2 ** (DATA_WIDTH - 1) - 1;
				  number >= - ( 2 ** (DATA_WIDTH - 1));
				  }
endclass

四、激励发生器(Stimulator)文件

//testbench.sv

`timescale 1ns/1ns

program automatic stimulator #(
	parameter DATA_WIDTH = 8,
	parameter DATA_DEPTH = 8
)
(
    fifo_if.STIMULATOR fifoif
);
 
Transaction #
(
    .DATA_WIDTH(DATA_WIDTH)
) tr;

initial begin
	tr = new();
end

initial forever @fifoif.cb_wr begin
	    assert(numb0.randomize());
		fifoif.cb_wr_n.data_in <= tr.number;
		fifoif.cb_wr_n.wr_en <= tr.wr_en_rand;
end


initial forever @fifoif.cb_rd begin
		assert(numb1.randomize());
		fifoif.cb_rd_n.rd_en <= tr.rd_en_rand;
end

initial begin
    #10000;
    $finish;
end

initial begin
    $monitor("@%0t: data_out = %0d; full = %0d; empty = %0d;", $time, fifoif.cb_rd_p.data_out, fifoif.cb_wr_p.full, fifoif.cb_rd_p.empty);
end

endprogram
		
			

五、测试平台顶层(top)文件

//top.sv

module top;

parameter DATA_WIDTH = 8;
parameter DATA_DEPTH = 8;

bit wr_clk, rd_clk;
bit wr_rst_n, rd_rst_n;

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

initial begin
	wr_rst_n = 1;
	rd_rst_n = 1;
	#3
	wr_rst_n = 0;
	rd_rst_n = 0;
	#20
	wr_rst_n = 1;
	rd_rst_n = 1;
end

//interface
fifo_if #(
    .DATA_WIDTH(DATA_WIDTH),
	.DATA_DEPTH(DATA_DEPTH)
)
fifoif (
    .wr_clk(wr_clk),
    .rd_clk(rd_clk),
    .wr_rst_n (wr_rst_n ),
    .rd_rst_n (rd_rst_n )
);


//DUT
async_fifo #(
    .DATA_WIDTH(DATA_WIDTH),
    .DATA_DEPTH(DATA_DEPTH)
)
fifo_u (
    .wr_clk(fifoif.wr_clk),
    .rd_clk(fifoif.rd_clk),
    .wr_rst_n (fifoif.wr_rst_n ),
    .rd_rst_n (fifoif.rd_rst_n ),
    .wr_en(fifoif.wr_en),
    .rd_en(fifoif.rd_en),    
    .data_in(fifoif.data_in),
    .data_out(fifoif.data_out),
    .full(fifoif.full),
    .empty(fifoif.empty)
);


//stimulator
stimulator #(
    .DATA_WIDTH(DATA_WIDTH),
	.DATA_DEPTH(DATA_DEPTH)
)
stimulator_u (
    fifoif
);


endmodule

六、仿真结果

工具:Cadence的EDA工具INCISIVE15.2。使用方法可参考:Cadence公司的数字IC设计工具:仿真 + 查看波形_qq_42922513的博客-CSDN博客

                                         PS:觉得有用就点个赞收藏吧

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值