------------------------------------------------------------------------------- -- File name : am29bl162c.vhd ------------------------------------------------------------------------------- -- Copyright (C) 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 N.Makljenovic 04 Aug 27 Inital Release -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH -- Technology: Flash Memory -- Part: am29bl162c -- -- Description: 16Mbit (1M x16-Bit) Simultaneous opration, Burst mode, -- Top boot sector -- ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- 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 FOR am29bl162c ------------------------------------------------------------------------------- ENTITY am29bl162c 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; tipd_A10 : VitalDelayType01 := VitalZeroDelay01; 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_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; tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; 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_LBANeg : VitalDelayType01 := VitalZeroDelay01; tipd_BAANeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; tipd_CLK : VitalDelayType01 := VitalZeroDelay01; -- tpd delays for FLASH tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01; tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; tpd_CLK_RY : VitalDelayType01 := UnitDelay01; tpd_CLK_DQ0 : VitalDelayType01 := UnitDelay01; tpd_WENeg_RY : VitalDelayType01Z := UnitDelay01Z; tpd_CLK_IND : VitalDelayType01Z := UnitDelay01Z; tsetup_A0_WENeg : VitalDelayType := UnitDelay; tsetup_DQ0_WENeg : VitalDelayType := UnitDelay; tsetup_CENeg_WENeg : VitalDelayType := UnitDelay; tsetup_WENeg_CENeg : VitalDelayType := UnitDelay; tsetup_CENeg_CLK : VitalDelayType := UnitDelay; tsetup_LBANeg_CLK : VitalDelayType := UnitDelay; tsetup_BAANeg_CLK : VitalDelayType := UnitDelay; tsetup_A0_CLK : VitalDelayType := UnitDelay; tsetup_OENeg_WENeg : VitalDelayType := UnitDelay; tsetup_WENeg_OENeg : VitalDelayType := UnitDelay; tsetup_RY_CENeg : VitalDelayType := UnitDelay; thold_A0_WENeg : VitalDelayType := UnitDelay; thold_DQ0_WENeg : VitalDelayType := UnitDelay; thold_DQ0_CLK : VitalDelayType := UnitDelay; thold_LBANeg_CLK : VitalDelayType := UnitDelay; thold_BAANeg_CLK : VitalDelayType := UnitDelay; thold_A0_CLK : VitalDelayType := UnitDelay; thold_CENeg_WENeg : VitalDelayType := UnitDelay; thold_WENeg_CENeg : VitalDelayType := UnitDelay; thold_CENeg_RESETNeg : VitalDelayType := UnitDelay; thold_OENeg_RESETNeg : VitalDelayType := UnitDelay; tpw_RESETNeg_negedge : VitalDelayType := UnitDelay; -- tRP -- ASync Write tpw_WENeg_negedge : VitalDelayType := UnitDelay; -- tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; -- tWPH tpw_CENeg_negedge : VitalDelayType := UnitDelay; -- tWP tpw_CENeg_posedge : VitalDelayType := UnitDelay; -- tWPH -- tdevice values: values for internal delays tdevice_POW : VitalDelayType := 9 us; --Sector Erase Operation tWHWH2 tdevice_SEO : VitalDelayType := 1 sec; --erase suspend timeout - only max time specified tdevice_ESTART_T1 : VitalDelayType := 20 us;--max 20 us --sector erase command sequence timeout tdevice_CTMOUT : VitalDelayType := 50 us; --device ready after Hardware reset(during embeded algorithm) tdevice_READY : VitalDelayType := 20 us; --tReady -- 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"; UserPreload : BOOLEAN := TRUE; LongTimming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( A0 : IN std_ulogic := 'U'; A1 : IN std_ulogic := 'U'; A2 : IN std_ulogic := 'U'; A3 : IN std_ulogic := 'U'; A4 : IN std_ulogic := 'U'; A5 : IN std_ulogic := 'U'; A6 : IN std_ulogic := 'U'; A7 : IN std_ulogic := 'U'; A8 : IN std_ulogic := 'U'; A9 : IN std_ulogic := 'U'; A10 : IN std_ulogic := 'U'; A11 : IN std_ulogic := 'U'; A12 : IN std_ulogic := 'U'; A13 : IN std_ulogic := 'U'; A14 : IN std_ulogic := 'U'; A15 : IN std_ulogic := 'U'; A16 : IN std_ulogic := 'U'; A17 : IN std_ulogic := 'U'; A18 : IN std_ulogic := 'U'; A19 : 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'; DQ8 : INOUT std_ulogic := 'U'; 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_ulogic := 'U'; LBANeg : IN std_ulogic := 'U'; BAANeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RESETNeg : IN std_ulogic := 'U'; CLK : IN std_ulogic := 'U'; IND : OUT std_ulogic := 'U'; RY : OUT std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of am29bl162c : ENTITY IS TRUE; END am29bl162c; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of am29bl162c IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "am29bl162c"; CONSTANT MaxData : NATURAL := 16#FFFF#; CONSTANT MemSize : NATURAL := 16#FFFFF#; CONSTANT SecSize : NATURAL := 16#1FFFF#; CONSTANT SecNum : NATURAL := 8; CONSTANT SubSecNum : NATURAL := 4; CONSTANT HiAddrBit : NATURAL := 19; CONSTANT LowSecAddrBit : NATURAL := 17; CONSTANT BottomSec : NATURAL := 0; CONSTANT BurstMode_bit : NATURAL := 0; -- interconnect path delay signals SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL A2_ipd : std_ulogic := 'U'; SIGNAL A3_ipd : std_ulogic := 'U'; SIGNAL A4_ipd : std_ulogic := 'U'; SIGNAL A5_ipd : std_ulogic := 'U'; SIGNAL A6_ipd : std_ulogic := 'U'; SIGNAL A7_ipd : std_ulogic := 'U'; SIGNAL A8_ipd : std_ulogic := 'U'; SIGNAL A9_ipd : std_ulogic := 'U'; SIGNAL A10_ipd : std_ulogic := 'U'; SIGNAL A11_ipd : std_ulogic := 'U'; SIGNAL A12_ipd : std_ulogic := 'U'; SIGNAL A13_ipd : std_ulogic := 'U'; SIGNAL A14_ipd : std_ulogic := 'U'; SIGNAL A15_ipd : std_ulogic := 'U'; SIGNAL A16_ipd : std_ulogic := 'U'; SIGNAL A17_ipd : std_ulogic := 'U'; SIGNAL A18_ipd : std_ulogic := 'U'; SIGNAL A19_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 RESETNeg_ipd : std_ulogic := 'U'; SIGNAL LBANeg_ipd : std_ulogic := 'U'; SIGNAL BAANeg_ipd : std_ulogic := 'U'; SIGNAL CLK_ipd : std_ulogic := 'U'; --- internal delays SIGNAL POW_out : std_ulogic := '0'; SIGNAL POU_out : std_ulogic := '0'; SIGNAL SEO_out : std_ulogic := '0'; SIGNAL POW_in : std_ulogic := '0'; SIGNAL POU_in : std_ulogic := '0'; SIGNAL SEO_in : std_ulogic := '0'; SIGNAL ESTART_T1_out : std_ulogic := '0'; --Erase Start TimeOut SIGNAL ESTART_T1_in : std_ulogic := '0'; SIGNAL CTMOUT_out : std_ulogic := '0'; -- start erease timeout SIGNAL CTMOUT_in : std_ulogic := '0'; SIGNAL READY_in : std_ulogic := '0'; SIGNAL READY_out : std_ulogic := '0'; -- Device ready after reset SIGNAL WAIT_C : NATURAL; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays POW :VitalBuf(POW_out, POW_in, (tdevice_POW ,UnitDelay)); SEO :VitalBuf(SEO_out, SEO_in, (tdevice_SEO ,UnitDelay)); CTMOUT :VitalBuf(CTMOUT_out, CTMOUT_in, (tdevice_CTMOUT ,UnitDelay)); READY :VitalBuf(READY_out, READY_in, (tdevice_READY ,UnitDelay)); ESTART_T1 :VitalBuf(ESTART_T1_out, ESTART_T1_in, (tdevice_ESTART_T1,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN 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 (LBANeg_ipd, LBANeg, tipd_LBANeg); w_41 : VitalWireDelay (CLK_ipd, CLK, tipd_CLK); w_42 : VitalWireDelay (BAANeg_ipd, BAANeg, tipd_BAANeg); 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_logic_vector(15 DOWNTO 0) := (OTHERS => 'Z'); CENeg : IN std_ulogic := 'U'; LBANeg : IN std_ulogic := 'U'; BAANeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RESETNeg : IN std_ulogic := 'U'; CLK : IN std_ulogic := 'U'; IND : OUT std_ulogic := 'U'; RY : OUT std_ulogic := 'U' ); PORT MAP ( 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, LBANeg => LBANeg_ipd, BAANeg => BAANeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, RESETNeg => RESETNeg_ipd, CLK => CLK, IND => IND, RY => RY ); -- State Machine : State_Type TYPE state_type IS ( RESET, Z001, -- unlock cycle 1 PREL_SETBWB, -- unlock cycle 2 PREL_ULBYPASS, SET_MODE, UNLOCK_RESET, -- unlock reset state CFI, -- CFI MOD AS, -- autoselect AS_CFI, -- CFI from autoselect A0SEEN, -- program preeliminary C8, -- erase preeliminary C8_Z001, -- erase unlock bypass1 C8_PREL, -- erase unlock bypass2 ERS, -- erase SERS, -- sector erase ESPS, SERS_EXEC, ESP, ESP_AS, ESP_Z001, -- erase unlock 1 ESP_SETBWB, -- erase unlock 2 ESP_CFI, -- ersae CFI MOD ESP_ULBYPASS, -- unlock bypass ESP_UNLOCK_RESET, -- reset unlock during suspend ESP_AS_CFI, ESP_A0SEEN, -- erase programing PGMS ); -- State for read FLASH TYPE read_mem_type IS (IDLE_READ, BURST_READ); --Array of Sub sector start-end address within sector TYPE SubSecAddr IS ARRAY (0 TO SubSecNum-1) OF NATURAL; TYPE SecType IS ARRAY (0 TO SecSize) OF INTEGER RANGE -1 TO MaxData; TYPE MemArray IS ARRAY (0 TO SecNum-1) OF SecType; -- states SIGNAL current_state : state_type; SIGNAL next_state : state_type; SIGNAL BurstState : read_mem_type; -- powerup SIGNAL PoweredUp : std_logic := '0'; --zero delay signals SIGNAL DOut_zd : std_logic_vector(15 DOWNTO 0) := (OTHERS =>'Z'); SIGNAL RY_zd : std_logic := 'Z'; SIGNAL DOut_pass : std_logic_vector(15 DOWNTO 0) := (OTHERS =>'Z'); --FSM control signals SIGNAL ULBYPASS : std_logic := '0'; SIGNAL SERS_ACT : std_logic := '0'; --Program Emabaded SIGNAL PGMS_ACT : std_logic := '0'; --Erase Emabaded -- signal for sector security process SIGNAL SecSicurity : 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 ESTART_SUSP : std_logic := '0'; --Start and 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-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL ERS_SUBBot_QUEUE : std_logic_vector(SubSecNum-1 DOWNTO 0) := (OTHERS => '0'); --Command Register SIGNAL write : std_logic := '0'; SIGNAL read : std_logic := '0'; --Address within sector SHARED VARIABLE Address : NATURAL RANGE 0 TO SecSize := 0; SHARED VARIABLE SSA : NATURAL RANGE 0 TO SubSecNum := 0; SHARED VARIABLE SA : NATURAL RANGE 0 TO SecNum := 0; SHARED VARIABLE Addr : NATURAL RANGE 0 TO 16#7FF# := 0; SHARED VARIABLE BrAddrSt: NATURAL RANGE 0 TO SecSize := 0; SIGNAL AddressLatch : std_logic_vector(HiAddrBit DOWNTO 0); SIGNAL AddressLatch_flag : BOOLEAN := FALSE; SIGNAL D_tmp : NATURAL RANGE 0 TO MaxData; SIGNAL D_tmp0 : NATURAL RANGE 0 TO MaxData; --glitch protection SIGNAL gWE_n : std_logic := '1'; SIGNAL gCE_n : std_logic := '1'; SIGNAL gOE_n : std_logic := '1'; SIGNAL RST : std_logic := '1'; SIGNAL reseted : std_logic := '0'; -- Mem(BA)(SecAddr)(Address).... SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS => MaxData)); --protected sectors and sub sectors SIGNAL Sec_Prot : std_logic_vector(SecNum-1 DOWNTO 0) := (OTHERS => '1'); SIGNAL SubSecBot_Prot : std_logic_vector(SubSecNum-1 DOWNTO 0) := (OTHERS => '1'); SHARED VARIABLE sssa : SubSecAddr := (16#00000#, 16#2000#, 16#03000#, 16#4000#); SHARED VARIABLE ssea : SubSecAddr:= (16#01FFF#, 16#02FFF#, 16#03FFF#, 16#1FFFF#); -- timing check violation SIGNAL Viol : X01 := '0'; SIGNAL End_burst : std_logic:= '0'; SIGNAL Start_burst : std_logic:= '0'; SIGNAL End_burst_internal : std_logic:= '0'; SIGNAL Burst_enable : std_logic; SHARED VARIABLE clk_period : TIME := 0 ns; SIGNAL IND_zd : std_logic := '1'; SIGNAL IND_pass : std_logic := '0'; SIGNAL IND_sig : std_logic; -- temp RY signal SIGNAL RY_sig : std_logic; -- signal that enable delay from clk SIGNAL clk_oe_en : BOOLEAN := FALSE; SIGNAL clk_addr_en : BOOLEAN := TRUE; SIGNAL tpd_fromOE : std_logic := '0'; SIGNAL tpd_fromCE : std_logic := '0'; SHARED VARIABLE FROMOE,FROMCE, FROMCLK, OPENLATCH : boolean; SHARED VARIABLE tpd_from_OE : BOOLEAN := FALSE; SHARED VARIABLE tpd_from_CE : BOOLEAN := FALSE; SHARED VARIABLE Open3state : BOOLEAN := FALSE; SHARED VARIABLE ASynchroMod : BOOLEAN := TRUE; SHARED VARIABLE Start_burst_tmp : BOOLEAN := FALSE; SHARED VARIABLE ERASE_START : TIME; BEGIN --------------------------------------------------------------------------- --Power Up time 100 ns; --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 100 ns; RST <= RESETNeg AFTER 500 ns; PERIOD_P : PROCESS(CLK) VARIABLE time_tmp : TIME := 0 ns; BEGIN IF rising_edge(CLK) THEN clk_period := NOW - time_tmp; time_tmp := NOW; END IF; END PROCESS; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(CENeg, LBANeg, BAANeg, WENeg, OENeg, RESETNeg,A, CLK, RY_sig, DIn) --Setup/Hold checks variables VARIABLE Tviol_CENeg_CLK : X01 := '0'; VARIABLE Tviol_LBANeg_CLK : X01 := '0'; VARIABLE Tviol_BAANeg_CLK : X01 := '0'; VARIABLE Tviol_DQ0_CLK : X01 := '0'; VARIABLE Tviol_RY_CENeg : X01 := '0'; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE Tviol_OENeg_RESETNeg : X01 := '0'; VARIABLE Tviol_OENeg_WENeg : X01 := '0'; VARIABLE Tviol_A0_CLK : X01 := '0'; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE Tviol_WENeg_OENeg : X01 := '0'; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE Tviol_A0_CENeg : X01 := '0'; VARIABLE Tviol_WENeg_CENeg_setup : X01 := '0'; VARIABLE Tviol_WENeg_CENeg_hold : X01 := '0'; VARIABLE Tviol_CENeg_WENeg_setup : X01 := '0'; VARIABLE Tviol_CENeg_WENeg_hold : X01 := '0'; VARIABLE TD_LBANeg_CLK : VitalTimingDataType; VARIABLE TD_BAANeg_CLK : VitalTimingDataType; VARIABLE TD_DQ0_CLK : VitalTimingDataType; VARIABLE TD_RY_CENeg : VitalTimingDataType; VARIABLE TD_CENeg_CLK : VitalTimingDataType; VARIABLE TD_WENeg_CENeg : VitalTimingDataType; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE TD_OENeg_RESETNeg : VitalTimingDataType; VARIABLE TD_OENeg_WENeg : VitalTimingDataType; VARIABLE TD_A0_CLK : VitalTimingDataType; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE TD_WENeg_OENeg : VitalTimingDataType; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE TD_A0_CENeg : VitalTimingDataType; VARIABLE TD_WENeg_CENeg_setup : VitalTimingDataType; VARIABLE TD_WENeg_CENeg_hold : VitalTimingDataType; VARIABLE TD_CENeg_WENeg_setup : VitalTimingDataType; VARIABLE TD_CENeg_WENeg_hold : VitalTimingDataType; -- Pulse width cheks variables VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01; BEGIN IF TimingChecksOn THEN -- Setup/Hold Checks Violation := '0'; VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_A0_WENeg, SetupHigh => tsetup_A0_WENeg, HoldLow => thold_A0_WENeg, HoldHigh => thold_A0_WENeg, CheckEnabled => CENeg='0' , RefTransition => '\', HeaderMsg => InstancePath & partID, TimingData => TD_A0_WENeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_A0_WENeg ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CENeg", SetupLow => tsetup_A0_WENeg, SetupHigh => tsetup_A0_WENeg, HoldLow => thold_A0_WENeg, HoldHigh => thold_A0_WENeg, CheckEnabled => WENeg='0' , RefTransition => '\', HeaderMsg => InstancePath & partID, TimingData => TD_A0_CENeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_A0_CENeg ); --tCES VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_CENeg_CLK, CheckEnabled => LBANeg = '0', RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_CENeg_CLK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_CENeg_CLK ); VitalSetupHoldCheck ( TestSignal => LBANeg, TestSignalName => "LBANeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_LBANeg_CLK, HoldLow => thold_LBANeg_CLK, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_LBANeg_CLK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_LBANeg_CLK ); VitalSetupHoldCheck ( TestSignal => BAANeg, TestSignalName => "BAANeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_BAANeg_CLK, HoldLow => thold_BAANeg_CLK, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_BAANeg_CLK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_BAANeg_CLK ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_A0_CLK, SetupHigh => tsetup_A0_CLK, HoldLow => thold_A0_CLK, HoldHigh => thold_A0_CLK, CheckEnabled => LBANeg = '0' , RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_A0_CLK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_A0_CLK ); VitalSetupHoldCheck ( TestSignal => Din, TestSignalName => "Din", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_DQ0_WENeg, SetupHigh => tsetup_DQ0_WENeg, HoldLow => thold_DQ0_WENeg, HoldHigh => thold_DQ0_WENeg, CheckEnabled => CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_DQ0_WENeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_DQ0_WENeg ); VitalSetupHoldCheck ( TestSignal => Din, TestSignalName => "Din", RefSignal => CENeg, RefSignalName => "CENeg", SetupLow => tsetup_DQ0_WENeg, SetupHigh => tsetup_DQ0_WENeg, HoldLow => thold_DQ0_WENeg, HoldHigh => thold_DQ0_WENeg, CheckEnabled => WENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_DQ0_CENeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_DQ0_CENeg ); VitalSetupHoldCheck ( TestSignal => DIn, TestSignalName => "DOut", RefSignal => CLK, RefSignalName => "CLK", HoldLow => thold_DQ0_CLK, HoldHigh => thold_DQ0_CLK, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_DQ0_CLK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_DQ0_CLK ); VitalSetupHoldCheck ( TestSignal => RY_sig, TestSignalName => "RY", RefSignal => CENeg, RefSignalName => "CENeg", SetupLow => tsetup_RY_CENeg, SetupHigh => tsetup_RY_CENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_RY_CENeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_RY_CENeg ); VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_OENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & partID, TimingData => TD_OENeg_WENeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_OENeg_WENeg ); VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => OENeg, RefSignalName => "OENeg", SetupHigh => tsetup_WENeg_OENeg, CheckEnabled => PGMS_ACT = '1'AND SERS_ACT = '1', RefTransition => '\', HeaderMsg => InstancePath & partID, TimingData => TD_WENeg_OENeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_WENeg_OENeg ); VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_CENeg_RESETNeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_CENeg_RESETNeg ); VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_OENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_OENeg_RESETNeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_OENeg_RESETNeg ); VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_CENeg_WENeg_hold, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_CENeg_WENeg_hold ); VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CENeg, RefSignalName => "CENeg", HoldLow => thold_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_WENeg_CENeg_hold, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_WENeg_CENeg_hold ); VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CENeg, RefSignalName => "CENeg", HoldLow => tsetup_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & partID, TimingData => TD_WENeg_CENeg_setup, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_WENeg_CENeg_setup ); VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & partID, TimingData => TD_CENeg_WENeg_setup, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_CENeg_WENeg_setup ); VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CENeg", PulseWidthHigh => tpw_CENeg_posedge, PulseWidthLow => tpw_CENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CENeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CENeg ); -- VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WENeg", PulseWidthHigh => tpw_WENeg_posedge, PulseWidthLow => tpw_WENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_WENeg ); -- RESET pulse width will be shorter than tpw_RESETNeg_negedge during simulatio -- in order to check if device works properly. If you still want these warnings -- uncomment the following section VitalPeriodPulseCheck ( TestSignal => RESETNeg, TestSignalName => "RESETNeg", PulseWidthLow => tpw_RESETNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RESETNeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_RESETNeg ); Violation := Tviol_CENeg_CLK OR Tviol_LBANeg_CLK OR Tviol_BAANeg_CLK OR Tviol_DQ0_CLK OR Tviol_RY_CENeg OR Tviol_CENeg_RESETNeg OR Tviol_OENeg_RESETNeg OR Tviol_OENeg_WENeg OR Tviol_A0_CLK OR Tviol_DQ0_WENeg OR Tviol_DQ0_CENeg OR Tviol_WENeg_OENeg OR Tviol_A0_WENeg OR Tviol_A0_CENeg OR Tviol_WENeg_CENeg_setup OR Tviol_WENeg_CENeg_hold OR Tviol_CENeg_WENeg_setup OR Tviol_CENeg_WENeg_hold OR Pviol_CENeg OR Pviol_WENeg OR Pviol_RESETNeg; ASSERT Violation = '0' REPORT InstancePath & partID & " simulation may be inaccurate due to timing violations" SEVERITY WARNING; viol <= violation; END IF; -- TimingChecksOn END PROCESS VITALTimingCheck; --------------------------------------------------------------------------- -- sequential process for reset control and FSM state transition --------------------------------------------------------------------------- StateTransition : PROCESS(next_state, RESETNeg, RST, READY_out, 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_out = '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_out = '0') OR (R = '1' AND RESETNeg = '1' AND RST = '0' AND READY_out = '0') OR (R = '1' AND RESETNeg = '1' AND RST = '1' AND READY_out = '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; gCE_n <= CENeg AFTER 5 ns; gOE_n <= OENeg AFTER 5 ns; --latch address on rising edge and data on falling edge of write write_dc: PROCESS (gWE_n, gCE_n, gOE_n, LBANeg, RESETNeg, reseted) BEGIN IF RESETNeg /= '0' AND reseted = '1' THEN IF (gWE_n = '0') AND (gCE_n = '0') AND (gOE_n = '1') THEN write <= '1'; ELSIF (gWE_n = '1' OR gCE_n = '1') AND gOE_n = '1' THEN write <= '0'; ELSE write <= '0'; END IF; ELSE write <= '0'; END IF; IF reseted = '1' THEN IF ((gWE_n = '1') AND (gCE_n = '0') AND (gOE_n = '0')) THEN read <= '1'; ELSE read <= '0'; END IF; ELSE read <= '0'; END IF; END PROCESS write_dc; --------------------------------------------------------------------------- --Process that reports warning when changes on signals WE#, CE#, OE# are --discarded --------------------------------------------------------------------------- PulseWatch : PROCESS (WENeg, CENeg, OENeg, gWE_n, gCE_n, gOE_n) BEGIN IF (WENeg'EVENT AND (WENeg = gWE_n)) OR (CENeg'EVENT AND (CENeg = gCE_n)) OR (OENeg'EVENT AND (OENeg = gOE_n)) THEN ASSERT false REPORT "Glitch detected on control signals" SEVERITY warning; END IF; END PROCESS PulseWatch; --------------------------------------------------------------------------- -- Latch address on falling edge of WE# or CE# what ever comes later -- Latches data on rising edge of WE# or CE# what ever comes first -- also Write cycle decode --------------------------------------------------------------------------- BusCycleDecode : PROCESS(A, Din, write, WENeg, CENeg, OENeg, --BYTENeg, reseted, CLK, LBANeg) VARIABLE Addr_latch : BOOLEAN := FALSE; BEGIN IF reseted = '1' THEN IF (CENeg = '0' AND WENeg /= OENeg AND ASynchroMod = TRUE) OR (CENeg = '0' AND WENeg = '0' AND ASynchroMod = FALSE) OR --asynchro read (rising_edge(CLK) AND CENeg='0' AND LBANeg = '0' AND ASynchroMod = FALSE AND Addr_Latch = FALSE ) THEN Addr := to_nat(A(10 DOWNTO 0)); Address := to_nat(A(LowSecAddrBit-1 DOWNTO 0)); CASE to_nat(A(LowSecAddrBit-1 DOWNTO LowSecAddrBit-5)) IS WHEN 2 => SSA := 1; WHEN 3 => SSA := 2; WHEN 0 |1 => SSA := 0; WHEN OTHERS => SSA := 3; END CASE; SA := to_nat(A(HiAddrBit DOWNTO LowSecAddrBit)); AddressLatch <= A; ELSIF (rising_edge(WENeg) OR rising_edge(CENeg)) AND write = '1' THEN D_tmp0 <= to_nat(Din(7 DOWNTO 0)); D_tmp <= to_nat(Din(15 DOWNTO 0)); END IF; IF (rising_edge(CLK) AND CENeg = '0' AND LBANeg = '0') THEN Addr_latch := TRUE; END IF; IF rising_edge(CENeg) OR rising_edge(LBANeg) THEN Addr_latch := FALSE; END IF; AddressLatch_flag <= Addr_latch; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Program Operations --------------------------------------------------------------------------- ProgTime : PROCESS(PSTART, reseted) VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE pow : time; BEGIN IF LongTimming THEN pow := tdevice_POW; ELSE pow := tdevice_POW/2; END IF; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programing terminated ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE = '1' THEN IF ((SA /= BottomSec) AND Sec_Prot(SA) = '0' AND Ers_Queue(SA) = '0') OR (SA = BottomSec AND SubSecBot_Prot(SSA) = '0' AND Ers_SubBot_Queue(SSA) = '0') THEN duration := pow; elapsed := 0 ns; PDONE <= '0', '1' AFTER duration; start := NOW; ELSE PERR <= '1', '0' AFTER 1 us; ASSERT FALSE REPORT "CANNOT WRITE IN SUSPEND/PROTECTED SECTOR" SEVERITY NOTE; END IF; END IF; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Erase Operations --------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, ESUSP, ESTART_SUSP, ERES, Ers_Queue, Ers_SubBot_Queue, reseted) VARIABLE cnt : NATURAL; VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE seo : time; BEGIN IF LongTimming THEN seo := tdevice_SEO; ELSE seo := tdevice_SEO/1000; END IF; IF rising_edge(reseted) THEN EDONE <= '1'; -- reset done, ERASE terminated ELSIF reseted = '1' THEN IF (rising_edge(ESTART) OR rising_edge(ESTART_SUSP)) AND EDONE = '1' THEN cnt := 0; FOR i IN 0 TO SecNum-1 LOOP IF (i /= BottomSec) THEN IF Ers_Queue(i) = '1' AND Sec_Prot(i) = '0' THEN cnt := cnt + 1; END IF; ELSE FOR y IN 0 TO SubSecNum-1 LOOP IF Ers_SubBot_Queue(y) = '1' AND SubSecBot_Prot(y) = '0' THEN cnt := cnt + 1; END IF; END LOOP; END IF; END LOOP; IF cnt > 0 THEN elapsed := 0 ns; duration := cnt * seo; EDONE <= '0', '1' AFTER duration; start := NOW; ELSE EERR <= '1', '0' AFTER 100 us; END IF; END IF; IF (rising_edge(ESUSP) OR rising_edge(ESTART_SUSP)) 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; ----------------------------------------------------------------------- -- Process that generate BURST control signals ----------------------------------------------------------------------- BurstControl : PROCESS (CLK, LBANeg, CENeg, gCE_N, gWE_n) VARIABLE burstClk_init : BOOLEAN := FALSE; BEGIN IF (LBANeg = '0' AND rising_edge(CLK) AND burstClk_init = FALSE AND ASynchroMod = FALSE AND CENeg = '0' AND WENeg /= '0') THEN burstClk_init:= TRUE; Start_burst <= '1' , '0' AFTER 1 ns; Start_burst_tmp := TRUE; END IF; IF rising_edge(LBANeg) THEN burstClk_init:= FALSE; END IF; IF (rising_edge(CENeg) AND gCE_n = '0') OR -- GLITCH START BURST (rising_edge(gCE_n) AND CENeg = '1') -- REGULAR END OR falling_edge(gWE_n)THEN End_burst <= '1' , '0' AFTER 1 ns; END IF; END PROCESS; ----------------------------------------------------------------------- -- Burst Control process ----------------------------------------------------------------------- ReadState : PROCESS (Start_burst ,End_burst, End_burst_internal, reseted) BEGIN IF rising_edge(Start_burst) THEN BurstState <= BURST_READ; END IF; IF rising_edge(End_burst) OR falling_edge(reseted) THEN BurstState <= IDLE_READ; END IF; IF rising_edge(End_burst_internal) OR falling_edge(reseted) THEN BurstState <= IDLE_READ; END IF; END PROCESS; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(write, PDONE, EDONE, CTMOUT_out, ESTART_T1_out, reseted, READY_out, PERR, EERR) VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO MaxData := 0; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(write) THEN DataLo := D_tmp0; PATTERN_1 := (Addr = 16#555#) AND (DataLo = 16#AA#) ; PATTERN_2 := (Addr = 16#2AA#) AND (DataLo = 16#55#) ; A_PAT_1 := (Addr = 16#555#) ; 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 = 16#55#) AND (DataLo = 16#98#)) THEN next_state <= CFI; ELSE next_state <= RESET; END IF; 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#A0#)) THEN next_state <= A0SEEN; ELSIF (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#C0#)) THEN next_state <= SET_MODE; ELSIF (A_PAT_1 AND (DataLo = 16#80#)) THEN next_state <= C8; ELSE next_state <= RESET; END IF; END IF; WHEN PREL_ULBYPASS => IF falling_edge(write) THEN IF DataLo = 16#90# THEN next_state <= UNLOCK_RESET; ELSIF (DataLo = 16#A0#) THEN next_state <= A0SEEN; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; WHEN SET_MODE => IF falling_edge(write) THEN next_state <= RESET; END IF; WHEN UNLOCK_RESET => IF falling_edge(write) THEN IF (DataLo = 16#00#) THEN next_state <= RESET; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; WHEN AS => IF falling_edge(write) THEN IF (DataLo = 16#F0#) THEN next_state <= RESET; ELSIF ((Addr = 16#55#) AND (DataLo = 16#98#)) THEN next_state <= AS_CFI; END IF; END IF; WHEN AS_CFI => IF falling_edge(write) THEN IF (DataLo = 16#F0#) THEN next_state <= AS; END IF; END IF; WHEN CFI => IF falling_edge(write) THEN IF (DataLo = 16#F0#) THEN next_state <= RESET; END IF; END IF; WHEN A0SEEN => IF falling_edge(write) THEN next_state <= PGMS; ELSE next_state <= A0SEEN; 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 AND DataLo = 16#10# THEN next_state <= ERS; ELSIF DataLo = 16#30# THEN next_state <= SERS; ELSE next_state <= RESET; END IF; END IF; WHEN ERS => IF rising_edge(EDONE) OR falling_edge(EERR) THEN next_state <= RESET; END IF; WHEN SERS => IF (CTMOUT_out = '1') THEN next_state <= SERS_EXEC; ELSIF falling_edge(write) THEN IF (DataLo = 16#B0#) THEN IF ASynchroMod THEN next_state <= ESP; -- ESP according to datasheet END IF; ELSIF (DataLo = 16#30#) THEN next_state <= SERS; ELSE next_state <= RESET; END IF; END IF; WHEN SERS_EXEC => IF rising_edge(EDONE) OR falling_edge(EERR) THEN next_state <= RESET; ELSIF EERR /= '1' THEN IF falling_edge(write) THEN IF DataLo = 16#B0# AND ASynchroMod THEN next_state <= ESPS; END IF; END IF; END IF; WHEN ESPS => IF (ESTART_T1_out = '1') THEN next_state <= ESP; END IF; WHEN ESP => IF falling_edge(write) THEN IF DataLo = 16#30# THEN next_state <= SERS_EXEC; ELSE IF Addr = 16#55# AND DataLo = 16#98# THEN next_state <= ESP_CFI; ELSIF PATTERN_1 THEN next_state <= ESP_Z001; END IF; END IF; END IF; WHEN ESP_ULBYPASS => IF falling_edge(write) THEN IF (DataLo = 16#A0#) THEN next_state <= ESP_A0SEEN; ELSIF DataLo = 16#90# THEN next_state <= ESP_UNLOCK_RESET; END IF; END IF; WHEN ESP_UNLOCK_RESET => IF falling_edge(write) THEN IF (DataLo = 16#00#) THEN next_state <= ESP; ELSE next_state <= ESP_ULBYPASS; END IF; END IF; WHEN ESP_Z001 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= ESP_SETBWB; ELSE next_state <= ESP; END IF; END IF; WHEN ESP_SETBWB => IF falling_edge(write) THEN IF (A_PAT_1 AND (DataLo = 16#90#)) THEN next_state <= ESP_AS; ELSIF A_PAT_1 AND DataLo = 16#A0# THEN next_state <= ESP_A0SEEN; ELSIF (A_PAT_1 AND (DataLo = 16#20#)) THEN next_state <= ESP_ULBYPASS; ELSE next_state <= ESP; END IF; END IF; WHEN ESP_AS => IF falling_edge(write) THEN IF (DataLo = 16#F0#) THEN next_state <= ESP; ELSIF ((Addr = 16#55#) AND (DataLo = 16#98#)) THEN next_state <= ESP_AS_CFI; ELSE next_state <= ESP_AS; END IF; END IF; WHEN ESP_CFI => IF falling_edge(write) THEN IF DataLo = 16#F0# THEN next_state <= ESP; END IF; END IF; WHEN ESP_AS_CFI => IF falling_edge(write) THEN IF DataLo = 16#F0# THEN next_state <= ESP_AS; ELSE next_state <= ESP_AS_CFI; END IF; END IF; WHEN ESP_A0SEEN => IF falling_edge(write) THEN next_state <= PGMS; END IF; WHEN PGMS => IF rising_edge(PDONE) OR falling_edge(PERR) THEN IF SERS_ACT = '1' THEN IF ULBYPASS = '0' THEN next_state <= ESP; ELSE next_state <= ESP_ULBYPASS; END IF; ELSIF ULBYPASS = '1' THEN next_state <= PREL_ULBYPASS; ELSE next_state <= RESET; END IF; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS(write, read, AddressLatch, CLK, PDONE, PERR, EDONE, ESTART_T1_out, CTMOUT_out, RST, reseted, READY_out, gOE_n, gCE_n, current_state, LBANeg, Start_burst, End_burst, OENeg, End_burst_internal) --SubSect changed same time as Address PROCEDURE SET_IND IS BEGIN IF NOT ASynchroMod THEN IF (BrAddrSt MOD 32 = 0) AND (Address MOD 32 = 31) THEN IND_zd <= '0'; ELSIF (Address = BrAddrSt - 1) THEN IND_zd <= '0'; ELSE IND_zd <= '1'; END IF; END IF; END PROCEDURE SET_IND; PROCEDURE BurstInit( VARIABLE Wait_Cycle : INOUT NATURAL; VARIABLE WrapCnt : INOUT INTEGER; VARIABLE WrapMode : INOUT INTEGER; VARIABLE EntEmbaded : OUT BOOLEAN; VARIABLE BrEmbaded : OUT BOOLEAN; VARIABLE erase_active : INOUT BOOLEAN; VARIABLE erase_suspend : INOUT BOOLEAN) IS BEGIN EntEmbaded := FALSE; BrEmbaded := FALSE; Address := to_nat(AddressLatch(LowSecAddrBit-1 DOWNTO 0)); BrAddrSt := to_nat(AddressLatch(LowSecAddrBit-1 DOWNTO 0)); Burst_enable <= '0' , '1' AFTER tpd_A0_DQ0(tr01); WrapCnt := 32 - to_nat(AddressLatch(4 DOWNTO 0)); WrapMode := 32; END PROCEDURE BurstInit; PROCEDURE BurstCycle( VARIABLE Wait_Cycle : INOUT NATURAL; VARIABLE WrapCnt : INOUT INTEGER; VARIABLE WrapMode : INOUT INTEGER; VARIABLE EntEmbaded : INOUT BOOLEAN; VARIABLE BrEmbaded : INOUT BOOLEAN; VARIABLE erase_active : INOUT BOOLEAN; VARIABLE erase_suspend : INOUT BOOLEAN ) IS BEGIN IF rising_edge(CLK) AND Burst_enable = '1' AND BAANeg = '0' THEN WrapCnt := WrapCnt - 1; IF WrapCnt > 0 THEN --wrap mode Address := Address +1; ELSIF WrapCnt = 0 THEN -- wrap turn around Address := Address - WrapMode +1; WrapCnt := WrapMode; END IF; IF EntEmbaded = TRUE THEN End_burst_internal <= '1' , '0' AFTER 1 ns; END IF; ELSIF rising_edge(Start_burst) THEN BurstInit( Wait_Cycle,WrapCnt, WrapMode, EntEmbaded, BrEmbaded, erase_active, erase_suspend); END IF; END PROCEDURE BurstCycle; PROCEDURE SetBurstParam( VARIABLE EntEmbaded : INOUT BOOLEAN; VARIABLE Wait_Cycle : INOUT NATURAL; VARIABLE WrapCnt : INOUT INTEGER; VARIABLE WrapMode : INOUT INTEGER; VARIABLE BrEmbaded : INOUT BOOLEAN; VARIABLE erase_active : INOUT BOOLEAN; VARIABLE erase_suspend : INOUT BOOLEAN ) IS BEGIN IF ASynchroMod = FALSE THEN CASE BurstState IS WHEN IDLE_READ => IF rising_edge(Start_burst) THEN BurstInit( Wait_Cycle, WrapCnt, WrapMode, EntEmbaded, BrEmbaded, erase_active, erase_suspend); ELSIF rising_edge(End_burst) THEN null; END IF; WHEN BURST_READ => BurstCycle( Wait_Cycle, WrapCnt, WrapMode, EntEmbaded, BrEmbaded, erase_active, erase_suspend); IF rising_edge(End_burst) THEN END IF; END CASE; END IF; END PROCEDURE SetBurstParam; PROCEDURE DriveOut IS BEGIN IF Mem(SA)(Address) = -1 THEN DOut_zd(15 DOWNTO 0) <= (OTHERS => 'X'); ELSE DOut_zd(15 DOWNTO 0) <= to_slv(Mem(SA)(Address),16); END IF; SET_IND; END PROCEDURE DriveOut; -- PROCEDURE FOR READ AUTOSELECT SECTOR PROCEDURE Read_autoselect IS VARIABLE AutoselAddress : NATURAL; VARIABLE AutoselData : std_logic_vector(15 DOWNTO 0); BEGIN AutoselAddress := Address MOD 16#100#; IF AutoselAddress = 0 THEN AutoselData := to_slv(1,16); ELSIF AutoselAddress = 1 THEN AutoselData := to_slv(16#2203#,16); ELSIF AutoselAddress = 2 THEN IF (((SA /= BottomSec) AND (Sec_Prot(SA) = '0')) OR ((SA = BottomSec) AND (SubSecBot_Prot(SSA) = '0'))) THEN -- sector unlock AutoselData := to_slv(16#0000#,16); ELSE -- sector lock AutoselData := to_slv(16#0001#,16); END IF; ELSIF AutoselAddress = 3 THEN IF ASynchroMod THEN AutoselData := to_slv(0,16); ELSE AutoselData := to_slv(1,16); END IF; ELSE AutoselData := (OTHERS =>'Z'); END IF; DOut_zd <= AutoselData; END PROCEDURE Read_autoselect; -- procedure for read from memory when erase embaded algoritam is suspend PROCEDURE Readmem_EraseSuspend( VARIABLE EntEmbaded : INOUT BOOLEAN; VARIABLE WrapCnt : IN INTEGER; VARIABLE Status : INOUT std_logic_vector(7 DOWNTO 0) ) IS VARIABLE read_nosuspend_sect : BOOLEAN := TRUE; BEGIN read_nosuspend_sect := TRUE; IF (SA /= BottomSec) THEN IF Ers_Queue(SA) = '1' AND Sec_Prot(SA) = '0' THEN read_nosuspend_sect := FALSE; END IF; ELSE IF Ers_SubBot_Queue(SSA) = '1' AND SubSecBot_Prot(SSA) = '0' THEN read_nosuspend_sect := FALSE; END IF; END IF; IF read_nosuspend_sect = TRUE THEN DriveOut; ELSE IF EntEmbaded = FALSE THEN ----------------------------------------------------------- --read status / erase suspend timeout - stil erasing ----------------------------------------------------------- --------------------------------------------------- Status(7) := '1'; -- Status(6) No toggle Status(5) := '0'; Status(2) := NOT Status(2); --toggle EntEmbaded := TRUE; END IF; DOut_zd(7 DOWNTO 0) <= Status; DOut_zd(15 DOWNTO 8) <= (OTHERS => 'Z'); END IF; END PROCEDURE Readmem_EraseSuspend; PROCEDURE Read_EraseStatus ( VARIABLE Status : INOUT std_logic_vector(7 DOWNTO 0)) IS BEGIN Status(7) := '0'; Status(6) := NOT Status(6); --toggle Status(5) := '0'; Status(3) := '1'; IF NOW - ERASE_START > 100 us THEN IF (SA /= BottomSec AND Ers_Queue(SA) = '1' AND Sec_Prot(SA) = '0') OR (SA = BottomSec AND Ers_SubBot_Queue(SSA) = '1' AND SubSecBot_Prot(SSA) = '0') THEN Status(2) := NOT Status(2); --toggle END IF; ELSE IF (SA /= BottomSec AND Ers_Queue(SA) = '1') OR (SA = BottomSec AND Ers_SubBot_Queue(SSA) = '1') THEN Status(2) := NOT Status(2); --toggle END IF; END IF; END PROCEDURE Read_EraseStatus; --Common Flash Interface Query codes TYPE CFItype IS ARRAY (16#10# TO 16#4C#) OF INTEGER RANGE -1 TO 16#FF#; VARIABLE CFI_array : CFItype := (OTHERS => -1); VARIABLE WRData : INTEGER := 0; VARIABLE Mem_tmp : INTEGER := 0; VARIABLE WRSA : NATURAL := 0; VARIABLE WRAddress : NATURAL := 0; VARIABLE A_PAT_1 : boolean := FALSE; VARIABLE oe : boolean := FALSE; --Status reg. VARIABLE Status : std_logic_vector(7 DOWNTO 0) := (OTHERS => '0'); --DATA Full VARIABLE Data : NATURAL Range 0 TO MaxData := 0; --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO MaxData := 0; VARIABLE temp : std_logic_vector(7 DOWNTO 0); VARIABLE read_nosuspend_sect : BOOLEAN; VARIABLE i_sec : NATURAL; VARIABLE i_sub : NATURAL; VARIABLE new_data : std_logic_vector(15 DOWNTO 0); VARIABLE old_data : std_logic_vector(15 DOWNTO 0); VARIABLE data_mem : natural; VARIABLE EntEmbaded : BOOLEAN := FALSE; VARIABLE Wait_Cycle : NATURAL; VARIABLE WrapCnt : INTEGER; VARIABLE WrapMode : INTEGER; VARIABLE BrEmbaded : BOOLEAN; VARIABLE erase_active : BOOLEAN; VARIABLE erase_suspend : BOOLEAN; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF ((rising_edge(gCE_n) OR rising_edge(gOE_n)) AND ASynchroMod) OR (falling_edge(LBANeg) AND NOT ASynchroMod) THEN EntEmbaded := FALSE; END IF; IF falling_edge(write) THEN DataLo := D_tmp0; Data := D_tmp; A_PAT_1 := Addr = 16#555#; END IF; oe := (rising_edge(read) OR (read = '1' AND (AddressLatch'EVENT)) OR (read = '1' AND ASynchroMod = FALSE AND LBANeg = '1' AND rising_edge(CLK))); SetBurstParam( EntEmbaded, Wait_Cycle, WrapCnt, WrapMode, BrEmbaded, erase_active, erase_suspend); IF reseted = '1' THEN RY_zd <= '1'; CASE current_state IS WHEN RESET => ULBYPASS <= '0'; Ers_Queue <= (OTHERS => '0'); Ers_SubBot_Queue <= (OTHERS => '0'); SERS_ACT <= '0'; PGMS_ACT <= '0'; CTMOUT_in <= '0'; IF falling_edge(write) THEN NULL; ELSIF oe THEN DriveOut; END IF; WHEN Z001 => null; WHEN PREL_SETBWB => null; WHEN SET_MODE => IF falling_edge(write) THEN IF DataLo MOD 2 = 0 THEN AsynchroMod := TRUE; ELSE AsynchroMod := FALSE; END IF; END IF; WHEN AS => IF oe THEN IF (ASynchroMod = TRUE OR (ASynchroMod = FALSE AND EntEmbaded = FALSE)) THEN Read_autoselect; EntEmbaded := TRUE; END IF; END IF; WHEN PREL_ULBYPASS => ULBYPASS <= '1'; WHEN UNLOCK_RESET | ESP_UNLOCK_RESET => IF falling_edge(write) THEN IF (DataLo = 16#00#) THEN ULBYPASS <= '0'; END IF; END IF; WHEN CFI | AS_CFI | ESP_CFI | ESP_AS_CFI => IF oe THEN IF (ASynchroMod = TRUE OR (ASynchroMod = FALSE AND EntEmbaded = FALSE)) THEN DOut_zd(15 DOWNTO 0) <= (OTHERS => '0'); IF ((to_nat(AddressLatch) >= 16#10# AND to_nat(AddressLatch) <= 16#3C#) OR (to_nat(AddressLatch) >= 16#40# AND to_nat(AddressLatch) <= 16#4C#)) THEN DOut_zd(7 DOWNTO 0) <= to_slv(CFI_array(to_nat(AddressLatch)),8); ELSE ASSERT FALSE REPORT "Invalid CFI query address" SEVERITY warning; DOut_zd <= (OTHERS =>'Z'); END IF; EntEmbaded := TRUE; END IF; END IF; WHEN A0SEEN | ESP_A0SEEN => IF falling_edge(write) THEN IF (SA /= BottomSec AND Sec_Prot(SA) = '0' AND Ers_Queue(SA) = '0') OR (SA = BottomSec AND SubSecBot_Prot(SSA) = '0' AND Ers_SubBot_Queue(SSA) = '0') THEN PSTART <= '1', '0' AFTER 1 ns; WRData := Data; WRSA := SA; WRAddress := Address; Mem_tmp := Mem(WRSA)(WRAddress); Mem(WRSA)(WRAddress) := -1; temp := to_slv(DataLo, 8); Status(7) := NOT temp(7); ELSE temp := to_slv(DataLo, 8); Status(7) := NOT temp(7); PSTART <= '1', '0' AFTER 1 ns; END IF; END IF; WHEN PGMS => RY_zd <= '0'; PGMS_ACT <= '1'; IF oe THEN ----------------------------------------------------------- --read status ----------------------------------------------------------- IF EntEmbaded = FALSE THEN Status(6) := NOT Status(6); --toggle Status(5) := '0'; --Status(2) no toggle Status(1) := '0'; EntEmbaded := TRUE; END IF; DOut_zd(7 DOWNTO 0) <= Status; DOut_zd(15 DOWNTO 8) <= (OTHERS => 'Z'); END IF; IF falling_edge(PERR) THEN PGMS_ACT <= '0'; END IF; IF PERR /= '1' THEN IF rising_edge(PDONE) AND (NOT PERR'EVENT) THEN PGMS_ACT <= '0'; IF Mem_tmp /= -1 AND WRData /= -1 THEN new_data := to_slv(WRData,16); old_data := to_slv(Mem_tmp,16); data_mem := to_nat(new_data AND old_data); Mem(WRSA)(WRAddress) := data_mem; Mem_tmp := Mem(WRSA)(WRAddress); ELSE Mem(WRSA)(WRAddress) := WRData; END IF; END IF; END IF; WHEN C8 => IF falling_edge(write) THEN null; END IF; WHEN C8_Z001 => IF falling_edge(write) THEN null; END IF; WHEN C8_PREL => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo = 16#10# THEN ESTART <= '1', '0' AFTER 1 ns; ESUSP <= '0'; ERES <= '0'; Ers_Queue <= (OTHERS => '1'); Ers_SubBot_Queue <= (OTHERS => '1'); Status := "00001000"; SERS_ACT <= '1'; ERASE_START := NOW; ELSIF DataLo = 16#30# THEN --put selected sector to sec. ers. queue --start timeout Ers_Queue <= (OTHERS => '0'); Ers_SubBot_Queue <= (OTHERS => '0'); IF (SA = BottomSec) THEN Ers_SubBot_Queue(SSA) <= '1'; ELSE Ers_Queue(SA) <= '1'; END IF; CTMOUT_in <= '1'; SERS_ACT <= '1'; END IF; END IF; WHEN ERS => RY_zd <= '0'; IF oe THEN IF EntEmbaded = FALSE THEN Read_EraseStatus(Status); EntEmbaded := TRUE; END IF; DOut_zd(7 DOWNTO 0) <= Status; DOut_zd(15 DOWNTO 8) <= (OTHERS => 'Z'); END IF; IF EERR /= '1' THEN IF NOT CLK'EVENT THEN FOR i IN 0 TO SecNum -1 LOOP IF i /= BottomSec THEN IF Sec_Prot(i) = '0' THEN Mem(i) := (OTHERS => -1); END IF; ELSE FOR y IN 0 TO SubSecNum -1 LOOP IF SubSecBot_Prot(y) = '0' THEN Mem(BottomSec)(sssa(y) TO ssea(y)) := (OTHERS => -1); END IF; END LOOP; END IF; END LOOP; END IF; IF EDONE = '1' THEN FOR i IN 0 TO SecNum -1 LOOP IF i/= BottomSec THEN IF Sec_Prot(i) = '0' THEN Mem(i) := (OTHERS => MaxData); END IF; ELSE FOR y IN 0 TO SubSecNum -1 LOOP IF SubSecBot_Prot(y) = '0' THEN Mem(BottomSec)(sssa(y) TO ssea(y)) := (OTHERS => MaxData); END IF; END LOOP; END IF; Ers_Queue <= (OTHERS => '0'); Ers_SubBot_Queue <= (OTHERS => '0'); END LOOP; END IF; END IF; WHEN SERS => IF (CTMOUT_out = '1') THEN CTMOUT_in <= '0'; ESTART_T1_in <= '0'; ESTART <= '1', '0' AFTER 1 ns; ESUSP <= '0'; ERES <= '0'; ERASE_START := NOW; ELSIF falling_edge(write) THEN IF (DataLo = 16#B0#) THEN IF ASynchroMod THEN --need to start erase process prior to suspend ESTART_SUSP <= '1', '0' AFTER 1 ns; CTMOUT_in <= '0'; ERES <= '0'; END IF; ELSIF (DataLo = 16#30#) THEN CTMOUT_in <= '0', '1' AFTER 1 NS; IF (SA = BottomSec) THEN Ers_SubBot_Queue(SSA) <= '1'; ELSE Ers_Queue(SA) <= '1'; END IF; ELSE CTMOUT_in <= '0'; Ers_Queue <= (OTHERS => '0'); Ers_SubBot_Queue <= (OTHERS => '0'); END IF; ELSIF oe THEN ---------------------------------------------------------- --read status - sector erase timeout ---------------------------------------------------------- IF EntEmbaded = FALSE THEN Status(3) := '0'; EntEmbaded := TRUE; END IF; DOut_zd(7 DOWNTO 0) <= Status; DOut_zd(15 DOWNTO 8) <= (OTHERS => 'Z'); END IF; WHEN ESPS => RY_zd <= '0'; IF (ESTART_T1_out = '1') THEN ESTART_T1_in <= '0'; ELSIF oe THEN IF EntEmbaded = FALSE THEN ---------------------------------------------------------- --read status / erase suspend timeout - stil erasing ---------------------------------------------------------- Read_EraseStatus(Status); EntEmbaded := TRUE; END IF; DOut_zd(7 DOWNTO 0) <= Status; DOut_zd(15 DOWNTO 8) <= (OTHERS => 'Z'); END IF; WHEN SERS_EXEC => RY_zd <= '0'; IF oe THEN ----------------------------------------------------------- --read status Erase Busy ----------------------------------------------------------- IF EntEmbaded = FALSE THEN Read_EraseStatus(Status); EntEmbaded := TRUE; END IF; DOut_zd(7 DOWNTO 0) <= Status; DOut_zd(15 DOWNTO 8) <= (OTHERS => 'Z'); END IF; IF EERR /= '1' THEN IF EDONE /= '1' THEN IF NOT CLK'EVENT THEN FOR i IN 0 TO SecNum -1 LOOP IF i /= BottomSec THEN IF Sec_Prot(i) = '0' AND Ers_Queue(i) = '1' THEN Mem(i) := (OTHERS => -1); END IF; ELSE FOR y IN 0 TO SubSecNum -1 LOOP IF SubSecBot_Prot(y) = '0' AND Ers_SubBot_Queue(y) = '1' THEN Mem(BottomSec)(sssa(y) TO ssea(y)) := (OTHERS => -1); END IF; END LOOP; END IF; END LOOP; END IF; ELSE FOR i IN 0 TO SecNum-1 LOOP IF i/= BottomSec THEN IF Sec_Prot(i) = '0' AND Ers_Queue(i) = '1' THEN Mem(i) := (OTHERS => MaxData); END IF; ELSE FOR y IN 0 TO SubSecNum -1 LOOP IF SubSecBot_Prot(y) = '0' AND Ers_SubBot_Queue(y) = '1' THEN Mem(BottomSec)(sssa(y) TO ssea(y)) := (OTHERS => MaxData); END IF; END LOOP; END IF; END LOOP; END IF; IF falling_edge(write) THEN IF DataLo = 16#B0# AND ASynchroMod THEN ESTART_T1_in <= '1'; ESUSP <= '1', '0' AFTER 1 ns; END IF; END IF; END IF; WHEN ESP => IF falling_edge(write) THEN IF DataLo = 16#30# THEN ERES <= '1', '0' AFTER 1 ns; END IF; ELSIF oe THEN ----------------------------------------------------------- --read memory ----------------------------------------------------------- Readmem_EraseSuspend( EntEmbaded , WrapCnt, Status); END IF; WHEN ESP_Z001 => null; WHEN ESP_SETBWB => null; WHEN ESP_ULBYPASS => ULBYPASS <= '1'; WHEN ESP_AS => IF oe THEN IF (ASynchroMod = TRUE OR (ASynchroMod = FALSE AND EntEmbaded = FALSE)) THEN Read_autoselect; EntEmbaded := TRUE; END IF; END IF; END CASE; ELSE Ers_Queue <= (OTHERS => '0'); Ers_SubBot_Queue <= (OTHERS => '0'); ASynchroMod := TRUE; END IF; --Output Disable Control IF (gOE_n = '1' OR gCE_n = '1') OR (RESETNeg = '0'AND RST = '0') THEN DOut_zd <= (OTHERS => 'Z'); END IF; IF rising_edge(read) AND reseted = '1' THEN clk_oe_en <= TRUE AFTER 1 ns; ELSIF falling_edge(read) OR reseted = '0' THEN clk_oe_en <= FALSE; END IF; IF (gOE_n = '1' OR gCE_n = '1') OR (RESETNeg = '0'AND RST = '0') THEN IND_zd <= '1'; END IF; --Preload Control ----------------------------------------------------------------------- -- File read Section ----------------------------------------------------------------------- IF NOW = 0 ns THEN ----------------------------------------------------------------------- --CFI array data ----------------------------------------------------------------------- --CFI query identification string -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr --CFI query identification string CFI_array(16#10#) := 16#51#; CFI_array(16#11#) := 16#52#; CFI_array(16#12#) := 16#59#; CFI_array(16#13#) := 16#02#; CFI_array(16#14#) := 16#00#; CFI_array(16#15#) := 16#40#; CFI_array(16#16#) := 16#00#; CFI_array(16#17#) := 16#00#; CFI_array(16#18#) := 16#00#; CFI_array(16#19#) := 16#00#; CFI_array(16#1A#) := 16#00#; --system interface string CFI_array(16#1B#) := 16#27#; CFI_array(16#1C#) := 16#36#; CFI_array(16#1D#) := 16#00#; CFI_array(16#1E#) := 16#00#; CFI_array(16#1F#) := 16#04#; CFI_array(16#20#) := 16#00#; CFI_array(16#21#) := 16#0A#; CFI_array(16#22#) := 16#00#; CFI_array(16#23#) := 16#05#; CFI_array(16#24#) := 16#00#; CFI_array(16#25#) := 16#04#; CFI_array(16#26#) := 16#00#; --device geometry definition CFI_array(16#27#) := 16#15#; CFI_array(16#28#) := 16#01#; CFI_array(16#29#) := 16#00#; CFI_array(16#2A#) := 16#00#; CFI_array(16#2B#) := 16#00#; CFI_array(16#2C#) := 16#04#; CFI_array(16#2D#) := 16#00#; CFI_array(16#2E#) := 16#00#; CFI_array(16#2F#) := 16#40#; CFI_array(16#30#) := 16#00#; CFI_array(16#31#) := 16#01#; CFI_array(16#32#) := 16#00#; CFI_array(16#33#) := 16#20#; CFI_array(16#34#) := 16#00#; CFI_array(16#35#) := 16#00#; CFI_array(16#36#) := 16#00#; CFI_array(16#37#) := 16#80#; CFI_array(16#38#) := 16#03#; CFI_array(16#39#) := 16#06#; CFI_array(16#3A#) := 16#00#; CFI_array(16#3B#) := 16#00#; CFI_array(16#3C#) := 16#04#; --primary vendor-specific extended query CFI_array(16#40#) := 16#50#; CFI_array(16#41#) := 16#52#; CFI_array(16#42#) := 16#49#; CFI_array(16#43#) := 16#31#; CFI_array(16#44#) := 16#30#; CFI_array(16#45#) := 16#00#; CFI_array(16#46#) := 16#02#; CFI_array(16#47#) := 16#01#; CFI_array(16#48#) := 16#01#; CFI_array(16#49#) := 16#04#; CFI_array(16#4A#) := 16#00#; CFI_array(16#4B#) := 16#03#; CFI_array(16#4C#) := 16#00#; END IF; END PROCESS Functional; --------------------------------------------------------------------------- ---- File read Section - Preload Control --------------------------------------------------------------------------- MemPreload : PROCESS -- text file input variables FILE mem_f : text is mem_file_name; FILE prot_f : text is prot_file_name; CONSTANT SecS : NATURAL := SecSize+1; VARIABLE addr_ind : NATURAL; VARIABLE sec_ind : NATURAL; VARIABLE offset : NATURAL; VARIABLE ind : NATURAL; VARIABLE buf : line; VARIABLE sect : NATURAL; VARIABLE report_err : BOOLEAN := FALSE; BEGIN --Preload Control ----------------------------------------------------------------------- -- File Read Section ----------------------------------------------------------------------- IF UserPreload AND (mem_file_name /= "none" ) THEN addr_ind := 0; WHILE (not ENDFILE (mem_f)) LOOP READLINE (mem_f, buf); IF buf(1) = '/' THEN --comment NEXT; ELSIF buf(1) = '@' THEN --address addr_ind := h(buf(2 to 6)); sec_ind := addr_ind / SecS; offset := addr_ind - (sec_ind * SecS); ELSE IF addr_ind <= MemSize THEN Mem(sec_ind)(offset):= h(buf(1 to 4)); addr_ind := (addr_ind + 1); sec_ind := addr_ind / SecS; offset := addr_ind - (sec_ind * SecS); ELSE IF report_err = FALSE THEN REPORT "Memory file:" & mem_file_name & " Address range error" SEVERITY error; report_err := TRUE; END IF; END IF; END IF; END LOOP; END IF; ind := 0; SubSecBot_Prot <= (OTHERS => '0'); Sec_Prot <= (OTHERS => '0'); IF UserPreload AND (prot_file_name /= "none" ) THEN WHILE (not ENDFILE (prot_f)) LOOP READLINE (prot_f, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 TO 2)); ELSE IF ind <= SecNum + SubSecNum-1 AND h(buf(1 TO 1)) = 1 THEN IF ind < 4 THEN SubSecBot_Prot(ind) <= '1'; ELSE Sec_Prot(ind-3) <= '1'; END IF; END IF; ind := ind + 1; END IF; END LOOP; END IF; WAIT; END PROCESS; ----------------------------------------------------------------------- -- Path Delay Section ----------------------------------------------------------------------- DOutPassThrough : PROCESS(DOut_zd) VARIABLE tOD : time := 0 ns; VARIABLE tCD : time := 0 ns; VARIABLE tAD : time := 0 ns; BEGIN IF DOut_zd(0) /= 'Z' THEN IF ASynchroMod = TRUE THEN tpd_from_OE := FALSE; tpd_from_CE := FALSE; Open3state := TRUE; tOD := -OENeg'LAST_EVENT + tpd_OENeg_DQ0(trz1); tCD := -CENeg'LAST_EVENT + tpd_CENeg_DQ0(trz1); tAD := -A'LAST_EVENT + tpd_A0_DQ0(tr10); IF tOD >= tCD AND tOD > 0 ns THEN tpd_from_OE := TRUE; ELSIF tCD >= tOD AND tCD > 0 ns THEN tpd_from_CE := TRUE; END IF; IF tAD > 0 ns AND ((tAD >= tOD AND tpd_from_OE = TRUE) OR (tAD >= tCD AND tpd_from_CE = TRUE)) THEN Dout_pass <= "XXXXXXXXXXXXXXXX", Dout_zd AFTER tAD; ELSE Dout_pass <= Dout_zd; END IF; ELSE IF Start_burst = '0' THEN tAD := -Start_burst'LAST_EVENT -1 ns + tpd_A0_DQ0(tr10); ELSE tAD := -Start_burst'LAST_EVENT + tpd_A0_DQ0(tr10); END IF; IF tAD > 0 ns THEN clk_addr_en <= FALSE AFTER 1 ns, TRUE AFTER tAD + 1 ns ; Dout_pass <= Dout_zd AFTER tAD; ELSE Dout_pass <= Dout_zd; END IF; END IF; ELSE tCD := -CENeg'LAST_EVENT + tpd_CENeg_DQ0(tr0z); tOD := -OENeg'LAST_EVENT + tpd_OENeg_DQ0(tr0z); tpd_from_OE := (tOD <= tCD) AND (tOD > 0 ns); tpd_from_CE := (tCD < tOD) AND (tCD > 0 ns); IF tpd_from_CE = TRUE THEN tpd_from_OE := FALSE; ELSIF tpd_from_OE = TRUE THEN tpd_from_CE := FALSE; ELSE tpd_from_OE := TRUE; tpd_from_CE := TRUE; END IF; Open3state := FALSE; DOut_Pass <= DOut_zd; END IF; END PROCESS DOutPassThrough; IndOutPadd : PROCESS(IND_zd) VARIABLE tAD : time := 0 ns; BEGIN IND_pass <= IND_zd; END PROCESS; IND_OUT: PROCESS(IND_pass) VARIABLE IND_GlitchData : VitalGlitchDataType; VARIABLE INDData : std_logic; BEGIN INDData := IND_pass; VitalPathDelay01Z( OutSignal => IND_sig, OutSignalName => "IND", OutTemp => INDData, Mode => VitalTransport, GlitchData => IND_GlitchData, Paths => ( 0 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => tpd_CLK_IND, PathCondition => CENeg = '0' AND OENeg = '0' AND ASynchroMod = FALSE AND clk_addr_en AND clk_oe_en), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => ASynchroMod = FALSE AND tpd_from_OE), 2 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => ASynchroMod = FALSE AND tpd_from_CE) ) ); END PROCESS IND_Out; IND <= IND_sig; RY_OUT: PROCESS(RY_zd) VARIABLE RY_GlitchData : VitalGlitchDataType; VARIABLE RYData : std_logic; BEGIN IF RY_zd = '1' THEN RYData := 'Z'; ELSE RYData := RY_zd; END IF; VitalPathDelay01Z( OutSignal => RY_sig, OutSignalName => "RY", OutTemp => RYData, Mode => VitalTransport, GlitchData => RY_GlitchData, Paths => ( 0 => (InputChangeTime => WENeg'LAST_EVENT, PathDelay => tpd_WENeg_RY, PathCondition => TRUE), 1 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_WENeg_RY, PathCondition => OENeg = '0')) ); END PROCESS RY_Out; RY <= RY_sig; --------------------------------------------------------------------------- -- Path Delay Section for DOut signal --------------------------------------------------------------------------- D_Out_PathDelay_Gen : FOR i IN 0 TO 15 GENERATE --Dout_zd'RANGE GENERATE PROCESS(DOut_pass(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_pass(i), GlitchData => D0_GlitchData, IgnoreDefaultDelay => TRUE, Mode => VitalTransport, RejectFastPath => false, Paths => ( 0 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => --FROMOE), tpd_from_OE), 1 => (InputChangeTime => AddressLatch'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => NOT (tpd_from_OE OR tpd_from_CE)), 2 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => --FROMCE), tpd_from_CE), 3 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_DQ0), PathCondition => CENeg = '0' AND OENeg = '0' AND ASynchroMod = FALSE AND clk_addr_en AND clk_oe_en)) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral;