📄 nand256r3a.v
字号:
/****************************************************************************************
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 + -