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

📄 tb.v

📁 nand flash 仿真模型,支持ONFI 2.0
💻 V
📖 第 1 页 / 共 4 页
字号:
        latch_command_pio (8'hB8);
        latch_data_pio (drivestrength);
        #tWHRIO_min;
    end
    endtask

    task get_features;
        input [7 : 0] feature_address;
    begin
        latch_command (8'hEE);
        latch_address (feature_address);
        //use wait_ready task to wait for busy to return inactive
        //then use serial_read task to output data
    end
    endtask

    task set_features;
        input [7 : 0] feature_address;
        //these are defined as only 8 bit features regardless of DQ_BITS width
        input [7:0] p1;
        input [7:0] p2;
        input [7:0] p3;
        input [7:0] p4;
    begin

        Ce_n <=0;
        if (feature_address == 8'h01) begin
            Ce2_n <= 0;
        end
        if (sync_mode == 0) begin
            #tCS_min; //avoid CE setup time violation if we're in async mode
        end
        latch_command (8'hEF);
        latch_address (feature_address);
        #tADL_min;
        if (sync_mode) begin
            latch_data_sync (p1,p1);
            latch_data_sync (p2,p2);
            latch_data_sync (p3,p3);
            latch_data_sync (p4,p4);
            go_idle;
        end else begin
            latch_data_async (p1);
            latch_data_async (p2);
            latch_data_async (p3);
            latch_data_async (p4);
        end
    end
    endtask

    // multi die status read
    task multi_die_status_read;
        input [BLCK_BITS - 1 : 0] blck_addr;

        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   [23          :00] tsk_row_addr;
    begin
        // Decode Address
        tsk_row_addr = fn_row_addr(blck_addr, 0, 1'b0);
        row_addr_1 = tsk_row_addr[07:00];
        row_addr_2 = tsk_row_addr[15:08];
        row_addr_3 = tsk_row_addr[23:16];

        // Decode Command
        latch_command (8'h78);
        latch_address (row_addr_1);
        latch_address (row_addr_2);
        latch_address (row_addr_3);
        #(tWHR_min);
    end
    endtask

    // locked block status read
    task block_lock_status_read;
        input [BLCK_BITS - 1 : 0] blck_addr;

        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   [23          : 0] tsk_row_addr;
    begin
        // Decode Address
        tsk_row_addr = fn_row_addr(blck_addr, 0, 1'b0);
        row_addr_1 = tsk_row_addr[07:00];
        row_addr_2 = tsk_row_addr[15:08];
        row_addr_3 = tsk_row_addr[23:16];

        // Decode Command
        latch_command (8'h7A);
        latch_address (row_addr_1);
        latch_address (row_addr_2);
        latch_address (row_addr_3);
        #tWHR_min;
    end
    endtask

    task unlock_block;
        input [BLCK_BITS - 1 : 0] blck_addr_one;
        input [BLCK_BITS - 1 : 0] blck_addr_two;
        input invert;

        reg   [DQ_BITS - 1 : 0] row_addr_1_one;
        reg   [DQ_BITS - 1 : 0] row_addr_2_one;
        reg   [DQ_BITS - 1 : 0] row_addr_3_one;
        reg   [DQ_BITS - 1 : 0] row_addr_1_two;
        reg   [DQ_BITS - 1 : 0] row_addr_2_two;
        reg   [DQ_BITS - 1 : 0] row_addr_3_two;
        reg   [23          : 0] tsk_row_addr;
        reg   [23          : 0] tsk_row_addr2;

    begin
        tsk_row_addr   = fn_row_addr(blck_addr_one, 0, 1'b0);
        row_addr_1_one = {tsk_row_addr[07:01], (tsk_row_addr[00] | invert)};
        row_addr_2_one = tsk_row_addr[15:08];
        tsk_row_addr2  = fn_row_addr(blck_addr_two, 0, 1'b0);
        row_addr_1_two = {tsk_row_addr2[07:01], (tsk_row_addr2[00] | invert)};
        row_addr_2_two = tsk_row_addr2[15:08];
        row_addr_3_one = tsk_row_addr[23:16];
        row_addr_3_two = tsk_row_addr2[23:16];
        // Decode Command
        latch_command (8'h23);
        latch_address (row_addr_1_one);
        latch_address (row_addr_2_one);
        latch_address (row_addr_3_one);
        latch_command (8'h24);
        latch_address (row_addr_1_two);
        latch_address (row_addr_2_two);
        latch_address (row_addr_3_two);
        #tWHR_min;

    end
    endtask

    // Erase Block (60h -> D0h)
    //      tp     = address is 1st of two planes
    task erase_block;
        input [BLCK_BITS - 1 : 0] blck_addr;
        input tp;
        input onfi;

        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   [23          : 0] tsk_row_addr;
    begin
        // Decode Address
        tsk_row_addr = fn_row_addr(blck_addr, 0, 1'b0);
        row_addr_1 = tsk_row_addr[07:00];
        row_addr_2 = tsk_row_addr[15:08];
        row_addr_3 = tsk_row_addr[23:16];
        // Decode Command
        latch_command (8'h60);
        latch_address (row_addr_1);
        latch_address (row_addr_2);
        latch_address (row_addr_3);
        if (~tp) begin
            latch_command (8'hD0);
        end else if (onfi) begin
            latch_command (8'hD1);
        end
        #tRR_min;
    end
    endtask

    // Multi-Plane Page Read (00h -> 32h)
    // blck_addr = block address
    // page_addr = page address
    //  col_addr = column address
    //
    // This is an ONFI 2.0 command : queues a plane to be read during a multi-plane page read
    //
    task multiplane_read_page;
        input [BLCK_BITS - 1 : 0] blck_addr;
        input [PAGE_BITS - 1 : 0] page_addr;
        input [COL_BITS - 1 : 0]  col_addr;

        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   [23          :00] tsk_row_addr;

    begin
        // Decode Address
        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 and address sequence
        latch_command (8'h00);
        latch_address (col_addr_1);
        latch_address (col_addr_2);
        latch_address (row_addr_1);
        latch_address (row_addr_2);
        latch_address (row_addr_3);
        latch_command (8'h32);
    end
    endtask //multiplane_read_page
    
    // Page Read (00h -> [30h])
    // blck_addr = block address
    // page_addr = page address
    //  col_addr = column address
    //      tp     = address is 1st of two planes
    //    idm    = read for internal data move
    //    otp    = OTP page read
    //
    // For twoplane, first issue read_page with tp=1, output == 00h with address
    //                 followed by read_page with tp=0, output == 00h with address and 30h
    //
    task read_page;
        input [BLCK_BITS - 1 : 0] blck_addr;
        input [PAGE_BITS - 1 : 0] page_addr;
        input [COL_BITS - 1 : 0]  col_addr;
        input tp;
        input idm;
        input otp;
        input copyback2;

        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   [23          :00] tsk_row_addr;

    begin
        //once another page read starts, we're not in cache page read anymore
        if (otp && (tp || idm)) $display("%m at time %t: ERROR: Illegal task option.  Can't read OTP page with twoplane or internal data move", $realtime);
        // Decode Address
        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];
        // Decode Command
        if (otp) begin
            latch_command (8'hAF);
        end else begin
            latch_command (8'h00);
        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

        if (~tp) begin
            if (idm) begin
                latch_command (8'h35);
            end else begin
                if (copyback2) begin
                    latch_command (8'h3A);
                end else begin
                    latch_command (8'h30);
                end
            end
        end
        //$display("%m at time %t: INFO: Read Page block addr=%s, page addr=%s, column addr=%s", $realtime,blck_addr, page_addr, col_addr);
    end
    endtask
    
    task cache_read;
    input last;
    begin
        if (last) begin
            latch_command(8'h3F);
        end else begin
            latch_command(8'h31);
        end
    end
    endtask

    task cache_read_random;
      input [BLCK_BITS - 1 : 0] blck_addr;
      input [PAGE_BITS - 1 : 0] page_addr;
      input [COL_BITS - 1 : 0]  col_addr;

      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   [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'h00);
        latch_address (col_addr_1);
        latch_address (col_addr_2);
        latch_address (row_addr_1);
        latch_address (row_addr_2);
        latch_address (row_addr_3);
        latch_command (8'h31);
    end
    endtask

    //tp =  0 = page random data (2 address cycles)
    //      1 = two-plane random data (5 address cycles)
    task random_data_read;
        input [BLCK_BITS - 1 : 0] blck_addr;
        input [PAGE_BITS - 1 : 0] page_addr;
        input [COL_BITS - 1 : 0]  col_addr;
        input tp;

        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   [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];

        if (tp) begin
            latch_command (8'h06);
            latch_address (col_addr_1);
            latch_address (col_addr_2);
            latch_address (row_addr_1);
            latch_address (row_addr_2);
            latch_address (row_addr_3);
        end else begin
            latch_command (8'h05);
            latch_address (col_addr_1);
            latch_address (col_addr_2);
        end
        latch_command (8'hE0);
        #tWHR_min;
    end
    endtask

    // Program Page (80h -> 10h)
    // blck_addr = block address
    // page_addr = page address
    //  col_addr = column address
    //      data = your first data value
    //      size = number of serial data to be written
    //   pattern = modify data pattern
    //             00 = no change
    //             01 = inc
       //             10 = dec
      //             11 = random

    //    tp     = address is 1st of two planes
    //    idm    = program for internal data move
    //                 0 = no idm
    //               1 = program for internal data move (for 2plane, 1st half of idm program)
    //    otp    = OTP page read
    //     cache   = cache mode program (not last page)
    //   final  = if low, will not finalize write -- indicates that a random data write will follow
    task program_page;
        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 idm;
        input otp;
        input cache;
        input copyback2;
        input finalCmd;

        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   [23          :00] tsk_row_addr;
        reg   [COL_BITS  - 1 : 0] i;
    begin

        if (otp && (tp || idm || cache)) $display("%m at time %t: ERROR: Illegal task option.  Can't write OTP page with cache, twoplane, or internal data move commands", $realtime);

        
        // Decode Address
        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];

⌨️ 快捷键说明

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