⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tb.v

📁 nand flash 仿真模型,支持ONFI 2.0
💻 V
📖 第 1 页 / 共 4 页
字号:
////////////////////////////////////////////////
//[Disclaimer]    
//This software code and all associated documentation, comments
//or other information (collectively "Software") is provided 
//"AS IS" without warranty of any kind. MICRON TECHNOLOGY, INC. 
//("MTI") EXPRESSLY DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED,
//INCLUDING BUT NOT LIMITED TO, NONINFRINGEMENT OF THIRD PARTY
//RIGHTS, AND ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
//FOR ANY PARTICULAR PURPOSE. MTI DOES NOT WARRANT THAT THE
//SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF
//THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. FURTHERMORE,
//MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR THE
//RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
//ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT
//OF USE OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO
//EVENT SHALL MTI, ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE
//LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR
//SPECIAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
//OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF INFORMATION)
//ARISING OUT OF YOUR USE OF OR INABILITY TO USE THE SOFTWARE,
//EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
//Because some jurisdictions prohibit the exclusion or limitation
//of liability for consequential or incidental damages, the above
//limitation may not apply to you.
//
//Copyright 2006-2008 Micron Technology, Inc. All rights reserved.
////////////////////////////////////////////////
`timescale 1ns / 1ps

module tb;


`include "nand_parameters.vh"

initial begin
`ifdef VCD
$dumpfile("jcnmvcd.vcd");
$dumpvars(0,uut);
`endif
end 

    // Ports Declaration
    reg  [DQ_BITS - 1 : 0] Io;
    reg                      Cle;
    reg                      Ale;
    reg                      Ce_n;
    reg                      Re_n;
    reg                      We_n;
    reg                      Wp_n;
    reg                      Ce2_n;
    reg                      Ce3_n; //reserved for future use
    reg                      Ce4_n; //reserved for future use
    reg                      Pre;
    reg                      Lock;
    reg                      Dqs;
    tri1                     Rb2_n; // pullup
    tri1                     Rb_n;  // pullup
    tri1                     Rb3_n; //reserved for future use
    tri1                     Rb4_n; //reserved for future use


    wire [DQ_BITS - 1 : 0] IO = Io;
    // high-speed sync signals
    wire                      Clk = We_n;
    wire                      Wr_n = Re_n;
    wire DQS = Dqs;

//  some testbench signals here
    wire cache_mode;
    wire sync_mode;
    wire any_device_active = ~Ce_n || ~Ce2_n || ~Ce3_n || ~Ce4_n;
    reg rd_verify;
    reg enable_rd_verify;
    reg rd_verify_sync;
    reg device;
    reg [DQ_BITS -1 : 0] rd_dq;
    reg [7:0] lastCmd;
    reg [2:0] lastState;
    reg Clk_int = 0;
    reg check_idle = 0;
    //read cycle timing parameters
    real tRP; //read cycle pulse width low
    real tREH;//read cycle high
    real tRC; //read cycle time
    //write cycle timing parameters
    real tWP; //write cycle pulse width low
    real tWH; //write cycle high
    real tWC; //write cycle time
    realtime tm_ren_pos=0;
    realtime tm_ren_neg=0;
    realtime tm_cen_pos=0;
    realtime tm_cen_neg=0;
    realtime tm_wen_pos=0;
    realtime tm_wen_neg=0;
    realtime tm_ale_pos=0;
    realtime tm_ale_neg=0;
    realtime tm_ale_clk=0;
    realtime tm_cle_pos=0;
    realtime tm_cle_neg=0;
    realtime tm_cle_clk=0;
    realtime tm_ce2n_pos=0;
    realtime tm_ce2n_neg=0;
    realtime tm_rbn_pos=0;
    realtime tm_io =0;
    realtime tm_cad_r=0;
    realtime tm_clk_pos=0;
    realtime tm_clk_neg=0;
    realtime tm_dqs_pos=0;
    realtime tm_dqs_neg=0;
    real     tCK_sync;
    
    initial begin
        // ----------------------------
        //these toggle times are set to larger values to allow the IO bus to transition back to z before the next read
        //  to demonstrate the data->x->z transition.  For min cycles, set these appropriately. 
        // Redefine these as needed with the set_read_cycle and set_write_cycle tasks.
	    tRP = tCEA_cache_max ; // Re_n low pulse width, adjust as needed
	    tREH = tRHZ_max; // Re_n high width, adjust as needed
    	tRC = tRP + tREH;
        tWP = tWP_cache_min;
        tWC = tWC_cache_min;
		if ((tWC - tWP) > tWH_cache_min) begin
	        tWH = tWC - tWP;
		end else begin
			tWH = tWH_cache_min;
		end
        // ----------------------------

        //initialize some regs that will be used
        rd_verify = 0;
        enable_rd_verify = 0;
        rd_verify_sync = 0;
        device = 0;
        lastCmd = 8'h00;
        lastState = 3'b000;
        Dqs = 1'bz;
    end


//to determine whether or not the testbench needs to use cache mode timing when driving the NAND inputs,
// we'll keep track of whether any of the NAND dies are in cache mode.
    // `ifdef (CLASSB || CLASSC || CLASSD || CLASSE || CLASSQ || CLASSR)
    `ifdef CLASSB
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode);
    `else `ifdef CLASSC
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode);
    `else `ifdef CLASSD
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode);
    `else `ifdef CLASSE
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode);
    `else `ifdef CLASSQ
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode);
    `else `ifdef CLASSR
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode);

    // `else `ifdef (CLASSF || CLASSG || CLASST || CLASSU)
    `else `ifdef CLASSF
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op  || tb.uut.uut_2.cache_op  || tb.uut.uut_3.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode || tb.uut.uut_2.sync_mode || tb.uut.uut_3.sync_mode);
    `else `ifdef CLASSG
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op  || tb.uut.uut_2.cache_op  || tb.uut.uut_3.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode || tb.uut.uut_2.sync_mode || tb.uut.uut_3.sync_mode);
    `else `ifdef CLASST
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op  || tb.uut.uut_2.cache_op  || tb.uut.uut_3.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode || tb.uut.uut_2.sync_mode || tb.uut.uut_3.sync_mode);
    `else `ifdef CLASSU
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op  || tb.uut.uut_2.cache_op  || tb.uut.uut_3.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode || tb.uut.uut_2.sync_mode || tb.uut.uut_3.sync_mode);

    // `else `ifdef (CLASSK || CLASSW)
    `else `ifdef CLASSK
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op  || tb.uut.uut_2.cache_op  || tb.uut.uut_3.cache_op  || tb.uut.uut_4.cache_op  || tb.uut.uut_5.cache_op  || tb.uut.uut_6.cache_op  || tb.uut.uut_7.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode || tb.uut.uut_2.sync_mode || tb.uut.uut_3.sync_mode || tb.uut.uut_4.sync_mode || tb.uut.uut_5.sync_mode || tb.uut.uut_6.sync_mode || tb.uut.uut_7.sync_mode);
    `else `ifdef CLASSW
        assign cache_mode = (tb.uut.uut_0.cache_op  || tb.uut.uut_1.cache_op  || tb.uut.uut_2.cache_op  || tb.uut.uut_3.cache_op  || tb.uut.uut_4.cache_op  || tb.uut.uut_5.cache_op  || tb.uut.uut_6.cache_op  || tb.uut.uut_7.cache_op);
        assign sync_mode  = (tb.uut.uut_0.sync_mode || tb.uut.uut_1.sync_mode || tb.uut.uut_2.sync_mode || tb.uut.uut_3.sync_mode || tb.uut.uut_4.sync_mode || tb.uut.uut_5.sync_mode || tb.uut.uut_6.sync_mode || tb.uut.uut_7.sync_mode);

    `else
    assign cache_mode = tb.uut.uut_0.cache_op;
    assign sync_mode  = tb.uut.uut_0.sync_mode;
          `endif `endif `endif `endif `endif `endif `endif `endif `endif `endif `endif 
    `endif

    nand_model uut (

    `ifdef CLASSC         Ce2_n,
    `else `ifdef CLASSD   Ce2_n, Rb2_n,
    `else `ifdef CLASSE   Ce2_n, Rb2_n, IO2, Cle2, Ale2, Clk_We2_n, Wr_Re2_n, Wp2_n,
    `else `ifdef CLASSF   Ce2_n, Rb2_n,
    `else `ifdef CLASSG   Ce2_n, Rb2_n, IO2, Cle2, Ale2, Clk_We2_n, Wr_Re2_n, Wp2_n,
    `else `ifdef CLASSK   Ce2_n, Ce3_n, Ce4_n, Rb2_n, Rb3_n, Rb4_n, IO2, Cle2, Ale2, Clk_We2_n, Wr_Re2_n, Wp2_n,
    `else `ifdef CLASSQ   Ce2_n, Rb2_n,
    `else `ifdef CLASSR   Ce2_n, Rb2_n, IO2, Cle2, Ale2, Clk_We2_n, Wr_Re2_n, Wp2_n, 
    `else `ifdef CLASST   Ce2_n, Rb2_n,
    `else `ifdef CLASSU   Ce2_n, Rb2_n, IO2, Cle2, Ale2, Clk_We2_n, Wr_Re2_n, Wp2_n, 
    `else `ifdef CLASSW   Ce2_n, Ce3_n, Ce4_n, Rb2_n, Rb3_n, Rb4_n, IO2, Cle2, Ale2, Clk_We2_n, Wr_Re2_n, Wp2_n, 
    `else                 // CLASS A,B,M
          `endif `endif `endif `endif `endif `endif `endif `endif `endif `endif 
    `endif

        IO, 
        Cle, 
        Ale, 
        We_n, 
        Re_n, 
        Ce_n, 
        Wp_n, 
        Rb_n
        );

    
    always @(posedge Re_n) begin
        tm_ren_pos = $realtime;
    end
    always @(negedge Re_n) begin
        tm_ren_neg = $realtime;
    end
    always @(posedge We_n) begin
        tm_wen_pos <= $realtime;
    end


    always @(posedge Clk) begin
        tm_clk_pos = $realtime;
        if (sync_mode && any_device_active && Ale && ~Cle) begin
            tm_ale_clk <= $realtime;
        end
        if (sync_mode && any_device_active && ~Ale && Cle) begin
            tm_cle_clk <= $realtime;
        end
    end
    always @(negedge Clk) tm_clk_neg = $realtime;

    always @(negedge We_n) begin
        tm_wen_neg = $realtime;
    end
    always @(posedge Ce_n) begin
        tm_cen_pos = $realtime;
    end
    always @(negedge Ce_n) begin
        tm_cen_neg = $realtime;
    end
    always @(posedge Ce2_n) begin
        tm_ce2n_pos = $realtime;
    end
    always @(negedge Ce2_n) begin
        tm_ce2n_neg = $realtime;
    end
    always @(posedge Cle) begin
        tm_cle_pos = $realtime;
    end
    always @(negedge Cle) begin
        tm_cle_neg = $realtime;
    end
    always @(posedge Ale) begin
        tm_ale_pos = $realtime;
    end
    always @(negedge Ale) begin
        tm_ale_neg = $realtime;
    end
    always @(posedge Rb_n) begin
        tm_rbn_pos = $realtime;
    end
    always @(IO) begin
        tm_io = $realtime;
    end
    
  function    [23           : 0]     fn_row_addr  ;
    input     [BLCK_BITS -1 : 0]     blck_addr    ;
    input     [PAGE_BITS -1 : 0]     page_addr    ;
    input                            page_en      ;
    begin
    `ifdef PAGEBITSGT8
        fn_row_addr [07:00] = {8{page_en}} & page_addr [(PAGE_BITS -1 -(PAGE_BITS-8)) : 0];
        fn_row_addr [15:08] = {blck_addr [(15 - PAGE_BITS) : 0], ({(PAGE_BITS-8){page_en}} & page_addr[PAGE_BITS-8: 8])};
            fn_row_addr [23:16] = {{(24 - (BLCK_BITS + PAGE_BITS)){1'b0}}, blck_addr [(BLCK_BITS -1) : (16 - PAGE_BITS)]};
    `else `ifdef PAGEBITS8
        fn_row_addr [07:00] = {8{page_en}} & page_addr[7 : 0];
        fn_row_addr [15:08] = blck_addr [(15 - PAGE_BITS) : 0];
            fn_row_addr [23:16] = {{(24 - (BLCK_BITS + PAGE_BITS)){1'b0}}, blck_addr [(BLCK_BITS -1) : (16 - PAGE_BITS)]};
    `else
        fn_row_addr [07:00] = {blck_addr [(7 - PAGE_BITS):0],({PAGE_BITS {page_en}} & page_addr[PAGE_BITS-1:0])};
        fn_row_addr [15:08] = blck_addr [(15 - PAGE_BITS) : (8 - PAGE_BITS)];
            fn_row_addr [23:16] = {{(24 - (BLCK_BITS + PAGE_BITS)){1'b0}}, blck_addr [(BLCK_BITS -1) : (16 - PAGE_BITS)]};
    `endif `endif
    end
  endfunction

    //lets user define read cycle time parameters
    task set_read_cycle;
    input tRP_new;   //low time
    input tREH_new;  //high time
    real tRP_new;   //low time
    real tREH_new;  //high time
    begin
        tRP = tRP_new;
        tREH = tREH_new;
        tRC = tRP + tREH;
    end
    endtask
    
    //lets user define read cycle time parameters
    task set_write_cycle;
    input tWP_new;
    input tWH_new;
    real tWP_new;
    real tWH_new;
    begin
        tWP = tWP_new;
        tWH = tWH_new;
        tWC = tRP + tREH;
    end
    endtask
    
    task wait_posedge_clk;
    begin
        if (Clk === 1) wait (Clk === 0);
        wait (Clk === 1);
    end
    endtask
    
    task wait_negedge_clk;
    begin
        if (Clk === 0) wait (Clk === 1);
        wait (Clk === 0);
    end
    endtask

    // 0 = dies controlled by Ce_n, 1 = dies controlled by Ce2_n
    task activate_device;
    input dev;
    begin
        device = dev;   //device variable is global
        if (sync_mode) begin //can't transition Ce pin while data is on Io/Dq
        end
        if (dev==1) begin
            if (Ce_n == 0) begin
                Ce_n <= 1;
            end
            Ce2_n <= 0;            
        end else begin
            if (Ce2_n == 0) begin
                Ce2_n <= 1;
            end
            Ce_n <= 0;
        end
    end
    endtask
    
    task disable_device;
    input [1:0] dev;
    begin
        if (sync_mode) begin //can't transition Ce pin while data is on Io/Dq
        end
        case (dev)
        2'b00 : Ce_n  <= 1;
        2'b01 : Ce2_n <= 1;
        2'b10 : Ce3_n <= 1;
        2'b11 : Ce4_n <= 1;
        endcase
    end
    endtask

    // Wait Ready : wait for [ready]->busy->ready
    task wait_ready;
    begin
        if (device == 1) begin
            if (Rb2_n === 1) begin
                if (($realtime - tm_wen_pos) < tWB_max) #tWB_max;
                wait (Rb2_n === 1);
            end else if (Rb2_n === 0) begin
                   wait (Rb2_n === 1);
            end
            #tRR_min;
        end else begin
            if (Rb_n === 1) begin
                if (sync_mode) begin
                end else begin
                    if (($realtime - tm_wen_pos) < tWB_max) #tWB_max;
                    wait (Rb_n === 1);
                end
            end else if (Rb_n === 0) begin
                   wait (Rb_n === 1);
            end
            #tRR_min;
        end
    end
    endtask


    //pulse Re_n to latch read data
    task latch_read;
//    parameter trl=tRP;
//    parameter trh=(tRC - tRP);
      real tCCS;
      real tCCS_cache;
    begin
        Cle = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -