------------------------------------------------------------------------------ -- File name : am29bds128h.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2003-2004 Free Model Foundry; http://www.FreeModelFoundry.com -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2 as -- published by the Free Software Foundation. -- -- MODIFICATION HISTORY : -- -- version: | author: | mod date: | changes made: -- V1.0 A.Savic 04 Jan 14 Initial release -- V1.1 A.Savic 04 Feb 19 Preload section update - sector -- contents independent preload -- Preload section update - last -- memory address preload -- Memory wrap with busy sector check -- HW RESET flag update -- Erase suspended sector programming -- restriciton -- V1.2 A.Savic 04 Jun 28 Aligned to new datasheet revision : -- June 7, 2004 AM29BDS128H/064H_00_A4 -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: AMD -- Technology: Flash Memory -- Part: am29bds128h -- -- Description: 128 Megabit (8 M x 16-Bit) CMOS 1.8 Volt-only -- Simultaneous Read/Write, Burst Mode Flash Memory -- ------------------------------------------------------------------------------- -- Known Bugs: -- ------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.VITAL_timing.ALL; USE IEEE.VITAL_primitives.ALL; USE STD.textio.ALL; LIBRARY FMF; USE FMF.gen_utils.all; USE FMF.conversions.all; ------------------------------------------------------------------------------- -- ENTITY DECLARATION ------------------------------------------------------------------------------- ENTITY am29bds128h IS GENERIC ( -- tipd delays: interconnect path delays tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A22 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_CLK : VitalDelayType01 := VitalZeroDelay01; tipd_AVDNeg : VitalDelayType01 := VitalZeroDelay01; tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; tipd_ACC : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z;--tCE tpd_CENeg_RDY : VitalDelayType01Z := UnitDelay01Z;--tCR tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z;--tOE tpd_CLK_DQ0 : VitalDelayType01Z := UnitDelay01Z;--tCKA/tCKZ tpd_CLK_RDY : VitalDelayType01 := UnitDelay01; --tRACC --tsetup values tsetup_A0_AVDNeg : VitalDelayType := UnitDelay;--tAAVDS,tAAS,/ tsetup_CENeg_AVDNeg : VitalDelayType := UnitDelay;--tCAS tsetup_A0_CLK : VitalDelayType := UnitDelay;--tACS tsetup_CENeg_CLK : VitalDelayType := UnitDelay;--tCES tsetup_AVDNeg_CLK : VitalDelayType := UnitDelay;--tAVC tsetup_OENeg_CLK : VitalDelayType := UnitDelay;--tOES tsetup_A0_WENeg : VitalDelayType := UnitDelay;--tAS,\ tsetup_DQ0_WENeg : VitalDelayType := UnitDelay;--tDS,/ tsetup_CENeg_WENeg : VitalDelayType := UnitDelay;--tCS tsetup_AVDNeg_WENeg : VitalDelayType := UnitDelay;--tAVSW tsetup_CLK_WENeg : VitalDelayType := UnitDelay;--tCSW --thold values thold_A0_AVDNeg : VitalDelayType := UnitDelay;--tAAVDH,tAAH,/ thold_A0_CLK : VitalDelayType := UnitDelay;--tACH thold_A0_WENeg : VitalDelayType := UnitDelay;--tAH,\ thold_DQ0_WENeg : VitalDelayType := UnitDelay;--tDH / thold_WENeg_OENeg : VitalDelayType := UnitDelay;--tGHWL,/ thold_CENeg_WENeg : VitalDelayType := UnitDelay;--tCH,\ thold_AVDNeg_WENeg : VitalDelayType := UnitDelay;--tAVHW,\ thold_AVDNeg_CLK : VitalDelayType := UnitDelay;--tAVHC thold_OENeg_RESETNeg: VitalDelayType := UnitDelay;--tRH,/ thold_CENeg_RESETNeg: VitalDelayType := UnitDelay;--tRH,/ --tpw values tpw_AVDNeg_negedge : VitalDelayType := UnitDelay; --tAVDP tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP --tdevice values: values for internal delays tdevice_POW : VitalDelayType := 9 us; --Sector Erase Operation tWHWH2 tdevice_SEO32KW : VitalDelayType := 400 ms; tdevice_SEO4KW : VitalDelayType := 200 ms; --Timing Limit Exceeded tdevice_HANG : VitalDelayType := 400 ms; --program/erase suspend timeout tdevice_START : VitalDelayType := 20 us; --sector erase command sequence timeout tdevice_CTMOUTP : VitalDelayType := 50 us; --device ready after Hardware reset(during embeded algorithm) tdevice_READYP : VitalDelayType := 30 us; --tReady --Continuous Burst Read Cycle tdevice_TRCC : VitalDelayType := 1 ms; -- Protection Bit Program tdevice_PROTP : VitalDelayType := 150 us; -- Protection Bit Erase tdevice_PROTE : VitalDelayType := 15 ms; -- Initial Access for Burst Read tdevice_TIACC_ODD : VitalDelayType := 58 ns; tdevice_TIACC_EVEN : VitalDelayType := 46 ns; -- Password Unlock tdevice_UNLOCK : VitalDelayType := 2 us; -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- memory file to be loaded mem_file_name : STRING := "none"; prot_file_name : STRING := "none"; secsi_file_name : STRING := "none"; UserPreload : BOOLEAN ; -- For FMF SDF technology file usage TimingModel : STRING -- ); PORT ( A22 : IN std_ulogic := 'U'; -- A21 : IN std_ulogic := 'U'; -- A20 : IN std_ulogic := 'U'; -- A19 : IN std_ulogic := 'U'; -- A18 : IN std_ulogic := 'U'; -- A17 : IN std_ulogic := 'U'; -- A16 : IN std_ulogic := 'U'; -- A15 : IN std_ulogic := 'U'; -- A14 : IN std_ulogic := 'U'; -- A13 : IN std_ulogic := 'U'; --address A12 : IN std_ulogic := 'U'; --lines A11 : IN std_ulogic := 'U'; -- A10 : IN std_ulogic := 'U'; -- A9 : IN std_ulogic := 'U'; -- A8 : IN std_ulogic := 'U'; -- A7 : IN std_ulogic := 'U'; -- A6 : IN std_ulogic := 'U'; -- A5 : IN std_ulogic := 'U'; -- A4 : IN std_ulogic := 'U'; -- A3 : IN std_ulogic := 'U'; -- A2 : IN std_ulogic := 'U'; -- A1 : IN std_ulogic := 'U'; -- A0 : IN std_ulogic := 'U'; -- DQ15 : INOUT std_ulogic := 'U'; -- DQ14 : INOUT std_ulogic := 'U'; -- DQ13 : INOUT std_ulogic := 'U'; -- DQ12 : INOUT std_ulogic := 'U'; -- DQ11 : INOUT std_ulogic := 'U'; -- DQ10 : INOUT std_ulogic := 'U'; -- DQ9 : INOUT std_ulogic := 'U'; -- data DQ8 : INOUT std_ulogic := 'U'; -- lines DQ7 : INOUT std_ulogic := 'U'; -- DQ6 : INOUT std_ulogic := 'U'; -- DQ5 : INOUT std_ulogic := 'U'; -- DQ4 : INOUT std_ulogic := 'U'; -- DQ3 : INOUT std_ulogic := 'U'; -- DQ2 : INOUT std_ulogic := 'U'; -- DQ1 : INOUT std_ulogic := 'U'; -- DQ0 : INOUT std_ulogic := 'U'; -- CENeg : IN std_logic := 'U'; OENeg : IN std_logic := 'U'; WENeg : IN std_logic := 'U'; CLK : IN std_logic := 'U'; AVDNeg : IN std_logic := 'U'; RESETNeg : IN std_logic := 'U'; WPNeg : IN std_logic := 'U'; ACC : IN std_logic := 'U'; RDY : OUT std_logic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of am29bds128h : ENTITY IS TRUE; END am29bds128h; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of am29bds128h IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "am29bds128h"; CONSTANT MaxData : NATURAL := 16#FFFF#; --255; CONSTANT SecSize : NATURAL := 16#7FFF#; --32KW CONSTANT SecNum : NATURAL := 269; CONSTANT GroupNum : NATURAL := 83; CONSTANT SecSiSize : NATURAL := 127; CONSTANT HiAddrBit : NATURAL := 22; CONSTANT AddrRANGE : NATURAL := 16#7FFFFF#; CONSTANT OW : NATURAL := to_nat("00011010"); CONSTANT PL : NATURAL := to_nat("00001010"); CONSTANT SL : NATURAL := to_nat("00010010"); CONSTANT WP : NATURAL := to_nat("00000010"); CONSTANT WPE : NATURAL := to_nat("01000010"); -- interconnect path delay signals SIGNAL A22_ipd : std_ulogic := 'U'; SIGNAL A21_ipd : std_ulogic := 'U'; SIGNAL A20_ipd : std_ulogic := 'U'; SIGNAL A19_ipd : std_ulogic := 'U'; SIGNAL A18_ipd : std_ulogic := 'U'; SIGNAL A17_ipd : std_ulogic := 'U'; SIGNAL A16_ipd : std_ulogic := 'U'; SIGNAL A15_ipd : std_ulogic := 'U'; SIGNAL A14_ipd : std_ulogic := 'U'; SIGNAL A13_ipd : std_ulogic := 'U'; SIGNAL A12_ipd : std_ulogic := 'U'; SIGNAL A11_ipd : std_ulogic := 'U'; SIGNAL A10_ipd : std_ulogic := 'U'; SIGNAL A9_ipd : std_ulogic := 'U'; SIGNAL A8_ipd : std_ulogic := 'U'; SIGNAL A7_ipd : std_ulogic := 'U'; SIGNAL A6_ipd : std_ulogic := 'U'; SIGNAL A5_ipd : std_ulogic := 'U'; SIGNAL A4_ipd : std_ulogic := 'U'; SIGNAL A3_ipd : std_ulogic := 'U'; SIGNAL A2_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL DQ15_ipd : std_ulogic := 'U'; SIGNAL DQ14_ipd : std_ulogic := 'U'; SIGNAL DQ13_ipd : std_ulogic := 'U'; SIGNAL DQ12_ipd : std_ulogic := 'U'; SIGNAL DQ11_ipd : std_ulogic := 'U'; SIGNAL DQ10_ipd : std_ulogic := 'U'; SIGNAL DQ9_ipd : std_ulogic := 'U'; SIGNAL DQ8_ipd : std_ulogic := 'U'; SIGNAL DQ7_ipd : std_ulogic := 'U'; SIGNAL DQ6_ipd : std_ulogic := 'U'; SIGNAL DQ5_ipd : std_ulogic := 'U'; SIGNAL DQ4_ipd : std_ulogic := 'U'; SIGNAL DQ3_ipd : std_ulogic := 'U'; SIGNAL DQ2_ipd : std_ulogic := 'U'; SIGNAL DQ1_ipd : std_ulogic := 'U'; SIGNAL DQ0_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL CLK_ipd : std_ulogic := 'U'; SIGNAL AVDNeg_ipd : std_ulogic := 'U'; SIGNAL RESETNeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; SIGNAL ACC_ipd : std_ulogic := 'U'; --- internal delays SIGNAL HANG_out : std_ulogic := '0'; --Program/Erase Timing Limit SIGNAL HANG_in : std_ulogic := '0'; SIGNAL START_T1 : std_ulogic := '0'; --Start TimeOut; SUSPEND SIGNAL START_T1_in : std_ulogic := '0'; SIGNAL CTMOUT : std_ulogic := '0'; --Sector Erase TimeOut SIGNAL CTMOUT_in : std_ulogic := '0'; SIGNAL READY_in : std_ulogic := '0'; SIGNAL READY : std_ulogic := '0'; SIGNAL TRCC_in : std_ulogic := '0'; SIGNAL ROWBOUND_in : std_ulogic := '0'; SIGNAL TRCC_out : std_ulogic := '0'; SIGNAL TIACC_in : std_ulogic := '0'; SIGNAL TIACC_out : std_ulogic := '0'; SIGNAL PBPROG_in : std_ulogic := '0'; SIGNAL PBPROG_out : std_ulogic := '0'; SIGNAL PBERASE_in : std_ulogic := '0'; SIGNAL PBERASE_out : std_ulogic := '0'; SIGNAL UNLOCKDONE_in : std_ulogic := '0'; SIGNAL UNLOCKDONE_out : std_ulogic := '0'; SIGNAL PASSPDONE_in : std_ulogic := '0'; SIGNAL PASSPDONE_out : std_ulogic := '0'; -- Annotate SIGNAL P1_in : std_ulogic := '0'; SIGNAL P1_out : std_ulogic := '0'; SIGNAL P2_in : std_ulogic := '0'; SIGNAL P2_out : std_ulogic := '0'; SIGNAL P3_in : std_ulogic := '0'; SIGNAL P3_out : std_ulogic := '0'; SIGNAL P4_in : std_ulogic := '0'; SIGNAL P4_out : std_ulogic := '0'; SIGNAL P5_in : std_ulogic := '0'; SIGNAL P5_out : std_ulogic := '0'; SIGNAL P6_in : std_ulogic := '0'; SIGNAL P6_out : std_ulogic := '0'; SIGNAL P7_in : std_ulogic := '0'; SIGNAL P7_out : std_ulogic := '0'; SIGNAL P8_in : std_ulogic := '0'; SIGNAL P8_out : std_ulogic := '0'; SIGNAL P9_in : std_ulogic := '0'; SIGNAL P9_out : std_ulogic := '0'; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays HANG :VitalBuf(HANG_out,HANG_in, (tdevice_HANG ,UnitDelay)); START :VitalBuf(START_T1,START_T1_in,(tdevice_START ,UnitDelay)); CTMOUTP :VitalBuf(CTMOUT, CTMOUT_in, (tdevice_CTMOUTP ,UnitDelay)); READYP :VitalBuf(READY, READY_in, (tdevice_READYP ,UnitDelay)); --------------------------------------------------------------------------- -- Annotate --------------------------------------------------------------------------- POW : VitalBuf(P1_out,P1_in, (tdevice_POW ,UnitDelay)); SEO32KW : VitalBuf(P2_out,P1_in, (tdevice_SEO32KW ,UnitDelay)); SEO4KW : VitalBuf(P3_out,P3_in, (tdevice_SEO4KW ,UnitDelay)); TRCC : VitalBuf(P4_out,P4_in, (tdevice_TRCC ,UnitDelay)); PROTP : VitalBuf(P5_out,P5_in, (tdevice_PROTP ,UnitDelay)); PROTE : VitalBuf(P6_out,P6_in, (tdevice_PROTE ,UnitDelay)); TIACC_ODD : VitalBuf(P7_out,P7_in, (tdevice_TIACC_ODD ,UnitDelay)); TIACC_EVEN : VitalBuf(P8_out,P8_in, (tdevice_TIACC_EVEN ,UnitDelay)); UNLOCK : VitalBuf(P9_out,P9_in, (tdevice_UNLOCK ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_46 : VitalWireDelay (A22_ipd, A22, tipd_A22); w_45 : VitalWireDelay (A21_ipd, A21, tipd_A21); w_44 : VitalWireDelay (A20_ipd, A20, tipd_A20); w_0 : VitalWireDelay (A19_ipd, A19, tipd_A19); w_1 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_2 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_3 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_4 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_5 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_6 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_7 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_8 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_9 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_10 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_11 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_12 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_13 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_14 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_15 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_16 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_17 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_18 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_19 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_20 : VitalWireDelay (DQ15_ipd, DQ15, tipd_DQ15); w_21 : VitalWireDelay (DQ14_ipd, DQ14, tipd_DQ14); w_22 : VitalWireDelay (DQ13_ipd, DQ13, tipd_DQ13); w_23 : VitalWireDelay (DQ12_ipd, DQ12, tipd_DQ12); w_24 : VitalWireDelay (DQ11_ipd, DQ11, tipd_DQ11); w_25 : VitalWireDelay (DQ10_ipd, DQ10, tipd_DQ10); w_26 : VitalWireDelay (DQ9_ipd, DQ9, tipd_DQ9); w_27 : VitalWireDelay (DQ8_ipd, DQ8, tipd_DQ8); w_28 : VitalWireDelay (DQ7_ipd, DQ7, tipd_DQ7); w_29 : VitalWireDelay (DQ6_ipd, DQ6, tipd_DQ6); w_30 : VitalWireDelay (DQ5_ipd, DQ5, tipd_DQ5); w_31 : VitalWireDelay (DQ4_ipd, DQ4, tipd_DQ4); w_32 : VitalWireDelay (DQ3_ipd, DQ3, tipd_DQ3); w_33 : VitalWireDelay (DQ2_ipd, DQ2, tipd_DQ2); w_34 : VitalWireDelay (DQ1_ipd, DQ1, tipd_DQ1); w_35 : VitalWireDelay (DQ0_ipd, DQ0, tipd_DQ0); w_36 : VitalWireDelay (OENeg_ipd , OENeg , tipd_OENeg); w_37 : VitalWireDelay (WENeg_ipd , WENeg , tipd_WENeg); w_38 : VitalWireDelay (RESETNeg_ipd, RESETNeg, tipd_RESETNeg); w_39 : VitalWireDelay (CENeg_ipd , CENeg , tipd_CENeg); w_40 : VitalWireDelay (WPNeg_ipd , WPNeg , tipd_WPNeg); w_41 : VitalWireDelay (ACC_ipd , ACC , tipd_ACC); w_42 : VitalWireDelay (CLK_ipd , CLK , tipd_CLK); w_43 : VitalWireDelay (AVDNeg_ipd, AVDNeg, tipd_AVDNeg); END BLOCK; --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior: BLOCK PORT ( A : IN std_logic_vector(HiAddrBit downto 0) := (OTHERS => 'U'); DIn : IN std_logic_vector(15 downto 0) := (OTHERS => 'U'); DOut : OUT std_ulogic_vector(15 downto 0) := (OTHERS => 'Z'); CENeg : IN std_logic := 'U'; OENeg : IN std_logic := 'U'; WENeg : IN std_logic := 'U'; CLK : IN std_logic := 'U'; AVDNeg : IN std_logic := 'U'; RESETNeg : IN std_logic := 'U'; WPNeg : IN std_logic := 'U'; ACC : IN std_logic := 'U'; RDY : OUT std_logic := 'U' ); PORT MAP ( A(22) => A22_ipd, A(21) => A21_ipd, A(20) => A20_ipd, A(19) => A19_ipd, A(18) => A18_ipd, A(17) => A17_ipd, A(16) => A16_ipd, A(15) => A15_ipd, A(14) => A14_ipd, A(13) => A13_ipd, A(12) => A12_ipd, A(11) => A11_ipd, A(10) => A10_ipd, A(9) => A9_ipd, A(8) => A8_ipd, A(7) => A7_ipd, A(6) => A6_ipd, A(5) => A5_ipd, A(4) => A4_ipd, A(3) => A3_ipd, A(2) => A2_ipd, A(1) => A1_ipd, A(0) => A0_ipd, DIn(15) => DQ15_ipd, DIn(14) => DQ14_ipd, DIn(13) => DQ13_ipd, DIn(12) => DQ12_ipd, DIn(11) => DQ11_ipd, DIn(10) => DQ10_ipd, DIn(9) => DQ9_ipd, DIn(8) => DQ8_ipd, DIn(7) => DQ7_ipd, DIn(6) => DQ6_ipd, DIn(5) => DQ5_ipd, DIn(4) => DQ4_ipd, DIn(3) => DQ3_ipd, DIn(2) => DQ2_ipd, DIn(1) => DQ1_ipd, DIn(0) => DQ0_ipd, DOut(15) => DQ15, DOut(14) => DQ14, DOut(13) => DQ13, DOut(12) => DQ12, DOut(11) => DQ11, DOut(10) => DQ10, DOut(9) => DQ9, DOut(8) => DQ8, DOut(7) => DQ7, DOut(6) => DQ6, DOut(5) => DQ5, DOut(4) => DQ4, DOut(3) => DQ3, DOut(2) => DQ2, DOut(1) => DQ1, DOut(0) => DQ0, CENeg => CENeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, CLK => CLK_ipd, AVDNeg => AVDNeg_ipd, RESETNeg => RESETNeg_ipd, WPNeg => WPNeg_ipd, ACC => ACC_ipd, RDY => RDY ); -- State Machine : State_Type TYPE state_type IS ( RESET, Z001, PREL_SETBWB, PREL_ULBYPASS, RES_ULBYPASS, CFI, UBP_CFI, AS, A0SEEN, C8, C8_Z001, C8_PREL, ERS, SERS, ESPS, SERS_EXEC, ESP, ESP_Z001, ESP_PREL, ESP_CFI, ESP_A0SEEN, ESP_AS, PGMS, PASSPROG_PREL, PASSPROG, PASSVERIFY, PASSUNLOCK0, PASSUNLOCK1, PASSUNLOCK2, PASSUNLOCK3, PASSUNLOCK, PROTBIT_PREL, PPB_LOCK_SET, PPBDYB, DYBWE, PPB_PROGRAM, PPB_PROGRAM_VERIFY, PPB_ERASE_VERIFY, PPB_ERASE, PPMLB_PROGRAM, SPMLB_PROGRAM, SSPB_PROGRAM, PPMLB_VERIFY, SPMLB_VERIFY, SSPB_VERIFY, OTP, OTP_Z001, OTP_PREL, OTP_PROTBIT, OTP_AS, OTP_A0SEEN, EXIT_1, EXIT_2, EXIT_3 ); --Flash Memory Array TYPE SecType IS ARRAY (0 TO SecSize) OF INTEGER RANGE -1 TO MaxData; TYPE MemArray IS ARRAY (0 TO SecNum) OF SecType; -- alias, four bank architecture TYPE Bank IS (ABank, BBank, CBank, DBank); TYPE burst_modes IS ( NOSYNC, CONTINUOUS, LINEAR, SYNCR); TYPE PASS_TYPE IS ARRAY(0 TO 3) OF std_logic_vector(15 downto 0); --SecSi Sector TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF INTEGER RANGE -1 TO MaxData; -- states SIGNAL current_state : state_type; -- SIGNAL next_state : state_type; -- SIGNAL ExitFrom : state_type; -- SIGNAL READ_MODE : burst_modes; -- powerup SIGNAL PoweredUp : std_logic := '0'; --zero delay signals SIGNAL DOut_zd : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); SIGNAL DOut_Pass : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); SIGNAL RY_zd : std_logic := 'Z'; SIGNAL RY_async : std_logic := 'Z'; SIGNAL RY_sync : std_logic := 'Z'; --FSM control signals SIGNAL ULBYPASS : std_logic := '0'; --Unlock Bypass Active SIGNAL ESP_ACT : std_logic := '0'; --Erase Suspend SIGNAL OTP_ACT : std_logic := '0'; --Model should never hang!!!!!!!!!!!!!!! SIGNAL HANG : std_logic := '0'; SIGNAL PDONE : std_logic := '1'; --Prog. Done SIGNAL PSTART : std_logic := '0'; --Start Programming --Program location is in protected sector SIGNAL PERR : std_logic := '0'; SIGNAL EDONE : std_logic := '1'; --Ers. Done SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL ESUSP : std_logic := '0'; --Suspend Erase SIGNAL ERES : std_logic := '0'; --Resume Erase --All sectors selected for erasure are protected SIGNAL EERR : std_logic := '0'; --Sectors selected for erasure SIGNAL ERS_QUEUE : std_logic_vector(SecNum downto 0) := (OTHERS => '0'); --Command Register SIGNAL WRITE : std_logic := '1'; SIGNAL READ : std_logic := '1'; SIGNAL BURST : std_logic := '1'; SIGNAL ReadINIT : std_logic := '1'; SHARED VARIABLE BankID : BANK; SHARED VARIABLE BankASEL : BANK; SHARED VARIABLE BankPROGRAM : BANK; SHARED VARIABLE BankUBPASS : BANK; SHARED VARIABLE BankERASE : std_logic_vector(3 downto 0); SIGNAL SecAddr : NATURAL RANGE 0 TO SecNum := 0; SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; SIGNAL D_tmp : NATURAL RANGE 0 TO MaxData := 0; --Address within sector SIGNAL Addr : NATURAL RANGE 0 TO SecSize := 0; SHARED VARIABLE SSWAddr : NATURAL RANGE 0 TO SecSize := 0; --glitch protection SIGNAL gWE_n : std_logic := '1'; SIGNAL gCE_n : std_logic := '1'; SIGNAL gOE_n : std_logic := '1'; SIGNAL OE_burst : std_logic := '1'; SIGNAL RST : std_logic := '1'; SIGNAL reseted : std_logic := '0'; SIGNAL CLKMerge : std_logic; SIGNAL AddrREF : std_logic := '0'; -- Mem(SecAddr)(Address).... SHARED VARIABLE Mem : MemArray := (OTHERS =>(OTHERS=> MaxData)); SHARED VARIABLE SecSi : SecSiType := (OTHERS => MaxData); SHARED VARIABLE ConfReg : std_logic_vector(19 downto 0); SHARED VARIABLE Password : PASS_TYPE; -- Protection parameters SHARED VARIABLE DYB : std_logic_vector(SecNum downto 0) := (OTHERS => '0'); SHARED VARIABLE PPB : std_logic_vector(GroupNum downto 0) := (OTHERS => '0'); SHARED VARIABLE PPBLock : std_logic; SHARED VARIABLE PPMLB : std_logic; SHARED VARIABLE SPMLB : std_logic; SHARED VARIABLE SSPB : std_logic; SHARED VARIABLE Reduced : BOOLEAN; SHARED VARIABLE FROMOE : BOOLEAN; SHARED VARIABLE FROMCE : BOOLEAN; SHARED VARIABLE BurstDelay : NATURAL; -- timing check violation SIGNAL Viol : X01 := '0'; FUNCTION ReturnSectorID(ADDR : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; VARIABLE conv : NATURAL; BEGIN conv := ADDR / 16#8000#; IF ( conv = 0 ) THEN result := ADDR / 16#1000#; ELSIF ( conv >= 1 ) AND ( conv <= 254 ) THEN result := 7 + conv; ELSE result := 262 + (ADDR - 16#7F8000#)/16#1000#; END IF; RETURN result; END ReturnSectorID; FUNCTION GroupID(SECADDR : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; BEGIN IF ( SECADDR <= 10 ) THEN result := SECADDR; ELSIF ( SECADDR >= 11 ) AND ( SECADDR <= 258 ) THEN result := 11 + (SECADDR-11)/4; ELSE result := 73 + (SECADDR - 259); END IF; RETURN result; END GroupID; FUNCTION ReturnBank(ADDR : NATURAL) RETURN BANK IS VARIABLE BankResult : BANK; BEGIN CASE ADDR / 16#100000# IS WHEN 0 => BankResult := DBank; WHEN 1 | 2 | 3 => BankResult := CBank; WHEN 4 | 5 | 6 => BankResult := BBank; WHEN OTHERS => BankResult := ABank; END CASE; RETURN BankResult; END ReturnBank; FUNCTION BusyBankE ( BankERASE : std_logic_vector; BankID : BANK ) RETURN BOOLEAN IS VARIABLE result : BOOLEAN; BEGIN result := ((BankID = DBank) AND BankERASE(0) = '1') OR ((BankID = CBank) AND BankERASE(1) = '1') OR ((BankID = BBank) AND BankERASE(2) = '1') OR ((BankID = ABank) AND BankERASE(3) = '1'); RETURN result; END BusyBankE; PROCEDURE BankE( VARIABLE BankERASE : INOUT std_logic_vector; BankID : BANK; SetBankVars : boolean ) IS BEGIN IF ( SetBankVars ) THEN IF BankID = DBank THEN BankERASE(0) := '1'; ELSIF BankID = CBank THEN BankERASE(1) := '1'; ELSIF BankID = BBank THEN BankERASE(2) := '1'; ELSE--ABank BankERASE(3) := '1'; END IF; ELSE BankERASE := "0000"; END IF; END; PROCEDURE ADDRHILO( VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE SectorID : NATURAL) IS BEGIN IF (SectorID <= 7) THEN AddrLOW := SectorID*16#01000#; AddrHIGH := SectorID*16#01000# + 16#FFF#; ELSIF (SectorID > 7) AND (SectorID < 262) THEN AddrLOW := (SectorID-7)*16#08000#; AddrHIGH := (SectorID-7)*16#08000#+16#07FFF#; ELSE AddrLOW := (SectorID - 262)*16#1000# + 16#7F8000#; AddrHIGH := (SectorID - 262)*16#1000# + 16#7F8000# + 16#FFF#; END IF; END ADDRHILO; FUNCTION READMEM(Data : INTEGER RANGE -1 TO MaxData) RETURN STD_LOGIC_VECTOR IS VARIABLE ReadData : STD_LOGIC_VECTOR(15 downto 0); BEGIN IF Data = -1 THEN ReadData := (OTHERS=>'X'); ELSE ReadData := to_slv(Data,16); END IF; RETURN ReadData; END READMEM; BEGIN ---------------------------------------------------------------------------- --Power Up time 100 ns; --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 100 ns; RST <= RESETNeg AFTER 500 ns;-- WHEN RESETNeg = '0' --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A, Din, CENeg, OENeg, WENeg, RESETNeg, CLK, AVDNeg) -- Timing Check Variables VARIABLE Tviol_A0_CLKP : X01 := '0'; VARIABLE TD_A0_CLKP : VitalTimingDataType; VARIABLE Tviol_A0_CLKN : X01 := '0'; VARIABLE TD_A0_CLKN : VitalTimingDataType; VARIABLE Tviol_CENeg_CLKP : X01 := '0'; VARIABLE TD_CENeg_CLKP : VitalTimingDataType; VARIABLE Tviol_CENeg_CLKN : X01 := '0'; VARIABLE TD_CENeg_CLKN : VitalTimingDataType; VARIABLE Tviol_OENeg_CLKP : X01 := '0'; VARIABLE TD_OENeg_CLKP : VitalTimingDataType; VARIABLE Tviol_OENeg_CLKN : X01 := '0'; VARIABLE TD_OENeg_CLKN : VitalTimingDataType; VARIABLE Tviol_A0_AVDNeg : X01 := '0'; VARIABLE TD_A0_AVDNeg : VitalTimingDataType; VARIABLE Tviol_CENeg_AVDNeg : X01 := '0'; VARIABLE TD_CENeg_AVDNeg : VitalTimingDataType; VARIABLE Tviol_AVDNeg_CLKP : X01 := '0'; VARIABLE TD_AVDNeg_CLKP : VitalTimingDataType; VARIABLE Tviol_AVDNeg_CLKN : X01 := '0'; VARIABLE TD_AVDNeg_CLKN : VitalTimingDataType; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_A0_CENeg : X01 := '0'; VARIABLE TD_A0_CENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE Tviol_WENeg_OENeg : X01 := '0'; VARIABLE TD_WENeg_OENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENegS : X01 := '0'; VARIABLE TD_CENeg_WENegS : VitalTimingDataType; VARIABLE Tviol_CENeg_WENegH : X01 := '0'; VARIABLE TD_CENeg_WENegH : VitalTimingDataType; VARIABLE Tviol_CLK_WENegP : X01 := '0'; VARIABLE TD_CLK_WENegP : VitalTimingDataType; VARIABLE Tviol_CLK_WENegN : X01 := '0'; VARIABLE TD_CLK_WENegN : VitalTimingDataType; VARIABLE Tviol_AVDNeg_WENeg : X01 := '0'; VARIABLE TD_AVDNeg_WENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg : X01 := '0'; VARIABLE TD_OENeg_WENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_RESETNeg : X01 := '0'; VARIABLE TD_OENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE Pviol_AVDNeg : X01 := '0'; VARIABLE PD_AVDNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between A and CLK active edge --tACS, tACH VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLK", SetupHigh => tsetup_A0_CLK, SetupLow => tsetup_A0_CLK, HoldHigh => thold_A0_CLK, HoldLow => thold_A0_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '1' AND AVDNeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CLKP, Violation => Tviol_A0_CLKP ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLK", SetupHigh => tsetup_A0_CLK, SetupLow => tsetup_A0_CLK, HoldHigh => thold_A0_CLK, HoldLow => thold_A0_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '0' AND AVDNeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CLKN, Violation => Tviol_A0_CLKN ); -- CE# setup time to CLK -- tCES VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_CENeg_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '1' AND AVDNeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLKP, Violation => Tviol_CENeg_CLKP ); VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_CENeg_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '0' AND AVDNeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLKN, Violation => Tviol_CENeg_CLKN ); -- OE# setup time to CLK -- tOES VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_OENeg_CLK, SetupHigh => tsetup_OENeg_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_CLKP, Violation => Tviol_OENeg_CLKP ); VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_OENeg_CLK, SetupHigh => tsetup_OENeg_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_CLKN, Violation => Tviol_OENeg_CLKN ); -- Setup/Hold Check between A and AVDNeg rising edge -- tAAS, tAAH VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupHigh => tsetup_A0_AVDNeg, SetupLow => tsetup_A0_AVDNeg, HoldHigh => thold_A0_AVDNeg, HoldLow => thold_A0_AVDNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_AVDNeg, Violation => Tviol_A0_AVDNeg ); -- CE# setup time to AVD# -- tCAS VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupLow => tsetup_CENeg_AVDNeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_AVDNeg, Violation => Tviol_CENeg_AVDNeg ); -- AVD# setup/hold time to CLK -- tAVC,tAVHC VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_AVDNeg_CLK, HoldLow => thold_AVDNeg_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_CLKP, Violation => Tviol_AVDNeg_CLKP ); VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_AVDNeg_CLK, HoldLow => thold_AVDNeg_CLK, CheckEnabled => ConfReg(19) = '0' AND ConfReg(17) = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_CLKN, Violation => Tviol_AVDNeg_CLKN ); -- Setup/Hold Check between A and WENeg falling edge -- tAS, tAH VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_A0_WENeg, SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, HoldLow => thold_A0_WENeg, CheckEnabled => CENeg = '0' AND OENeg = '1' AND AVDNeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_A0_WENeg, SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, HoldLow => thold_A0_WENeg, CheckEnabled => WENeg = '0' AND OENeg = '1' AND AVDNeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CENeg, Violation => Tviol_A0_CENeg ); -- Setup/Hold Check between DATA and WENeg rising edge -- tDS, tDH VitalSetupHoldCheck ( TestSignal => DIn, TestSignalName => "DIn", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_WENeg, HoldLow => thold_DQ0_WENeg, CheckEnabled => CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_WENeg, Violation => Tviol_DQ0_WENeg ); VitalSetupHoldCheck ( TestSignal => DIn, TestSignalName => "DIn", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_WENeg, HoldLow => thold_DQ0_WENeg, CheckEnabled => WENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CENeg, Violation => Tviol_DQ0_CENeg ); -- WE# hold HIGH time after OE# rising edge -- tGHWL VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => OENeg, RefSignalName => "OENeg", HoldHigh => thold_WENeg_OENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_OENeg, Violation => Tviol_WENeg_OENeg ); -- CE# hold LOW time after WE# rising edge -- tCH VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENegH, Violation => Tviol_CENeg_WENegH ); -- CLK setup time to WENeg falling edge ( Asynchronous ) -- tCSW VitalSetupHoldCheck ( TestSignal => CLK, TestSignalName => "CLK", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_CLK_WENeg, CheckEnabled => ConfReg(17) = '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLK_WENegP, Violation => Tviol_CLK_WENegP ); VitalSetupHoldCheck ( TestSignal => CLK, TestSignalName => "CLK", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_CLK_WENeg, CheckEnabled => ConfReg(17) = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLK_WENegN, Violation => Tviol_CLK_WENegN ); -- CE# setup LOW time before WE# falling edge -- tCS VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENegS, Violation => Tviol_CENeg_WENegS ); -- AVD# setup/hold LOW time around WE# falling edge -- tAVSW, tAVHW VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_AVDNeg_WENeg, HoldLow => thold_AVDNeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_WENeg, Violation => Tviol_AVDNeg_WENeg ); -- OE# hold HIGH time after RESET rising edge -- tRH VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_OENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_RESETNeg, Violation => Tviol_OENeg_RESETNeg ); -- CE# hold HIGH time after RESET rising edge -- tRH VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RESETNeg, Violation => Tviol_CENeg_RESETNeg ); -- PulseWidth Check for AVDNeg VitalPeriodPulseCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", PulseWidthLow => tpw_AVDNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_AVDNeg, Violation => Pviol_AVDNeg ); -- PulseWidth Check for RESETNeg VitalPeriodPulseCheck ( TestSignal => RESETNeg, TestSignalName => "RESETNeg", PulseWidthLow => tpw_RESETNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RESETNeg, Violation => Pviol_RESETNeg ); -- PulseWidth Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WENeg", PulseWidthLow => tpw_WENeg_negedge, PulseWidthHigh => tpw_WENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); Violation := Tviol_A0_CLKP OR Tviol_A0_CLKN OR Tviol_CENeg_CLKP OR Tviol_CENeg_CLKN OR Tviol_OENeg_CLKP OR Tviol_OENeg_CLKN OR Tviol_A0_AVDNeg OR Tviol_CENeg_AVDNeg OR Tviol_AVDNeg_CLKP OR Tviol_AVDNeg_CLKN OR Tviol_A0_WENeg OR Tviol_A0_CENeg OR Tviol_DQ0_WENeg OR Tviol_DQ0_CENeg OR Tviol_WENeg_OENeg OR Tviol_CENeg_WENegH OR Tviol_CLK_WENegP OR Tviol_CLK_WENegN OR Tviol_CENeg_WENegS OR Tviol_AVDNeg_WENeg OR Tviol_OENeg_RESETNeg OR Tviol_CENeg_RESETNeg OR Pviol_AVDNeg OR Pviol_RESETNeg OR Pviol_WENeg; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; ---------------------------------------------------------------------------- -- sequential process for reset control and FSM state transition ---------------------------------------------------------------------------- StateTransition : PROCESS(next_state, RESETNeg, RST, READY, PDone, EDone, PoweredUp) VARIABLE R : std_logic := '0'; --prog or erase in progress VARIABLE E : std_logic := '0'; --reset timming error BEGIN IF PoweredUp='1' THEN --Hardware reset timing control IF falling_edge(RESETNeg) THEN E := '0'; IF (PDONE='0' OR EDONE='0') THEN --if program or erase in progress READY_in <= '1'; R :='1'; ELSE READY_in <= '0'; R:='0'; --prog or erase not in progress END IF; ELSIF rising_edge(RESETNeg) AND RST='1' THEN --RESET# pulse < tRP READY_in <= '0'; R := '0'; E := '1'; END IF; IF RESETNeg='1' AND ( R='0' OR (R='1' AND READY='1')) THEN current_state <= next_state; READY_in <= '0'; E := '0'; R := '0'; reseted <= '1'; ELSIF (R='0' AND RESETNeg='0' AND RST='0')OR (R='1' AND RESETNeg='0' AND RST='0' AND READY='0')OR (R='1' AND RESETNeg='1' AND RST='0' AND READY='0')OR (R='1' AND RESETNeg='1' AND RST='1' AND READY='0') THEN --no state transition while RESET# low current_state <= RESET; --reset start reseted <= '0'; END IF; ELSE current_state <= RESET; -- reset reseted <= '0'; E := '0'; R := '0'; END IF; END PROCESS StateTransition; --------------------------------------------------------------------------- --Glitch Protection: Inertial Delay does not propagate pulses <5ns --------------------------------------------------------------------------- gWE_n <= WENeg AFTER 5 ns WHEN WENeg = '0' ELSE WENeg; gCE_n <= CENeg AFTER 5 ns WHEN CENeg = '0' ELSE CENeg; gOE_n <= OENeg AFTER 5 ns WHEN OENeg = '0' ELSE OENeg; --------------------------------------------------------------------------- -- Latch open detection, needed for burst sequences --------------------------------------------------------------------------- OE_burst <= OENeg AFTER tpd_OENeg_DQ0(trz0) WHEN OENeg = '0' ELSE '1'; --------------------------------------------------------------------------- -- Clock active edge --> CLKMerge rising edge, needed for burst sequences --------------------------------------------------------------------------- CLKGen : PROCESS(CLK) BEGIN IF ConfReg(17) = '0' THEN CLKMerge <= NOT CLK; ELSE CLKMerge <= CLK; END IF; END PROCESS CLKGen; ---------------------------------------------------------------------------- -- Device internal operation control ---------------------------------------------------------------------------- -- Protection Bit Program ProtPROG : PROCESS(PBPROG_in) BEGIN IF PBPROG_in = '0' THEN PBPROG_out <= '0'; ELSE PBPROG_out <= '1' AFTER (tdevice_PROTP - 1 ns); END IF; END PROCESS ProtPROG; -- Protection Bit Erase ProtERS : PROCESS(PBERASE_in) VARIABLE EraseSIM : TIME; BEGIN IF PBERASE_in = '0' THEN PBERASE_out <= '0'; ELSE EraseSIM := tdevice_PROTE; PBERASE_out <= '1' AFTER (EraseSIM - 1 ns); END IF; END PROCESS ProtERS; -- Password Unlock UNL : PROCESS(UNLOCKDONE_in) BEGIN IF UNLOCKDONE_in = '0' THEN UNLOCKDONE_out <= '0'; ELSE UNLOCKDONE_out <= '1' AFTER (tdevice_UNLOCK - 1 ns); END IF; END PROCESS UNL; -- Password Program PassP : PROCESS(PASSPDONE_in) BEGIN IF PASSPDONE_in = '0' THEN PASSPDONE_out <= '0'; ELSE PASSPDONE_out <= '1' AFTER (tdevice_POW - 1 ns); END IF; END PROCESS PassP; -- Burst Access TRCCB : PROCESS(TRCC_in, ROWBOUND_in) BEGIN IF falling_edge(TRCC_in) OR falling_edge(ROWBOUND_in) THEN TRCC_out <= '0'; ELSIF rising_edge(TRCC_in) OR rising_edge(ROWBOUND_in) THEN TRCC_out <= '1' AFTER (tdevice_TRCC - 1 ns); END IF; END PROCESS TRCCB; TIACCB : PROCESS(TIACC_in) BEGIN IF TIACC_in = '0' THEN TIACC_out <= '0'; ELSE IF Reduced AND Addr mod 2 = 0 THEN TIACC_out <= '1' AFTER (tdevice_TIACC_EVEN - 1 ns); ELSE TIACC_out <= '1' AFTER (tdevice_TIACC_ODD - 1 ns); END IF; END IF; END PROCESS TIACCB; --------------------------------------------------------------------------- -- Address Latch and Bus Cycle Decode --------------------------------------------------------------------------- BusCycleDecode : PROCESS(--A, Din, write, A, gWE_n, gCE_n, gOE_n, WENeg, CENeg, OENeg, reseted, AVDNeg, CLKMerge) VARIABLE AddressLatched : NATURAL RANGE 0 TO ADDRRange; VARIABLE AddrLO : NATURAL RANGE 0 TO ADDRRange; VARIABLE AddrHI : NATURAL RANGE 0 TO ADDRRange; VARIABLE READCYCLE : BOOLEAN; VARIABLE WRITECYCLE : BOOLEAN; VARIABLE LATCHED : BOOLEAN; VARIABLE SecLatched : NATURAL; BEGIN IF reseted='1' AND ConfReg(19) = '1' THEN -- Asynchronous Mode address latch IF RESETNeg /= '0' AND ((falling_edge(gWE_n) OR falling_edge(gCE_n)) AND gCE_n = '0' AND gWE_n = '0' AND OENeg = '1' AND AVDNeg = '0') THEN AddressLatched := to_nat(A); SecLatched := ReturnSectorID(AddressLatched); ADDRHILO(AddrLO, AddrHI, SecLatched); END IF; IF ( (falling_edge(AVDNeg) OR (A'EVENT AND AVDNeg = '0')) AND CENeg = '0' AND WENeg = '1') THEN -- tACC count AddrREF <= NOT AddrREF; END IF; IF (rising_edge(AVDNeg) AND CENeg = '0' AND WENeg = '1') OR (A'EVENT AND AVDNeg = '0' AND WENeg = '1' AND CENeg = '0') THEN AddressLatched := to_nat(A); SecLatched := ReturnSectorID(AddressLatched); ADDRHILO(AddrLO, AddrHI, SecLatched); END IF; IF ((falling_edge(OENeg) OR falling_edge(CENeg) OR (A'EVENT AND AVDNeg = '0')) AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN -- Initiate READ SecAddr <= ReturnSectorID(AddressLatched); BankID := ReturnBank(AddressLatched); Addr <= AddressLatched - AddrLO; READ <= '0', '1' AFTER 1 ns; END IF; IF RESETNeg /= '0' AND ((rising_edge(gWE_n) AND gCE_n = '0') OR (rising_edge(gCE_n) AND gWE_n = '0') OR (rising_edge(gWE_n) AND rising_edge(gCE_n))) AND OENeg = '1' THEN -- WRITE operation SecAddr <= ReturnSectorID(AddressLatched); BankID := ReturnBank(AddressLatched); Addr <= AddressLatched - AddrLO; D_tmp <= to_nat(Din(15 downto 0)); WRITE <= '0', '1' AFTER 1 ns; END IF; ELSIF reseted = '1' AND ConfReg(19) = '0' THEN IF falling_edge(AVDNeg) THEN LATCHED := FALSE; READCYCLE := FALSE; WRITECYCLE := FALSE; END IF; --Initiate READ (Burst mode) IF rising_edge(CLKMerge) AND READCYCLE THEN READCYCLE := FALSE; BURST <= '0', '1' AFTER 2 ns; END IF; -- Synchronous CLK active edge address latch IF rising_edge(CLKMerge) AND gWE_n = '1' AND --gOE_n = '1' AND gCE_n = '0' AND AVDNeg = '0' AND NOT LATCHED THEN READCYCLE := TRUE; LATCHED := TRUE; AddressLatched := to_nat(A); SecAddr <= ReturnSectorID(AddressLatched); BankID := ReturnBank(AddressLatched); SecLatched := ReturnSectorID(AddressLatched); ADDRHILO(AddrLO, AddrHI, SecLatched); Addr <= AddressLatched - AddrLO; BurstDelay := 0; TRCC_in <= '0', '1' AFTER 1 ns; TIACC_in <= '0', '1' AFTER 1 ns; AddrREF <= NOT AddrREF; IF OENeg = '0' THEN READ <= '0', '1' AFTER 1 ns; END IF; END IF; -- Synchronous AVD# rising edge address latch IF rising_edge(AVDNeg) AND gWE_n = '1' AND --gOE_n = '1' AND gCE_n = '0' AND NOT LATCHED THEN READCYCLE := TRUE; LATCHED := TRUE; AddressLatched := to_nat(A); SecAddr <= ReturnSectorID(AddressLatched); BankID := ReturnBank(AddressLatched); SecLatched := ReturnSectorID(AddressLatched); ADDRHILO(AddrLO, AddrHI, SecLatched); Addr <= AddressLatched - AddrLO; BurstDelay := 1; TRCC_in <= '0', '1' AFTER 1 ns; TIACC_in <= '0', '1' AFTER 1 ns; AddrREF <= NOT AddrREF; IF OENeg = '0' THEN READ <= '0', '1' AFTER 1 ns; END IF; END IF; -- Synchronous WRITE cycle IF (falling_edge(gWE_n) OR falling_edge(gCE_n)) AND gCE_n = '0' AND gWE_n = '0' AND gOE_n = '1' AND READCYCLE THEN READCYCLE := FALSE; WRITECYCLE := TRUE; END IF; -- Synchronous WRITE operation data latch IF ((rising_edge(gWE_n) AND gCE_n = '0') OR (rising_edge(gCE_n) AND gWE_n = '0') OR (rising_edge(gWE_n) AND rising_edge(gCE_n))) AND WRITECYCLE AND gOE_n = '1' AND RESETNeg /= '0' THEN WRITECYCLE := FALSE; SecAddr <= ReturnSectorID(AddressLatched); BankID := ReturnBank(AddressLatched); SecLatched := ReturnSectorID(AddressLatched); ADDRHILO(AddrLO, AddrHI, SecLatched); Addr <= AddressLatched - AddrLO; D_tmp <= to_nat(Din(15 downto 0)); WRITE <= '0', '1' AFTER 1 ns; END IF; -- Asynchronous WRITE cycle Address Latch -- Supported in synchronous mode IF (falling_edge(gWE_n) OR falling_edge(gCE_n)) AND gCE_n = '0' AND gWE_n = '0' AND gOE_n = '1' AND AVDNeg = '0' THEN READCYCLE := FALSE; WRITECYCLE := TRUE; LATCHED := TRUE; AddressLatched := to_nat(A); SecAddr <= ReturnSectorID(AddressLatched); BankID := ReturnBank(AddressLatched); SecLatched := ReturnSectorID(AddressLatched); ADDRHILO(AddrLO, AddrHI, SecLatched); Addr <= AddressLatched - AddrLO; END IF; -- Inititate READ, Syncronous mode IF (falling_edge(OENeg) AND WENeg = '1' AND CENeg = '0') THEN -- Initiate READ SecAddr <= ReturnSectorID(AddressLatched); BankID := ReturnBank(AddressLatched); Addr <= AddressLatched - AddrLO; READ <= '0', '1' AFTER 1 ns; END IF; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Program operation -- start/ suspend/ resume --------------------------------------------------------------------------- ProgTime :PROCESS(PSTART, reseted) VARIABLE pow : time; BEGIN pow := tdevice_POW; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programming terminated ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE='1' THEN IF ((SA /= 0 AND ( DYB(SA) = '0' AND PPB(GroupID(SA)) = '0' AND (Ers_queue(SA) = '0' OR ESP_ACT = '0') ) ) OR (SA = 0 AND ((OTP_ACT = '0' AND DYB(0) = '0' AND PPB(0) = '0') OR OTP_ACT = '1'))) AND NOT (ACC = '0') AND NOT (WPNeg = '0' AND (SA <= 3 OR SA >= SecNum-3)) AND NOT (OTP_ACT = '1' AND ( SA /= 0 OR (SSWAddr < 64 OR (SSWAddr >= 64 AND SSPB = '1')))) THEN PDONE <= '0', '1' AFTER pow; ELSE PERR <= '1', '0' AFTER 1 us; END IF; END IF; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Erase Operations --------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, ESUSP, ERES, reseted)--,Ers_Queue VARIABLE cnt : NATURAL RANGE 0 TO SecNum := 0; VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE seoSMALL : time; VARIABLE seoLARGE : time; BEGIN seoSMALL := tdevice_SEO4KW; seoLARGE := tdevice_SEO32KW; IF rising_edge(reseted) THEN EDONE <= '1'; -- reset done, ERASE terminated ELSIF reseted = '1' THEN IF rising_edge(ESTART) AND EDONE = '1' THEN cnt := 0; duration := 0 ns; FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND DYB(i) = '0' AND PPB(GroupID(i)) = '0' AND NOT (WPNeg = '0' AND (i <= 3 OR i >= SecNum-3)) AND NOT (ACC = '0') THEN cnt := cnt +1; IF i <= 7 OR i >= SecNum-7 THEN duration := duration + seoSMALL; ELSE duration := duration + seoLARGE; END IF; END IF; END LOOP; IF cnt > 0 THEN elapsed := 0 ns; EDONE <= '0', '1' AFTER duration; start := NOW; ELSE EERR <= '1', '0' AFTER 100 us; END IF; ELSIF rising_edge(ESUSP) AND EDONE = '0' THEN elapsed := NOW - start; duration := duration - elapsed; EDONE <= '0'; ELSIF rising_edge(ERES) AND EDONE = '0' THEN start := NOW; EDONE <= '0', '1' AFTER duration; END IF; END IF; END PROCESS; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(WRITE, PDONE, EDONE, HANG, CTMOUT, BURST, START_T1, reseted, PERR, EERR, gCE_n, AVDNeg, RST, UNLOCKDONE_out) VARIABLE PATTERN_1 : BOOLEAN := FALSE; VARIABLE PATTERN_2 : BOOLEAN := FALSE; VARIABLE A_PAT_1 : BOOLEAN := FALSE; VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE DataLo : NATURAL RANGE 0 TO 16#FF# := 0; VARIABLE BURST_TR : BOOLEAN; VARIABLE SYNCREAD : BOOLEAN; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(WRITE) THEN Data := D_tmp; DataLo := D_tmp mod 16#100#; PATTERN_1 := (Addr mod 16#1000# = 16#555#) AND (DataLo = 16#AA#) ; PATTERN_2 := (Addr mod 16#1000# = 16#2AA#) AND (DataLo = 16#55#) ; A_PAT_1 := (Addr mod 16#1000# = 16#555#); END IF; BURST_TR := FALSE; SYNCREAD := FALSE; IF falling_edge(RST) AND RESETNeg = '0' THEN READ_MODE <= NOSYNC; OTP_ACT <= '0'; END IF; IF reseted /= '1' THEN next_state <= current_state; ELSE CASE current_state IS WHEN RESET => IF falling_edge(WRITE) THEN IF (PATTERN_1)THEN next_state <= Z001; ELSIF ((Addr mod 16#100# = 16#55#) AND (DataLo=16#98#))THEN next_state <= CFI; ELSE next_state <= RESET; END IF; END IF; IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN Z001 => IF falling_edge(WRITE) THEN IF (PATTERN_2) THEN next_state <= PREL_SETBWB; ELSE next_state <= RESET; END IF; END IF; WHEN PREL_SETBWB => IF falling_edge(WRITE) THEN IF (A_PAT_1 AND (DataLo = 16#20#)) THEN next_state <= PREL_ULBYPASS; ELSIF (A_PAT_1 AND (DataLo = 16#90#)) THEN next_state <= AS; ELSIF (A_PAT_1 AND (DataLo = 16#A0#)) THEN next_state <= A0SEEN; ELSIF (A_PAT_1 AND (DataLo = 16#80#)) THEN next_state <= C8; ELSIF (A_PAT_1 AND (DataLo = 16#C0#)) THEN next_state <= RESET; ELSIF (A_PAT_1 AND (DataLo = 16#38#)) AND PPMLB /= '1' THEN next_state <= PASSPROG_PREL; ELSIF (A_PAT_1 AND (DataLo = 16#C8#)) THEN next_state <= PASSVERIFY; ELSIF (A_PAT_1 AND (DataLo = 16#28#)) THEN next_state <= PASSUNLOCK0; ELSIF (A_PAT_1 AND (DataLo = 16#60#)) THEN next_state <= PROTBIT_PREL; ELSIF (A_PAT_1 AND (DataLo = 16#78#)) THEN next_state <= PPB_LOCK_SET; ELSIF (A_PAT_1 AND (DataLo = 16#58#)) THEN next_state <= PPBDYB; ELSIF (A_PAT_1 AND (DataLo = 16#48#)) THEN next_state <= DYBWE; ELSIF (A_PAT_1 AND (DataLo = 16#88#)) THEN next_state <= OTP; OTP_ACT <= '1'; ELSE next_state <= RESET; END IF; END IF; WHEN PREL_ULBYPASS => IF falling_edge(WRITE) THEN IF (DataLo = 16#A0#) THEN next_state <= A0SEEN; ELSIF (DataLo = 16#98#) THEN next_state <= UBP_CFI; ELSIF (DataLo = 16#80#) THEN next_state <= C8_PREL; ELSIF (DataLo = 16#90# AND BankID = BankUBPASS) THEN next_state <= RES_ULBYPASS; ELSE next_state <= PREL_ULBYPASS; END IF; ELSIF falling_edge(BURST) THEN IF BankID /= BankUBPASS THEN BURST_TR := TRUE; END IF; END IF; WHEN RES_ULBYPASS => IF falling_edge(WRITE) THEN IF (DataLo = 16#00#) THEN next_state <= RESET; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; WHEN CFI => IF falling_edge(WRITE) THEN IF (DataLo = 16#F0#) THEN next_state <= RESET; ELSE next_state <= CFI; END IF; ELSIF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN UBP_CFI => IF falling_edge(WRITE) AND (DataLo = 16#F0#) THEN next_state <= PREL_ULBYPASS; ELSIF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN AS => IF falling_edge(WRITE) THEN IF (DataLo = 16#F0#) THEN next_state <= RESET; ELSE next_state <= AS; END IF; ELSIF falling_edge(BURST) THEN IF BankID = BankASEL THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN A0SEEN => IF falling_edge(WRITE) THEN IF ULBYPASS = '1' THEN IF BankID = BankUBPASS THEN next_state <= PGMS; ELSE next_state <= PREL_ULBYPASS; END IF; ELSE next_state <= PGMS; END IF; END IF; WHEN C8 => IF falling_edge(WRITE) THEN IF PATTERN_1 THEN next_state <= C8_Z001; ELSE next_state <= RESET; END IF; END IF; WHEN C8_Z001 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= C8_PREL; ELSE next_state <= RESET; END IF; END IF; WHEN C8_PREL => IF falling_edge(WRITE) THEN IF ( A_PAT_1 OR ULBYPASS = '1' ) AND DataLo = 16#10# THEN next_state <= ERS; ELSIF DataLo = 16#30# AND NOT (ULBYPASS = '1' AND BankID /= BankUBPASS ) THEN next_state <= SERS; ELSIF ULBYPASS = '1' THEN next_state <= PREL_ULBYPASS; ELSE next_state <= RESET; END IF; END IF; WHEN ERS => IF rising_edge(EDONE) OR falling_edge(EERR) THEN IF ULBYPASS = '1' THEN next_state <= PREL_ULBYPASS; ELSE next_state <= RESET; END IF; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN SERS => IF CTMOUT'EVENT AND CTMOUT = '1' THEN next_state <= SERS_EXEC; ELSIF falling_edge(WRITE) THEN IF (DataLo = 16#B0# AND BusyBankE(BankERASE,BankID)) THEN next_state <= ESP; -- ESP according to datasheet ELSIF (DataLo = 16#30#) THEN --No bank restriction ----> AND BankID = BankERASE ) THEN next_state <= SERS; ELSIF ULBYPASS = '1' THEN next_state <= PREL_ULBYPASS;--C8_PREL; ELSE next_state <= RESET; END IF; END IF; IF falling_edge(BURST) THEN IF BusyBankE(BankERASE,BankID) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ESPS => IF (START_T1 = '1') THEN next_state <= ESP; END IF; IF falling_edge(BURST) THEN IF BusyBankE(BankERASE,BankID) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN SERS_EXEC => IF rising_edge(EDONE) OR falling_edge(EERR) THEN IF ULBYPASS = '1' THEN next_state <= PREL_ULBYPASS; ELSE next_state <= RESET; END IF; ELSIF EERR /= '1' THEN IF falling_edge(WRITE) THEN IF DataLo = 16#B0# AND BusyBankE(BankERASE,BankID) THEN next_state <= ESPS; END IF; END IF; END IF; IF falling_edge(BURST) THEN IF BusyBankE(BankERASE,BankID) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ESP => IF falling_edge(WRITE) THEN IF DataLo = 16#30# AND BusyBankE(BankERASE,BankID) THEN next_state <= SERS_EXEC; ELSIF (DataLo = 16#A0#) AND ULBYPASS = '1' AND BankID = BankUBPASS THEN next_state <= ESP_A0SEEN; ELSIF ( Addr mod 16#100# = 16#55# OR (ULBYPASS = '1' AND BankID = BankUBPASS))AND DataLo = 16#98# THEN next_state <= ESP_CFI; ELSIF PATTERN_1 THEN next_state <= ESP_Z001; END IF; ELSIF falling_edge(BURST) THEN IF BusyBankE(BankERASE,BankID) AND Ers_Queue(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ESP_Z001 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= ESP_PREL; ELSE next_state <= ESP; END IF; END IF; WHEN ESP_PREL => IF falling_edge(WRITE) THEN IF A_PAT_1 AND DataLo = 16#A0# THEN next_state <= ESP_A0SEEN; ELSIF A_PAT_1 AND DataLo = 16#90# THEN next_state <= ESP_AS; ELSIF A_PAT_1 AND DataLo = 16#88# THEN next_state <= OTP; OTP_ACT <= '1'; ELSE next_state <= ESP; END IF; END IF; WHEN ESP_CFI => IF falling_edge(WRITE) AND DataLo = 16#F0# THEN next_state <= ESP; ELSIF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN ESP_A0SEEN => IF falling_edge(WRITE) AND Ers_Queue(SecAddr) /= '1' THEN next_state <= PGMS; --set ESP END IF; WHEN ESP_AS => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN -- reset ULBYPASS next_state <= ESP; END IF; ELSIF falling_edge(BURST) THEN IF BankID = BankASEL THEN SYNCREAD := TRUE; ELSIF BusyBankE(BankERASE,BankID) AND BankID /= BankASEL AND Ers_Queue(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PGMS => IF rising_edge(PDONE) OR falling_edge(PERR) THEN IF OTP_ACT = '1' THEN next_state <= OTP; ELSIF ESP_ACT = '1' THEN next_state <= ESP; ELSIF ULBYPASS = '1' THEN next_state <= PREL_ULBYPASS; ELSE next_state <= RESET; END IF; END IF; IF falling_edge(BURST) THEN IF BankID = BankPROGRAM THEN SYNCREAD := TRUE; ELSIF BankID /= BankPROGRAM AND ESP_ACT = '1' AND BusyBankE(BankERASE,BankID) AND Ers_Queue(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PASSPROG_PREL => IF falling_edge(WRITE) THEN next_state <= PASSPROG; END IF; WHEN PASSPROG => IF falling_edge(WRITE) AND PASSPDONE_out = '1' AND DataLo = 16#F0# THEN next_state <= RESET; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PASSVERIFY => IF falling_edge(WRITE) AND PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= PASSVERIFY; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PASSUNLOCK0 => IF falling_edge(WRITE) THEN IF (Addr mod 4 = 0) THEN next_state <= PASSUNLOCK1; ELSE next_state <= RESET; END IF; END IF; WHEN PASSUNLOCK1 => IF falling_edge(WRITE) THEN IF (Addr mod 4 = 1) THEN next_state <= PASSUNLOCK2; ELSE next_state <= RESET; END IF; END IF; WHEN PASSUNLOCK2 => IF falling_edge(WRITE) THEN IF (Addr mod 4 = 2) THEN next_state <= PASSUNLOCK3; ELSE next_state <= RESET; END IF; END IF; WHEN PASSUNLOCK3 => IF falling_edge(WRITE) THEN IF (Addr mod 4 = 3) THEN next_state <= PASSUNLOCK; ELSE next_state <= RESET; END IF; END IF; WHEN PASSUNLOCK => IF falling_edge(WRITE) AND PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= PASSUNLOCK; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PPB_LOCK_SET => IF falling_edge(WRITE) AND PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= PPB_LOCK_SET; END IF; WHEN PROTBIT_PREL => IF falling_edge(WRITE) THEN IF DataLo = 16#68# AND (Addr mod 16#100# = WP) THEN next_state <= PPB_PROGRAM; ELSIF DataLo = 16#60# AND (Addr mod 16#100# = WPE) THEN next_state <= PPB_ERASE; ELSIF DataLo = 16#68# AND (Addr mod 16#100# = PL) THEN next_state <= PPMLB_PROGRAM; ELSIF DataLo = 16#68# AND (Addr mod 16#100# = SL) THEN next_state <= SPMLB_PROGRAM; ELSE next_state <= RESET; END IF; END IF; WHEN PPBDYB => IF falling_edge(WRITE) AND PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= PPBDYB; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN DYBWE => IF falling_edge(WRITE) AND DataLo = 16#F0# THEN next_state <= RESET; END IF; WHEN PPB_PROGRAM => IF falling_edge(WRITE) AND PBPROG_out = '1' AND DataLo = 16#48# AND ( Addr mod 16#100# = WP ) THEN next_state <= PPB_PROGRAM_VERIFY; END IF; WHEN PPB_PROGRAM_VERIFY => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= RESET; ELSIF PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= PPB_PROGRAM_VERIFY; ELSIF DataLo = 16#68# AND (Addr mod 16#100# = WP) THEN next_state <= PPB_PROGRAM; END IF; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PPB_ERASE => IF falling_edge(WRITE) AND PBERASE_out = '1' AND DataLo = 16#40# AND ( Addr mod 16#100# = WPE ) THEN next_state <= PPB_ERASE_VERIFY; END IF; WHEN PPB_ERASE_VERIFY => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= RESET; ELSIF PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= PPB_ERASE_VERIFY; ELSIF DataLo = 16#60# AND (Addr mod 16#100# = WPE) THEN next_state <= PPB_ERASE; END IF; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PPMLB_PROGRAM => IF falling_edge(WRITE) AND PBPROG_out = '1' AND DataLo = 16#48# AND ( Addr mod 16#100# = PL ) THEN next_state <= PPMLB_VERIFY; END IF; WHEN SPMLB_PROGRAM => IF falling_edge(WRITE) AND PBPROG_out = '1' AND DataLo = 16#48# AND ( Addr mod 16#100# = SL ) THEN next_state <= SPMLB_VERIFY; END IF; WHEN SSPB_PROGRAM => IF falling_edge(WRITE) AND PBPROG_out = '1' AND DataLo = 16#48# AND ( Addr mod 16#100# = OW ) THEN next_state <= SSPB_VERIFY; END IF; WHEN PPMLB_VERIFY => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= RESET; ELSIF PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= PPMLB_VERIFY; END IF; END IF; IF falling_edge(BURST) AND ( Addr mod 16#100# = PL ) THEN SYNCREAD := TRUE; END IF; WHEN SPMLB_VERIFY => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= RESET; ELSIF PATTERN_1 THEN next_state <= EXIT_1; ExitFrom <= SPMLB_VERIFY; END IF; END IF; IF falling_edge(BURST) AND ( Addr mod 16#100# = SL ) THEN SYNCREAD := TRUE; END IF; WHEN SSPB_VERIFY => IF falling_edge(WRITE) AND DataLo = 16#F0# THEN next_state <= OTP; END IF; IF falling_edge(BURST) AND ( Addr mod 16#100# = OW ) THEN SYNCREAD := TRUE; END IF; WHEN OTP => IF falling_edge(WRITE) THEN IF PATTERN_1 THEN next_state <= OTP_Z001; ELSE next_state <= OTP; END IF; END IF; IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN OTP_Z001 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= OTP_PREL; ELSE next_state <= OTP; END IF; END IF; WHEN OTP_PREL => IF falling_edge(WRITE) THEN IF (A_PAT_1 AND (DataLo = 16#90#))THEN next_state <= OTP_AS; ELSIF (A_PAT_1 AND (DataLo = 16#A0#))THEN next_state <= OTP_A0SEEN; ELSIF (A_PAT_1 AND (DataLo = 16#60#))THEN next_state <= OTP_PROTBIT; ELSE next_state <= OTP; END IF; END IF; WHEN OTP_PROTBIT => IF falling_edge(WRITE) THEN IF DataLo = 16#68# AND (Addr mod 16#100# = OW) THEN next_state <= SSPB_PROGRAM; ELSE next_state <= OTP; END IF; END IF; WHEN OTP_AS => IF falling_edge(WRITE) THEN IF DataLo=16#00# THEN IF ESP_ACT = '1' THEN next_state <= ESP; ELSE next_state <= RESET; END IF; OTP_ACT <= '0'; ELSE next_state <= OTP; END IF; END IF; WHEN OTP_A0SEEN => IF falling_edge(write) THEN next_state <= PGMS; --set OTP END IF; WHEN EXIT_1 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= EXIT_2; ELSE next_state <= ExitFrom; END IF; END IF; WHEN EXIT_2 => IF falling_edge(WRITE) THEN IF (A_PAT_1 AND (DataLo = 16#90#))THEN next_state <= EXIT_3; ELSE next_state <= ExitFrom; END IF; END IF; WHEN EXIT_3 => IF falling_edge(WRITE) THEN IF DataLo=16#00# THEN next_state <= RESET; ELSE next_state <= ExitFrom; END IF; END IF; END CASE; IF (rising_edge(gCE_n) OR falling_edge(AVDNeg)) AND (READ_MODE /= NOSYNC) THEN READ_MODE <= NOSYNC; END IF; IF BURST_TR THEN IF ConfReg(16 downto 15) = "00" THEN READ_MODE <= CONTINUOUS; ELSE READ_MODE <= LINEAR; END IF; ReadINIT <= '0', '1' AFTER 2 ns; ELSIF SYNCREAD THEN READ_MODE <= SYNCR; ReadINIT <= '0', '1' AFTER 2 ns; END IF; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS(WRITE, READ, BURST, Addr, SecAddr, CLKMerge,ReadINIT, PDONE, EDONE, HANG, START_T1, CTMOUT, RST, reseted, READY, gOE_n, current_state, OENeg, CENeg, WENeg, PERR, EERR, PBPROG_out, PBERASE_out, PASSPDONE_out, UNLOCKDONE_out, AVDNeg) --Common Flash Interface Query codes TYPE CFItype IS ARRAY (16#10# TO 16#5B#) OF NATURAL RANGE 0 TO 16#FF#; TYPE ASELtype IS ARRAY (0 TO 16#0F#) OF NATURAL RANGE 0 TO 16#FFFF#; --Program VARIABLE CFI_array : CFItype :=(OTHERS=>0); VARIABLE ASEL_array : ASELtype :=(OTHERS=>0); VARIABLE WData : INTEGER RANGE -1 TO MaxData; VARIABLE WAddr : INTEGER RANGE -1 TO SecSize; VARIABLE SecSiAddr : NATURAL RANGE 0 TO SecSize; VARIABLE cnt : NATURAL RANGE 0 TO 31 := 0; VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; VARIABLE oe : boolean := FALSE; --Status reg. VARIABLE Status : std_logic_vector(15 downto 0) := (OTHERS=>'0'); VARIABLE old_bit : std_logic_vector(15 downto 0); VARIABLE new_bit : std_logic_vector(15 downto 0); VARIABLE old_int : INTEGER RANGE -1 to MaxData; VARIABLE new_int : INTEGER RANGE -1 to MaxData; VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE ASELInd : NATURAL RANGE 0 TO 15; VARIABLE temp : std_logic_vector(7 downto 0); VARIABLE tmpA : std_logic_vector(HiAddrBit downto 0); VARIABLE AddrCFI : NATURAL; VARIABLE tmpSect : NATURAL RANGE 0 TO SecNum; VARIABLE ReadOK : BOOLEAN; VARIABLE DataLo : NATURAL RANGE 0 TO MaxData; VARIABLE AddrLOW : NATURAL RANGE 0 TO ADDRRange; VARIABLE AddrHIGH : NATURAL RANGE 0 TO ADDRRange; VARIABLE AddrCHECK : NATURAL RANGE 0 TO ADDRRange; VARIABLE BurstAddr : NATURAL RANGE 0 TO ADDRRange; VARIABLE BurstOffset : NATURAL; VARIABLE BurstSect : NATURAL RANGE 0 TO SecNum; VARIABLE AddrSuspend : NATURAL RANGE 0 TO ADDRRange; VARIABLE SectSuspend : NATURAL RANGE 0 TO SecNum; VARIABLE RYSuspend : std_logic; VARIABLE LatencyAddr : NATURAL RANGE 0 TO ADDRRange; VARIABLE LatencySect : NATURAL RANGE 0 TO SecNum; VARIABLE BurstBorder : NATURAL RANGE 0 TO 32; VARIABLE WrapMax : NATURAL RANGE 0 TO 128; VARIABLE BusyBOUND : BOOLEAN; VARIABLE CrossData : std_logic_vector(15 downto 0); VARIABLE LATCHED_3E_3F : BOOLEAN; VARIABLE INITIAL : BOOLEAN; VARIABLE RESUMED : BOOLEAN; VARIABLE LatencyRESUME : BOOLEAN; VARIABLE LatencyBOUND : BOOLEAN; VARIABLE LatencyBUSY : BOOLEAN; VARIABLE STALL : BOOLEAN; VARIABLE ResumeCODE : NATURAL RANGE 0 TO 6; VARIABLE BoundCODE : NATURAL RANGE 0 TO 6; VARIABLE BusyCODE : NATURAL RANGE 0 TO 6; VARIABLE OutputD : std_logic_vector(15 downto 0); VARIABLE SyncData : std_logic_vector(15 downto 0); VARIABLE WAddrPass : NATURAL RANGE 0 TO 3; VARIABLE WDataPass : std_logic_vector(15 downto 0); VARIABLE UnlockPass : BOOLEAN; VARIABLE PBSecAddr : NATURAL RANGE 0 TO SecNum; PROCEDURE UpdateADDR( BurstSect : INOUT NATURAL; BurstAddr : INOUT NATURAL ) IS VARIABLE AddrCHECK : NATURAL; VARIABLE SecTemp : NATURAL; BEGIN ADDRHILO(AddrLOW, AddrHIGH, SecTemp); AddrCHECK := AddrLOW + BurstAddr; --Address Update IF ReturnSectorID(AddrCHECK) /= ReturnSectorID((AddrCHECK+1) mod (ADDRRange+1)) THEN IF BurstSect = SecNum THEN BurstSect := 0; ELSE BurstSect := BurstSect + 1; END IF; BurstAddr := 0; ELSE BurstAddr := BurstAddr + 1; END IF; END PROCEDURE UpdateADDR; PROCEDURE UpdateADDRL( BurstAddr : INOUT NATURAL; BurstBorder : NATURAL ) IS BEGIN BurstAddr := BurstAddr + 1; IF BurstAddr mod BurstBorder = 0 THEN BurstAddr := BurstAddr - BurstBorder; END IF; END PROCEDURE UpdateADDRL; PROCEDURE CheckBoundary(BusyBound : INOUT BOOLEAN; CrossData : INOUT STD_LOGIC_VECTOR(15 downto 0); BurstAddr : INOUT NATURAL; BurstSect : INOUT NATURAL) IS VARIABLE BankCHECK : BANK; VARIABLE SectorCHECK : NATURAL; VARIABLE AddrCHECK : NATURAL; BEGIN ADDRHILO(AddrLOW, AddrHIGH, BurstSect); AddrCHECK := AddrLOW + BurstAddr; BankCHECK := ReturnBank((AddrCHECK+1) mod (ADDRRange+1)); SectorCHECK := ReturnSectorID((AddrCHECK+1) mod (ADDRRange+1)); BusyBOUND := FALSE; IF (BankCHECK = BankASEL AND (current_state=AS OR current_state=ESP_AS))THEN CrossData := to_slv(ASEL_array(0),16); BusyBOUND := TRUE; ELSIF (BankCHECK=BankPROGRAM AND current_state=PGMS) THEN CrossData := Status; BusyBOUND := TRUE; ELSIF (BusyBankE(BankERASE,BankCHECK) AND (current_state=SERS OR current_state=SERS_EXEC OR current_state=ESPS)) THEN CrossData := Status; BusyBOUND := TRUE; ELSIF (BankCHECK=BankUBPASS AND current_state=PREL_ULBYPASS) THEN CrossData := (OTHERS => 'Z'); BusyBOUND := TRUE; ELSIF (Ers_Queue(SectorCHECK) = '1' AND (current_state = ESP OR current_state = ESPS)) THEN CrossData := Status; BusyBOUND := TRUE; ELSIF (Ers_Queue(SectorCHECK) = '1' AND (current_state = PGMS AND ESP_ACT = '1')) THEN CrossData := Status; CrossData(7) := '1'; BusyBOUND := TRUE; END IF; BusyBOUND := BusyBOUND AND ( ReturnBank(AddrCHECK)/= BankCHECK OR ReturnSectorID(AddrCHECK)/= SectorCHECK ); END PROCEDURE CheckBoundary; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(WRITE) THEN Data := D_tmp; DataLo := Data mod 16#100#; PATTERN_1 := (Addr mod 16#1000# = 16#555#) AND (DataLo = 16#AA#) ; PATTERN_2 := (Addr mod 16#1000# = 16#2AA#) AND (DataLo = 16#55#) ; A_PAT_1 := (Addr mod 16#1000# = 16#555#); END IF; oe := falling_edge(READ); IF falling_edge(RST) AND RESETNeg = '0' THEN ConfReg(19 downto 12) := "11100101"; ULBYPASS <= '0'; ESP_ACT <= '0'; IF PPMLB = '1' THEN PPBLock := '1'; ELSE PPBLock := '0'; END IF; DYB := (OTHERS => '0'); PBPROG_in <= '0'; PBERASE_in <= '0'; PASSPDONE_in <= '0'; UNLOCKDONE_in <= '0'; BankE(BankERASE,BankID,FALSE); END IF; IF falling_edge(BURST) THEN INITIAL := TRUE; BurstBorder := to_nat(ConfReg(16 downto 15))*8; IF ConfReg(16 downto 15) = "11" THEN BurstBorder := 32; END IF; BurstAddr := Addr; BurstSect := SecAddr; BurstDelay := BurstDelay + to_nat(ConfReg(14 downto 12)) + 1; RESUMED := TRUE; STALL := FALSE; LatencyRESUME := FALSE; LatencyBUSY := FALSE; LatencyBOUND := FALSE; IF ConfReg(16 downto 15) = "00" THEN LATCHED_3E_3F := (BurstAddr mod 16#40# = 16#3E# OR BurstAddr mod 16#40# = 16#3F#); IF Reduced AND LATCHED_3E_3F THEN BurstDelay := BurstDelay + 2; ELSIF BurstAddr mod 2 = 1 AND Reduced THEN BurstDelay := BurstDelay + 1; END IF; ELSE WrapMax := 128; IF BurstAddr mod 2 = 1 AND Reduced THEN BurstDelay := BurstDelay + 1; END IF; END IF; END IF; IF falling_edge(AVDNeg) THEN RY_sync <= '0'; END IF; IF reseted = '1' THEN CASE current_state IS WHEN RESET => RY_async <= '1'; ESP_ACT <= '0'; IF oe THEN DOut_zd <= READMEM(Mem(SecAddr)(Addr)); END IF; WHEN Z001 => NULL; WHEN PREL_SETBWB => IF falling_edge(WRITE) THEN IF (A_PAT_1 AND (DataLo = 16#20#)) THEN ULBYPASS <= '1'; BankUBPASS := BankID; ELSIF (A_PAT_1 AND DataLo = 16#90#) THEN BankASEL := BankID; ELSIF (A_PAT_1 AND DataLo = 16#C0#) THEN tmpSect := SecAddr; ADDRHILO(AddrLOW, AddrHIGH, tmpSect); tmpA := to_slv((AddrLOW+Addr),HiAddrBit+1); ConfReg(19 downto 12) := tmpA(19 downto 12); IF to_nat(tmpA(14 downto 12)) = 0 THEN ConfReg(18) := '1'; END IF; ELSIF (A_PAT_1 AND DataLo = 16#78#) THEN PPBLock := '1'; ELSIF (A_PAT_1 AND DataLo = 16#88#) THEN NULL; END IF; END IF; WHEN PREL_ULBYPASS => IF BankID = BankUBPASS THEN OutputD := (OTHERS => 'Z'); ELSE OutputD := READMEM(Mem(SecAddr)(Addr)); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN RES_ULBYPASS => IF falling_edge(WRITE) AND (DataLo = 16#00#) THEN ULBYPASS <= '0'; END IF; WHEN CFI | UBP_CFI => OutputD := (OTHERS=>'0'); IF (( Addr >= 16#10#) AND (Addr <= 16#3C#)) OR ((Addr >= 16#40#) AND (Addr <= 16#50#)) OR ((Addr >= 16#57#) AND (Addr <= 16#5B#)) THEN OutputD(7 downto 0) := to_slv(CFI_array(Addr),8); ELSIF oe THEN--OR falling_edge(BURST) THEN ASSERT FALSE REPORT "Invalid CFI query address" SEVERITY warning; END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN AS => IF BankID = BankASEL THEN ASELInd := Addr mod 16; IF ASELInd = 0 OR ASELInd = 1 OR ASELInd = 3 OR ASELInd = 16#0E# OR ASELInd = 16#0F# THEN OutputD := to_slv(ASEL_array(ASELInd),16); ELSIF ASELInd = 2 THEN OutputD := to_slv(0,16); OutputD(0) := PPB(GroupID(SecAddr)); END IF; ELSE OutputD := READMEM(Mem(SecAddr)(Addr)); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN A0SEEN => IF falling_edge(WRITE) AND NOT (ULBYPASS = '1' AND BankID /= BankUBPASS) THEN BankPROGRAM := BankID; PSTART <= '1', '0' AFTER 1 ns; WData := Data; WAddr := Addr; SA <= SecAddr; temp := to_slv(Data, 8); Status(7) := NOT temp(7); RY_async <= '0'; END IF; WHEN C8 => NULL; WHEN C8_Z001 => NULL; WHEN C8_PREL => IF falling_edge(WRITE) THEN IF ( A_PAT_1 OR ULBYPASS = '1' )AND DataLo = 16#10# THEN --Start Chip Erase ESTART <= '1', '0' AFTER 1 ns; RY_async <= '0'; ESUSP <= '0'; ERES <= '0'; Ers_Queue <= (OTHERS => '1'); Status := "0000000000001000"; ELSIF ( DataLo = 16#30# ) AND NOT (ULBYPASS = '1' AND BankID /= BankUBPASS) THEN BankE(BankERASE, BankID, TRUE); --put selected sector to sec. ers. queue --start timeout Ers_Queue <= (OTHERS => '0'); Ers_Queue(SecAddr) <= '1'; CTMOUT_in <= '0', '1' AFTER 2 ns; END IF; END IF; WHEN ERS => ----------------------------------------------------------- -- read status / embeded erase algorithm - Chip Erase ----------------------------------------------------------- IF oe THEN--OR falling_edge(BURST) THEN Status(5) := '0'; Status(3) := '1'; Status(6) := NOT Status(6); --toggle Status(7) := '0'; Status(2) := NOT Status(2); --toggle OutputD := Status; END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; IF falling_edge(EDONE) AND EERR /= '1' THEN FOR i IN 0 TO SecNum LOOP IF ( DYB(i) = '0' AND PPB(GroupID(i)) = '0' AND NOT (WPNeg = '0' AND (i <= 3 OR i >= SecNum-3)) AND NOT (ACC = '0')) THEN Mem(i):= (OTHERS => -1); END IF; END LOOP; END IF; IF rising_edge(EDONE) AND EERR /= '1' THEN FOR i IN 0 TO SecNum LOOP IF ( DYB(i) = '0' AND PPB(GroupID(i)) = '0' AND NOT (WPNeg = '0' AND (i <= 3 OR i >= SecNum-3)) AND NOT (ACC = '0')) THEN Mem(i):= (OTHERS => MaxData); END IF; END LOOP; END IF; IF rising_edge(EDONE) THEN RY_async <= '1'; END IF; -- busy signal active WHEN SERS => IF CTMOUT'EVENT AND CTMOUT = '1' THEN CTMOUT_in <= '0'; START_T1_in <= '0'; ESTART <= '1', '0' AFTER 1 ns; RY_async <= '0'; ESUSP <= '0'; ERES <= '0'; ELSIF falling_edge(WRITE) THEN IF (DataLo = 16#B0#) AND BusyBankE(BankERASE,BankID) THEN ESTART <= '1', '0' AFTER 1 ns; ERES <= '0'; --suspend timeout (should be 0 according to datasheet) START_T1_in <= '0';--- ?????????????????? ESUSP <= '1' AFTER 2 ns, '0' AFTER 3 ns; ELSIF (DataLo = 16#30#) THEN -- No bank restriction ----> AND BankID = BankErase THEN BankE(BankERASE, BankID, TRUE); CTMOUT_in <= '0', '1' AFTER 2 ns; Ers_Queue(SecAddr) <= '1'; END IF; END IF; Status(7) := '1'; Status(3) := '0'; IF BusyBankE(BankERASE,BankID) THEN OutputD := Status; ELSE OutputD := READMEM(Mem(SecAddr)(Addr)); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN ESPS => IF (START_T1 = '1') THEN ESP_ACT <= '1'; START_T1_in <= '0'; RY_async <= '1'; END IF; ----------------------------------------------------------- --read status / erase suspend timeout - stil erasing ----------------------------------------------------------- IF oe THEN--OR falling_edge(BURST) THEN Status(6) := NOT Status(6); --toggle Status(5) := '0'; Status(3) := '1'; IF Ers_Queue(SecAddr) = '1' THEN Status(7) := '0'; Status(2) := NOT Status(2); --toggle END IF; IF BusyBankE(BankERASE,BankID) THEN OutputD := Status; ELSE OutputD := READMEM(Mem(SecAddr)(Addr)); END IF; END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN SERS_EXEC => IF oe THEN --OR falling_edge(BURST) THEN Status(6) := NOT Status(6); --toggle Status(5) := '0'; Status(3) := '1'; IF Ers_Queue(SecAddr) = '1' THEN Status(2) := NOT Status(2); --toggle Status(7) := '0'; END IF; IF BusyBankE(BankERASE,BankID) THEN OutputD := Status; ELSE OutputD := READMEM(Mem(SecAddr)(Addr)); END IF; END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; IF falling_edge(EDONE) AND EERR /= '1' THEN FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND DYB(i) = '0' AND PPB(GroupID(i)) = '0' AND NOT (WPNeg = '0' AND (i <= 3 OR i >= SecNum-3)) AND NOT (ACC = '0') THEN Mem(i) := (OTHERS => -1); END IF; END LOOP; END IF; IF rising_edge(EDONE) AND EERR /= '1' THEN FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND DYB(i) = '0' AND PPB(GroupID(i)) = '0' AND NOT (WPNeg = '0' AND (i <= 3 OR i >= SecNum-3)) AND NOT (ACC = '0') THEN Mem(i) := (OTHERS => MaxData); END IF; END LOOP; END IF; IF rising_edge(EDONE) THEN RY_async <= '1'; BankE(BankERASE,BankID,FALSE); END IF; IF falling_edge(WRITE) AND EERR /= '1' AND DataLo = 16#B0# THEN START_T1_in <= '1'; ESUSP <= '1', '0' AFTER 1 ns; END IF; WHEN ESP => IF falling_edge(WRITE) THEN IF DataLo = 16#30# AND BusyBankE(BankERASE,BankID) THEN --resume erase ERES <= '1', '0' AFTER 1 ns; RY_async <= '0'; END IF; END IF; IF oe THEN--OR falling_edge(BURST) THEN Status(5) := '0'; IF Ers_Queue(SecAddr) = '1' THEN Status(7) := '1'; Status(2) := NOT Status(2); --toggle END IF; IF ( Ers_Queue(SecAddr) /= '1' ) THEN OutputD := READMEM(Mem(SecAddr)(Addr)); ELSE OutputD := Status; END IF; END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN ESP_Z001 => NULL; WHEN ESP_PREL => IF falling_edge(WRITE) AND DataLo = 16#90# THEN BankASEL := BankID; END IF; WHEN ESP_CFI => OutputD := (OTHERS=>'0'); IF ((Addr >= 16#10#) AND (Addr <= 16#3C#)) OR ((Addr >= 16#40#) AND (Addr <= 16#50#)) OR ((Addr >= 16#57#) AND (Addr <= 16#5B#)) THEN OutputD(7 downto 0) := to_slv(CFI_array(Addr) ,8); ELSIF oe THEN --OR falling_edge(BURST) THEN ASSERT FALSE REPORT "Invalid CFI query address" SEVERITY warning; END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN ESP_A0SEEN => IF falling_edge(WRITE) AND Ers_Queue(SecAddr) /= '1' THEN ESP_ACT <= '1'; PSTART <= '1', '0' AFTER 1 ns; RY_async <= '0'; WData := Data; WAddr := Addr; SA <= SecAddr; temp := to_slv(Data, 8); Status(7) := NOT temp(7); BankPROGRAM := BankID; END IF; WHEN ESP_AS => IF BankID = BankASEL THEN ASELInd := Addr mod 16; IF ASELInd = 0 OR ASELInd = 1 OR ASELInd = 3 OR ASELInd = 16#0E# OR ASELInd = 16#0F# THEN OutputD := to_slv(ASEL_array(ASELInd),16); ELSIF ASELInd = 2 THEN OutputD := to_slv(0,16); OutputD(0) := PPB(GroupID(SecAddr)); END IF; ELSIF BankID /= BankASEL AND BusyBankE(BankERASE,BankID) AND oe AND Ers_Queue(SecAddr) = '1' THEN Status(7) := '1'; Status(5) := '0'; Status(2) := NOT Status(2); --toggle OutputD := Status; ELSE OutputD := READMEM(Mem(SecAddr)(Addr)); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN PGMS => IF oe THEN --OR falling_edge(BURST) THEN Status(6) := NOT Status(6); --toggle Status(5) := '0'; -- Status(2) no toggle Status(1) := '0'; IF BankID = BankPROGRAM THEN OutputD := Status; ELSIF BankID /= BankPROGRAM AND ESP_ACT = '1' AND BusyBankE(BankERASE,BankID) AND Ers_Queue(SecAddr) = '1' THEN Status(2) := NOT Status(2); OutputD := Status; ELSE OutputD := READMEM(Mem(SecAddr)(Addr)); END IF; END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; IF PERR/='1' THEN new_int:= WData; IF OTP_ACT = '1' THEN old_int := SecSi(WAddr); ELSE old_int:=Mem(SA)(WAddr); END IF; IF new_int>-1 THEN new_bit:=to_slv(new_int,16); IF old_int>-1 THEN old_bit:=to_slv(old_int,16); FOR j IN 0 TO 15 LOOP IF old_bit(j) = '0' THEN new_bit(j):='0'; END IF; END LOOP; new_int:=to_nat(new_bit); END IF; WData:= new_int; ELSE WData := -1; END IF; IF NOT falling_edge(PERR) THEN IF OTP_ACT = '1' THEN SecSi(WAddr) := -1; ELSE Mem(SA)(WAddr) := -1; END IF; END IF; IF HANG /= '1' AND PDONE = '1' AND (NOT PERR'EVENT) THEN RY_async <= '1'; IF OTP_ACT = '1' THEN SecSi(WAddr) := WData; ELSE Mem(SA)(WAddr) := WData; END IF; END IF; END IF; WHEN PASSPROG_PREL => IF falling_edge(WRITE) THEN WAddrPASS := Addr mod 4; WDataPASS := to_slv(Data,16); PASSPDONE_in <= '0', '1' AFTER 1 ns; RY_async <= '0'; END IF; WHEN PASSPROG => IF rising_edge(PASSPDONE_out) THEN Password(WAddrPASS) := WDataPass AND Password(WAddrPASS); RY_async <= '1'; END IF; IF oe AND PASSPDONE_out = '0' THEN Status(7) := NOT WDataPass(7); Status(6) := NOT Status(6); Status(5) := '0'; Status(1) := '0'; END IF; IF oe THEN DOut_zd <= Status; SyncData := Status; END IF; WHEN PASSVERIFY => IF PPMLB /= '1' THEN OutputD := Password(Addr mod 4); ELSE OutputD := (OTHERS => '1'); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN PASSUNLOCK0 => IF falling_edge(WRITE) AND (Addr mod 4 = 0) THEN UnlockPass := to_nat(Password(Addr mod 4)) = Data; END IF; WHEN PASSUNLOCK1 => IF falling_edge(WRITE) AND (Addr mod 4 = 1) THEN UnlockPass := UnlockPass AND to_nat(Password(Addr mod 4)) = Data; END IF; WHEN PASSUNLOCK2 => IF falling_edge(WRITE) AND (Addr mod 4 = 2) THEN UnlockPass := UnlockPass AND to_nat(Password(Addr mod 4)) = Data; END IF; WHEN PASSUNLOCK3 => IF falling_edge(WRITE) AND (Addr mod 4 = 3) THEN UnlockPass := UnlockPass AND to_nat(Password(Addr mod 4)) = Data; UNLOCKDONE_in <= '0','1' AFTER 1 ns; RY_async <= '0'; END IF; WHEN PASSUNLOCK => IF rising_edge(UNLOCKDONE_out) THEN IF UnlockPass THEN PPBLock := '0'; END IF; RY_async <= '1'; END IF; IF oe AND UNLOCKDONE_out = '0' THEN Status(6) := NOT Status(6); END IF; IF oe THEN DOut_zd <= Status; SyncData := Status; END IF; WHEN PROTBIT_PREL => IF falling_edge(WRITE) THEN IF DataLo = 16#68# AND (Addr mod 16#100# = WP) THEN PBSecAddr := SecAddr; PBPROG_in <= '0', '1' AFTER 1 ns; RY_async <= '0'; ELSIF DataLo = 16#60# AND (Addr mod 16#100# = WPE) THEN PBErase_in <= '0', '1' AFTER 1 ns; RY_async <= '0'; ELSIF DataLo = 16#68# AND (Addr mod 16#100# = PL) THEN PBPROG_in <= '0', '1' AFTER 1 ns; RY_async <= '0'; ELSIF DataLo = 16#68# AND (Addr mod 16#100# = SL) THEN PBPROG_in <= '0', '1' AFTER 1 ns; RY_async <= '0'; END IF; END IF; WHEN PPBDYB => OutputD := (OTHERS => '0'); OutputD(1) := PPBLock; OutputD(0) := DYB(SecAddr); IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN DYBWE => IF falling_edge(WRITE) THEN IF Data mod 2 = 0 THEN DYB(SecAddr) := '0'; ELSE DYB(SecAddr) := '1'; END IF; END IF; WHEN PPB_PROGRAM => IF rising_edge(PBPROG_out) THEN IF PPBLock = '0' THEN PPB(GroupID(PBSecAddr)) := '1'; END IF; RY_async <= '1'; END IF; WHEN PPB_PROGRAM_VERIFY => OutputD := (OTHERS => '0'); OutputD(0) := PPB(GroupID(SecAddr)); IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN PPB_ERASE_VERIFY => OutputD := (OTHERS => '0'); OutputD(0) := PPB(GroupID(SecAddr)); IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN PPB_ERASE => IF rising_edge(PBERASE_out) THEN IF PPBLock = '0' THEN PPB := (OTHERS => '0'); END IF; RY_async <= '1'; END IF; WHEN PPMLB_PROGRAM => IF rising_edge(PBPROG_out) THEN IF SPMLB /= '1' THEN PPMLB := '1'; END IF; RY_async <= '1'; END IF; WHEN SPMLB_PROGRAM => IF rising_edge(PBPROG_out) THEN IF PPMLB /= '1' THEN SPMLB := '1'; END IF; RY_async <= '1'; END IF; WHEN SSPB_PROGRAM => IF rising_edge(PBPROG_out) THEN SSPB := '1'; ASEL_array(3) := to_nat( to_slv(ASEL_array(3),16) OR "0000000001000000"); RY_async <= '1'; END IF; WHEN PPMLB_VERIFY => IF Addr mod 16#100# = PL THEN OutputD := (OTHERS => '0'); OutputD(0) := PPMLB; ELSE OutputD := (OTHERS => 'Z'); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN SPMLB_VERIFY => IF Addr mod 16#100# = SL THEN OutputD := (OTHERS => '0'); OutputD(0) := SPMLB; ELSE OutputD := (OTHERS => 'Z'); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN SSPB_VERIFY => IF Addr mod 16#100# = OW THEN OutputD := (OTHERS => '0'); OutputD(0) := SSPB; ELSE OutputD := (OTHERS => 'Z'); END IF; IF oe THEN DOut_zd <= OutputD; SyncData := OutputD; END IF; WHEN OTP => SecSiAddr := Addr MOD (SecSiSize + 1); IF SecSi(SecSiAddr) = -1 THEN OutputD := (OTHERS => 'X'); ELSE OutputD := to_slv