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