【原创】基于FPGA的异步FIFO验证
1赞
发表于 1/16/2016 8:27:25 PM
阅读(8021)
现在开始对上一篇博文介绍的异步FIFO进行功能验证,上一篇博文地址:http://blog.chinaaet.com/crazybird/p/5100000872 。对异步FIFO验证的平台如图1所示。
图1 异步FIFO验证平台
其中,clock为时钟生成器,asyn_fifo_if为产生异步FIFO读写命令的模块,asyn_fifo为异步FIFO设计模块。
验证顶层模块testbench的代码如下所示:
/*******************************版权申明******************************** ** 电子技术应用网站, CrazyBird ** http://www.chinaaet.com, http://blog.chinaaet.com/crazybird ** **------------------------------文件信息-------------------------------- ** 文件名: clock.v ** 创建者: CrazyBird ** 创建日期: 2016-1-16 ** 版本号: v1.0 ** 功能描述: 时钟生成器 ** ***********************************************************************/ // synopsys translate_off `timescale 1 ns / 1 ps // synopsys translate_on module testbench; //****************************************************************** // 变量定义 //****************************************************************** wire wr_rst_n; wire wr_clk; wire wr_en; wire [7:0] wr_data; wire wr_full; wire [4:0] wr_cnt; wire rd_rst_n; wire rd_clk; wire rd_en; wire [7:0] rd_data; wire rd_empty; wire [4:0] rd_cnt; //****************************************************************** // 时钟生成器例化 //****************************************************************** clock #( .C_CLK_FREQ(100.0) ) u_clock_wr ( .clk ( wr_clk ) ); clock #( .C_CLK_FREQ(70.0) ) u_clock_rd ( .clk ( rd_clk ) ); //****************************************************************** // 异步FIFO读写指令产生模块例化 //****************************************************************** asyn_fifo_if #( .C_DATA_WIDTH(8) ) u_asyn_fifo_if ( .wr_rst_n ( wr_rst_n ), .wr_clk ( wr_clk ), .wr_en ( wr_en ), .wr_data ( wr_data ), .wr_full ( wr_full ), .rd_rst_n ( rd_rst_n ), .rd_clk ( rd_clk ), .rd_en ( rd_en ), .rd_empty ( rd_empty ) ); //****************************************************************** // 异步FIFO模块例化 //****************************************************************** asyn_fifo #( .C_DATA_WIDTH(8), .C_FIFO_DEPTH_WIDTH (4) ) u_asyn_fifo ( .wr_rst_n ( wr_rst_n ), .wr_clk ( wr_clk ), .wr_en ( wr_en ), .wr_data ( wr_data ), .wr_full ( wr_full ), .wr_cnt ( wr_cnt ), .rd_rst_n ( rd_rst_n ), .rd_clk ( rd_clk ), .rd_en ( rd_en ), .rd_data ( rd_data ), .rd_empty ( rd_empty ), .rd_cnt ( rd_cnt ) ); endmodule
时钟模块clock的代码实现如下所示(时钟的频率可设置):
/*******************************版权申明******************************** ** 电子技术应用网站, CrazyBird ** http://www.chinaaet.com, http://blog.chinaaet.com/crazybird ** **------------------------------文件信息-------------------------------- ** 文件名: clock.v ** 创建者: CrazyBird ** 创建日期: 2016-1-16 ** 版本号: v1.0 ** 功能描述: 时钟生成器 ** ***********************************************************************/ // synopsys translate_off `timescale 1 ns / 1 ps // synopsys translate_on module clock( clk ); //****************************************************************** // 参数定义 //****************************************************************** parameter C_CLK_FREQ = 100.0; //MHz localparam C_CLK_CYCLE = 1000.0 / C_CLK_FREQ; //****************************************************************** // 端口定义 //****************************************************************** output reg clk; //****************************************************************** // 时钟生成 //****************************************************************** initial begin clk = 0; forever #(C_CLK_CYCLE/2) clk = ~clk; end endmodule
本次测试的步骤如下所示:
(1)只写异步FIFO
(2)只读异步FIFO
(3)同时读写异步FIFO
测试步骤的代码在asyn_fifo_if模块中,如下所示:
/*******************************版权申明******************************** ** 电子技术应用网站, CrazyBird ** http://www.chinaaet.com, http://blog.chinaaet.com/crazybird ** **------------------------------文件信息-------------------------------- ** 文件名: asyn_fifo_if.v ** 创建者: CrazyBird ** 创建日期: 2016-1-16 ** 版本号: v1.0 ** 功能描述: 产生异步FIFO的读写命令 ** ***********************************************************************/ // synopsys translate_off `timescale 1 ns / 1 ps // synopsys translate_on module asyn_fifo_if( wr_rst_n, wr_clk, wr_en, wr_data, wr_full, rd_rst_n, rd_clk, rd_en, rd_empty ); //****************************************************************** // 参数定义 //****************************************************************** parameter C_DATA_WIDTH = 8; //****************************************************************** // 端口定义 //****************************************************************** output reg wr_rst_n; input wr_clk; output reg wr_en; output reg [C_DATA_WIDTH-1:0] wr_data; input wr_full; output reg rd_rst_n; input rd_clk; output reg rd_en; input rd_empty; //****************************************************************** // 内部变量定义 //****************************************************************** reg normal_wr; reg normal_rd; //****************************************************************** // 变量初始化 //****************************************************************** initial begin wr_rst_n = 1'b0; rd_rst_n = 1'b0; normal_wr = 1'b0; normal_rd = 1'b0; #492; wr_rst_n = 1'b1; rd_rst_n = 1'b1; #100; //只写FIFO normal_wr = 1'b1; repeat(20) @(negedge wr_clk); normal_wr = 1'b0; //只读FIFO normal_rd = 1'b1; repeat(20) @(negedge rd_clk); normal_rd = 1'b0; //同时读写FIFO normal_wr = 1'b1; normal_rd = 1'b1; repeat(100) @(negedge wr_clk); normal_wr = 1'b0; normal_rd = 1'b0; repeat(20) @(negedge rd_clk); $stop; end //****************************************************************** // 写FIFO信号的产生 //****************************************************************** always @(negedge wr_clk or negedge wr_rst_n) begin if(wr_rst_n == 1'b0) begin wr_en <= 1'b0; wr_data <= {(C_DATA_WIDTH){1'b0}}; end else if(normal_wr == 1'b1) begin if(wr_full == 1'b0) begin wr_en <= 1'b1; wr_data <= {$random%((1 << C_DATA_WIDTH)-1)}; end else begin wr_en <= 1'b0; wr_data <= {(C_DATA_WIDTH){1'b0}}; end end else begin wr_en <= 1'b0; wr_data <= {(C_DATA_WIDTH){1'b0}}; end end //****************************************************************** // 读FIFO信号的产生 //****************************************************************** always @(negedge wr_clk or negedge wr_rst_n) begin if(wr_rst_n == 1'b0) rd_en <= 1'b0; else if(normal_rd == 1'b1) begin if(rd_empty == 1'b0) rd_en <= 1'b1; else rd_en <= 1'b0; end else rd_en <= 1'b0; end endmodule
modelsim仿真结果如图2~4所示(具体情况可自行分析)。
图2 只写异步FIFO
图3 只读异步FIFO
图4 同时读写异步FIFO
至此,异步FIFO的设计和验证都完成了。现在预告下一篇博文:参数化的优先级编码器设计。哈哈,不要以为很简单哦。记住,是“参数化”,即输入信号的位宽可设置。大家也可以先想想如何实现。也许,灵感一来很快就想出来了,否则,半个小时、1个小时、甚至很多。