使用fifo 原语进行读写测试,利用modelsim软件进行仿真
a_tb_FifoSim.v文件,文件中例化了colorbar 模块,generate_test_data 模块,fifo_module模块。三个模块的作用为:
- colorbar 模块用来产生图像时序;
- generate_test_data用来根据图像时序生成测试的递增数据;
- fifo_module用来封装一个原语fifo,并将参数接口引出来,方便以后使用;
下面将给出a_tb_FifoSim.v文件、generate_test_data 、fifo_module的verilig程序。colorbar 模块请参考上一篇博客“verilog实现colorbar”。
a_tb_FifoSim.v文件
`timescale 1ps/1ps
module a_tb_FifoSim();
reg clk_50m ;
reg clk_100m ;
reg clk_200m ;
reg clk_400m ;
reg clk_800m ;
reg clk_74p25m ;
reg clk_148p5m ;
reg rst_n ;
initial begin
clk_50m = 0;
clk_100m = 0;
clk_200m = 0;
clk_400m = 0;
clk_800m = 0;
clk_74p25m = 0;
clk_148p5m = 0;
rst_n = 0;
#200000
rst_n = 1;
end
always #10000 clk_50m = ~clk_50m;
always #5000 clk_100m = ~clk_100m;
always #2500 clk_200m = ~clk_200m;
always #1250 clk_400m = ~clk_400m;
always #625 clk_800m = ~clk_800m;
always #6734 clk_74p25m = ~clk_74p25m;
always #3367 clk_148p5m = ~clk_148p5m;
glbl glbl();
wire colorbar_vde ;
wire colorbar_vs ;
wire colorbar_hs ;
wire [ 23:0] colorbar_dat ;
colorbar colorbar (
.pclk (clk_100m ),//时钟
.rst_n (rst_n ),//复位,低电平有效
.frame_size (32'd128072050 ),
.o_vde (colorbar_vde ),//数据使能信号
.o_hs (colorbar_hs ),//行同步信号
.o_vs (colorbar_vs ),//场同步信号
.o_dat (colorbar_dat ) //RGB888颜色数据
);
wire test_vde ;
wire test_vs ;
wire [ 15:0] test_dat ;
generate_test_data generate_test_data(
.pclk (clk_100m ),
.rst_n (rst_n ),
.i_vs (colorbar_vs ),
.i_vde (colorbar_vde ),
.o_vde (test_vde ),
.o_vs (test_vs ),
.o_dat (test_dat )
);
wire rd_en ;
wire fifo_rst ;
wire [16-1:0] dout ;
assign fifo_rst = ~rst_n;
fifo_module#(
.WRITE_DATA_WIDTH (16 ),
.READ_DATA_WIDTH (16 ),
.FIFO_DEPTH (4096 ),
.EMPTY_PROG (1280 - 1 )
)fifo_module_u1(
.fifo_rst (~rst_n ),
.rd_clk (clk_100m ),
.wr_clk (clk_100m ),
.wr_en (test_vde ),
.din (test_dat ),
.o_rd_en (rd_en ),
.o_dout (dout )
);
endmodule
/*-----在modelsim中添加vivoda的仿真库文件-----*/
// vsim -gui work.a_tb_FifoSim -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/secureip -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/simprims_ver -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/unifast -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/unifast_ver -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/unimacro -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/unimacro_ver -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/unisim -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/unisims_ver -L D:/modelsim_dlx64_10.6c/win64pe/vivado_2018.3_sim_lib/xpm
fifo_module.v
该模块例化了一个xpm_fifo_async原语fifo。
module fifo_module#(
parameter WRITE_DATA_WIDTH = 16 ,
parameter READ_DATA_WIDTH = 16 ,
parameter FIFO_DEPTH = 4096 ,
parameter EMPTY_PROG = 1280 - 1
)
(
input fifo_rst ,
input rd_clk ,
input wr_clk ,
input wr_en ,
input [WRITE_DATA_WIDTH-1:0] din ,
output o_rd_en ,
output [READ_DATA_WIDTH-1:0] o_dout
);
wire empty ;
wire full ;
wire prog_empty ;
wire prog_full ;
wire [READ_DATA_WIDTH-1:0] dout ;
reg rd_en ;
reg [ 15:0] read_count ;
xpm_fifo_async #(
.CDC_SYNC_STAGES (2 ),// DECIMAL
.DOUT_RESET_VALUE ("0" ),// String
.ECC_MODE ("no_ecc" ),// String
.FIFO_MEMORY_TYPE ("auto" ),// String
.FIFO_READ_LATENCY (1 ),// DECIMAL
.FIFO_WRITE_DEPTH (FIFO_DEPTH ),// DECIMAL
.FULL_RESET_VALUE (0 ),// DECIMAL
.PROG_EMPTY_THRESH (EMPTY_PROG ),// DECIMAL
.PROG_FULL_THRESH (10 ),// DECIMAL
.RD_DATA_COUNT_WIDTH (1 ),// DECIMAL
.READ_DATA_WIDTH (READ_DATA_WIDTH ),// DECIMAL
.READ_MODE ("fwft" ),// String
.RELATED_CLOCKS (0 ),// DECIMAL
.USE_ADV_FEATURES ("0707" ),// String
.WAKEUP_TIME (0 ),// DECIMAL
.WRITE_DATA_WIDTH (WRITE_DATA_WIDTH ),// DECIMAL
.WR_DATA_COUNT_WIDTH (1 ) // DECIMAL
)xpm_fifo_async_inst (
.almost_empty ( ),// 1-bit output: Almost Empty : When asserted, this signal indicates that only one more read can be performed before the FIFO goes to empty.
.almost_full ( ),// 1-bit output: Almost Full: When asserted, this signal indicates that only one more write can be performed before the FIFO is full.
.data_valid ( ),// 1-bit output: Read Data Valid: When asserted, this signal indicates that valid data is available on the output bus (dout).
.dbiterr ( ),// 1-bit output: Double Bit Error: Indicates that the ECC decoder detected a double-bit error and data in the FIFO core is corrupted.
.dout (dout ),// READ_DATA_WIDTH-bit output: Read Data: The output data bus is driven when reading the FIFO.
.empty (empty ),// 1-bit output: Empty Flag: When asserted, this signal indicates that the FIFO is empty. Read requests are ignored when the FIFO is empty, initiating a read while empty is not destructive to the FIFO.
.full (full ),// 1-bit output: Full Flag: When asserted, this signal indicates that the FIFO is full. Write requests are ignored when the FIFO is full, initiating a write when the FIFO is full is not destructive to the contents of the FIFO.
.overflow ( ),// 1-bit output: Overflow: This signal indicates that a write request (wren) during the prior clock cycle was rejected, because the FIFO is full. Overflowing the FIFO is not destructive to the contents of the FIFO.
.prog_empty (prog_empty ),// 1-bit output: Programmable Empty: This signal is asserted when the number of words in the FIFO is less than or equal to the programmable empty threshold value. It is de-asserted when the number of words in the FIFO exceeds the programmable empty threshold value.
.prog_full (prog_full ),// 1-bit output: Programmable Full: This signal is asserted when the number of words in the FIFO is greater than or equal to the programmable full threshold value. It is de-asserted when the number of words in the FIFO is less than the programmable full threshold value.
.rd_data_count ( ),// RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates the number of words read from the FIFO.
.rd_rst_busy ( ),// 1-bit output: Read Reset Busy: Active-High indicator that the FIFO read domain is currently in a reset state. 1-bit output: Single Bit Error: Indicates that the ECC decoder detected and fixed a single-bit error.
.underflow ( ),// 1-bit output: Underflow: Indicates that the read request (rd_en) during the previous clock cycle was rejected because the FIFO is empty. Under flowing the FIFO is not destructive to the FIFO.
.wr_ack ( ),// 1-bit output: Write Acknowledge: This signal indicates that a write request (wr_en) during the prior clock cycle is succeeded.
.wr_data_count ( ),// WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates the number of words written into the FIFO.
.wr_rst_busy ( ),// 1-bit output: Write Reset Busy: Active-High indicator that the FIFO write domain is currently in a reset state.
.din (din ),// WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when writing the FIFO.
.injectdbiterr ( ),// 1-bit input: Double Bit Error Injection: Injects a double bit error if the ECC feature is used on block RAMs or UltraRAM macros.
.injectsbiterr ( ),// 1-bit input: Single Bit Error Injection: Injects a single bit error if the ECC feature is used on block RAMs or UltraRAM macros.
.rd_clk (rd_clk ),// 1-bit input: Read clock: Used for read operation. rd_clk must be a free running clock.
.rd_en (rd_en ),// 1-bit input: Read Enable: If the FIFO is not empty, asserting this signal causes data (on dout) to be read from the FIFO. Must be held active-low when rd_rst_busy is active high.
.rst (fifo_rst ),// 1-bit input: Reset: Must be synchronous to wr_clk. The clock(s) can be unstable at the time of applying reset, but reset must be released only after the clock(s) is/are stable.
.sleep (1'b0 ),// 1-bit input: Dynamic power saving: If sleep is High, the memory/fifo block is in power saving mode.
.wr_clk (wr_clk ),// 1-bit input: Write clock: Used for write operation. wr_clk must be a free running clock.
.wr_en (wr_en ) // 1-bit input: Write Enable: If the FIFO is not full, asserting this signal causes data (on din) to be written to the FIFO. Must be held active-low when rst or wr_rst_busy is active high.
);
always @(posedge rd_clk) begin
if(fifo_rst)
rd_en <= 1'b0;
else if(read_count == EMPTY_PROG)
rd_en <= 1'b0;
else if(~prog_empty)
rd_en <= 1'b1;
else
rd_en <= rd_en;
end
always @(posedge rd_clk) begin
if(fifo_rst)
read_count <= 'd0;
else if(rd_en)
read_count <= read_count + 1'b1;
else
read_count <= 'd0;
end
assign o_rd_en = rd_en;
assign o_dout = dout;
endmodule
generate_test_data .v
产生测试的递增数,通过递增数可以很容易判断fifo读写是否正确。
module generate_test_data(
input pclk ,
input rst_n ,
input i_vs ,
input i_vde ,
output o_vde ,
output o_vs ,
output [ 15:0] o_dat
);
reg i_vde_dly ;
reg i_vs_dly ;
always @(posedge pclk) begin
i_vde_dly <= i_vde;
i_vs_dly <= i_vs;
end
reg [15:0] test_dat;
always @(posedge pclk or negedge rst_n) begin
if(~rst_n)
test_dat <= 'd0;
else if(i_vde)
test_dat <= test_dat + 1'b1;
else
test_dat <= 'd0;
end
assign o_vde = i_vde_dly;
assign o_vs = i_vs_dly;
assign o_dat = test_dat;
endmodule
modelsim仿真结果
图1:数据写入到fifo,数据由1、2、3、…递增,然后写入到fifo中
图2:递增数据依次从fifo中读出