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

📄 nand256r3a.v

📁 256Mbits (x8) 528 Bytes Page, NAND Flash Memory Verilog HDL Model User Manual
💻 V
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************************

  NAND256R3A Parameters Definitions

  256Mbits (x8, 2048 Blocks, 32 Pages, 528 Bytes) 1.8V NAND Flash Memory

  Copyright (c) 2004 STMicroelectronics

*****************************************************************************************

  Model Version : 1.0

  Author : Xue-Feng Hu

*****************************************************************************************

  Model Version History:
-----------------------------------------------------------------------------------------
  1.0: Oct. 2004  First Version Release.

****************************************************************************************/

`timescale      1ns/1ns
`include  "NAND_PARAM.v"

//-----------------------------------------------------------------------------
// Memory control
//-----------------------------------------------------------------------------
`define MEMORY_ALLOC        1  //1:whole 0:partial
`define NO_OF_BLK_ALLOC     5  //the number of partial blocks if above is '0'

//-----------------------------------------------------------------------------
// Difinitions of Electronic Signature
//-----------------------------------------------------------------------------
`define MANUFC_CODE         8'h20
`define DEVICE_CODE         8'h35

//=======================================================================================
// NAND256R3A 256Mbits(x8 bus width), 528 Bytes Page, 1.8V Device Simulation Model
//=======================================================================================
module NAND256R3A(
                   IO,
                   CE,
                   WE,
                   RE,
                   WP,
                   CLE,
                   ALE,
                   RY_BY,
                   VDD,
                   VSS
                 );

parameter NUM_BLKS = `MEMORY_ALLOC ? `BLK_IN_MEMORY : `NO_OF_BLK_ALLOC;
parameter MEM_SIZE = `MEMORY_ALLOC ? `PAGE_IN_BLOCK * `COL_IN_PAGE * `BLK_IN_MEMORY :
                                     `PAGE_IN_BLOCK * `COL_IN_PAGE * `NO_OF_BLK_ALLOC;

//===============================================
// Difinition regarding input/output signal
//===============================================
inout [7:0]        IO;
input              CE;
input              WE;
input              RE;
input              WP;
input              CLE;
input              ALE;
input              VDD;
input              VSS;
output             RY_BY;

//=============================================================================
// For Input Signals: Attach 'I', For Output Signals: Attach 'O'.
// RY_BY is output by buffer, output '0' is strong and '1' is Weak.
//=============================================================================
reg [7:0] dout;
reg eIO;
//-----------------------------------------------
wire[`D_WIDTH-1:0] iIO    ;
wire[`D_WIDTH-1:0] oIO    ;
wire               iCE    ;
wire               iWE    ;
wire               iRE    ;
wire               iWP    ;
wire               iCLE   ;
wire               iALE   ;
wire               oRY_BY ;
//-----------------------------------------------
assign iCE    =    CE  & 1'b1;
assign iWE    =    WE  & 1'b1;
assign iRE    =    RE  & 1'b1;
assign iWP    =    WP  & 1'b1;
assign iCLE   =    CLE & 1'b1;
assign iALE   =    ALE & 1'b1;
assign IO     =    eIO ? oIO : 8'hzz;
assign oIO    =    dout;
assign iIO    =    IO  & 8'hff ;
assign RY_BY  =    oRY_BY ? 1'bz : 1'b0;

//-----------------------------------------------
//RY_BY output, an open drain output
//-----------------------------------------------
reg BUSY_BY_RD,BUSY_BY_PG,BUSY_BY_BE,BUSY_BY_RESET;
//-----------------------------------------------
assign oRY_BY = BUSY_BY_RESET & BUSY_BY_RD & BUSY_BY_PG & BUSY_BY_BE;

//=============================================================================
// Back up previous values of input signals; Named by addition 'b'.
//=============================================================================
reg[`D_WIDTH-1:0] bIO  ;
reg               bCE  ;
reg               bWE  ;
reg               bRE  ;
reg               bWP  ;
reg               bCLE ;
reg               bALE ;
//-----------------------------------------------
always@(iIO)      bIO  <= iIO  ;
always@(iCE)      bCE  <= iCE  ;
always@(iWE)      bWE  <= iWE  ;
always@(iRE)      bRE  <= iRE  ;
always@(iWP)      bWP  <= iWP  ;
always@(iCLE)     bCLE <= iCLE ;
always@(iALE)     bALE <= iALE ;

//===============================================
// Parameters Regarding Commands
//===============================================
parameter CMD_READ_A          = 8'h00 ;
parameter CMD_READ_B          = 8'h01 ;
parameter CMD_READ_C          = 8'h50 ;
parameter CMD_RESET           = 8'hff ;
parameter CMD_READ_ES         = 8'h90 ;
parameter CMD_READ_SR         = 8'h70 ;
parameter CMD_PAGE_PROGRAM_1  = 8'h80 ; //page program setup code
parameter CMD_PAGE_PROGRAM_2  = 8'h10 ; //page program and copy back program confirm code
parameter CMD_COPY_BACK_PG    = 8'h8A ; //copy back program
parameter CMD_BLOCK_ERASE_1   = 8'h60 ; //block erase setup code
parameter CMD_BLOCK_ERASE_2   = 8'hD0 ; //block erase confirm code

//===============================================
// Parameters Regarding Commands
//===============================================
reg[1:0]  operation;
//-----------------------------------------------
parameter OP_READY            = 2'b00 ;
parameter OP_READ             = 2'b01 ;
parameter OP_PROGRAM          = 2'b10 ;
parameter OP_ERASE            = 2'b11 ;

//===============================================
// Memory Main Register
//===============================================
reg [`D_WIDTH-1:0] DATA[`COL_IN_PAGE-1:0];
reg [`D_WIDTH-1:0] MEMORY[MEM_SIZE-1:0];
reg [`D_WIDTH-1:0] REG_CMD;
reg [`ADD_BIT-1:0] REG_ADD;
reg [`D_WIDTH-1:0] REG_STAT;
reg [`BLK_BIT-1:0] addr_block;
reg [`PAG_BIT-1:0] addr_page;
reg [`COL_BIT-1:0] addr_column;

//===============================================
// Variable of AC Timing
//===============================================
reg  iIO_C;
reg  iCE_R,iCE_F;
reg  iWE_R,iWE_F;
reg  iRE_R,iRE_F;
reg  iCLE_R,iCLE_F;
reg  iALE_R,iALE_F;
//---------------------------
time tc_iIO;
time tr_iCE,tf_iCE;
time tr_iWE,tf_iWE;
time tr_iRE,tf_iRE;
time tr_iCLE,tf_iCLE;
time tr_iALE,tf_iALE;

//===============================================
// Generate Mode Signals By Decoding Commands
//===============================================
wire  MOD_READ_A          ;
wire  MOD_READ_B          ;
wire  MOD_READ_C          ;
wire  MOD_RESET           ;
wire  MOD_READ_ES         ;
wire  MOD_READ_SR         ;
wire  MOD_PAGE_PROGRAM_1  ;
wire  MOD_PAGE_PROGRAM_2  ;
wire  MOD_COPY_BACK_PG    ;
wire  MOD_BLOCK_ERASE_1   ;
wire  MOD_BLOCK_ERASE_2   ;
wire  MOD_READ_MODE       ; //read mode A or B or C
//-----------------------------------------------------------------------------
assign MOD_READ_A         = ( REG_CMD == CMD_READ_A );
assign MOD_READ_B         = ( REG_CMD == CMD_READ_B );
assign MOD_READ_C         = ( REG_CMD == CMD_READ_C );
assign MOD_RESET          = ( REG_CMD == CMD_RESET  );
assign MOD_READ_ES        = ( REG_CMD == CMD_READ_ES );
assign MOD_READ_SR        = ( REG_CMD == CMD_READ_SR );
assign MOD_PAGE_PROGRAM_1 = ( REG_CMD == CMD_PAGE_PROGRAM_1 );
assign MOD_PAGE_PROGRAM_2 = ( REG_CMD == CMD_PAGE_PROGRAM_2 );
assign MOD_COPY_BACK_PG   = ( REG_CMD == CMD_COPY_BACK_PG );
assign MOD_BLOCK_ERASE_1  = ( REG_CMD == CMD_BLOCK_ERASE_1 );
assign MOD_BLOCK_ERASE_2  = ( REG_CMD == CMD_BLOCK_ERASE_2 );
assign MOD_READ_MODE      = ( MOD_READ_A ) || ( MOD_READ_B ) || (MOD_READ_C);

//=============================================================================
integer addr_temp1,addr_temp2;
integer l,signature,add_cycle;
//-------------------------------------
reg COPYBACK_ID1;
reg COPYBACK_ID2;
reg ADD_COMPLETE;
reg DIN_COMPLETE;
reg programming1;
reg programming2;
reg blockerasing;
//-------------------------------------
reg power_on,reset,wr_addr_bk;
reg area_a,area_b,area_c;
reg not_blank,wr_protect,last_data;
//-------------------------------------
reg [`CHP_BIT-1:0] address_src;
reg [`CHP_BIT-1:0] address_tgt;
reg [`COL_BIT-1:0] start_addr,end_addr;
integer m;
//=============================================================================
initial begin
  $display ("%t: Note: Load memory with Initial content.",$realtime); 
  for(l=0;l< NUM_BLKS;l=l+1) begin
    //$display("%d,%d",l*528*32,(l*528*32+528*32-1));
    $readmemh("NAND_BLK_INIT.txt",MEMORY,l*528*32,(l*528*32+528*32-1));
  end
  $display ("%t: Note: Initial Load End.\n",$realtime);
  //-----------------------------------------------------------------
  operation      = OP_READY;
  power_on       = 1'b0;
  reset          = 1'b0;
  BUSY_BY_RESET  = 1'b1;
  BUSY_BY_RD     = 1'b1;    
  BUSY_BY_PG     = 1'b1;    
  BUSY_BY_BE     = 1'b1;
end

//=============================================================================
// Genarate power_on signal
// power_on: has initial value 0, after power supply is provided, gets to 1
//           indicates if the correct voltage has been supplied.
//=============================================================================
always@(VDD or VSS)
begin
  if( VSS !== 1'b0 )
  begin
    power_on <= 1'b0; $display("%t Note: Vss is not connected to the ground well!\n",$realtime);
  end
  else if(( VDD == 1'b1 ) && ( VSS == 1'b0 ))
  begin
    power_on <= 1'b1; $display("%t Note: Device is powered on!\n",$realtime);
  end
  else if(( power_on == 1'b1 ) && ( VDD !== 1'b1 ) && ( VSS == 1'b0 ))
  begin
    power_on <= 1'b0; $display("%t Note: Device is powered off!\n",$realtime);
  end
  else if(( power_on == 1'b0 ) && ( VDD !== 1'b1 ) && ( VSS == 1'b0 ))
  begin
    power_on <= 1'b0; $display("%t Note: Device is not powered on!\n",$realtime);
  end
end

//=========================================================
// Genarate wr_protect signal
//=========================================================
always@(negedge iWP)
begin
  if(power_on && ({bWP,iWP} == 2'b10) && (MOD_PAGE_PROGRAM_1 || MOD_BLOCK_ERASE_1 || MOD_COPY_BACK_PG))
  begin
    wr_protect <= 1'b1;
    REG_STAT[7] <= 1'b0;  //wrprotected
  end
end
//---------------------------------------------------------
always@(posedge MOD_COPY_BACK_PG or posedge MOD_PAGE_PROGRAM_1 or posedge MOD_BLOCK_ERASE_1)
begin
  if(power_on && iWP === 1'b0)
  begin
    wr_protect <= 1'b1;
    REG_STAT[7] <= 1'b0;  //wrprotected
  end
  if(power_on && iWP === 1'b1)
  begin
    wr_protect <= 1'b0;
    REG_STAT[7] <= 1'b1;  //unprotected
  end
end

//=========================================================
// Generate signal which indicate the selected area
//=========================================================
always@(posedge MOD_READ_A) {area_a,area_b,area_c}<=3'b100;
always@(posedge MOD_READ_B) {area_a,area_b,area_c}<=3'b010;
always@(posedge MOD_READ_C) {area_a,area_b,area_c}<=3'b001;

//=========================================================
//                   reset operation
//=========================================================
always@(posedge MOD_RESET) reset <= 1'b1;
//---------------------------------------------------------
always@(posedge reset or posedge power_on)
begin
  //power on reset
  operation     <= OP_READY;
  signature     <= 0;
  add_cycle     <= 0;
  reset         <= 1'b0;
  not_blank     <= 1'b0;
  eIO           <= 1'b0;
  area_a        <= 1'b1;
  area_b        <= 1'b0;
  area_c        <= 1'b0;
  wr_protect    <= 1'b0;
  wr_addr_bk    <= 1'b1;
  last_data     <= 1'b0;
  BUSY_BY_RD    <= 1'b1;    
  BUSY_BY_PG    <= 1'b1;    
  BUSY_BY_BE    <= 1'b1;
  COPYBACK_ID1  <= 1'b0;
  COPYBACK_ID2  <= 1'b0;
  REG_CMD       <= 8'h00;
  REG_ADD       <= 8'h00;
  REG_STAT      <= 8'he0;
  //if reset command is active
  if(power_on && reset)
  begin
    $display("%t Note: Memory internal reset!\n",$realtime);
    case(operation)
      OP_READY   : begin BUSY_BY_RESET <= 1'b0; BUSY_BY_RESET <= #(`tRESET_RY) 1'b1; end
      OP_READ    : begin BUSY_BY_RESET <= 1'b0; BUSY_BY_RESET <= #(`tRESET_RD) 1'b1; end
      OP_PROGRAM : begin BUSY_BY_RESET <= 1'b0; BUSY_BY_RESET <= #(`tRESET_PG) 1'b1; end
      OP_ERASE   : begin BUSY_BY_RESET <= 1'b0; BUSY_BY_RESET <= #(`tRESET_ER) 1'b1; end
    endcase
  end
end

//=========================================================
// Command Input Bus Operation
//=========================================================
always@(posedge iWE)
begin

⌨️ 快捷键说明

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