FIFO IP核仿真
1.FIFO IP核配置
2.FIFO测试逻辑代码
首先往FIFO里面写入512个数据(FIFO深度的一半),然后再开始同时往FIFO里面写入,读出数据。FIFO读和写的时钟域不同,对于不同时钟域的信号应该进行区分,状态机也应该分开来写。
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: chensimin // // Create Date: 2017/10/23 16:11:32 // Design Name: // Module Name: top // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module top( rst, wr_clk, rd_clk, dout, full, empty, rd_data_count, wr_data_count ); //input input rst; input wr_clk; input rd_clk; //output output [7:0]dout; output full; output empty; output [9:0]rd_data_count; output [9:0]wr_data_count; //write state reg [2:0]i; reg read_start; reg [7:0]din_r; reg clear_fifo_full; reg wr_en_r; wire wr_en; wire [7:0]din; wire [9:0]wr_data_count; wire full; always@(posedge wr_clk) begin if(rst) begin wr_en_r <= 1'b0; i <= 3'd0; read_start <= 1'b0; clear_fifo_full <= 1'b0; din_r <= 8'd0; end else begin case(i) 0: begin if(!full) begin wr_en_r <= 1'b1; i<=i+1'b1; end else wr_en_r <= 1'b0; end 1: begin if(wr_data_count ==10'd512) begin read_start <=1'b1; din_r <= din_r +1'b1; i<=i+1'b1; end else din_r <= din_r +1'b1; end 2: begin if(full) begin clear_fifo_full <= 1'b1; wr_en_r <= 1'b0; i<=3'd0; end else din_r <= din_r +1'b1; end endcase end end assign wr_en = wr_en_r; assign din = din_r; //read state reg rd_en_r; reg [2:0]j; reg clear_fifo_empty; wire rd_en; always@(posedge rd_clk) begin if(rst) begin rd_en_r <= 1'b0; j <= 3'd0; clear_fifo_empty <= 1'b0; end else begin case(j) 0: begin if(read_start & !empty) begin rd_en_r <= 1'b1; j<=j+1'b1; end else rd_en_r <= 1'b0; end 1: begin if(empty) begin clear_fifo_empty <= 1'b1; rd_en_r <= 1'b0; j<=3'd0; end else rd_en_r <= 1'b1; end endcase end end assign rd_en = rd_en_r; fifo_generator_0 U1 ( .rst(rst), // input wire rst .wr_clk(wr_clk), // input wire wr_clk .rd_clk(rd_clk), // input wire rd_clk .din(din), // input wire [7 : 0] din .wr_en(wr_en), // input wire wr_en .rd_en(rd_en), // input wire rd_en .dout(dout), // output wire [7 : 0] dout .full(full), // output wire full .empty(empty), // output wire empty .rd_data_count(rd_data_count), // output wire [9 : 0] rd_data_count .wr_data_count(wr_data_count) // output wire [9 : 0] wr_data_count ); endmodule
3.测试脚本
add_force {/top/rst} -radix hex {1 0ns} {0 150000ps} add_force {/top/wr_clk} -radix hex {0 0ns} {1 50000ps} -repeat_every 100000ps add_force {/top/rd_clk} -radix hex {0 0ns} {1 49500ps} -repeat_every 99000ps
4.仿真波形分析
仿真波形图
对FIFO进行复位操作,开始full,empty都会拉高一段时间,然后才会恢复正常。
与写状态有关的信号分析
当full恢复正常后,写使能,同时状态机跳转。
当写入512个数据后(wr_data_count == 512),read_start信号开始拉高,FIFO开始读出数据,同时状态机也在此刻跳转,下一个状态再写数据的同时,也在监测FIFO是否已经被写满。
下面来看FIFO读数据端的仿真波形
当read_start信号拉高时,re_en信号开始拉高,FIFO才开始从dout端口读出数据,可以看到,刚开读出的数据为FIFO din端口最先写入的数据。从rd_data_count端口可以看到,此时FIFO里面已经有500多个数据可以读。
结论:仿真结果与预期相符。