MIPS/resources/soc/rtl/APB_DEV/NAND/nand.v

1431 lines
76 KiB
Verilog

/*------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Copyright (c) 2016, Loongson Technology Corporation Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of Loongson Technology Corporation Limited nor the names of
its contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL LOONGSON TECHNOLOGY CORPORATION LIMITED BE LIABLE
TO ANY PARTY FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
module NAND_top(
nand_type,
pclk,
prst_,
psel,
penable,
pwrite,
ADDR,
DAT_I,
DAT_O,
NAND_CE_o,
NAND_REQ,
NAND_I,
NAND_O,
NAND_EN_,
NAND_ALE,
NAND_CLE,
NAND_WR_,
NAND_RD_,
NAND_IORDY_i,
nand_int
);
input [1:0]nand_type;
input pclk;
input prst_;
input pwrite;
input psel;
input penable;
input [10:0]ADDR;
input [31:0]DAT_I;
output [31:0]DAT_O;
output [3:0]NAND_CE_o;
output NAND_REQ;
input [7:0]NAND_I;
output [7:0]NAND_O;
output NAND_EN_;
output NAND_ALE;
output NAND_CLE;
output NAND_WR_;
output NAND_RD_;
input [3:0]NAND_IORDY_i;
output nand_int;
/************************************************************/
reg [31:0]REG_DAT_T;
reg [13:0]nand_addr_c;
reg [24:0]nand_addr_r;
reg [31:0]nand_op_num;
reg [31:0]nand_parameter;
reg [31:0]nand_ce_map0;
reg [31:0]nand_ce_map1;
reg [31:0]nand_rdy_map0;
reg [31:0]nand_rdy_map1;
reg [31:0]nand_command;
reg [15:0] nand_timing;
reg [37:0] addr_in_die;
reg [4:0] NAND_STATE;
reg [31:0] NAND_OP_NUM;
reg [13:0] WRITE_MAX_COUNT;
reg [13:0] READ_MAX_COUNT;
reg nand_clr_ack;
reg NAND_DONE;
reg NAND_CE_;
reg nand_int;
wire [13:0] op_scope;
wire [2:0] nand_id_num;
wire [3:0] nand_size;
wire main_op;
wire spare_op;
wire nand_int_en;
wire nand_dma_ack_i;
wire NANDtag;
wire NAND_IORDY;
wire HIT0 =psel & ADDR[10:0] == 11'h00;
wire HIT1 =psel & ADDR[10:0] == 11'h04;
wire HIT2 =psel & ADDR[10:0] == 11'h08;
wire HIT3 =psel & ADDR[10:0] == 11'h0c;
wire HIT4 =psel & ADDR[10:0] == 11'h10;
wire HIT5 =psel & ADDR[10:0] == 11'h14;
wire HIT6 =psel & ADDR[10:0] == 11'h18;
wire HIT7 =psel & ADDR[10:0] == 11'h1c;
wire HIT8 =psel & ADDR[10:0] == 11'h20;
wire HIT9 =psel & ADDR[10:0] == 11'h24;
wire HIT10=psel & ADDR[10:0] == 11'h28;
wire HIT11=psel & ADDR[10:0] == 11'h2c;
wire NAND_HIT =penable & ADDR[10:0] == 11'h40;
assign nand_dma_ack_i=psel & ADDR[10:0] == 11'h40;
assign DAT_O = REG_DAT_T;
reg NAND_DMA_REQ;
reg nand_cmd_valid;
always @(posedge pclk)
begin
if(~prst_)
begin
nand_int <= 1'b0;
end
else
begin
nand_int <= NAND_DONE&nand_int_en;
end
end
always @(posedge pclk)
begin
if(~prst_)
begin
nand_clr_ack <= 1'b1;
nand_command <= {1'b0,1'b0,1'b0,1'b0,9'b0,1'b0,NANDtag};
nand_timing <= {8'h4,8'h12};
nand_op_num <= 2048;
nand_addr_c <= 14'h0;
nand_addr_r <= 25'h0;
nand_parameter<= (nand_type==2'h3) ? 32'h800_5100:
(nand_type==2'h2) ? 32'h800_5000: //2'h2 means 1Gbit
(nand_type==2'h1) ? 32'h200_4b00:32'h200_4c00;
nand_ce_map0 <= 32'h0;
nand_ce_map1 <= 32'h0;
nand_rdy_map0 <= 32'h0;
nand_rdy_map1 <= 32'h0;
nand_cmd_valid<=nand_command[0];
end
else
begin
nand_cmd_valid<=nand_command[0];
if(pwrite& HIT0) begin
nand_command[15:0] <= DAT_I[15:0];
end
else if(NAND_DONE && nand_command[0]) begin
nand_command [0] <= 1'b0;
nand_command [10] <= 1'b1;
nand_clr_ack <= 1'b1;
end
else begin
nand_command[31:16] <={NAND_DMA_REQ,1'b0,1'b0,NAND_STATE,NAND_CE_o,NAND_IORDY_i};
if(~NAND_DONE) nand_clr_ack <= 1'b0;
end
if(pwrite& HIT1) nand_addr_c <= DAT_I[13:0];
if(pwrite& HIT2) nand_addr_r <= DAT_I[24:0];
if(pwrite& HIT3) begin
nand_timing[7:0] <= (DAT_I[7:0]<5) ? 8'h5: DAT_I[7:0];
nand_timing[15:8] <= (DAT_I[15:8]<2) ? 8'h2: DAT_I[15:8];
end
if(pwrite& HIT6) nand_parameter<= DAT_I;
if(pwrite& HIT7) nand_op_num <= DAT_I;
if(pwrite& HIT8) nand_ce_map0 <= DAT_I;
if(pwrite& HIT9) nand_ce_map1 <= DAT_I;
else nand_ce_map1 <= {READ_MAX_COUNT,NAND_OP_NUM[15:0]};
if(pwrite& HIT10) nand_rdy_map0 <= DAT_I;
if(pwrite& HIT11) nand_rdy_map1 <= DAT_I;
else nand_rdy_map1 <= {WRITE_MAX_COUNT,NAND_OP_NUM[15:0]};
end
end
assign NANDtag = ~prst_ ? 1'b0 : nand_cmd_valid;
assign op_scope = nand_parameter[29:16];
assign nand_id_num = nand_parameter[14:12];
assign nand_size = nand_parameter[11:8];
assign main_op = nand_command[8];
assign spare_op = nand_command[9];
assign nand_int_en = nand_command[13];
reg [7:0] status;
reg [1:0] nand_number;
reg [47:0] ID_INFORM;
reg [31:0] NAND_DAT_O_RD;
wire [3:0] NAND_CE_pre_o;
wire [3:0] NAND_IORDY_post_i;
always @(posedge pclk)
begin
if(~prst_)
begin
addr_in_die <= 38'h0;
nand_number <= 2'h0;
end
else begin
case(nand_size)
4'h0: begin
nand_number <= nand_addr_r[17:16]; // 1Gb in a single die , page 2048
addr_in_die <= {9'h0,nand_addr_r[15:0],4'b0,nand_addr_c[11:0]};
end
4'h1: begin
nand_number <= nand_addr_r[18:17];
addr_in_die <= {5'h0,nand_addr_r[16:0],4'b0,nand_addr_c[11:0]};
end
4'h2: begin
nand_number <= nand_addr_r[19:18];
addr_in_die <= {4'h0,nand_addr_r[17:0],4'b0,nand_addr_c[11:0]};
end
4'h3: begin
nand_number <= nand_addr_r[20:19];
addr_in_die <= {3'h0,nand_addr_r[18:0],4'b0,nand_addr_c[11:0]};
end
4'h4: begin
nand_number <= nand_addr_r[20:19];
addr_in_die <= {3'h0,nand_addr_r[18:0],3'b0,nand_addr_c[12:0]};
end
4'h5: begin
nand_number <= nand_addr_r[20:19];
addr_in_die <= {3'h0,nand_addr_r[18:0],2'b0,nand_addr_c[13:0]};
end
4'h6: begin
nand_number <= nand_addr_r[21:20];
addr_in_die <= {2'h0,nand_addr_r[19:0],2'b0,nand_addr_c[13:0]};
end
4'h7: begin
nand_number <= nand_addr_r[22:21];
addr_in_die <= {1'h0,nand_addr_r[20:0],2'b0,nand_addr_c[13:0]};
end
4'h9: begin
nand_number <= nand_addr_r[15:14];
addr_in_die <= {15'h0,nand_addr_r[13:0],nand_addr_c[8:0]};
end
4'ha: begin
nand_number <= nand_addr_r[16:15];
addr_in_die <= {14'h0,nand_addr_r[14:0],nand_addr_c[8:0]};
end
4'hb: begin
nand_number <= nand_addr_r[17:16];
addr_in_die <= {13'h0,nand_addr_r[15:0],nand_addr_c[8:0]};
end
4'hc: begin
nand_number <= nand_addr_r[18:17];
addr_in_die <= {12'h0,nand_addr_r[16:0],nand_addr_c[8:0]};
end
4'hd: begin
nand_number <= nand_addr_r[19:18];
addr_in_die <= {11'h0,nand_addr_r[17:0],nand_addr_c[8:0]};
end
default: begin
nand_number <= 2'b0;
addr_in_die <= 38'b0;
end
endcase
end
end
assign NAND_CE_pre_o[0] = (nand_number ==4'h0) ? NAND_CE_ : 1'b1;
assign NAND_CE_pre_o[1] = (nand_number ==4'h1) ? NAND_CE_ : 1'b1;
assign NAND_CE_pre_o[2] = (nand_number ==4'h2) ? NAND_CE_ : 1'b1;
assign NAND_CE_pre_o[3] = (nand_number ==4'h3) ? NAND_CE_ : 1'b1;
assign NAND_IORDY = (nand_number ==4'h0) ? NAND_IORDY_post_i[0]:
(nand_number ==4'h1) ? NAND_IORDY_post_i[1]:
(nand_number ==4'h2) ? NAND_IORDY_post_i[2]:
(nand_number ==4'h3) ? NAND_IORDY_post_i[3]:1'b1;
assign NAND_CE_o[0] = NAND_CE_pre_o[0];
assign NAND_IORDY_post_i[0] = NAND_IORDY_i[0];
assign NAND_CE_o[1] = nand_ce_map0[8 ] ? NAND_CE_pre_o[0]:
nand_ce_map0[9 ] ? NAND_CE_pre_o[1]:
nand_ce_map0[10] ? NAND_CE_pre_o[2]:
nand_ce_map0[11] ? NAND_CE_pre_o[3]:1'b1;
assign NAND_IORDY_post_i[1] = nand_ce_map0[12] ? NAND_IORDY_i[0]:
nand_ce_map0[13] ? NAND_IORDY_i[1]:
nand_ce_map0[14] ? NAND_IORDY_i[2]:
nand_ce_map0[15] ? NAND_IORDY_i[3]:1'b1;
assign NAND_CE_o[2] = nand_ce_map0[16] ? NAND_CE_pre_o[0]:
nand_ce_map0[17] ? NAND_CE_pre_o[1]:
nand_ce_map0[18] ? NAND_CE_pre_o[2]:
nand_ce_map0[19] ? NAND_CE_pre_o[3]:1'b1;
assign NAND_IORDY_post_i[2] = nand_ce_map0[20] ? NAND_IORDY_i[0]:
nand_ce_map0[21] ? NAND_IORDY_i[1]:
nand_ce_map0[22] ? NAND_IORDY_i[2]:
nand_ce_map0[23] ? NAND_IORDY_i[3]:1'b1;
assign NAND_CE_o[3] = nand_ce_map0[24] ? NAND_CE_pre_o[0]:
nand_ce_map0[25] ? NAND_CE_pre_o[1]:
nand_ce_map0[26] ? NAND_CE_pre_o[2]:
nand_ce_map0[27] ? NAND_CE_pre_o[3]:1'b1;
assign NAND_IORDY_post_i[3] = nand_ce_map0[28] ? NAND_IORDY_i[0]:
nand_ce_map0[29] ? NAND_IORDY_i[1]:
nand_ce_map0[30] ? NAND_IORDY_i[2]:
nand_ce_map0[31] ? NAND_IORDY_i[3]:1'b1;
always @(pwrite or penable or NAND_HIT or
HIT0 or HIT1 or HIT2 or HIT3 or
HIT4 or HIT5 or HIT6 or HIT7 or
HIT8 or HIT9 or HIT10 or HIT11 or
nand_command or nand_op_num or nand_addr_c or nand_addr_r or
nand_ce_map0 or nand_ce_map1 or nand_rdy_map0 or nand_rdy_map1 or
nand_timing or nand_parameter or status or ID_INFORM or NAND_DAT_O_RD)
begin
if(~pwrite & HIT0 &penable)
REG_DAT_T = nand_command;
else if(~pwrite & HIT1&penable)
REG_DAT_T = {20'b0,nand_addr_c};
else if(~pwrite & HIT2&penable)
REG_DAT_T = {7'b0,nand_addr_r};
else if(~pwrite & HIT3&penable)
REG_DAT_T = nand_timing;
else if(~pwrite & HIT4&penable)
REG_DAT_T = ID_INFORM[31:0];
else if(~pwrite & HIT5&penable)
REG_DAT_T = {status,ID_INFORM[47:32]};
else if(~pwrite & HIT6&penable)
REG_DAT_T = nand_parameter;
else if(~pwrite & HIT7&penable)
REG_DAT_T = nand_op_num;
else if(~pwrite & HIT8&penable)
REG_DAT_T = nand_ce_map0 ;
else if(~pwrite & HIT9&penable)
REG_DAT_T = nand_ce_map1;
else if(~pwrite & HIT10&penable)
REG_DAT_T = nand_rdy_map0 ;
else if(~pwrite & HIT11&penable)
REG_DAT_T = nand_rdy_map1 ;
else if(~pwrite & NAND_HIT &penable)
REG_DAT_T = NAND_DAT_O_RD;
else REG_DAT_T = 0;
end
reg [1:0] ADDR_pointer;
reg [7:0] NAND_O;
reg [2:0] NAND_ADDR_COUNT;
reg [7:0] WAIT_NUM;
reg [7:0] HOLD_NUM;
reg [7:0] COMMAND;
reg [4:0] PRE_STATE;
reg [2:0] READ_ID_NUM;
reg [13:0] data_count;
reg [37:0] NAND_ADDR;
reg [31:0] NAND_DAT_I_WR;
reg NAND_WR_;
reg NAND_RD_;
reg NAND_CLE;
reg NAND_ALE;
reg NAND_GO;
reg NAND_ACK;
reg DMA_OP_DONE;
reg ERASE_SERIAL;
reg NAND_EN_;
reg now_up_half;
reg now_oob;
assign NAND_REQ =NAND_DMA_REQ;
parameter
NAND_IDLE = 5'b00000,
COMMAND_IN = 5'b00001,
ADDR_4_RD_WR = 5'b00010,
ADDR_4_ERASE_ID = 5'b01010,
READ_START = 5'b00011,
READ_WAIT = 5'b00100,
READ_WAIT_2 = 5'b00110,
READ_TRANSFER = 5'b00111,
WRITE_START = 5'b10000,
WRITE_DATA = 5'b10001,
PROGRAM = 5'b10010,
PROGRAM_FAIL = 5'b10011,
READ_ID = 5'b10100,
READ_STATUS = 5'b10101,
ID_TO_STATUS = 5'b10110,
ERASE = 5'b10111,
WAIT_ERASE = 5'b11000,
ERASE_FAIL = 5'b11001,
RESET = 5'b11010,
WAIT_RESET = 5'b11011;
always @(posedge pclk)
begin
if (~prst_||~NANDtag)
begin
now_up_half <= 1'b0;
now_oob <= 1'b0;
NAND_ACK <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_CE_ <= 1'b1;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_O <= 8'b0;
COMMAND <= 8'h55;
data_count <= 14'b0;
NAND_ADDR <= 38'b0;
NAND_DONE <= 1'b0;
NAND_GO <= 1'b0;
if(~prst_) status <= 8'b0;
if(~prst_) ID_INFORM <= 48'h0;
WAIT_NUM <= 8'h14;
HOLD_NUM <= 8'h4;
PRE_STATE <= 5'b0;
ADDR_pointer <= 2'b0;
NAND_DMA_REQ <= 1'b0;
ERASE_SERIAL <= 1'b0;
NAND_OP_NUM <= 32'h0;
NAND_EN_ <= 1'b0;
NAND_ADDR_COUNT <= 3'b0;
READ_MAX_COUNT <= 14'b0;
WRITE_MAX_COUNT <= 14'b0;
DMA_OP_DONE <= 1'b0;
NAND_DAT_I_WR <= 32'b0;
NAND_DAT_O_RD <= 32'h12345678;
READ_ID_NUM <= 3'b100;
NAND_STATE <= NAND_IDLE;
end
else
begin
case(NAND_STATE)
NAND_IDLE:
begin
HOLD_NUM <= nand_timing[15:8];
if(nand_command[0])
begin
DMA_OP_DONE <= 1'b0;
if(nand_clr_ack)
NAND_DONE <= 1'b0;
if(NAND_OP_NUM==32'b0) begin
NAND_ADDR <= addr_in_die;
NAND_OP_NUM <= nand_op_num;
end
if(nand_command[1] &&NAND_GO && ~NAND_DONE&& (nand_size[3])&&(~main_op||main_op&&NAND_ADDR[8]&&now_up_half)&&spare_op)
begin
COMMAND <= 8'h50;
NAND_EN_ <= 1'b0;
NAND_GO <= 1'b0;
now_oob <= 1'b1;
now_up_half <= 1'b0;
end
else if(nand_command[1] && NAND_ADDR[8]&&nand_size[3]&&NAND_GO && ~NAND_DONE)
begin
COMMAND <= 8'h01;
NAND_EN_ <= 1'b0;
NAND_GO <= 1'b0;
now_oob <= 1'b0;
now_up_half <= main_op&spare_op;
end
else if(nand_command[1] && NAND_GO && ~NAND_DONE)
begin
COMMAND <= 8'h00;
NAND_EN_ <= 1'b0;
NAND_GO <= 1'b0;
now_oob <= 1'b0;
now_up_half <= 1'b0;
end
else if(nand_command[2]&&NAND_GO && ~NAND_DONE&& nand_size[3]&&(~main_op||main_op&&NAND_ADDR[8]&&now_up_half)&&spare_op)
begin
COMMAND <= 8'h50;
NAND_GO <= 1'b0;
now_oob <= 1'b1;
now_up_half <= 1'b0;
end
else if(nand_command[2]&&NAND_GO && ~NAND_DONE&& nand_size[3]&&NAND_ADDR[8])
begin
COMMAND <= 8'h01;
NAND_GO <= 1'b0;
now_oob <= 1'b0;
now_up_half <= main_op&spare_op;
end
else if(nand_command[2]&&NAND_GO && ~NAND_DONE&& nand_size[3]&&~NAND_ADDR[8])
begin
COMMAND <= 8'h0;
NAND_GO <= 1'b0;
now_oob <= 1'b0;
now_up_half <= 1'b0;
end
else if(nand_command[2]&&NAND_GO && ~NAND_DONE)
begin
COMMAND <= 8'h80;
NAND_GO <= 1'b0;
end
else if(nand_command[3]&&NAND_GO&& ~NAND_DONE )
begin
COMMAND <= 8'h60;
NAND_GO <= 1'b0;
ERASE_SERIAL <= nand_command[4];
end
else if(nand_command[5]&&NAND_GO&& ~NAND_DONE)
begin
COMMAND <= 8'h90;
NAND_GO <= 1'b0;
end
else if(nand_command[6]&&NAND_GO&& ~NAND_DONE)
begin
COMMAND <= 8'hFF;
NAND_GO <= 1'b0;
end
else if(nand_command[7]&&NAND_GO&& ~NAND_DONE)
begin
COMMAND <= 8'h70;
NAND_GO <= 1'b0;
end
else if((COMMAND==8'h00 || COMMAND==8'h70 || COMMAND==8'h80 || COMMAND==8'h01 || COMMAND==8'h50 ||
COMMAND==8'h60 || COMMAND==8'h90 || COMMAND==8'hFF)&& ~NAND_DONE) begin
NAND_STATE<= COMMAND_IN;
PRE_STATE <= NAND_IDLE;
WAIT_NUM <= nand_timing[7:0];
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_EN_ <= 1'b0;
end
else begin
COMMAND <= 8'h55;
NAND_GO <= ~NAND_DONE & nand_command[0];
if (~nand_command[0]) NAND_DONE <=1'b0;
end
end else begin
COMMAND <= 8'h55;
NAND_CE_ <= 1'b1;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_STATE <= NAND_IDLE;
NAND_GO <= ~NAND_DONE&nand_command[0];
if(~NAND_GO) begin
NAND_ADDR <= nand_command[0] ? addr_in_die : 38'h3f_ffff_ffff;
NAND_OP_NUM <= nand_command[0] ? nand_op_num : 32'b0;
end
if(nand_clr_ack)
NAND_DONE <= 1'b0;
end
end
COMMAND_IN:
begin
if(WAIT_NUM == nand_timing[7:0]) begin
NAND_CLE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if(WAIT_NUM == (nand_timing[7:0]-1)) begin
NAND_CLE <= 1'b1;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if(WAIT_NUM < nand_timing[7:0] && WAIT_NUM>HOLD_NUM) begin
NAND_O <= COMMAND;
NAND_CLE <= 1'b1;
NAND_WR_ <= 1'b0;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if(WAIT_NUM<=HOLD_NUM && WAIT_NUM) begin
NAND_CLE <= 1'b1;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else
begin
if(PRE_STATE==NAND_IDLE) begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_ALE <= 1'b0;
NAND_DONE <= 1'b0;
NAND_O <= 8'b0;
PRE_STATE <= COMMAND_IN;
if((nand_command[1]||nand_command[2])&&(COMMAND==8'h00||COMMAND==8'h01||COMMAND==8'h50)) begin
NAND_STATE <= nand_command[1] ? READ_START:WRITE_START;
WAIT_NUM <= nand_timing[7:0];
end
else if(nand_command[2]&&(COMMAND==8'h80)) begin
NAND_STATE <= WRITE_START;
WAIT_NUM <= nand_timing[7:0];
end
else if((COMMAND==8'h60)) begin
NAND_STATE <= ERASE;
PRE_STATE <= COMMAND_IN;
WAIT_NUM <= nand_timing[7:0]+2'b11;
end
else if((COMMAND==8'h70)) begin
NAND_STATE <= READ_STATUS;
WAIT_NUM <= nand_timing[7:0]+2'b11;
end
else if((COMMAND==8'h90)) begin
NAND_STATE <= READ_ID;
WAIT_NUM <= nand_timing[7:0]+2'b11;
end
else if((COMMAND==8'hFF)) begin
NAND_STATE <= RESET;
WAIT_NUM <= nand_timing[7:0]+2'b11;
end
else begin
NAND_STATE <= NAND_IDLE;
NAND_OP_NUM <= 32'b0;
NAND_CE_ <= 1'b1;
NAND_DONE <= 1'b1;
end
end
else
begin
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_GO <= 1'b1;
NAND_STATE <= PRE_STATE;
PRE_STATE <= COMMAND_IN;
WAIT_NUM <= nand_timing[7:0];
end
end
end
ADDR_4_ERASE_ID:
begin
if(NAND_ADDR_COUNT != 3'b0)
begin
if(WAIT_NUM > (nand_timing[7:0] - HOLD_NUM+1'b1))
begin
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if(WAIT_NUM > (nand_timing[7:0] - HOLD_NUM))
begin
NAND_ALE <= 1'b1;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if(WAIT_NUM>=HOLD_NUM)
begin
NAND_ALE <= 1'b1;
NAND_WR_ <= 1'b0;
WAIT_NUM <= WAIT_NUM - 1'b1;
if(NAND_ADDR_COUNT == 2'b11) begin
if(nand_size==4'hc||nand_size==4'hd) NAND_O <= NAND_ADDR[16:9];
else NAND_O <= NAND_ADDR[23:16];
end
else if(NAND_ADDR_COUNT==2'b10) begin
if(nand_size==4'h9||nand_size==4'ha||nand_size==4'hb) NAND_O <= NAND_ADDR[16:9];
else if(nand_size==4'hc||nand_size==4'hd) NAND_O <= NAND_ADDR[24:17];
else if(nand_size==4'h0) NAND_O <= NAND_ADDR[23:16];
else NAND_O <= NAND_ADDR[31:24];
end
else if(NAND_ADDR_COUNT==3'b001) begin
if(PRE_STATE == READ_ID)
NAND_O <= NAND_ADDR[7:0];
else
if(nand_size==4'h9||nand_size==4'ha||nand_size==4'hb) NAND_O <= NAND_ADDR[24:17];
else if(nand_size==4'hc||nand_size==4'hd) NAND_O <= NAND_ADDR[32:25];
else if(nand_size==4'h0) NAND_O <= NAND_ADDR[31:24];
else NAND_O <= NAND_ADDR[35:32];
end
end
else if((WAIT_NUM<HOLD_NUM) && WAIT_NUM) begin
NAND_ALE <= 1'b1;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1;
end
else
begin
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0] + 2'b10;
NAND_ADDR_COUNT <= NAND_ADDR_COUNT - 1'b1;
end
end
else
begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_STATE<= PRE_STATE;
PRE_STATE <= ADDR_4_ERASE_ID;
WAIT_NUM <= nand_timing[7:0]+1'b1;
end
end
ADDR_4_RD_WR:
begin
if(NAND_ADDR_COUNT != 3'b0) begin
if(WAIT_NUM > (nand_timing[7:0] - HOLD_NUM + 1'b1)) begin
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if(WAIT_NUM > (nand_timing[7:0]- HOLD_NUM)) begin
NAND_ALE <= 1'b1;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if(WAIT_NUM>=HOLD_NUM) begin
NAND_ALE <= 1'b1;
NAND_WR_ <= 1'b0;
WAIT_NUM <= WAIT_NUM - 1'b1;
if(NAND_ADDR_COUNT==3'b101)
NAND_O <= NAND_ADDR[7:0];
else if(NAND_ADDR_COUNT==3'b100) begin
if(nand_size==4'hc||nand_size==4'hd) NAND_O <= NAND_ADDR[7:0];
else if(nand_size==4'h0) NAND_O <= NAND_ADDR[7:0];
else NAND_O <= NAND_ADDR[15:8];
end
else if(NAND_ADDR_COUNT==3'b11) begin
if(nand_size==4'h9||nand_size==4'ha||nand_size==4'hb) NAND_O <= NAND_ADDR[7:0];
else if(nand_size==4'hc||nand_size==4'hd) NAND_O <= NAND_ADDR[16:9];
else if(nand_size==4'h0) NAND_O <= NAND_ADDR[15:8];
else NAND_O <= NAND_ADDR[23:16];
end
else if(NAND_ADDR_COUNT==3'b10)begin
if(nand_size==4'h9||nand_size==4'ha||nand_size==4'hb) NAND_O <= NAND_ADDR[16:9];
else if(nand_size==4'hc||nand_size==4'hd) NAND_O <= NAND_ADDR[24:17];
else if(nand_size==4'h0) NAND_O <= NAND_ADDR[23:16];
else NAND_O <= NAND_ADDR[31:24];
end
else if(NAND_ADDR_COUNT==3'b1) begin
if(nand_size==4'h9||nand_size==4'ha||nand_size==4'hb) NAND_O <= NAND_ADDR[24:17];
else if(nand_size==4'hc||nand_size==4'hd) NAND_O <= NAND_ADDR[32:25];
else if(nand_size==4'h0) NAND_O <= NAND_ADDR[31:24];
else NAND_O <= NAND_ADDR[37:32];
end
end
else if((WAIT_NUM<HOLD_NUM) && WAIT_NUM) begin
NAND_ALE <= 1'b1;
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else begin
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0]+2'b10;
NAND_ADDR_COUNT <= NAND_ADDR_COUNT - 1'b1;
end
end
else begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_STATE <= PRE_STATE;
PRE_STATE <= ADDR_4_RD_WR;
WAIT_NUM <= nand_timing[7:0]+1'b1;
end
end
READ_START:
begin
if( (PRE_STATE==COMMAND_IN) && (COMMAND == 8'h30)||(PRE_STATE==ADDR_4_RD_WR)&&nand_size[3] ) begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_STATE<= NAND_IORDY ? READ_START : READ_WAIT;
end
else if((PRE_STATE==ADDR_4_RD_WR) && (COMMAND != 8'h30) ) begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0];
PRE_STATE <= READ_START;
NAND_STATE<= COMMAND_IN;
COMMAND <= 8'h30;
end
else begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0];
PRE_STATE <= READ_START;
NAND_STATE<= ADDR_4_RD_WR;
NAND_ADDR_COUNT <= (nand_size==4'h9||nand_size==4'ha||nand_size==4'hb) ? 3'b011 : (nand_size==4'h0||nand_size==4'hc||nand_size==4'hd) ? 3'b100:3'b101;
end
end
READ_WAIT:
begin
if(NAND_IORDY==1'b0) begin
NAND_STATE <= READ_WAIT;
end
else begin
NAND_RD_ <= 1'b1;
NAND_STATE <= READ_WAIT_2;
end
end
READ_WAIT_2:
begin
data_count <= 14'b0;
ADDR_pointer <= 2'b0;
NAND_EN_ <= 1'b1;
DMA_OP_DONE <= 1'b1;
NAND_STATE <= READ_TRANSFER;
WAIT_NUM <= nand_timing[7:0];
case(nand_size)
4'h9,
4'ha,
4'hb,
4'hc,
4'hd:
begin
NAND_ADDR[7:0] <= 8'h0;
NAND_ADDR[30:8] <= spare_op&& (~main_op)? (NAND_ADDR[30:8] +2'b10) : now_up_half ? NAND_ADDR[30:8] : (NAND_ADDR[30:8] +1'b1);
if(spare_op && main_op&&~now_oob)
READ_MAX_COUNT <= (NAND_OP_NUM>(256-NAND_ADDR[7:0]))? (256-NAND_ADDR[7:0]) : NAND_OP_NUM;
else if(now_oob)
READ_MAX_COUNT <= (NAND_OP_NUM>(16-NAND_ADDR[3:0]))? (16-NAND_ADDR[3:0]) : NAND_OP_NUM;
else
READ_MAX_COUNT <= (NAND_OP_NUM>(256-NAND_ADDR[7:0]))? (256-NAND_ADDR[7:0]) : NAND_OP_NUM;
end
4'h0,
4'h1,
4'h2,
4'h3: begin
NAND_ADDR[10:0] <= 11'h0;
NAND_ADDR[11] <= spare_op&(~main_op);
NAND_ADDR[35:16] <= NAND_ADDR[35:16] +1'b1;
if(spare_op && main_op)
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[11:0]))? (op_scope-NAND_ADDR[11:0]) : NAND_OP_NUM;
else if(spare_op)
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[5:0])) ? (op_scope-NAND_ADDR[5:0]) : NAND_OP_NUM;
else
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[10:0]))? (op_scope-NAND_ADDR[10:0]) : NAND_OP_NUM;
end
4'h4: begin
NAND_ADDR[11:0] <= 12'h0;
NAND_ADDR[12] <= spare_op&(~main_op);
NAND_ADDR[35:16] <= NAND_ADDR[35:16] +1'b1;
if(spare_op && main_op)
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[12:0]))? (op_scope-NAND_ADDR[12:0]) : NAND_OP_NUM;
else if(spare_op)
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[6:0])) ? (op_scope-NAND_ADDR[6:0]) : NAND_OP_NUM;
else
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[11:0]))? (op_scope-NAND_ADDR[11:0]) : NAND_OP_NUM;
end
4'h5,
4'h6,
4'h7: begin
NAND_ADDR[12:0] <= 13'h0;
NAND_ADDR[13] <= spare_op&(~main_op);
NAND_ADDR[35:16] <= NAND_ADDR[35:16] +1'b1;
if(spare_op && main_op)
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[13:0]))? (op_scope-NAND_ADDR[13:0]) : NAND_OP_NUM;
else if(spare_op)
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[7:0])) ? (op_scope-NAND_ADDR[7:0]) : NAND_OP_NUM;
else
READ_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[12:0]))? (op_scope-NAND_ADDR[12:0]) : NAND_OP_NUM;
end
default: begin end
endcase
end
READ_TRANSFER:
begin
if(~NAND_IORDY)
begin
if (~DMA_OP_DONE && ~NAND_HIT)
begin
NAND_DMA_REQ <= 1'b1;
end
else if(NAND_DMA_REQ && NAND_HIT)
begin
NAND_DMA_REQ <= 1'b0;
DMA_OP_DONE <= 1'b1;
ADDR_pointer <= 2'b0;
WAIT_NUM <= nand_timing[7:0];
end
end
else if((data_count != READ_MAX_COUNT) && ~NAND_CE_)
begin
if ((~DMA_OP_DONE||DMA_OP_DONE &&ADDR_pointer==2'h3&&WAIT_NUM==2&&(data_count < (READ_MAX_COUNT-3'h4))) && ~NAND_HIT )
begin
NAND_DMA_REQ <= 1'b1;
end
else if(NAND_HIT && NAND_DMA_REQ) begin
NAND_DMA_REQ <= 1'b0;
DMA_OP_DONE <= 1'b1;
if(data_count == READ_MAX_COUNT -1'b1) begin
data_count <= READ_MAX_COUNT;
end
end
if ((WAIT_NUM > (nand_timing[7:0]-HOLD_NUM+1'b1))&&(DMA_OP_DONE||NAND_HIT)) begin
NAND_RD_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if ((WAIT_NUM > 1) && (DMA_OP_DONE&&~NAND_DMA_REQ) )
begin
NAND_RD_ <= 1'b0;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if((WAIT_NUM==1)&& (DMA_OP_DONE))
begin
NAND_RD_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0];
ADDR_pointer <= ADDR_pointer + 1'b1;
if(data_count!=READ_MAX_COUNT -1'b1) data_count <= data_count + 1'b1;
if(NAND_OP_NUM!=32'b0) NAND_OP_NUM <= NAND_OP_NUM - 1'b1;
if(ADDR_pointer==2'b0) NAND_DAT_O_RD[7:0] <= NAND_I;
else if(ADDR_pointer==2'b01) NAND_DAT_O_RD[15:8] <= NAND_I;
else if(ADDR_pointer==2'b10) NAND_DAT_O_RD[23:16] <= NAND_I;
else if(ADDR_pointer==2'b11) begin
NAND_DAT_O_RD[31:24] <= NAND_I;
DMA_OP_DONE <= 1'b0;
end
end
end
else
begin
NAND_DMA_REQ <= 1'b0;
data_count <= 14'b0;
NAND_STATE <= NAND_IDLE;
WAIT_NUM <= nand_timing[7:0];
if(NAND_OP_NUM==32'b0) begin
NAND_GO <= 1'b0;
NAND_DONE <= 1'b1;
NAND_CE_ <= 1'b1;
end
else begin
NAND_GO <= 1'b1;
NAND_DONE <= 1'b0;
NAND_CE_ <= 1'b0;
end
end
end
WRITE_START: begin
if(PRE_STATE == COMMAND_IN&&COMMAND!=8'h80) begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0];
PRE_STATE <= WRITE_START;
NAND_STATE<= COMMAND_IN;
COMMAND <= 8'h80;
end
else if(PRE_STATE == COMMAND_IN) begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0];
PRE_STATE <= WRITE_START;
NAND_STATE<= ADDR_4_RD_WR;
NAND_ADDR_COUNT <= (nand_size==4'h9||nand_size==4'ha||nand_size==4'hb) ? 3'b011 : (nand_size==4'h0||nand_size==4'hc||nand_size==4'hd) ? 3'b100:3'b101;
end
else if(PRE_STATE==ADDR_4_RD_WR) begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
ADDR_pointer<= 2'b0;
data_count <= 14'h0;
WAIT_NUM <= nand_timing[7:0];
NAND_STATE <= WRITE_DATA;
case(nand_size)
4'h9,
4'ha,
4'hb,
4'hc,
4'hd:
begin
NAND_ADDR[7:0] <= 8'h0;
NAND_ADDR[30:8] <= spare_op&& (~main_op)? (NAND_ADDR[30:8] +2'b10) : now_up_half ? NAND_ADDR[30:8] : (NAND_ADDR[30:8] +1'b1);
if(spare_op && main_op&&~now_oob)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(256-NAND_ADDR[7:0]))? (256-NAND_ADDR[7:0]) : NAND_OP_NUM;
else if(now_oob)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(16-NAND_ADDR[3:0])) ? (16-NAND_ADDR[3:0]) : NAND_OP_NUM;
else
WRITE_MAX_COUNT <= (NAND_OP_NUM>(256-NAND_ADDR[7:0]))? (256-NAND_ADDR[7:0]) : NAND_OP_NUM;
end
4'h0,
4'h1,
4'h2,
4'h3: begin
NAND_ADDR[10:0] <= 11'h0;
NAND_ADDR[11] <= spare_op&(~main_op);
NAND_ADDR[35:16] <= NAND_ADDR[35:16] +1'b1;
if(spare_op && main_op)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[11:0]))? (op_scope-NAND_ADDR[11:0]) : NAND_OP_NUM;
else if(spare_op)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[5:0])) ? (op_scope-NAND_ADDR[5:0]) : NAND_OP_NUM;
else
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[10:0]))? (op_scope-NAND_ADDR[10:0]) : NAND_OP_NUM;
end
4'h4: begin
NAND_ADDR[11:0] <= 12'h0;
NAND_ADDR[12] <= spare_op&(~main_op);
NAND_ADDR[35:16] <= NAND_ADDR[35:16] +1'b1;
if(spare_op && main_op)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[12:0]))? (op_scope-NAND_ADDR[12:0]) : NAND_OP_NUM;
else if(spare_op)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[6:0])) ? (op_scope-NAND_ADDR[6:0]) : NAND_OP_NUM;
else
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[11:0]))? (op_scope-NAND_ADDR[11:0]) : NAND_OP_NUM;
end
4'h5,
4'h6,
4'h7: begin
NAND_ADDR[12:0] <= 13'h0;
NAND_ADDR[13] <= spare_op&(~main_op);
NAND_ADDR[35:16] <= NAND_ADDR[35:16] +1'b1;
if(spare_op && main_op)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[13:0]))? (op_scope-NAND_ADDR[13:0]) : NAND_OP_NUM;
else if(spare_op)
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[7:0])) ? (op_scope-NAND_ADDR[7:0]) : NAND_OP_NUM;
else
WRITE_MAX_COUNT <= (NAND_OP_NUM>(op_scope-NAND_ADDR[12:0]))? (op_scope-NAND_ADDR[12:0]) : NAND_OP_NUM;
end
default: begin end
endcase
end
end
WRITE_DATA:
begin
if(data_count != WRITE_MAX_COUNT )
begin
if(~DMA_OP_DONE&&~NAND_HIT)
NAND_DMA_REQ <= 1'b1;
else if(DMA_OP_DONE&&~NAND_HIT&&ADDR_pointer==2'h3&&WAIT_NUM==2&&(data_count < (WRITE_MAX_COUNT-3'h4)))
NAND_DMA_REQ <= 1'b1;
else if(NAND_DMA_REQ && NAND_HIT) begin
NAND_DMA_REQ <= 1'b0;
ADDR_pointer <= 2'b0;
DMA_OP_DONE <= 1'b1;
NAND_DAT_I_WR <= DAT_I;
end
if ((WAIT_NUM > (nand_timing[7:0]-HOLD_NUM+1'b1))&&(DMA_OP_DONE||NAND_HIT)) begin
NAND_WR_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
end
else if ((WAIT_NUM > 1'b1) && DMA_OP_DONE) begin
NAND_WR_ <= 1'b0;
WAIT_NUM <= WAIT_NUM - 1'b1;
if (ADDR_pointer ==2'b0)
NAND_O <= NAND_DAT_I_WR[7:0];
else if (ADDR_pointer ==2'b1)
NAND_O <= NAND_DAT_I_WR[15:8];
else if (ADDR_pointer ==2'b10)
NAND_O<= NAND_DAT_I_WR[23:16];
else if (ADDR_pointer ==2'b11)
begin
NAND_O <= NAND_DAT_I_WR[31:24];
end
end
else if((WAIT_NUM == 1'b1)&&DMA_OP_DONE) begin
NAND_WR_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0];
ADDR_pointer <= ADDR_pointer + 1'b1;
if(ADDR_pointer ==2'b11) begin
DMA_OP_DONE <= 1'b0;
if(NAND_OP_NUM >=32'h4)
NAND_OP_NUM <= NAND_OP_NUM - 3'b100;
else
NAND_OP_NUM <= 32'h0;
if(NAND_OP_NUM == 32'h4)
data_count <= WRITE_MAX_COUNT;
else
data_count <= data_count + 3'b100;
end
end
end
else if(PRE_STATE != COMMAND_IN && COMMAND==8'h80)
begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_STATE <= COMMAND_IN;
PRE_STATE <= WRITE_DATA;
COMMAND <= 8'h10;
DMA_OP_DONE <= 1'b0;
WAIT_NUM <= nand_timing[7:0];
end
else if(PRE_STATE == COMMAND_IN && COMMAND==8'h10) begin
NAND_CE_ <= 1'b0;
NAND_STATE <= NAND_IORDY ? WRITE_DATA:PROGRAM;
end
else if(PRE_STATE == PROGRAM && COMMAND==8'h10) begin
NAND_STATE <= COMMAND_IN;
PRE_STATE <= WRITE_DATA;
COMMAND <= 8'h70;
WAIT_NUM <= nand_timing[7:0];
NAND_CE_ <= 1'b0;
end
else if(PRE_STATE == COMMAND_IN && COMMAND==8'h70) begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_STATE<= READ_STATUS;
PRE_STATE <= WRITE_DATA;
WAIT_NUM <= nand_timing[7:0]+2'b11;
NAND_EN_ <= 1'b1;
end
else if(PRE_STATE == READ_STATUS)
begin
if(status[0]==0 && NAND_OP_NUM ==32'b0)
begin
NAND_STATE <= NAND_IDLE;
NAND_DONE <= 1'b1;
NAND_DMA_REQ <= 1'b0;
end
else if(status[0]==0)
begin
NAND_STATE <= NAND_IDLE;
NAND_DONE <= 1'b0;
end
else
begin
NAND_STATE <= PROGRAM_FAIL;
NAND_DONE <= 1'b1;
NAND_DMA_REQ<= 1'b0;
end
end
else
begin
NAND_STATE <= NAND_IDLE;
NAND_DONE <=1;
NAND_DMA_REQ <= 1'b0;
end
end
PROGRAM:
begin
if(NAND_IORDY==1'b0) begin
NAND_STATE <= PROGRAM;
end
else begin
PRE_STATE <= PROGRAM;
NAND_STATE <= WRITE_DATA;
DMA_OP_DONE <= 1'b0;
end
end
RESET:
begin
if(NAND_IORDY==1'b1) begin
NAND_STATE <= RESET;
end
else begin
NAND_STATE <= WAIT_RESET;
PRE_STATE <= RESET;
end
end
WAIT_RESET:
begin
if(NAND_IORDY) begin
NAND_STATE <= NAND_IDLE;
PRE_STATE <= WAIT_RESET;
NAND_CE_ <= 1'b1;
NAND_DONE <= 1'b1;
NAND_GO <= 1'b0;
end
else
NAND_STATE <= WAIT_RESET;
end
READ_STATUS:
begin
if(WAIT_NUM >= (nand_timing[7:0]- HOLD_NUM+1'b1)) begin
WAIT_NUM <= WAIT_NUM - 1'b1;
NAND_STATE <= READ_STATUS;
NAND_RD_ <= 1'b1;
NAND_EN_ <= 1'b1;
end
else if(WAIT_NUM && WAIT_NUM >1 ) begin
WAIT_NUM <= WAIT_NUM - 1'b1;
NAND_STATE <= READ_STATUS;
NAND_RD_ <= 1'b0;
NAND_EN_ <= 1'b1;
end
else if(WAIT_NUM == 1) begin
WAIT_NUM <= WAIT_NUM - 1'b1;
NAND_STATE <= READ_STATUS;
status <= NAND_I;
NAND_RD_ <= 1'b1;
NAND_EN_ <= 1'b1;
end
else if(WAIT_NUM==8'b0) begin
NAND_RD_ <= 1'b1;
NAND_CE_ <= 1'b0;
PRE_STATE <= READ_STATUS;
NAND_STATE <= PRE_STATE;
WAIT_NUM <= nand_timing[7:0];
if(PRE_STATE == 5'h1)
NAND_DONE <= 1'b1;
end
else begin
WAIT_NUM <= WAIT_NUM - 1'b1;
NAND_STATE <= READ_STATUS;
NAND_RD_ <= 1'b1;
NAND_EN_ <= 1'b1;
end
end
PROGRAM_FAIL,ERASE_FAIL:
begin
NAND_STATE <= NAND_IDLE;
NAND_CE_ <= 1'b1;
NAND_DONE <= 1'b1;
end
ERASE:
begin
if( (PRE_STATE != ADDR_4_ERASE_ID) && (COMMAND == 8'h60) )
begin
NAND_STATE <= ADDR_4_ERASE_ID;
PRE_STATE <= ERASE;
WAIT_NUM <= nand_timing[7:0];
NAND_ADDR_COUNT <= (nand_size==4'h9||nand_size==4'ha||nand_size==4'hb||nand_size==4'h0) ? 3'b10:3'b011;
end
else if( (PRE_STATE != COMMAND_IN) && (COMMAND == 8'h60) )
begin
NAND_STATE <= COMMAND_IN;
PRE_STATE <= ERASE;
COMMAND <= 8'hD0;
WAIT_NUM <= nand_timing[7:0];
end
else if(PRE_STATE==COMMAND_IN && COMMAND== 8'hd0)
begin
NAND_STATE <= NAND_IORDY ? ERASE : WAIT_ERASE;
end
end
WAIT_ERASE:
begin
if(NAND_IORDY==1'b0) begin
NAND_STATE <= WAIT_ERASE;
end
else if(NAND_IORDY && PRE_STATE == COMMAND_IN && COMMAND == 8'h60)
begin
NAND_STATE <= ERASE;
PRE_STATE <= WAIT_ERASE;
end
else if(NAND_IORDY && COMMAND ==8'hd0 )
begin
NAND_OP_NUM <= NAND_OP_NUM - 1'b1;
NAND_STATE <= COMMAND_IN;
PRE_STATE <= WAIT_ERASE;
COMMAND <= 8'h70;
WAIT_NUM <= nand_timing[7:0];
NAND_CE_ <= 1'b0;
end
else if(NAND_IORDY && PRE_STATE == COMMAND_IN && COMMAND==8'h70)
begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_STATE<= READ_STATUS;
PRE_STATE <= WAIT_ERASE;
WAIT_NUM <= nand_timing[7:0]+2'b11;
NAND_EN_ <= 1'b1;
end
else if(NAND_IORDY && PRE_STATE == READ_STATUS)
begin
if(status[0]==1'b0 && (NAND_OP_NUM==32'b0 || ERASE_SERIAL == 1'b0) )
begin
NAND_STATE <= NAND_IDLE;
NAND_CE_ <= 1'b1;
NAND_DONE <= 1'b1;
NAND_ADDR <= 36'h0;
ERASE_SERIAL<= 1'b0;
end
else if(status[0]== 1'b0 && NAND_OP_NUM!=32'b0)
begin
NAND_STATE <= COMMAND_IN;
PRE_STATE <= WAIT_ERASE;
COMMAND <= 8'h60;
NAND_DONE <= 1'b0;
WAIT_NUM <= nand_timing[7:0];
NAND_CE_ <= 1'b0;
NAND_EN_ <= 1'b0;
if(nand_size[3]) NAND_ADDR[27:14] <= NAND_ADDR[27:14] + 1'b1;
else if(nand_size==4'h1||nand_size==4'h2||nand_size==4'h3) NAND_ADDR[35:22] <= NAND_ADDR[35:22] + 1'b1;
else if(nand_size==4'h4) NAND_ADDR[33:22] <= NAND_ADDR[33:22] + 1'b1;
else if(nand_size==4'h5) NAND_ADDR[33:24] <= NAND_ADDR[33:24] + 1'b1;
else NAND_ADDR[35:25] <= NAND_ADDR[35:25] + 1'b1;
end
else
begin
NAND_STATE <= ERASE_FAIL;
NAND_DONE <= 1'b1;
end
end
else begin
NAND_STATE <= NAND_IDLE;
NAND_CE_ <= 1'b1;
NAND_DONE <= 1'b1;
end
end
READ_ID:
begin
if((PRE_STATE != ADDR_4_ERASE_ID) && COMMAND == 8'h90)
begin
NAND_STATE <= ADDR_4_ERASE_ID;
PRE_STATE <= READ_ID;
WAIT_NUM <= nand_timing[7:0]+1'b1;
READ_ID_NUM <= nand_id_num;
NAND_ADDR_COUNT <= 3'b1;
end
else if (COMMAND != 8'h70)
begin
if (READ_ID_NUM!=3'b0)
begin
NAND_EN_ <= 1'b1;
if(WAIT_NUM>(nand_timing[7:0]+1'b1-HOLD_NUM))
begin
NAND_RD_ <= 1'b1;
WAIT_NUM <= WAIT_NUM - 1'b1;
NAND_STATE<= READ_ID;
end
else if (WAIT_NUM > 1)
begin
WAIT_NUM <= WAIT_NUM - 1'b1;
NAND_RD_ <= 1'b0;
NAND_STATE<= READ_ID;
end
else if(WAIT_NUM==1)
begin
NAND_STATE <= READ_ID;
NAND_RD_ <= 1'b1;
WAIT_NUM <= nand_timing[7:0];
READ_ID_NUM <= READ_ID_NUM - 2'b1;
if (READ_ID_NUM==3'b01)
ID_INFORM[7:0] <= NAND_I;
else if (READ_ID_NUM==3'b10)
ID_INFORM[15:8] <= NAND_I;
else if (READ_ID_NUM==3'b11)
ID_INFORM[23:16] <= NAND_I;
else if (READ_ID_NUM==3'b100)
ID_INFORM[31:24] <= NAND_I;
else if (READ_ID_NUM==3'b101)
ID_INFORM[39:32] <= NAND_I;
else if (READ_ID_NUM==3'b110)
ID_INFORM[47:40] <= NAND_I;
end
end
else
begin
NAND_STATE <= COMMAND_IN;
PRE_STATE <= READ_ID;
COMMAND <= 8'h70;
WAIT_NUM <= nand_timing[7:0];
NAND_CE_ <= 1'b0;
NAND_EN_ <= 1'b0;
end
end
else
begin
NAND_STATE <= ID_TO_STATUS;
PRE_STATE <= READ_ID;
NAND_EN_ <= 1'b1;
COMMAND <= 8'h70;
end
end
ID_TO_STATUS:
begin
if(PRE_STATE != READ_STATUS)
begin
NAND_CE_ <= 1'b0;
NAND_CLE <= 1'b0;
NAND_ALE <= 1'b0;
NAND_WR_ <= 1'b1;
NAND_RD_ <= 1'b1;
NAND_STATE<= READ_STATUS;
PRE_STATE <= ID_TO_STATUS;
WAIT_NUM <= nand_timing[7:0]+2'b11;
NAND_EN_ <= 1'b1;
end
else
begin
NAND_DONE <= 1'b1;
NAND_GO <= 1'b0;
NAND_STATE <= NAND_IDLE;
NAND_CE_ <= 1'b1;
end
end
default :
begin
NAND_STATE <= NAND_IDLE;
NAND_CE_ <= 1'b1;
NAND_GO <= 1'b0;
NAND_DONE <= 1'b0;
NAND_DMA_REQ <= 1'b0;
end
endcase
end
end
endmodule