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

📄 tb.v

📁 nand flash 仿真模型,支持ONFI 2.0
💻 V
📖 第 1 页 / 共 4 页
字号:

        // Decode Command
        if (otp) begin
            latch_command (8'hA0);
        end else begin
            if (idm) begin
                latch_command (8'h85);
            end else begin
                if (copyback2) begin
                    latch_command (8'h8C);
                end else begin
                    latch_command (8'h80);
                end
            end
        end
        latch_address (col_addr_1);
        latch_address (col_addr_2);
        latch_address (row_addr_1);
        if (otp) begin
            latch_address (8'h00);
            latch_address (8'h00);
        end else begin
            latch_address (row_addr_2);
            latch_address (row_addr_3);
        end

        #tADL_min;
                
        if (~idm && (size != 0)) begin
        //only input data if not an internal data move
        //random data writes are in a separate task
            write_data(data, size, pattern);
        end

        // Done Program
        if (finalCmd) begin
            if (tp) begin
                latch_command (8'h11);
            end else begin
                if (cache) begin
                    latch_command (8'h15);
                end else begin
                    //if (~idm[0]) begin
                        latch_command (8'h10);
                    //end
                end
            end
        end
    end
    endtask

// write data pattern, addresses already input
    task write_data;
        input [DQ_BITS - 1 : 0] data;
        input [COL_BITS  - 1 : 0] size;
        input             [1 : 0] pattern;
        integer i;
    begin
        // Decode Pattern
        if (sync_mode) begin
            for (i = 0; i <= size - 1; i = i + 2) begin
            case (pattern)
                2'b00 : latch_data_sync (data,data);
                2'b01 : latch_data_sync (data + i, data + (i+1));
                2'b10 : latch_data_sync (data - i, data - (i+1));
                2'b11 : latch_data_sync ({$random} % {DQ_BITS{1'b1}}, {$random} % {DQ_BITS{1'b1}});
            endcase
            end
            go_idle;
        end else begin
            for (i = 0; i <= size - 1; i = i + 1) begin
            case (pattern)
                2'b00 : latch_data_async (data);
                2'b01 : latch_data_async (data + i);
                2'b10 : latch_data_async (data - i);
                2'b11 : latch_data_async ({$random} % {DQ_BITS{1'b1}});
            endcase
            end
        end
    end
    endtask

    //used to write data to a random col address on current page
    //    tp     = address is 1st of two planes
    //     cache   = cache mode program (not last page)
    //   final  = if low, will not finalize write -- indicates that a random data write will follow
    task random_data_write;
        input [BLCK_BITS - 1 : 0]  blck_addr;
        input [PAGE_BITS - 1 : 0]  page_addr;
        input [COL_BITS - 1 : 0]  col_addr;
        input [DQ_BITS - 1 : 0] data;
        input [COL_BITS  - 1 : 0] size;
        input             [1 : 0] pattern;
        input tp;
        input cache;
        input finalCmd;
        input column_only; //used to determine whether this is a 5-address row change, or a 2-address column change

        reg   [DQ_BITS - 1 : 0] col_addr_1;
        reg   [DQ_BITS - 1 : 0] col_addr_2;
        reg   [DQ_BITS - 1 : 0] row_addr_1;
        reg   [DQ_BITS - 1 : 0] row_addr_2;
        reg   [DQ_BITS - 1 : 0] row_addr_3;
        reg   [COL_BITS  - 1 : 0] i;
        reg   [23          :00] tsk_row_addr;
    begin
        col_addr_1 [7 : 0] = col_addr [7 : 0];
        col_addr_2 [7 : 0] = {{(16 - COL_BITS){1'b0}}, col_addr [(COL_BITS -1) : 8]};
        tsk_row_addr = fn_row_addr(blck_addr, page_addr, 1'b1);
        row_addr_1 = tsk_row_addr[07:00];
        row_addr_2 = tsk_row_addr[15:08];
        row_addr_3 = tsk_row_addr[23:16];

        latch_command (8'h85);
        latch_address (col_addr_1);
        latch_address (col_addr_2);
        if (~column_only) begin
            latch_address(row_addr_1);
            latch_address(row_addr_2);
            latch_address(row_addr_3);
        end

        #tADL_min;

        write_data(data, size, pattern);

        if (finalCmd) begin
            if (tp) begin
                latch_command (8'h11);
            end else begin
                if (cache) begin
                    latch_command (8'h15);
                end else begin
                    latch_command (8'h10);
                end
            end
        end
    end
    endtask


    task OTP_protect;
    begin
        // Decode Command
        latch_command (8'hA5);
        latch_address (8'h00);
        latch_address (8'h00);
        latch_address (8'h01);
        latch_address (8'h00);
        latch_address (8'h00);
        latch_command (8'h10);
        wait_ready;
    end
    endtask

    // reset (FFh) - 
    task sync_reset;
    begin
        latch_command (8'hFC);
    end
    endtask

    // reset (FFh) - 
    task reset;
    begin
        latch_command (8'hFF);
        `ifdef SYNC2ASYNCRESET
            We_n <= 1'b1; // switching from sync to async mode after reset  // ??? awaiting timing answer
        `endif
    end
    endtask

    // Read ID (90h) - 
    task read_id;
    integer i;
    begin
        latch_command (8'h90);
        latch_address (0);
        #tWHR_min
        for (i = 0; i < NUM_ID_BYTES; i = i + 1)
            begin 
                latch_read;   // Byte i
            end
    end
    endtask

    //reads static ONFI regs
    task read_onfi;
    begin
        latch_command (8'h90);
        latch_address (8'h20);
        #tWHR_min;
    end
    endtask

    //command address sequence required to access ONFI parameter data page
    //can't really use serial_read here cuz won't know all expected data
    task read_onfi_params;
    begin
        latch_command (8'hEC);
        latch_address (8'h00);

    end
    endtask


    // Read speacial
    // special = special page read data
    //             0 = read ID2 
    //             1 = read unique
    task read_special;  // Not inherited from read_id, rather from page_read
    input sel;
    reg [12:0] i;
    begin
        latch_command (8'h30);
        latch_command (8'h65);
        latch_command (8'h00);
        latch_address (0);
        if (sel) begin
            //read_unique
            latch_address (0);
        end else begin
            //read_id2
            latch_address (2);
        end
        latch_address (2);
        latch_address (0);
        latch_address (0);
        latch_command (8'h30);
        wait_ready;
        #tRR_min;
        // Serial Read
        for (i = 0; i <= 255; i = i + 1) 
           begin
              latch_read;   // Byte 0
           end
        #tRR_min;
    end
    endtask

    //new ONFI read unique command sequence
    //leave it up to use to latch read data
    task read_unique;
    begin
        latch_command (8'hED);
        latch_address (0);
        #tRR_min;
    end
    endtask


    //pulse Re_n (async) or wait for Dqs (sync) and compares output data to expected value
    task serial_read;
        input [DQ_BITS -1: 0] data;
        input [1:0] pattern;
        input [ROW_BITS -1: 0] size;
        integer i;
        begin
            // Serial Read
            $display ("%m at time %t: READ DATA : size=%0d,\t data=%0h,\t pattern=%0d", $realtime, size, data, pattern);
            //async serial read
            for (i = 0; i <= size - 1; i = i + 1) begin
                latch_and_check_data(data);
                case (pattern)
                    2'b00 : ;
                    2'b01 : data = data + 1;
                    2'b10 : data = data - 1;
                    2'b11 : data = 0;
                endcase
            end
            #tRR_min;    
        end
    endtask

    task serial_read_pio;
        input [DQ_BITS -1: 0] data;
        begin
                latch_and_check_data_pio(data);
                #tRR_min;
        end
    endtask

    task latch_and_check_data;
    input [DQ_BITS -1: 0] exp_data;
    begin
        if (sync_mode) begin
        end else begin
            rd_dq = exp_data;
            //enable rd verify tells the latch read task
            // whether or not to toggle rd_verify to check data              
            enable_rd_verify = 1'b1;
            latch_read;
            enable_rd_verify = 1'b0;
        end
    end
    endtask

    task latch_and_check_data_pio;
    input [DQ_BITS -1: 0] exp_data;
    begin
        rd_dq = exp_data;
        //rd_verify <= 1;
        enable_rd_verify = 1'b1;
        latch_read_pio;
        enable_rd_verify = 1'b0;
    end
    endtask

    //always @(IO) begin : data_verify
        //integer i;
       always @ (posedge rd_verify ) begin
        // Verify the data word after output delay
        //if ((IO ^ rd_dq) !== {DQ_BITS{1'b0}}) begin
        if (IO !== rd_dq) begin
                $display ("%m at time %t: ERROR: Read data miscompare: Expected = %h, Actual = %h", $realtime, rd_dq, IO);
        end
        rd_verify <= #1 1'b0;
       end
    //end


    reg test_done;
    initial test_done = 0;

    // End-of-test triggered in 'subtest.vh'
    always @(test_done) begin : all_done
        if (test_done == 1) begin
      #5000
      $display ("%m at time %t: Simulation is Complete", $realtime);
            $stop(0);
            $finish;
        end
    end

wire DEADMAN_REQ = 1'b0;
integer   DEADMAN_TIMER = 0;
parameter DEADMAN_LIMIT = 10000000 ;
always @ (posedge Clk_int)
begin
	if (DEADMAN_REQ == 1'b1)
		DEADMAN_TIMER = 0;
	else
		DEADMAN_TIMER = DEADMAN_TIMER + 1 ;
	if (DEADMAN_TIMER == DEADMAN_LIMIT)
	begin
	    $display ("SWM: No Activity in %d Clocks.  Deadman Timer at time %t!!", DEADMAN_TIMER, $time);    
	    $stop();
	end
end

//    task clear_data_regs;
//    input [1:0] die_num;
//    input [1:0] plane;
//    begin
//        case (die_num)
//            2'b00 : force uut.uut_0.clear_data_register(plane);
//            2'b01 : force uut.uut_1.clear_data_register(plane);
//            2'b10 : force uut.uut_2.clear_data_register(plane);
//            2'b11 : force uut.uut_3.clear_data_register(plane);
//        endcase
//    end
//    endtask
//
//    task clear_cache_regs;
//    input [1:0] die_num;
//    input [1:0] plane;
//    begin
//        case (die_num)
//            2'b00 : force uut.uut_0.clear_cache_register(plane);
//            2'b01 : force uut.uut_1.clear_cache_register(plane);
//            2'b10 : force uut.uut_2.clear_cache_register(plane);
//            2'b11 : force uut.uut_3.clear_cache_register(plane);
//        endcase
//    end
//    endtask

`ifdef INIT_MEM
    initial begin
        #1;
        //
        //preloading of mem_array can be done here
        // This approach is more flexible than readmemh
        //
        //        memory_write(block, page, col, mem_select, data)
        //              mem_select : 0 = flash memory array
        //                           1 = OTP array
        //                           2 = special config data array
        //
        uut.uut_0.memory_write(0,0,0, 0, 8'h00);
        uut.uut_0.memory_write(0,0,1, 0, 8'h01);
        uut.uut_0.memory_write(0,0,2, 0, 8'h02);
        uut.uut_0.memory_write(0,0,3, 0, 8'h03);
        uut.uut_0.memory_write(0,0,4, 0, 8'h04);
        uut.uut_0.memory_write(0,0,5, 0, 8'h05);
        uut.uut_0.memory_write(0,0,6, 0, 8'h06);
    end
`endif

    
    `include "subtest.vh"
    
endmodule

⌨️ 快捷键说明

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