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

📄 nand256r3a.v

📁 256Mbits (x8) 528 Bytes Page, NAND Flash Memory Verilog HDL Model User Manual
💻 V
📖 第 1 页 / 共 3 页
字号:
  if(power_on && {iCE,iALE,iCLE,iRE,iWE,bWE}===6'b001110)
    if(CMD_CHECK(iIO) == 1'b1) REG_CMD <= iIO;
end
//---------------------------------------------------------
// Command Latch Enable, IO as input mode
//---------------------------------------------------------
always@(posedge iCLE)
begin
  if(power_on && iCE==1'b0)
  begin
    eIO <= 1'b0;
    ADD_COMPLETE <= 1'b0;
  end
end

//===================================================================
// Address Input Bus Operation
//===================================================================
always@(posedge iWE)
begin
  if(power_on && {iCE,iALE,iCLE,iRE,iWE,bWE}===6'b010110) begin
  //-----------------------------------------------------------------
  //1. Latch Address After Read, Program Command Setup Code
  //-----------------------------------------------------------------
    if(MOD_READ_MODE || MOD_PAGE_PROGRAM_1 || MOD_COPY_BACK_PG) begin
      case(add_cycle)
        3:   REG_ADD <= {REG_ADD[`ADD_BIT-1:9],area_b,iIO};
        2:   REG_ADD <= {REG_ADD[`ADD_BIT-1:17],iIO,REG_ADD[8:0]};
        1: begin
             REG_ADD <= {iIO,REG_ADD[16:0]};
             ADD_COMPLETE <= 1'b1; //cycles for address input is over
             if(MOD_PAGE_PROGRAM_1) wr_addr_bk <= 1'b1;
           end
      endcase
      ADD_CYC_DETECT;
    end
  //-----------------------------------------------------------------
  //2. Latch Address After Block Erase Command Setup Code
  //-----------------------------------------------------------------
    else if(MOD_BLOCK_ERASE_1) begin
      case(add_cycle)
        2:   REG_ADD <= {REG_ADD[`ADD_BIT-1:17],iIO,{`ADD_COL{1'b0}}};
        1: begin
             REG_ADD <= {iIO,REG_ADD[16:0]};
             ADD_COMPLETE <= 1'b1; //cycles for address input is over
           end
      endcase
      ADD_CYC_DETECT;
    end
  //-----------------------------------------------------------------
  //3. Latch Address After Read E.S. Command Code, (address is 00H)
  //-----------------------------------------------------------------
    else if(MOD_READ_ES) begin
      case(add_cycle)
        1: if(iIO == 8'h00) ADD_COMPLETE <= 1'b1;
           else begin
             REG_CMD <= 8'h55;  //command register reset to 55
             $display("%t, Error: Invalid Address[%h] in Read ES Command, the Address must be '00H'.\n",$realtime,iIO);
           end
      endcase
      ADD_CYC_DETECT;
    end
  //-----------------------------------------------------------------
  //4. In other Commands, they need not address input
  //-----------------------------------------------------------------
    else begin
      REG_CMD <= 8'h55;  //command register reset to 55
      $display("%t, Error: Invalid Command Sequence! A redundant address cycle is inputted!\n",$realtime);
    end
  end
end
//-------------------------------------------------------------------
always@(posedge ADD_COMPLETE)
begin
  if(power_on && MOD_READ_MODE || MOD_PAGE_PROGRAM_1 || MOD_COPY_BACK_PG || MOD_BLOCK_ERASE_1)
  begin
    addr_page <= REG_ADD[`ADD_BIT-`BLK_BIT-1:`ADD_BIT-`BLK_BIT-`PAG_BIT];
    addr_block <= REG_ADD[`ADD_BIT-1:`ADD_BIT-`BLK_BIT];
    if(MOD_READ_MODE) begin
      COPYBACK_ID1 <= #( 0 )  1'b1; //flag for wait copy back program command
      BUSY_BY_RD   <= #(`tR)  1'b1;
      BUSY_BY_RD   <= #(`tWB) 1'b0; //#(`tWB): write enable high to ready/busy low
    end
    if(MOD_COPY_BACK_PG)  COPYBACK_ID2 <= 1'b1;
  end 
end
//-------------------------------------------------------------------
task ADD_CYC_DETECT;
  begin
    if(add_cycle > 0) add_cycle <= add_cycle - 1;
    //input address cycles exceed
    else if(add_cycle == 0) begin
      REG_CMD <= 8'h55;  //command register reset to 55
      $display("%t, Error: Invalid Command Sequence! A redundant address cycle is inputted!\n",$realtime);
    end
  end
endtask

//===================================================================
//  Data Register Pointer (IN PAGE)
//===================================================================
always@(posedge iWE)
begin
  if(power_on && MOD_READ_MODE && {iCE,iALE,iCLE,iRE,iWE,bWE}===6'b010110) begin
    if(add_cycle === 3 && area_c === 1'b0) addr_column <= {area_c,area_b,iIO};
    if(add_cycle === 3 && area_c === 1'b1) addr_column <= {area_c,area_b,4'b0000,iIO[3:0]};
  end else
  if(power_on && MOD_PAGE_PROGRAM_1 && {iCE,iALE,iCLE,iRE,iWE,bWE}===6'b010110) begin
    if(add_cycle === 3 && area_c === 1'b0) addr_column <= {area_c,area_b,iIO};
    if(add_cycle === 3 && area_c === 1'b1) addr_column <= {area_c,area_b,4'b0000,iIO[3:0]};
  end
end

//===================================================================
//  Data Input Bus Operation (In PAGE PORGRAM MODE)
//===================================================================
always@(posedge iWE)
begin
  if(power_on && {iCE,iALE,iCLE,iRE,iWE,bWE}===6'b000110)
  begin
    //In Page Program mode, data is written in data buffer
    if(MOD_PAGE_PROGRAM_1 && ADD_COMPLETE)
    begin
      if(wr_addr_bk === 1'b1) begin
        wr_addr_bk <= 1'b0;
        start_addr <= addr_column;
      end
      if(addr_column < `COL_IN_PAGE) begin
        DATA[addr_column] <= iIO;
        end_addr <= addr_column;
        addr_column <= addr_column + 1;
      end
      //if(addr_column == (`COL_IN_PAGE-1))
      //begin
      //  DIN_COMPLETE <= 1'b1;
      //  $display("%t, Note: Input data is loaded into the last byte of data buffer.\n",$realtime);
      //end
    end
    //In Page Program mode, data input during addr input cycle
    if(MOD_PAGE_PROGRAM_1 && !ADD_COMPLETE)
    begin
      REG_CMD <= 8'h55;
      $display("%t, Error: Invalid Command Sequence! Data can't be inputted during address cycles!\n",$realtime);
    end
    //In other mode, they need not data byte input
    if(!MOD_PAGE_PROGRAM_1)
    begin                  
      REG_CMD <= 8'h55;
      $display("%t, Error: Invalid Command Sequence! A redundant data cycle is inputted!\n",$realtime);
    end
  end
end

//===================================================================
// read enable rising edge for read operation
//===================================================================
always@(posedge iRE)
begin
  if(power_on && operation === OP_READ)
  begin
    //data hold time tRHQZ has the value of 15ns~30ns; //2004/12/13
    //here first 15ns the data is maintained and the last 15ns the data is 'z'.
    dout <= #(`tRHZ/2) 8'hzz;
    //if read enable after the data in last column of page is output;
    //memory is busy, and next page is automatically loaded.
    if(MOD_READ_MODE && last_data === 1'b1)
    begin
      last_data <= 1'b0;
      BUSY_BY_RD <= #(`tRB) 1'b0;
      BUSY_BY_RD <= #(`tRB + `tBLBH1) 1'b1;
    end
  end
end

//===============================================
//          read memory array operation
//===============================================
always@(negedge iRE)
begin
  if(power_on && MOD_READ_MODE && ADD_COMPLETE && {iCE,iALE,iCLE,iRE,iWE,bRE,oRY_BY}===7'b0000111)
  begin
    //if the read operation is started;
    //the copy back program wait flag will be cleared.
    if(COPYBACK_ID1 === 1'b1) COPYBACK_ID1 <= 1'b0;
    //-----------------------------------------------------
    operation <= OP_READ;
    //"tREA" is rd enable low to output valid.
    eIO <= #(`tREA) 1'b1;
    dout <= #(`tREA) MEMORY[{addr_block,addr_page,addr_column} - ({addr_block,addr_page}*(1024-`COL_IN_PAGE))];
    //$display("address[%d]",{addr_block,addr_page,addr_column} - ({addr_block,addr_page}*(1024-`COL_IN_PAGE)));
    //-----------------------------------------------------
    //address increase 1 in the sequential read operation.
    if(addr_page <= `PAGE_IN_BLOCK-1 && addr_column < `COL_IN_PAGE-1)
      addr_column <= addr_column + 1'b1;
    //-----------------------------------------------------
    //last data of the page is output;
    //the next page will be loaded to output.
    else if(addr_page < `PAGE_IN_BLOCK-1 && addr_column === `COL_IN_PAGE-1)
    begin
      //last data byte in page is outputted.
      last_data <= 1'b1;
      if({area_a,area_b,area_c}===3'b100 || {area_a,area_b,area_c}===3'b010)
        addr_column <= `COL_BIT'h000; addr_page <= addr_page + 1'b1;
      if({area_a,area_b,area_c}===3'b001)
        addr_column <= `COL_BIT'h200; addr_page <= addr_page + 1'b1;
    end
    //-----------------------------------------------------
    //sequential read can only be used to read one block.
    else if(addr_page === `PAGE_IN_BLOCK-1 && addr_column === `COL_IN_PAGE-1)
      $display("%t, Note: Sequential Read Operation within Block[%d] is Completed.",$realtime,addr_block);
  end
end

//===============================================
//      read electronic signature operation
//===============================================
always@(negedge iRE)
begin
  if(power_on && MOD_READ_ES && ADD_COMPLETE && {iCE,iALE,iCLE,iRE,iWE,bRE}===6'b000011)
  begin
    $display("%t, Note: Read Electronic Signature.",$realtime);
    operation <= OP_READ;
    //"tREA" is rd enable low to output valid
    eIO <= #(`tREA) 1'b1;
    case(signature)
      0: begin dout <= #(`tREA) `MANUFC_CODE; signature <= 1; end
      1: begin dout <= #(`tREA) `DEVICE_CODE; signature <= 2; end
      2: begin dout <= #(`tREA)  8'hA5;       signature <= 3; end
      3: begin dout <= #(`tREA)  8'h00;       signature <= 0; end
    endcase
  end
end

//===============================================
//        read status register operation
//===============================================
always@(negedge iRE)
begin
  if(power_on && MOD_READ_SR && {iCE,iALE,iCLE,iRE,iWE,bRE}===6'b000011)
  begin
    $display("%t, Note: Read Status Register.",$realtime);
    operation <= OP_READ;
    //"tREA" is rd enable low to output valid
    eIO <= #(`tREA) 1'b1;
    dout <= #(`tREA) REG_STAT;
  end
end

//===============================================
//            block erase operation
//===============================================
always@(posedge MOD_BLOCK_ERASE_2)
begin
  if(power_on == 1'b1 && wr_protect == 1'b0)
  begin
    //memory is busy; p/e/r controller is active.
    //"tWB" is wr enable high to ready/busy low.
    operation    <= #(`tWB) OP_ERASE;
    BUSY_BY_BE   <= #(`tWB) 1'b0;
    REG_STAT[6]  <= #(`tWB) 1'b0;
    //memory is ready; p/e/r controller is inactive.
    //"tBERS" is block erase operation busy time.
    operation    <= #(`tWB + `tBERS) OP_READY;
    BUSY_BY_BE   <= #(`tWB + `tBERS) 1'b1;
    REG_STAT[6]  <= #(`tWB + `tBERS) 1'b1;
    //block erase operation.
    //all bits in the addressed block are set to '1'.
    blockerasing <= 1'b1;
    for(addr_temp2 = 0 ; addr_temp2 < `PAGE_IN_BLOCK ; addr_temp2 = addr_temp2 + 1)
      for(addr_temp1 = 0 ; addr_temp1 < `COL_IN_PAGE ; addr_temp1 = addr_temp1 + 1)
        MEMORY[{addr_block,addr_temp2[`PAG_BIT-1:0],addr_temp1[`COL_BIT-1:0]}
        - ({addr_block,addr_temp2[`PAG_BIT-1:0]}*(1024-`COL_IN_PAGE))] <= #(`tWB + `tBERS) {`D_WIDTH{1'b1}};
  end
  else if(wr_protect == 1'b1)
  begin
    //wr_protect <= 1'b0;
    //REG_STAT[7] <= 1'b1;
    $display("%t, Error: Write Protect, the Block Erase Operation is not accepted!\n",$realtime);
  end
end
//-----------------------------------------------
always@(posedge BUSY_BY_BE)
begin
  if(blockerasing == 1'b1) begin
    $display("%t, Note: Block[%d] Erase Operation is completed!\n",$realtime,addr_block);
    blockerasing <= 1'b0;
  end
end

//===============================================
//       copy back, page program operation
//===============================================
always@(posedge COPYBACK_ID1) address_src <= {addr_block,addr_page,addr_column};
always@(posedge COPYBACK_ID2) address_tgt <= {addr_block,addr_page,addr_column};

//-----------------------------------------------
//page program and copy back program confirm
//-----------------------------------------------
always@(posedge MOD_PAGE_PROGRAM_2)
begin
  if(power_on == 1'b1 && wr_protect == 1'b0)
  begin
    //memory is busy; p/e/r controller is active.
    //"tWB" is wr enable high to ready/busy low.
    operation   <= #(`tWB) OP_PROGRAM;
    BUSY_BY_PG  <= #(`tWB) 1'b0;
    REG_STAT[6] <= #(`tWB) 1'b0;
    //memory is ready; p/e/r controller is inactive.
    //"tPROG" is program operation busy time.
    operation   <= #(`tWB + `tPROG) OP_READY;
    BUSY_BY_PG  <= #(`tWB + `tPROG) 1'b1;
    REG_STAT[6] <= #(`tWB + `tPROG) 1'b1;
    //page program operation.
    //program tha data bytes to the memory array.
    if(COPYBACK_ID2 == 1'b0)
    begin
      programming1 <= 1'b1;
      for(addr_temp1 = start_addr ; addr_temp1 <= end_addr ; addr_temp1 = addr_temp1 + 1)
      begin
        if(MEMORY[{addr_block,addr_page,addr_temp1[`COL_BIT-1:0]}
           - ({addr_block,addr_page}*(1024-`COL_IN_PAGE))] & 8'hff === 8'hff)
          MEMORY[{addr_block,addr_page,addr_temp1[`COL_BIT-1:0]}
          - ({addr_block,addr_page}*(1024-`COL_IN_PAGE))] <= #(`tWB + `tPROG) DATA[addr_temp1[`COL_BIT-1:0]];
        else begin
          programming1 <= 1'b0;
          not_blank = 1'b1;
          REG_STAT[0] = 1'b1;
          $stop;
        end
      end
      if(not_blank == 1'b1)
      begin
        not_blank = 1'b0;
        $display("\n%t, Error: the bytes addressed to program are not blank, a Block Erase Command must be issued before page program!\n",$realtime);
      end
    end
    //copy back program operation.
    //copy the data stored in one page and reprogram it in another page.
    if(COPYBACK_ID2 === 1'b1 && address_src[`CHP_BIT-1] === address_tgt[`CHP_BIT-1])
    begin
      for(addr_temp1 = 0 ; addr_temp1 < `COL_IN_PAGE ; addr_temp1 = addr_temp1 + 1)
      begin
        if(MEMORY[{address_tgt[`CHP_BIT-1:10],addr_temp1[`COL_BIT-1:0]}
           - {address_tgt[`CHP_BIT-1:10]}*(1024-`COL_IN_PAGE)] & 8'hff !== 8'hff)
        begin
          not_blank = 1'b1;       //addressed page blank check
        end
      end
      if(not_blank == 1'b1)       //if the page is not blank
      begin

⌨️ 快捷键说明

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