www.pudn.com > NAND_Controller_and_ECC_VHDL.zip > st2FSM.vhd
------------------------------------------------------------------------------------------
--[Disclaimer]
--This VHDL code and all associated documentation, comments or other information
--(collectively "VHDL CODE") is provided "AS IS" without warranty of any kind. MICRON
--TECHNOLOGY, INC. ("MTI") EXPRESSLY DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED,
--INCLUDING BUT NOT LIMITED TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED
--WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
--WARRANT THAT THE VHDL CODE WILL MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF THE
--VHDL CODE WILL BE UNINTERRUPTED OR ERROR-FREE. FURTHERMORE, MTI DOES NOT MAKE ANY
--REPRESENTATIONS REGARDING THE USE OR THE RESULTS OF THE USE OF THE VHDL CODE IN TERMS
--OF ITS CORRECTNESS, ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT
--OF USE OR PERFORMANCE OF THE VHDL CODE REMAINS WITH YOU. IN NO EVENT SHALL MTI, ITS
--AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL,
--INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS,
--BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY
--TO USE THE VHDL CODE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
--Because some jurisdictions prohibit the exclusion or limitation of liability for
--consequential or incidental damages, the above limitation may not apply to you.
--
--Copyright 2005 Micron Technology, Inc. All rights reserved.
--------------------------------------------------------------------------------------------
---------------------------------------------------
-- FSM begins
---------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following lines to use the declarations that are
-- provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;
entity FSM_MNvcS2 is
generic(
nandBUSwidth: natural := 8;
ErrorFetchCommand: std_logic_vector(7 downto 0) := x"23"
);
port(
-- Debug signals
DebugCURaddreg: out std_logic;
DebugInternalCNT: out std_logic_vector(23 downto 0);
-- Standard synchronous inputs
clk : in std_logic;
Reset_L : in std_logic;
-- STANDARD SRAM interface
ADDR : in std_logic_vector(11 downto 0);
ST2outDATA : out std_logic_vector(7 downto 0);
ST2inDATA : in std_logic_vector(7 downto 0);
CE_L : in std_logic;
WE_L : in std_logic;
OE_L : in std_logic;
INT : out std_logic;
RB_L : out std_logic;
-- NAND or NAND ecc module interface
nandCE_L : out std_logic;
nandCLE_H : out std_logic;
nandALE_H : out std_logic;
nandWE_L : out std_logic;
nandRE_L : out std_logic;
nandWP_L : out std_logic;
nandPRE : out std_logic;
nandDATA : inout std_logic_vector(7 downto 0);
nandRB_L : in std_logic;
errINT : in std_logic;
-- Control signals
-- REGfile signals
--WE_regfile_H: out std_logic;
--REGnum: out std_logic_vector(3 downto 0);
--REGfile_DATA: out std_logic_vector(7 downto 0);
--REGfile_DATAout: in std_logic_vector(7 downto 0);
-- BUFFER1 signals
WE_buffer1_H: out std_logic;
buffer1_ADDR: out std_logic_vector(11 downto 0);
buffer1_DATA: out std_logic_vector(7 downto 0);
buffer1_DATAout: in std_logic_vector(7 downto 0);
-- BUFFER2 signals
WE_buffer2_H: out std_logic;
buffer2_ADDR: out std_logic_vector(11 downto 0);
buffer2_DATA: out std_logic_vector(7 downto 0);
buffer2_DATAout: in std_logic_vector(7 downto 0);
-- disabling ECC module signal
enableECCmodule: out std_logic
);
end FSM_MNvcS2;
architecture syn of FSM_MNvcS2 is
type state is (Start, enableTOG0, STreadstatusCMD, STreadstatusREAD, STreadID, STreadIDadd00,
STreadIDfourReads, STeraseblock, STeraseblockADDcycles, STeraseblockCMDd0,
STresetNAND, STreadpage, STreadpageADDlatch00, STreadpageADDlatch3cycles,
STreadpageCMDfinal30h, STreadpageREADS, STreadpageSWAPbuf, STwaitforRB0,
STwaitforRB1, STprogrampage, STprogrampageADDlatch00, STprogrampageADDlatch3cycles,
STprogrampageWRITES, STprogrampageCMDfinal10h, STprogrampageCHbuf,
STprogrampageSWstatusRB, STfetchERRORs, STfetchERRORseightReads, STreadpageCORwaitforRB,
STreadpageCORRECT, STreadpageCORRECTaddr);
type command is (ReadID, pageREAD, programPAGE, ReadSTATUS, erasepage, resetnand);
-- state signals for state machine
signal Cstate : state;
signal Nstate : state;
signal NEXTtonextST, NEXTtonextST2: state;
signal internal_nandDATA: std_logic_vector(nandBUSwidth - 1 downto 0);
-- FSM mux select signals
signal buffer1_nandDATA_in, buffer2_nandDATA_in, nandDATA_from_buffer1, nandDATA_from_buffer2, nandDATA_fsm : std_logic;
signal outputVEC1, outputVEC2: std_logic_vector(4 downto 0);
-- Repetition counter signals
signal internalCNT, CNTupto, internalCNTaddr: std_logic_vector(11 downto 0);
signal internalCNTRst_L, incintCNT, OnedelayedINCcnt : std_logic;
-- Toggle state machine stuff
signal enableTOGGLE, doneTOGGLE: std_logic;
type TOGstate is (toggleWAIT, toggle1, toggle2, toggleDONE);
signal cTOGstate: TOGstate;
signal delayCNT: std_logic_vector(2 downto 0);
signal incDcnt, rstDcnt_L: std_logic;
signal nTOGstate: TOGstate;
-- System attributes i.e. Register FILE registers
signal Device8_not16, ECCpresent, buffer1or2: std_logic;
signal Device_Size:std_logic_vector(1 downto 0);
signal CommandREG, StatusREG: std_logic_vector(7 downto 0);
-- Error location array
type errorLOCtype is array (7 downto 0) of std_logic_vector(7 downto 0);
signal errorLOC: errorLOCtype;
type nandIDtype is array (3 downto 0) of std_logic_vector(7 downto 0);
type regADDRtype is array (2 downto 0) of std_logic_vector(7 downto 0);
type DOUBLEregADDRtype is array (1 downto 0) of regADDRtype;
signal nandID: nandIDtype;
signal REGaddress: DOUBLEregADDRtype;
signal currentADDreg, flipTHEt: std_logic;
signal DEBUGstatevector: std_logic_vector(7 downto 0);
signal nandRB_Lreg1, nandRB_Lfinal: std_logic;
--signal ADDressaddr: std_logic_vector(1 downto 0);
-- signals for error correction
signal errCORaddrIN, corWE: std_logic;
signal corINPUTdata: std_logic_vector(7 downto 0);
signal corADDR: std_logic_vector(11 downto 0);
-- Constants based on control registers
signal bytesCONTROLLED: std_logic_vector(11 downto 0);
begin
punchOUTconstants: process(ECCpresent)
begin
if(ECCpresent = '0') then
bytesCONTROLLED <= x"840";
else
bytesCONTROLLED <= x"834";
end if;
end process punchOUTconstants;
doublebufnandRB_L:process(clk)
begin
if(rising_edge(clk)) then
nandRB_Lreg1 <= nandRB_L;
nandRB_Lfinal <= nandRB_Lreg1;
end if;
end process;
DebugCURaddreg <= OneDelayedINCcnt;
--DebugInternalCNT <= internalCNTaddr; --DebugInternalCNT <= "0000" & DEBUGstatevector;
--DebugInternalCNT <= buffer1or2 & nandDATA_fsm & nandDATA_from_buffer2 & nandDATA_from_buffer1 & DEBUGstatevector;
--DebugInternalCNT <= delayCNT & nandDATA_from_buffer1 & DEBUGstatevector;
DebugInternalCNT <= corADDR & corWE & errCORaddrIN & errINT & nandRB_L & DEBUGstatevector;
TflipFLOPprocess:process(clk, Reset_L, flipTHEt, currentADDreg)
begin
if(rising_edge(clk)) then
if(reset_L = '0') then
currentADDreg <= '0';
else
if(flipTHEt = '1') then
currentADDreg <= not(currentADDreg);
end if;
end if;
end if;
end process TflipFLOPprocess;
enableECCmodule <= ECCpresent;
statemachine: process(clk, Reset_L, cSTATE, nandRB_Lfinal, buffer1or2, buffer2_DATAout, buffer1_DATAout)
variable nandaddress1, nandaddress2, nandaddress3: std_logic_vector(7 downto 0);
-- Format
-- bit 0 - CE_L
-- bit 1 - CLE_H
-- bit 2 - ALE_H
-- bit 3 - WE_L
-- bit 4 - RE_L
variable currentCMD: command;
variable VARcorINPUTdata: std_logic_vector(7 downto 0);
variable outputFROMbuf: std_logic_vector(7 downto 0);
begin
if (buffer1or2 = '0') then
outputFROMbuf := buffer2_DATAout;
else
outputFROMbuf := buffer1_DATAout;
end if;
case errorLOC(conv_integer(internalCNT(1 downto 0) & '0'))(2 downto 0) is
when "000" =>
VARcorINPUTdata := outputFROMbuf(7 downto 1) & not(outputFROMbuf(0));
when "001" =>
VARcorINPUTdata := outputFROMbuf(7 downto 2) & not(outputFROMbuf(1)) & outputFROMbuf(0);
when "010" =>
VARcorINPUTdata := outputFROMbuf(7 downto 3) & not(outputFROMbuf(2)) & outputFROMbuf(1 downto 0);
when "011" =>
VARcorINPUTdata := outputFROMbuf(7 downto 4) & not(outputFROMbuf(3)) & outputFROMbuf(2 downto 0);
when "100" =>
VARcorINPUTdata := outputFROMbuf(7 downto 5) & not(outputFROMbuf(4)) & outputFROMbuf(3 downto 0);
when "101" =>
VARcorINPUTdata := outputFROMbuf(7 downto 6) & not(outputFROMbuf(5)) & outputFROMbuf(4 downto 0);
when "110" =>
VARcorINPUTdata := outputFROMbuf(7) & not(outputFROMbuf(6)) & outputFROMbuf(5 downto 0);
when "111" =>
VARcorINPUTdata := not(outputFROMbuf(7)) & outputFROMbuf(6 downto 0);
when others =>
VARcorINPUTdata := outputFROMbuf;
end case;
if(rising_edge(clk)) then
if(Reset_L = '0') then
Cstate <= Start;
NEXTtonextST <= Start;
CNTupto <= x"000";
internalCNTaddr <= x"000";
-- New REGfile handling
nandID <= (x"00", x"00", x"00", x"00");
REGaddress <= ((x"00", x"00", x"00"), (x"00", x"00", x"00"));
errorLOC <= (x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00");
Device8_not16 <= '0';
ECCpresent <= '0';
buffer1or2 <= '0';
Device_Size <= "00";
CommandREG <= x"00";
nandPRE <= '1';
else
nandPRE <= '1';
if(ADDR = x"FF4" and WE_L = '0' and CE_L = '0') then
REGaddress(conv_integer(currentADDreg))(0) <= ST2inDATA;
elsif(ADDR = x"FF5" and WE_L = '0' and CE_L = '0') then
REGaddress(conv_integer(currentADDreg))(1) <= ST2inDATA;
elsif(ADDR = x"FF6" and WE_L = '0' and CE_L = '0') then
REGaddress(conv_integer(currentADDreg))(2) <= ST2inDATA;
elsif(ADDR = x"FF7" and WE_L = '0' and CE_L = '0') then
Device8_not16 <= ST2inDATA(0);
Device_Size <= ST2inDATA(2 downto 1);
ECCpresent <= ST2inDATA(6);
elsif(ADDR = x"FF8" and WE_L = '0' and CE_L = '0') then
buffer1or2 <= ST2inDATA(0);
elsif(ADDR = x"FFA" and WE_L = '0' and CE_L = '0') then
CommandREG <= ST2inDATA;
end if;
internalCNTaddr <= internalCNT;
case cSTATE is
when Start =>
NEXTtonextST <= Start;
cntUPTO <= x"000";
NEXTtonextST2 <= Start;
-- Multiple Use states
when enableTOG0 =>
cntUPTO <= x"000";
when STwaitforRB0 =>
cntUPTO <= x"000";
when STwaitforRB1 =>
cntUPTO <= x"000";
-- Program cycles
when STprogrampageCHbuf =>
StatusREG(5) <= '0';
if(CommandREG(0) = '1') then
buffer1or2 <= not(CommandREG(1));
else
buffer1or2 <= not(buffer1or2);
end if;
NEXTtonextST <= STprogrampage;
when STprogrampage =>
NEXTtonextST <= STprogrampageADDlatch00;
when STprogrampageADDlatch00 =>
cntUPTO <= x"002";
NEXTtonextST <= STprogrampageADDlatch3cycles;
when STprogrampageADDlatch3cycles =>
cntUPTO <= x"003";
NEXTtonextST <= STprogrampageWRITES;
when STprogrampageWRITES =>
NEXTtonextST <= STprogrampageCMDfinal10h;
--cntUPTO <= x"834";
cntUPTO <= bytesCONTROLLED;
when STprogrampageCMDfinal10h =>
NEXTtonextST <= STprogrampageSWstatusRB;
when STprogrampageSWstatusRB =>
StatusREG(5) <= '1';
cntUPTO <= x"000";
NEXTtonextST <= Start;
-- Read cycles
when STreadpage =>
StatusREG(5) <= '0';
if(CommandREG(0) = '1') then
-- shift control to the buffer which is free
-- that is not the one in the command
buffer1or2 <= not(CommandREG(1));
end if;
NEXTtonextST <= STreadpageADDlatch00;
when STreadpageADDlatch00 =>
cntUPTO <= x"002";
NEXTtonextST <= STreadpageADDlatch3cycles;
when STreadpageADDlatch3cycles =>
cntUPTO <= x"003";
NEXTtonextST <= STreadpageCMDfinal30h;
when STreadpageCMDfinal30h =>
NEXTtonextST <= STreadpageREADS;
when STreadpageREADS =>
NEXTtonextST <= Start;
cntUPTO <= bytesCONTROLLED;
--cntUPTO <= x"834";
when STreadpageSWAPbuf =>
StatusREG(5) <= '1';
cntUPTO <= x"000";
buffer1or2 <= not(buffer1or2);
when STreadpageCORwaitforRB =>
NEXTtonextST2 <= STreadpageCORRECTaddr;
when STreadpageCORRECT =>
NEXTtonextST2 <= STreadpageCORRECTaddr;
when STreadpageCORRECTaddr =>
if (delayCNT = "001") then
corINPUTdata <= VARcorINPUTdata;
end if;
cntUPTO <= x"004";
-- Erase cycles
when STeraseblock =>
StatusREG(5) <= '0';
--internal_nandDATA <= x"60";
NEXTtonextST <= STeraseblockADDcycles;
when STeraseblockADDcycles =>
--internal_nandDATA <= REGfile_DATAout;
cntUPTO <= x"003";
NEXTtonextST <= STeraseblockCMDd0;
when STeraseblockCMDd0 =>
NEXTtonextST <= STprogrampageSWstatusRB;
--internal_nandDATA <= x"D0";
cntUPTO <= x"000";
-- Reset cycles
when STresetNAND =>
--internal_nandDATA <= x"FF";
NEXTtonextST <= Start;
cntUPTO <= x"000";
-- Fetch Error cycles
when STfetchERRORs =>
--internal_nandDATA <= x"90";
cntUPTO <= x"000";
NEXTtonextST <= STfetchERRORseightReads;
when STfetchERRORseightReads =>
if(incintCNT = '1') then
errorLOC(conv_integer(internalCNT(2 downto 0))) <= nandDATA;
end if;
cntUPTO <= x"008";
NEXTtonextST <= NEXTtonextST2;
-- Read ID cycles
when STreadID =>
--internal_nandDATA <= x"90";
cntUPTO <= x"000";
NEXTtonextST <= STreadIDadd00;
when STreadIDadd00 =>
--internal_nandDATA <= x"00";
NEXTtonextST <= STreadIDfourReads;
cntUPTO <= x"000";
when STreadIDfourReads =>
if(incintCNT = '1') then
nandID(conv_integer(internalCNT(1 downto 0))) <= nandDATA;
end if;
cntUPTO <= x"004";
NEXTtonextST <= Start;
-- Read Status cycles
when STreadstatusCMD =>
cntUPTO <= x"000";
NEXTtonextST <= STreadstatusRead;
--internal_nandDATA <= x"70";
when STreadstatusRead =>
if(incintCNT = '1') then
StatusREG <= nandDATA;
end if;
cntUPTO <= x"000";
when others =>
end case;
Cstate <= Nstate;
end if;
end if;
end process statemachine;
-- FallingEDGE
-- This process is to generate the latch signal on
-- RE going high.
FallingEDGE: process(clk, Reset_L)
begin
if(falling_edge(clk)) then
if (Reset_L='0') then
OnedelayedINCcnt <= '0';
else
OnedelayedINCcnt <= incintCNT;
end if;
end if;
end process FallingEDGE;
combFSMmain: process(cState, ADDR, we_L, ST2inDATA, doneTOGGLE, NEXTtonextST, incintCNT, CE_L, buffer1or2, OE_L,
internalCNT, nandRB_Lfinal, OnedelayedINCcnt, buffer1_DATAout, buffer2_DATAout, delayCNT,
nandRB_L, errINT, corWE, errorLOC)
begin
-- STANDARD SRAM interface
INT <= '0';
RB_L <= '0';
nandWP_L <= '1';
-- BUFFER 1 and 2 WE signals
WE_buffer1_H <= not(buffer1or2) and not(WE_L) and not(CE_L);
WE_buffer2_H <= buffer1or2 and not(WE_L) and not(CE_L);
-- Internal signals
buffer1_nandDATA_in <= '0';
buffer2_nandDATA_in <= '0';
nandDATA_from_buffer1 <= '0';
nandDATA_from_buffer2 <= '0';
-- Toggle state machine stuff
enableTOGGLE <= '0';
nandDATA_fsm <= '0';
outputVEC1 <= "11001";
outputVEC2 <= "11001";
flipTHEt <= '0';
Nstate <= Start;
internal_nandDATA <= x"00";
errCORaddrIN <= '0';
corADDR <= x"000";
corWE <= '0';
DEBUGstatevector <= x"0A";
case cSTATE is
when Start =>
if(ADDR = x"FFA" and WE_L = '0' and CE_L = '0') then
if(ST2inDATA(7 downto 4) = x"7") then
-- Status read
Nstate <= STreadstatusCMD;
elsif(ST2inDATA(7 downto 4) = x"9") then
-- Read ID
Nstate <= STreadID;
elsif(ST2inDATA(7 downto 4) = x"6") then
-- Erase Block
Nstate <= STeraseblock;
elsif(ST2inDATA(7 downto 4) = x"F") then
-- Reset NAND flash
Nstate <= STresetNAND;
elsif(ST2inDATA(7 downto 4) = x"8") then
-- Program Page
Nstate <= STprogrampageCHbuf;
elsif(ST2inDATA(7 downto 4) = x"0") then
-- Read Page
Nstate <= STreadpage;
elsif(ST2inDATA(7 downto 0) = x"23") then
-- Fetch Errors
Nstate <= STfetchERRORS;
else
Nstate <= Start;
end if;
else
Nstate <= Start;
end if;
RB_L <= '1';
DEBUGstatevector <= x"11";
-- The common done toggle state
when enableTOG0 =>
nandDATA_fsm <= '0';
enableTOGGLE <= '0';
outputVEC1 <= "11001";
outputVEC2 <= "11001";
if (doneTOGGLE = '0') then
Nstate <= NEXTtonextST;
else
Nstate <= enableTOG0;
end if;
DEBUGstatevector <= x"12";
when STwaitforRB0 =>
internal_nandDATA <= x"00";
outputVEC1 <= "11001";
outputVEC2 <= "11001";
nandDATA_fsm <= '0';
enableTOGGLE <= '0';
if (nandRB_Lfinal = '0') then
Nstate <= STwaitforRB1;
else
Nstate <= STwaitforRB0;
end if;
DEBUGstatevector <= x"13";
when STwaitforRB1 =>
internal_nandDATA <= x"00";
outputVEC1 <= "11001";
outputVEC2 <= "11001";
nandDATA_fsm <= '0';
enableTOGGLE <= '0';
if (nandRB_Lfinal = '1') then
Nstate <= NEXTtonextST;
else
Nstate <= STwaitforRB1;
end if;
-- Program cycles
when STprogrampageCHbuf =>
flipTHEt <= '1';
internal_nandDATA <= x"00";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '0';
enableTOGGLE <= '0';
Nstate <= STprogrampage;
when STprogrampage =>
internal_nandDATA <= x"80";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STprogrampage;
end if;
when STprogrampageADDlatch00 =>
internal_nandDATA <= x"00";
outputVEC1 <= "10100";
outputVEC2 <= "11100";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STprogrampageADDlatch00;
end if;
when STprogrampageADDlatch3cycles =>
outputVEC1 <= "10100";
outputVEC2 <= "11100";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STprogrampageADDlatch3cycles;
end if;
if(internalCNT(1 downto 0) = "11") then
internal_nandDATA <= x"00";
else
internal_nandDATA <=
REGaddress(conv_integer(not(currentADDreg)))(conv_integer(internalCNT(1 downto 0)));
end if;
when STprogrampageWRITES =>
outputVEC1 <= "10000";
outputVEC2 <= "11000";
nandDATA_fsm <= '0';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STprogrampageWRITES;
end if;
if(buffer1or2 = '0') then
-- This means the user has buffer 1
-- So use buffer 2 as the buffers have been
-- swapped
internal_nandDATA <= buffer2_DATAout;
nandDATA_from_buffer2 <= '1';
else
internal_nandDATA <= buffer1_DATAout;
nandDATA_from_buffer1 <= '1';
end if;
when STprogrampageCMDfinal10h =>
internal_nandDATA <= x"10";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= STwaitforRB0;
else
Nstate <= STprogrampageCMDfinal10h;
end if;
when STprogrampageSWstatusRB =>
Nstate <= Start;
-- Read Cycles
when STreadpage =>
internal_nandDATA <= x"00";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
flipTHEt <= not(delayCNT(0) or delayCNT(1) or delayCNT(2));
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STreadpage;
end if;
when STreadpageADDlatch00 =>
internal_nandDATA <= x"00";
outputVEC1 <= "10100";
outputVEC2 <= "11100";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STreadpageADDlatch00;
end if;
when STreadpageADDlatch3cycles =>
outputVEC1 <= "10100";
outputVEC2 <= "11100";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STreadpageADDlatch3cycles;
end if;
-- set the Register address on the lines
if(internalCNT(1 downto 0) = "11") then
internal_nandDATA <= x"00";
else
internal_nandDATA <=
REGaddress(conv_integer(not(currentADDreg)))(conv_integer(internalCNT(1 downto 0)));
end if;
when STreadpageCMDfinal30h =>
internal_nandDATA <= x"30";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= STwaitforRB0;
else
Nstate <= STreadpageCMDfinal30h;
end if;
when STreadpageREADS =>
internal_nandDATA <= x"00";
outputVEC1 <= "01000";
outputVEC2 <= "11000";
nandDATA_fsm <= '0';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= STreadpageCORwaitforRB;
else
Nstate <= STreadpageREADS;
end if;
if(buffer1or2 = '0') then
-- This means the user has buffer 1
-- to keep the default we do this:-
WE_buffer1_H <= not(WE_L) and not(CE_L);
-- to write to the other buffer
WE_buffer2_H <= OneDelayedINCcnt;
buffer2_nandDATA_in <= '1';
else
WE_buffer1_H <= OneDelayedINCcnt;
-- to keep the default
WE_buffer2_H <= not(WE_L) and not(CE_L);
buffer1_nandDATA_in <= '1';
end if;
DEBUGstatevector <= x"BB";
when STreadpageCORwaitforRB =>
if(nandRB_L = '0') then
Nstate <= STreadpageCORRECT;
elsif(ECCpresent = '0') then
Nstate <= STreadpageSWAPbuf;
else
Nstate <= STreadpageCORwaitforRB;
end if;
DEBUGstatevector <= x"CC";
when STreadpageCORRECT =>
if(nandRB_L = '1') then
if(errINT = '1') then
Nstate <= STfetchERRORs;
else
Nstate <= STreadpageSWAPbuf;
end if;
else
Nstate <= STreadpageCORRECT;
end if;
DEBUGstatevector <= x"CE";
when STreadpageCORRECTaddr =>
errCORaddrIN <= '1';
if(buffer1or2 = '0') then
-- This means the user has buffer 1
-- to keep the default we do this:-
WE_buffer1_H <= not(WE_L) and not(CE_L);
-- to write to the other buffer
WE_buffer2_H <= corWE;
buffer2_nandDATA_in <= '1';
else
WE_buffer1_H <= corWE;
-- to keep the default
WE_buffer2_H <= not(WE_L) and not(CE_L);
buffer1_nandDATA_in <= '1';
end if;
if(delayCNT = "011") then
corWE <= errorLOC(conv_integer(internalCNT(1 downto 0) & '1'))(4) and
not(errorLOC(conv_integer(internalCNT(1 downto 0) & '1'))(5));
else
corWE <= '0';
end if;
corADDR <= '0' & internalCNT(1 downto 0) &
errorLOC(conv_integer(internalCNT(1 downto 0) & '1'))(3 downto 0)
& errorLOC(conv_integer(internalCNT(1 downto 0) & '0'))(7 downto 3);
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= STreadpageSWAPbuf;
else
Nstate <= STreadpageCORRECTaddr;
end if;
DEBUGstatevector <= x"CF";
when STreadpageSWAPbuf =>
DEBUGstatevector <= x"DD";
Nstate <= Start;
-- Erase Block states
when STeraseblock =>
internal_nandDATA <= x"60";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
flipTHEt <= not(delayCNT(0) or delayCNT(1) or delayCNT(2));
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STeraseblock;
end if;
when STeraseblockADDcycles =>
outputVEC1 <= "10100";
outputVEC2 <= "11100";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STeraseblockADDcycles;
end if;
if(internalCNT(1 downto 0) = "11") then
internal_nandDATA <= x"00";
else
internal_nandDATA <=
REGaddress(conv_integer(not(currentADDreg)))(conv_integer(internalCNT(1 downto 0)));
end if;
when STeraseblockCMDd0 =>
internal_nandDATA <= x"D0";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= STwaitforRB0;
else
Nstate <= STeraseblockCMDd0;
end if;
-- Reset Nand state
when STresetNAND =>
internal_nandDATA <= x"FF";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= STwaitforRB0;
else
Nstate <= STresetNAND;
end if;
-- Fetch Error states
when STfetchERRORs =>
internal_nandDATA <= ErrorFetchCommand;
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STfetchERRORs;
end if;
DEBUGstatevector <= x"20";
when STfetchERRORseightReads =>
-- bit 0 - CE_L
-- bit 1 - CLE_H
-- bit 2 - ALE_H
-- bit 3 - WE_L
-- bit 4 - RE_L
outputVEC1 <= "01000";
outputVEC2 <= "11000";
nandDATA_fsm <= '0';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STfetchERRORseightReads;
end if;
DEBUGstatevector <= x"21";
-- Read ID states
when STreadID =>
internal_nandDATA <= x"90";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STreadID;
end if;
when STreadIDadd00 =>
internal_nandDATA <= x"00";
outputVEC1 <= "10100";
outputVEC2 <= "11100";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STreadIDadd00;
end if;
when STreadIDfourReads =>
-- bit 0 - CE_L
-- bit 1 - CLE_H
-- bit 2 - ALE_H
-- bit 3 - WE_L
-- bit 4 - RE_L
outputVEC1 <= "01000";
outputVEC2 <= "11000";
nandDATA_fsm <= '0';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STreadIDfourReads;
end if;
-- Status read states
when STreadstatusCMD =>
internal_nandDATA <= x"70";
outputVEC1 <= "10010";
outputVEC2 <= "11010";
nandDATA_fsm <= '1';
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= enableTOG0;
else
Nstate <= STreadstatusCMD;
end if;
when STreadstatusRead =>
nandDATA_fsm <= '0';
outputVEC1 <= "01000";
outputVEC2 <= "11000";
enableTOGGLE <= '1';
if (doneTOGGLE = '1') then
Nstate <= Start;
else
Nstate <= STreadstatusRead;
end if;
end case;
end process;
toggleFSM: process (clk, Reset_L)
begin
if(rising_edge(clk)) then
if(rstDcnt_L = '0') then
delayCNT <= "000";
else
if(delayCNT = "101") then
delayCNT <= "000";
elsif(incDcnt = '1') then
delayCNT <= delayCNT + 1;
end if;
end if;
if(Reset_L = '0') then
cTOGstate <= toggleWAIT;
-- NAND or NAND ecc module interface
--nandCE_L <= '1';
--nandCLE_H <= '0';
--nandALE_H <= '0';
--nandWE_L <= '1';
--nandRE_L <= '1';
else
-- nand DATA bus MUX
if(nandDATA_from_buffer1 = '1') then
nandDATA <= buffer1_DATAout;
elsif(nandDATA_from_buffer2 = '1') then
nandDATA <= buffer2_DATAout;
elsif(nandDATA_fsm = '1') then
nandDATA <= internal_nandDATA;
else
nandDATA <= (others => 'Z');
end if;
case cTOGstate is
when toggleWAIT =>
nandCE_L <= outputVEC1(0);
nandCLE_H <= outputVEC1(1);
nandALE_H <= outputVEC1(2);
nandWE_L <= outputVEC1(3);
nandRE_L <= outputVEC1(4);
when toggle1 =>
nandCE_L <= outputVEC1(0);
nandCLE_H <= outputVEC1(1);
nandALE_H <= outputVEC1(2);
nandWE_L <= outputVEC1(3);
nandRE_L <= outputVEC1(4);
when toggle2 =>
nandCE_L <= outputVEC2(0);
nandCLE_H <= outputVEC2(1);
nandALE_H <= outputVEC2(2);
nandWE_L <= outputVEC2(3);
nandRE_L <= outputVEC2(4);
when toggleDONE =>
nandCE_L <= '1';
nandCLE_H <= '0';
nandALE_H <= '0';
nandWE_L <= '1';
nandRE_L <= '1';
end case;
cTOGstate <= nTOGstate;
end if;
end if;
end process toggleFSM;
COMBtoggleFSM: process(cTOGstate, enableTOGGLE, delayCNT, internalCNT, CNTupto, outputVEC1, outputVEC2)
begin
doneTOGGLE <= '0';
internalCNTRst_L <= '1';
incintCNT <= '0';
rstDcnt_L <= '1';
incDcnt <= '0';
case cTOGstate is
when toggleWAIT =>
rstDcnt_L <= '0';
if(enableTOGGLE = '1') then
nTOGstate <= toggle1;
else
nTOGstate <= toggleWAIT;
end if;
internalCNTRst_L <= '0';
when toggle1 =>
incDcnt <= '1';
-- this is swtiching at 2 as
-- first it takes a clock cycle to switch
-- states and then it takes another clock to switch the register
if(delayCNT >= "011") then
nTOGstate <= toggle2;
else
nTOGstate <= toggle1;
end if;
when toggle2 =>
incDcnt <= '1';
if (delayCNT = "100") then
incintCNT <= '1';
end if;
-- switching at 4 as the same reason
-- 2 clocks before the signal goes back
if (delayCNT >= "101") then
if(internalCNT >= CNTupto) then
nTOGstate <= toggleDONE;
else
nTOGstate <= toggle1;
end if;
else
nTOGstate <= toggle2;
end if;
when toggleDONE =>
rstDcnt_L <= '0';
doneTOGGLE <= '1';
if (enableTOGGLE = '0') then
nTOGstate <= toggleWAIT;
else
nTOGstate <= toggleDONE;
end if;
end case;
end process COMBtoggleFSM;
REPETITIONcounter: process(clk, internalCNTRst_L, incintCNT)
begin
if(rising_edge(clk)) then
if(internalCNTRst_L = '0') then
internalCNT <= x"000";
else
if (incintCNT = '1') then
internalCNT <= internalCNT + 1;
end if;
end if;
end if;
end process REPETITIONcounter;
MUXoutsignals: process(buffer1_nandDATA_in, buffer2_nandDATA_in, nandDATA_from_buffer1, nandDATA_from_buffer2,
nandDATA, ST2inDATA, buffer1_DATAout, buffer2_DATAout, nandDATA_fsm, internal_nandDATA, buffer1or2,
ADDR, internalCNTaddr, nandID, ECCpresent, Device_Size, Device8_not16, StatusREG, CommandREG, OE_L,
CE_L, WE_L, currentADDreg, errorLOC, errCORaddrIN, corINPUTdata, corADDR)
begin
-- Buffer 1 and 2: data inputs
if(buffer1_nandDATA_in = '1') then
if(errCORaddrIN = '1') then
buffer1_DATA <= corINPUTdata;
else
buffer1_DATA <= nandDATA;
end if;
else
buffer1_DATA <= ST2inDATA;
end if;
if(buffer2_nandDATA_in = '1') then
if(errCORaddrIN = '1') then
buffer2_DATA <= corINPUTdata;
else
buffer2_DATA <= nandDATA;
end if;
else
buffer2_DATA <= ST2inDATA;
end if;
-- buffer addressing
if(buffer1or2 = '0') then
if(ADDR < x"840") then
buffer1_ADDR <= ADDR;
else
buffer1_ADDR <= x"840";
end if;
if(errCORaddrIN = '1') then
buffer2_ADDR <= corADDR;
else
buffer2_ADDR <= internalCNTaddr;
end if;
else
if(ADDR < x"840") then
buffer2_ADDR <= ADDR;
else
buffer2_ADDR <= x"840";
end if;
if(errCORaddrIN = '1') then
buffer1_ADDR <= corADDR;
else
buffer1_ADDR <= internalCNTaddr;
end if;
end if;
if(OE_L='0' and CE_L = '0' and WE_L = '1') then
if(ADDR(11 downto 4) = x"FF") then
if(ADDR(3 downto 0) = x"0") then
ST2outDATA <= nandID(0);
elsif(ADDR(3 downto 0) = x"1") then
ST2outDATA <= nandID(1);
elsif(ADDR(3 downto 0) = x"2") then
ST2outDATA <= nandID(2);
elsif(ADDR(3 downto 0) = x"3") then
ST2outDATA <= nandID(3);
elsif(ADDR(3 downto 0) = x"4") then
ST2outDATA <= REGaddress(conv_integer(currentADDreg))(0);
elsif(ADDR(3 downto 0) = x"5") then
ST2outDATA <= REGaddress(conv_integer(currentADDreg))(1);
elsif(ADDR(3 downto 0) = x"6") then
ST2outDATA <= REGaddress(conv_integer(currentADDreg))(2);
elsif(ADDR(3 downto 0) = x"7") then
ST2outDATA <= '0' & ECCpresent & "000" & Device_Size & Device8_not16;
elsif(ADDR(3 downto 0) = x"8") then
ST2outDATA <= "000000" & currentADDreg & buffer1or2;
elsif(ADDR(3 downto 0) = x"9") then
ST2outDATA <= StatusREG;
elsif(ADDR(3 downto 0) = x"A") then
ST2outDATA <= CommandREG;
else
--ST2outDATA <= (others => 'Z');
ST2outDATA <= x"AA";
end if;
elsif(ADDR(11 downto 3) = x"FE" & '0') then
ST2outDATA <= errorLOC(conv_integer(ADDR(2 downto 0)));
else
if(buffer1or2 = '0') then
ST2outDATA <= buffer1_DATAout;
else
ST2outDATA <= buffer2_DATAout;
end if;
end if;
else
ST2outDATA <= x"AA";
--DATA <= (others => 'Z');
end if;
end process MUXoutsignals;
end syn;
---------------------------------------------------
-- FSM Ends
---------------------------------------------------