博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

FIFO IP核仿真

Posted on 2017-10-26 18:48  沉默改良者  阅读(1281)  评论(0编辑  收藏  举报

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多个数据可以读。

结论:仿真结果与预期相符。