------------------------------------------------------------------------------ -- File name : am29bds640g.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 J.Bogosavljevic 04 Jan 16 Initial release -- V1.1 J.Bogosavljevic 04 Feb 26 - AS read for burst mode modified -- LoadtIACC procedure modified -- if addresses are latched by AVD# -- rising -- - elapsed_erase timer suspended as -- soon as erase suspend command issued -- - RDY control for standard handshake -- when starting address is 16#3E# added -- - tsetup/thold/tpd times modified -- - AddBankForErs -- V1.2 J.Bogosavljevic 04 Apr 30 - CTMOUT bug fix ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: AMD -- Technology: Flash Memory -- Part: am29bds640g -- -- Description: 64Mbit (4Mx16bit) Simultaneous opration, 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 am29bds640g 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_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; -- DQ15/A-1 tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; tipd_CLK : VitalDelayType01 := VitalZeroDelay01; tipd_AVDNeg : VitalDelayType01 := VitalZeroDelay01; tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; tipd_ACC : VitalDelayType01 := VitalZeroDelay01; ------------- -- tpd delays ------------- --tACc --asyn read tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;-- 70/85 --asyn read tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(tce,tce,toez,tce,toez,tce) --(70,70,10,70,10,70) --(85,85,10.5,85,10.5,85) --asyn read tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(-,-,tOEZ,tOE,tOEZ,tOE) --(13.5, 13.5,10 ,13.5, 10,13.5) --(20, 20,10.5 ,20, 10.5,20) --burst read tpd_CLK_DQ0 : VitalDelayType01 := UnitDelay01;--tBACC, --tRACC ----------------- --tsetup & thold ----------------- --Address setup and hold times -------------- --burst mode -------------- --setup/hold addresses to signal that latches addresses (AVD or CLK) --burst read --tAAS, tAAH, tACS, tACH --burst prgm/er --tAS,tAH ------------ --asyn mode ------------ --asyn read --setup/hold addresses to AVD --tAAVDS, tAAVDH tsetup_A0_AVDNeg : VitalDelayType := UnitDelay;--tAAS = 5 ns thold_A0_AVDNeg : VitalDelayType := UnitDelay;--tAAH = 7 ns ------------ --asyn mode ------------ --asyn pr/er --setup/hold addresses to AVD --asyn pr/er tsetup_A0_WENeg : VitalDelayType := UnitDelay;--tAS = 0 thold_A0_WENeg : VitalDelayType := UnitDelay;--tAH = 45 --Other setup and hold timings ------------- --burst read ------------- thold_DQ0_CLK : VitalDelayType := UnitDelay; --tBDH --setup RDY high tsetup_RDY_CLK : VitalDelayType := UnitDelay; --tRDYS --if CLK LA tsetup_CENeg_CLK : VitalDelayType := UnitDelay; --tCES tsetup_AVDNeg_CLK : VitalDelayType := UnitDelay; --tAVC ---------------- --ASYNCH. READ ---------------- -- toggle and data polling thold_OENeg_WENeg : VitalDelayType := UnitDelay; --toeh,edge / ------------------ --PRGM/ERS ----------------- --always tsetup_DQ0_WENeg : VitalDelayType := UnitDelay; --tDS --asyn pr/er tsetup_CLK_AVDNeg : VitalDelayType := UnitDelay; --tCSW1 -- asyn, WE LA addresses thold_CLK_WENeg : VitalDelayType := UnitDelay; --tCHW --async if WE LA addresses tsetup_AVDNeg_WENeg : VitalDelayType := UnitDelay; --tDS edge / WE thold_AVDNeg_WENeg : VitalDelayType := UnitDelay; --tDH = 0; --synch -- if CLK LA addresses tsetup_CLK_WENeg : VitalDelayType := UnitDelay; --tCSW2 --sync if CLK LA addresses thold_AVDNeg_CLK : VitalDelayType := UnitDelay; thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH -------------- --pulse width ------------- tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP tpw_AVDNeg_negedge : VitalDelayType := UnitDelay;--Tavd = 12ns tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH -- tdevice values: values for internal delays --Program Operation --word write tdevice_POW : VitalDelayType := 210 us; --unlock bypass word write tdevice_POU : VitalDelayType := 120 us; --Sector Erase Operation tWHWH2 tdevice_SEO : VitalDelayType := 5 sec; --erase suspend timeout tdevice_START_T1 : VitalDelayType := 35 us; --sector erase command sequence timeout tdevice_CTMOUT : VitalDelayType := 50 us; --device ready after Hardware reset(during embeded algorithm) tdevice_READY : VitalDelayType := 35 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"; UserPreload : BOOLEAN := FALSE; LongTimming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( A21 : IN std_ulogic := 'U'; --flash A20 : IN std_ulogic := 'U'; --flash A19 : IN std_ulogic := 'U'; --A19-A0 common 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 (common) 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'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RESETNeg : IN std_ulogic := 'U'; CLK : IN std_ulogic := 'U'; AVDNeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U'; ACC : IN std_ulogic := 'U'; RDY : OUT std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of am29bds640g : ENTITY IS TRUE; END am29bds640g; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of am29bds640g IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "am29bds640g"; CONSTANT BankNum : NATURAL := 3; CONSTANT MaxData : NATURAL := 16#FFFF#; CONSTANT MemSize : NATURAL := 16#3FFFFF#; --(SecNum-BootSecNum)*SecSIze_L+ (BootSecNum+1)*SecSize_S CONSTANT SecSize_L : NATURAL := 16#7FFF#; CONSTANT SecSize_S : NATURAL := 16#1FFF#; CONSTANT SecNum : NATURAL := 133; CONSTANT BootSecNum : NATURAL := 7; CONSTANT HiAddrBit : NATURAL := 21; CONSTANT HiConfBit : NATURAL := 19; CONSTANT LoConfBit : NATURAL := 12; CONSTANT MinCfiAddr : NATURAL := 16#10#; CONSTANT MaxCfiAddr : NATURAL := 16#5B#; -- scale divedes time needed for sector erase when LongTimming is FALSE -- scale must be less then: -- 2000 for min delays ->scale = 1900 -> tse = 105.2 us -- 4000 for typ delays->scale = 3800 -> tse = 105.2 us -- 50 000 for max delays->scale = 47600 -> tse = 105.4 us --otherwise sector erase time is shorter then 100 us -- CONSTANT scale : NATURAL := 47600;--1900;--3800;--47600; -- CONSTANT scale : NATURAL := 3800;--47600; CONSTANT scale : NATURAL := 1900;--3800;--47600; -- interconnect path delay signals 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 RESETNeg_ipd : std_ulogic := 'U'; SIGNAL CLK_ipd : std_ulogic := 'U'; SIGNAL AVDNeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; SIGNAL ACC_ipd : std_ulogic := 'U'; --- internal delays SIGNAL POW_in : std_ulogic := '0'; SIGNAL POW_out : std_ulogic := '0'; SIGNAL POU_in : std_ulogic := '0'; SIGNAL POU_out : std_ulogic := '0'; SIGNAL SEO_in : std_ulogic := '0'; SIGNAL SEO_out : std_ulogic := '0'; SIGNAL START_T1_out : std_ulogic := '0'; --Start TimeOut; SUSPEND SIGNAL START_T1_in : std_ulogic := '0'; SIGNAL CTMOUT_out : std_ulogic := '0'; --Sector Erase TimeOut SIGNAL CTMOUT_in : std_ulogic := '0'; SIGNAL READY_in : std_ulogic := '0'; SIGNAL READY_out : std_ulogic := '0'; -- Device ready after reset BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays POW : VitalBuf(POW_out, POW_in, (tdevice_POW ,UnitDelay)); POU : VitalBuf(POU_out, POU_in, (tdevice_POU ,UnitDelay)); SEO : VitalBuf(SEO_out, SEO_in, (tdevice_SEO ,UnitDelay)); START_T1: VitalBuf(START_T1_out, START_T1_in,(tdevice_START_T1,UnitDelay)); CTMOUT : VitalBuf(CTMOUT_out, CTMOUT_in, (tdevice_CTMOUT-5 ns, UnitDelay)); READY : VitalBuf(READY_out, READY_in, (tdevice_READY ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_0 : VitalWireDelay (A21_ipd, A21, tipd_A21); w_1 : VitalWireDelay (A20_ipd, A20, tipd_A20); w_2 : VitalWireDelay (A19_ipd, A19, tipd_A19); w_3 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_4 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_5 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_6 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_7 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_8 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_9 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_10 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_11 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_12 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_13 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_14 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_15 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_16 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_17 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_18 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_19 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_20 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_21 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_22 : VitalWireDelay (DQ15_ipd, DQ15, tipd_DQ15); w_23 : VitalWireDelay (DQ14_ipd, DQ14, tipd_DQ14); w_24 : VitalWireDelay (DQ13_ipd, DQ13, tipd_DQ13); w_25 : VitalWireDelay (DQ12_ipd, DQ12, tipd_DQ12); w_26 : VitalWireDelay (DQ11_ipd, DQ11, tipd_DQ11); w_27 : VitalWireDelay (DQ10_ipd, DQ10, tipd_DQ10); w_28 : VitalWireDelay (DQ9_ipd, DQ9, tipd_DQ9); w_29 : VitalWireDelay (DQ8_ipd, DQ8, tipd_DQ8); w_30 : VitalWireDelay (DQ7_ipd, DQ7, tipd_DQ7); w_31 : VitalWireDelay (DQ6_ipd, DQ6, tipd_DQ6); w_32 : VitalWireDelay (DQ5_ipd, DQ5, tipd_DQ5); w_33 : VitalWireDelay (DQ4_ipd, DQ4, tipd_DQ4); w_34 : VitalWireDelay (DQ3_ipd, DQ3, tipd_DQ3); w_35 : VitalWireDelay (DQ2_ipd, DQ2, tipd_DQ2); w_36 : VitalWireDelay (DQ1_ipd, DQ1, tipd_DQ1); w_37 : VitalWireDelay (DQ0_ipd, DQ0, tipd_DQ0); w_38 : VitalWireDelay (OENeg_ipd, OENeg, tipd_OENeg); w_39 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_40 : VitalWireDelay (RESETNeg_ipd, RESETNeg, tipd_RESETNeg); w_41 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); w_42 : VitalWireDelay (CLK_ipd, CLK, tipd_CLK); w_43 : VitalWireDelay (AVDNeg_ipd, AVDNeg, tipd_AVDNeg); w_44 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); w_45 : VitalWireDelay (ACC_ipd, ACC, tipd_ACC); 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_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RESETNeg : IN std_ulogic := 'U'; CLK : IN std_ulogic := 'U'; AVDNeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U'; ACC : IN std_ulogic := 'U'; RDY : OUT std_ulogic := 'U' ); PORT MAP ( 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, RESETNeg => RESETNeg_ipd, CLK => CLK_ipd, AVDNeg => AVDNeg_ipd, WPNeg => WPNeg_ipd, ACC => ACC_ipd, RDY => RDY ); -- State Machine : State_Type TYPE state_type IS ( RESET, Z001, PREL_SETBWB, PREL_ULBYPASS, SLU_Z001, SLU_PREL, SLU, CFI, AS, AS_CFI, A0SEEN, C8, C8_Z001, C8_PREL, ERS, SERS, ESPS, SERS_EXEC, ESP, ESP_Z001, ESP_PREL, ESP_CFI, ESP_A0SEEN, ESP_AS, PGMS ); TYPE MemArray IS ARRAY (0 TO MemSize) OF INTEGER RANGE -1 TO MaxData; --Common Flash Interface Query codes TYPE CFItype IS ARRAY (MinCfiAddr TO MaxCfiAddr) OF NATURAL RANGE 0 TO 16#FFFF#; TYPE BankArray IS ARRAY (0 TO BankNum) OF INTEGER RANGE -1 TO BankNum; -- states SIGNAL current_state : state_type; -- SIGNAL next_state : state_type; -- -- powerup SIGNAL PoweredUp : std_logic := '0'; --zero delay signals SIGNAL DOut_zd : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); SIGNAL RDY_zd : std_logic := 'Z'; --FSM control signals SIGNAL ULBYPASS : std_logic := '0'; --Unlock Bypass Active SIGNAL ESP_ACT : std_logic := '0'; --Erase Suspend --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'; --All sectors selected for erasure from bank0 are protected SIGNAL EERR0 : std_logic := '0'; --All sectors selected for erasure from bank1 are protected SIGNAL EERR1 : std_logic := '0'; --All sectors selected for erasure from bank2 are protected SIGNAL EERR2 : std_logic := '0'; --All sectors selected for erasure from bank3 are protected SIGNAL EERR3 : std_logic := '0'; --Sectors selected for erasure SIGNAL ERS_QUEUE : std_logic_vector(SecNum downto 0) := (OTHERS => '0'); --Command Register SIGNAL write : std_logic := '0'; SIGNAL read : std_logic := '0'; --Sector Address SIGNAL SecAddr : NATURAL RANGE 0 TO SecNum := 0; SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; --Address within sector SIGNAL Address : NATURAL RANGE 0 TO SecSize_L := 0; -- tmp ConfigRegister SIGNAL CR_Addr : std_logic_vector(HiConfBit downto 0) := (OTHERS => '0'); --buffer for input addresses SIGNAL Whole_Addr : std_logic_vector(HiAddrBit downto 0) := (OTHERS => '0'); -- asserted when addresses are latched SIGNAL LA : std_logic := '0'; --Config Register data SIGNAL ConfRegData : std_logic_vector(HiConfBit downto 0) := ("11100101000000000000"); --data buffer SIGNAL D_tmp0 : NATURAL RANGE 0 TO MaxData; --A18:A11 Don't Care SIGNAL Addr : NATURAL RANGE 0 TO 16#7FF# := 0; --internal address counter SIGNAL Addr_cnt : INTEGER RANGE -1 TO MemSize; --enables addr_cnt if address is not in bank where embedded algorithm --is active SIGNAL enable_cnt : std_logic := '1'; --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'; -- initial tIACC SIGNAL tIACC_cnt_dwn : NATURAL RANGE 0 TO 14; --tIACC max value 7(conf)+3(reduced, 3F)+1 odd addr --activated when boundary crossing SIGNAL bound_cross : std_logic := '0'; --activated when boundary crossing to bank where embedded algorith is active SIGNAL bound_cross_active : std_logic := '0'; SIGNAL CLK_active : std_logic; --Read Data in burst mode SIGNAL Dout_zd_burst : std_logic_vector(15 downto 0); ------- --bank signals --PGMS bank SIGNAL LB_P : INTEGER RANGE -1 TO BankNum; --AS bank SIGNAL LB_A : INTEGER RANGE -1 TO BankNum; --banks selected for erasure SIGNAL LB_Ei : BankArray; -- current bank SIGNAL BA : NATURAL; SHARED VARIABLE burst_mode : boolean := FALSE;--ConfReg(19) -- Mem(SecAddr)(Address).... SHARED VARIABLE Mem : MemArray := (OTHERS=> MaxData); SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) := (OTHERS => '0'); -- timing check violation SIGNAL Viol : X01 := '0'; --bottom or toparchitecture parameters SIGNAL vs : INTEGER;--0 if VarSect = 0 else 1 SIGNAL first_prot : INTEGER;-- what boot sectors to protect -- handshake procedure SIGNAL reduced_hnd : INTEGER; --chip selected used for VITALTimingCheck process SIGNAL cs : std_logic := '0'; ---------- --output delay control SHARED VARIABLE tpd_from_OE : BOOLEAN := FALSE; SHARED VARIABLE tpd_from_CE : BOOLEAN := FALSE; SHARED VARIABLE Open3state : BOOLEAN := FALSE; SHARED VARIABLE Addr_Valid : BOOLEAN := FALSE; SHARED VARIABLE max_wrap_thr : INTEGER := 0; SIGNAL DOut_z : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); ------------------------------------------------------------------------------- ------------------ --FUNCTIONS ------------------ ------------------ --Sector functions ------------------ FUNCTION SectSize(i : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; BEGIN result := 0; IF i >= 4 AND i <= 129 THEN result :=SecSize_L; ELSE result :=SecSize_S; END IF; RETURN result; END SectSize; --sector's starting address FUNCTION sssa(i : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; BEGIN result := 0; IF i <= 3 THEN result := (SectSize(i) + 1) * i; ELSIF i <= 129 THEN result := (SectSize(i) + 1) * (i-3); ELSE result := 16#3F8000# + (SectSize(i) + 1) * (i-130); -- SectSize_L*127 END IF; RETURN result; END sssa; --sector's ending address FUNCTION ssea(i : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; BEGIN result := 0; IF i <= 3 THEN result := (SectSize(i) + 1) * (i+1) - 1; ELSIF i <= 129 THEN result := (SectSize(i) + 1) * (i-3+1) - 1; ELSE result := 16#3F8000# + (SectSize(i) + 1) * (i-130 + 1) - 1; -- SectSize_L*127 END IF; RETURN result; END ssea; PROCEDURE RestoreSectAddr ( SIGNAL A : IN std_logic_vector(HiAddrBit downto 0); VARIABLE SecAddr : INOUT NATURAL RANGE 0 TO SecNum; VARIABLE A_tmp : INOUT NATURAL RANGE 0 TO SecSize_L ) IS VARIABLE SA_tmp : NATURAL RANGE 0 TO SecNum; BEGIN SA_tmp := to_nat (A(HiAddrBit downto 15)); IF (SA_tmp = 0) THEN --SecAddr = 0 OR SecAddr = SecNum - BootSecNum + 1) THEN--133-7 +1 SecAddr := SA_tmp + to_nat(A(14 downto 13)); A_tmp := to_nat(A(12 downto 0)); ELSIF (SA_tmp < SecNum - BootSecNum + 1) THEN SecAddr := SA_tmp + 3; A_tmp := to_nat(A(14 downto 0)); ELSE SecAddr := SA_tmp + 3 + to_nat(A(14 downto 13)); A_tmp := to_nat(A(12 downto 0)); END IF; END RestoreSectAddr; ------------------------ --BANK ACCESS FUNCTIONS ----------------------- --returns bank's starting address FUNCTION bsa(bank: NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL := 0; BEGIN IF bank = 0 THEN result := sssa(0); ELSIF bank = 1 THEN result := sssa(35); ELSIF bank = 2 THEN result := sssa(67); ELSE result := sssa(99); END IF; RETURN result; END bsa; --returns bank's ending address FUNCTION bea(bank: NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL := 0; BEGIN IF bank = 0 THEN result := ssea(34); ELSIF bank = 1 THEN result := ssea(66); ELSIF bank = 2 THEN result := ssea(98); ELSE result := ssea(133); END IF; RETURN result; END bea; --returns what bank sector belongs to FUNCTION ResolveBank(Sect: NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL :=0; BEGIN IF Sect <= 34 THEN result := 0;--bank D ELSIF Sect <= 66 THEN result := 1;--bank C ELSIF Sect <= 98 THEN result := 2;--bank B ELSE-- Sect <= 133 THEN result := 3;--bank C END IF; RETURN result; END ResolveBank; FUNCTION BankLockedForErs(LB_Ei : BankArray; BA : INTEGER) RETURN BOOLEAN IS VARIABLE result : BOOLEAN; BEGIN result := FALSE; IF BA >= 0 THEN FOR i IN 0 TO BankNum LOOP IF LB_Ei(i) = BA THEN result := TRUE; END IF; END LOOP; END IF; RETURN result; END BankLockedForErs; PROCEDURE AddBankForErs( SIGNAL BA : IN NATURAL; SIGNAL LB_Ei : INOUT BankArray ) IS VARIABLE i : NATURAL; VARIABLE found : BOOLEAN; BEGIN found := FALSE; -- check if bank is already added FOR i IN 0 TO BankNum LOOP IF LB_Ei(i) = BA THEN found := TRUE; END IF; END LOOP; i := 0; -- add bank for erasure if !found WHILE (i <= BankNum AND found = FALSE) LOOP IF LB_Ei(i) = -1 THEN found := TRUE; LB_Ei(i) <= BA; END IF; i := i+1; END LOOP; END PROCEDURE AddBankForErs; PROCEDURE ResetBankForErs( SIGNAL LB_Ei : INOUT BankArray; BA : NATURAL ) IS BEGIN FOR i IN 0 TO BankNum LOOP IF LB_Ei(i) = BA THEN LB_Ei(i) <= -1; END IF; END LOOP; END PROCEDURE ResetBankForErs; PROCEDURE ResetBankForErs( SIGNAL LB_Ei : INOUT BankArray ) IS BEGIN FOR i IN 0 TO BankNum LOOP LB_Ei(i) <= -1; END LOOP; END PROCEDURE ResetBankForErs; ---------------------------- --Address counter functions ---------------------------- PROCEDURE IncrAddr_cnt( VARIABLE Addr_cnt :INOUT NATURAL; VARIABLE Start_addr :IN NATURAL ) IS VARIABLE mode : NATURAL RANGE 0 TO 4; --segment startnig address for linear read VARIABLE Seg_SA : NATURAL; BEGIN mode := to_nat(ConfRegData(16 downto 15)); IF (mode = 3) THEN mode := mode +1; END IF; IF mode = 0 THEN IF Addr_cnt = MemSize THEN Addr_cnt := 0; --this should be default behaivour ELSE Addr_cnt := Addr_cnt + 1; END IF; ELSE IF max_wrap_thr < 127 THEN Seg_SA := ((Start_addr/(mode * 8)) * (mode*8)); IF Addr_cnt = Seg_SA + (mode*8) - 1 THEN --begining of segment Addr_cnt := Seg_SA; ELSE --increment counter Addr_cnt := Addr_cnt +1; END IF; max_wrap_thr := max_wrap_thr + 1; END IF; END IF; END PROCEDURE IncrAddr_cnt; PROCEDURE LoadtIACC( VARIABLE Address : IN std_logic_vector(HiAddrBit downto 0); SIGNAL ConfRegData: IN std_logic_vector(HiConfBit downto 0); VARIABLE bound_cross : BOOLEAN; VARIABLE bound_cross_active : BOOLEAN; SIGNAL tIACC : INOUT NATURAL RANGE 0 TO 14 ) IS VARIABLE Addr : NATURAL; VARIABLE mode : NATURAL RANGE 0 TO 3; VARIABLE tmp_tiacc : NATURAL; BEGIN mode := to_nat(ConfRegData(16 downto 15)); tmp_tiacc := 0; IF bound_cross_active THEN Addr := 0; ELSE Addr := to_nat(Address) mod 16#40#; END IF; IF (bound_cross = FALSE AND bound_cross_active = FALSE AND TimingModel(14) = '9' AND mode = 0 AND Addr = 16#3F#) THEN IF AVDNeg = '0' THEN tmp_tIACC := 2*(to_nat(ConfRegData(14 downto 12)) + 2)-1; ELSE tmp_tIACC := 2*(to_nat(ConfRegData(14 downto 12)) + 2); END IF; ELSIF (bound_cross = TRUE AND mode /= 0) THEN--linear tmp_tIACC := 0; --no latancy ELSIF (bound_cross = TRUE AND reduced_hnd = 1) THEN IF (Addr = 16#3F# OR Addr = 16#3E#) THEN tmp_tIACC := 0; --no latancy ELSE tmp_tIACC := 2; END IF; ELSE --initial for all: linear, continious, standard, reduced hnd shake -- booundary crossing for - continiuos standard IF AVDNeg = '0' THEN tmp_tIACC := to_nat(ConfRegData(14 downto 12)) + 2 - 1; ELSE tmp_tIACC := to_nat(ConfRegData(14 downto 12)) + 2; END IF; IF reduced_hnd = 1 THEN IF Addr mod 2 = 1 THEN-- odd address tmp_tIACC := tmp_tIACC + 1; END IF; IF (mode = 0 ) THEN --for continious IF Addr = 16#3D# THEN tmp_tIACC := tmp_tIACC + 1; ELSIF Addr = 16#3E# THEN tmp_tIACC := tmp_tIACC + 2; ELSIF Addr= 16#3F# THEN tmp_tIACC := tmp_tIACC + 3; END IF; END IF; END IF; END IF; tIACC <= tmp_tIACC; END LoadtIACC; FUNCTION ResolveSectFromAddr(Addr_cnt : INTEGER) RETURN INTEGER IS VARIABLE BurstBA : INTEGER RANGE -1 TO SecNum; BEGIN BurstBA := -1; IF Addr_cnt >= 0 THEN FOR i IN 0 TO SEcNum LOOP IF Addr_cnt >= sssa(i) AND Addr_cnt <= ssea(i) THEN BurstBA := i; END IF; END LOOP; END IF; RETURN BurstBA; END ResolveSectFromAddr; FUNCTION ResolveBankFromAddr(Addr_cnt : INTEGER) RETURN INTEGER IS VARIABLE BurstBA : INTEGER RANGE -1 TO BankNum; BEGIN BurstBA := -1; IF Addr_cnt >= 0 THEN FOR i IN 0 TO BankNum LOOP IF Addr_cnt >= bsa(i) AND Addr_cnt <= bea(i) THEN BurstBA := i; END IF; END LOOP; END IF; RETURN BurstBA; END ResolveBankFromAddr; PROCEDURE ActiveAlgo( active_algo : INOUT BOOLEAN; Addr_cnt : IN INTEGER RANGE -1 TO MemSize; BurstSA : IN INTEGER RANGE -1 TO SecNum ) IS VARIABLE i : INTEGER; BEGIN active_algo := FALSE; --if nexy bank is in prgms active_algo := lb_p > -1 AND Addr_cnt >= bsa(lb_p) AND Addr_cnt <= bea(lb_p); --if next bank is in autoselect mode IF (active_algo = FALSE) THEN active_algo := lb_a > -1 AND Addr_cnt >= bsa(lb_a) AND Addr_cnt <= bea(lb_a); END IF; --if next bank is in ERS IF ((ESP_ACT = '0') OR (ESP_ACT = '1' AND BurstSA > -1 AND Ers_Queue(BurstSA) = '1')) THEN i := 0; WHILE (NOT active_algo AND i <= BankNum) LOOP active_algo := lb_ei(i) > -1 AND Addr_cnt >= bsa(lb_ei(i)) AND Addr_cnt <= bea(lb_ei(i)); i := i+1; END LOOP; END IF; END ActiveAlgo; ---------------------- --PROCEDURES -------------------- ----------------------- --Reads (mem, AS, CFI) ---------------------- PROCEDURE MemRead ( SIGNAL SecAddr : IN NATURAL RANGE 0 TO SecNum; SIGNAL Address : IN NATURAL RANGE 0 TO SecSize_L; SIGNAL Addr_cnt : IN INTEGER RANGE -1 TO MemSize; SIGNAL DOut_zd : INOUT std_logic_vector(15 downto 0) ) IS VARIABLE A_tmp : INTEGER RANGE -1 TO MemSize; BEGIN IF NOT burst_mode THEN A_tmp := sssa(SecAddr) + Address; ELSE A_tmp := Addr_cnt; END IF; IF A_tmp <0 THEN DOut_zd(15 downto 0) <= (OTHERS => 'X'); ELSE IF Mem(A_tmp) = -1 THEN DOut_zd(15 downto 0) <= (OTHERS => 'X'); ELSE DOut_zd(15 downto 0) <= to_slv(Mem(A_tmp),16); END IF; END IF; END MemRead; --AsRead(Address, Addr_cnt, reduced_hnd, vs, SecAddr, Dout_zd); PROCEDURE AsRead ( SIGNAL Address : IN NATURAL RANGE 0 TO SecSize_L; SIGNAL Addr_cnt : IN INTEGER RANGE -1 TO MemSize; SIGNAL reduced_hnd : IN INTEGER; SIGNAL vs : IN INTEGER; SIGNAL SecAddr : IN NATURAL RANGE 0 TO SecNum; SIGNAL DOut_zd : INOUT std_logic_vector(15 downto 0) ) IS VARIABLE A_tmp : INTEGER RANGE -1 TO MemSize; VARIABLE SA_tmp : NATURAL RANGE 0 TO SecNum; VARIABLE SA : NATURAL RANGE 0 TO SecNum; VARIABLE A : std_logic_vector (HiAddrBit downto 0); BEGIN IF NOT burst_mode THEN A_tmp := Address; SA_tmp := SecAddr; ELSE A := (to_slv(Addr_cnt, HiAddrBit+1)); SA := to_nat (A(HiAddrBit downto 15)); IF (SA = 0) THEN SA_tmp := SA + to_nat(A(14 downto 13)); A_tmp := to_nat(A(12 downto 0)); ELSIF (SA < SecNum - BootSecNum + 1) THEN SA_tmp := SA + 3; A_tmp := to_nat(A(14 downto 0)); ELSE SA_tmp := SA + 3 + to_nat(A(14 downto 13)); A_tmp := to_nat(A(12 downto 0)); END IF; END IF; IF A_tmp = 1 OR A_tmp = 16#0E# OR A_tmp = 16#0F# THEN DOut_zd(15 downto 8) <= to_slv(16#22#,8); ELSE DOut_zd(15 downto 8) <= to_slv(0,8); END IF; IF A_tmp = 0 THEN DOut_zd(7 downto 0) <= to_slv(1,8); ELSIF A_tmp = 1 THEN DOut_zd(7 downto 0) <= to_slv(16#7E#,8); ELSIF A_tmp = 2 THEN DOut_zd(7 downto 1) <= to_slv(0,7); DOut_zd(0) <= Sec_Prot(SA_tmp); ELSIF A_tmp = 3 THEN --handshake option IF (reduced_hnd = 1) THEN DOut_zd(7 downto 0) <= to_slv(16#43#,8);--reduced ELSE DOut_zd(7 downto 0) <= to_slv(16#42#,8);--standard END IF; ELSIF A_tmp = 16#0E# THEN-- bamk address IF (vs = 1) THEN--top DOut_zd(7 downto 0) <= to_slv(16#04#,8); ELSE DOut_zd(7 downto 0) <= to_slv(16#24#,8); END IF; ELSIF A_tmp = 16#0F# THEN-- bamk address DOut_zd(7 downto 0) <= to_slv(16#01#,8); ELSE DOut_zd(15 downto 0) <= (OTHERS=>'Z'); ASSERT FALSE REPORT "Invalid AS address" SEVERITY warning; END IF; END AsRead; PROCEDURE CfiRead ( SIGNAL SecAddr : IN NATURAL RANGE 0 TO SecNum; SIGNAL Address : IN NATURAL RANGE 0 TO SecSize_L; SIGNAL Addr_cnt : IN INTEGER RANGE -1 TO MemSize; SIGNAL DOut_zd : INOUT std_logic_vector(15 downto 0) ) IS VARIABLE Addr : INTEGER RANGE -1 TO MemSize; BEGIN IF NOT burst_mode THEN Addr := sssa(SecAddr) + Address; ELSE Addr := Addr_cnt; END IF; DOut_zd(15 downto 0) <= (OTHERS=>'0'); IF ((Addr >= MinCfiAddr) AND (Addr <= MaxCfiAddr)) THEN DOut_zd(15 downto 0) <= to_slv(CFI_array(Addr) ,16); ELSE DOut_zd(15 downto 0) <= (OTHERS=>'Z'); ASSERT FALSE REPORT "Invalid CFI query address" SEVERITY warning; END IF; END CfiRead; BEGIN --flash selected cs <= NOT CENeg; --top/bottom architecture vs <= 1 WHEN TimingModel(1 to 12)="am29bds640gt" ELSE 0; first_prot <= SecNum - 1 WHEN TimingModel(1 to 12) = "am29bds640gt" ELSE 0; reduced_hnd <= 1 WHEN TimingModel(14)='8' ELSE 0; ---------------------------------------------------------------------------- --Power Up time 100 ns; --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 100 ns; RST <= RESETNeg AFTER 500 ns; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A, Din, CENeg, OENeg, WENeg, RESETNeg, AVDNeg, CLK, RDY_zd, LA) -- Timing Check Variables VARIABLE TD_A0_AVDNeg : VitalTimingDataType; VARIABLE Tviol_A0_AVDNeg : X01 := '0'; VARIABLE TD_A0_CLK_r : VitalTimingDataType; VARIABLE Tviol_A0_CLK_r : X01 := '0'; VARIABLE TD_A0_CLK_f : VitalTimingDataType; VARIABLE Tviol_A0_CLK_f : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_DQ0_CLK_r : VitalTimingDataType; VARIABLE Tviol_DQ0_CLK_r : X01 := '0'; VARIABLE TD_DQ0_CLK_f : VitalTimingDataType; VARIABLE Tviol_DQ0_CLK_f : X01 := '0'; VARIABLE TD_RDY_CLK_r : VitalTimingDataType; VARIABLE Tviol_RDY_CLK_r : X01 := '0'; VARIABLE TD_RDY_CLK_f : VitalTimingDataType; VARIABLE Tviol_RDY_CLK_f : X01 := '0'; VARIABLE TD_CENeg_CLK_r : VitalTimingDataType; VARIABLE Tviol_CENeg_CLK_r : X01 := '0'; VARIABLE TD_CENeg_CLK_f : VitalTimingDataType; VARIABLE Tviol_CENeg_CLK_f : X01 := '0'; VARIABLE TD_AVDNeg_CLK_r : VitalTimingDataType; VARIABLE Tviol_AVDNeg_CLK_r : X01 := '0'; VARIABLE TD_AVDNeg_CLK_f : VitalTimingDataType; VARIABLE Tviol_AVDNeg_CLK_f : X01 := '0'; VARIABLE TD_OENeg_WENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_CLK_AVDNeg : VitalTimingDataType; VARIABLE Tviol_CLK_AVDNeg : X01 := '0'; VARIABLE TD_CLK_WENeg_as : VitalTimingDataType; VARIABLE Tviol_CLK_WENeg_as : X01 := '0'; VARIABLE TD_CLK_WENeg_sy : VitalTimingDataType; VARIABLE Tviol_CLK_WENeg_sy : X01 := '0'; VARIABLE TD_AVDNeg_WENeg : VitalTimingDataType; VARIABLE Tviol_AVDNeg_WENeg : X01 := '0'; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE TD_OENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_OENeg_RESETNeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_AVDNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_AVDNeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE Violation : X01 := '0'; BEGIN ---------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN ------------------------------------------------- --Setup/hold address if AVD latches the addresses --burst or asyn ------------------------------------------------- --Setup/hold address to AVD rising VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupHigh => tsetup_A0_AVDNeg,--tAAVDS SetupLow => tsetup_A0_AVDNeg,--tAAVDS HoldHigh => thold_A0_AVDNeg,--tAAVDH HoldLow => thold_A0_AVDNeg,--tAAVDH CheckEnabled => (ConfRegData(19) = '1' OR (ConfRegData(19) = '0' AND rising_edge(LA))), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_AVDNeg, Violation => Tviol_A0_AVDNeg ); ------------------------------------------------- --Setup/hold address if CLK latches the addresses --burst ------------------------------------------------- --Setup/hold address to CLK zctive VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLK", SetupHigh => tsetup_A0_AVDNeg,--tACS SetupLow => tsetup_A0_AVDNeg,--tACS HoldHigh => thold_A0_AVDNeg,--tACH HoldLow => thold_A0_AVDNeg,--tACH CheckEnabled => ConfRegData(17) = '1' AND ConfRegData(19) = '0' AND rising_edge(LA), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CLK_r, Violation => Tviol_A0_CLK_r ); --Setup/hold address to CLK zctive VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLk", SetupHigh => tsetup_A0_AVDNeg,--tACS SetupLow => tsetup_A0_AVDNeg,--tACS HoldHigh => thold_A0_AVDNeg,--tACH HoldLow => thold_A0_AVDNeg,--tACH CheckEnabled => ConfRegData(17) = '0' AND ConfRegData(19) = '0' AND rising_edge(LA), RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CLK_f, Violation => Tviol_A0_CLK_f ); ------------------------------------------------- --Setup/hold address if WE latches the addresses --asyn ------------------------------------------------- VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_A0_WENeg,--tAS SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg,--tAH HoldLow => thold_A0_WENeg, CheckEnabled => ConfRegData(19) = '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); ---------------------------------- --Otehr setup and hold timings ---------------------------------- --BURST READ -- Hold Check DQ to CLK VitalSetupHoldCheck ( TestSignal => Din, TestSignalName => "DQ", RefSignal => CLK, RefSignalName => "CLK#", HoldHigh => thold_DQ0_CLK, HoldLow => thold_DQ0_CLK, CheckEnabled => ConfRegData(19) = '0' AND ConfRegData(17) = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CLK_r, Violation => Tviol_DQ0_CLK_r ); VitalSetupHoldCheck ( TestSignal => Din, TestSignalName => "DQ", RefSignal => CLK, RefSignalName => "CLK#", HoldHigh => thold_DQ0_CLK, HoldLow => thold_DQ0_CLK, CheckEnabled => ConfRegData(19) = '0' AND ConfRegData(17) = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CLK_f, Violation => Tviol_DQ0_CLK_f ); -- Setup Check RDY to CLK VitalSetupHoldCheck ( TestSignal => RDY_zd, TestSignalName => "RDY", RefSignal => CLK, RefSignalName => "CLK#", SetupHigh => tsetup_RDY_CLK, CheckEnabled => ConfRegData(17) = '1' AND ConfRegData(19) = '0' AND OENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_RDY_CLK_r, Violation => Tviol_RDY_CLK_r ); -- Setup Check RDY to CLK VitalSetupHoldCheck ( TestSignal => RDY_zd, TestSignalName => "RDY", RefSignal => CLK, RefSignalName => "CLK#", SetupHigh => tsetup_RDY_CLK, CheckEnabled => ConfRegData(17) = '0' AND ConfRegData(19) = '0' AND OENeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_RDY_CLK_f, Violation => Tviol_RDY_CLK_f ); -- Hold Check CENeg to CLK VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => CLK, RefSignalName => "CLK#", SetupLow => tsetup_CENeg_CLK, CheckEnabled => ConfRegData(17) = '1' AND ConfRegData(19) = '0' AND rising_edge(LA), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLK_r, Violation => Tviol_CENeg_CLK_r ); -- Hold Check CENeg to CLK VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => CLK, RefSignalName => "CLK#", SetupLow => tsetup_CENeg_CLK, CheckEnabled => ConfRegData(17) = '0' AND ConfRegData(19) = '0' AND rising_edge(LA), RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLK_f, Violation => Tviol_CENeg_CLK_f ); --Setup/hold AVDNeg to CLK zctive VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_AVDNeg_CLK,--tZVC HoldLow => thold_AVDNeg_CLK,--tAVCH CheckEnabled => ConfRegData(17) = '1' AND ConfRegData(19) = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_CLK_r, Violation => Tviol_AVDNeg_CLK_r ); --Setup/hold address to CLK zctive VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_AVDNeg_CLK,--tZVC HoldLow => thold_AVDNeg_CLK,--tACH CheckEnabled => ConfRegData(17) = '0' AND ConfRegData(19) = '0' AND rising_edge(LA), RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_CLK_f, Violation => Tviol_AVDNeg_CLK_f ); -- Hold Check between OENeg and WENeg VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_OENeg_WENeg,--toeh CheckEnabled => PDONE = '0' OR EDONE = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg, Violation => Tviol_OENeg_WENeg ); -- Setup/Hold Check between DQ and WENeg VitalSetupHoldCheck ( TestSignal => Din, TestSignalName => "DQ", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_WENeg, Violation => Tviol_DQ0_WENeg ); VitalSetupHoldCheck ( TestSignal => CLK, TestSignalName => "CLK_tcs", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupHigh => tsetup_CLK_AVDNeg,--tCSW1 SetupLow => tsetup_CLK_AVDNeg,--tCSW1 CheckEnabled => ConfRegData(19) = '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLK_AVDNeg, Violation => Tviol_CLK_AVDNeg ); VitalSetupHoldCheck ( TestSignal => CLK, TestSignalName => "CLK", RefSignal => WENeg, RefSignalName => "WENeg", HoldHigh => thold_CLK_WENeg,--tCHW HoldLow => thold_CLK_WENeg,--tCHW CheckEnabled => cs = '1' AND ConfRegData(19) = '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLK_WENeg_as, Violation => Tviol_CLK_WENeg_as ); VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_AVDNeg_WENeg,--tAVSW HoldLow => thold_AVDNeg_WENeg,--tAVHC CheckEnabled => ConfRegData(19) = '1',--async_write = TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_WENeg, Violation => Tviol_AVDNeg_WENeg ); VitalSetupHoldCheck ( TestSignal => CLK, TestSignalName => "CLK", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_CLK_WENeg,--tCSW2 --sync_write SetupLow => tsetup_CLK_WENeg,--tCSW2 --sync_write CheckEnabled => cs = '1' AND ConfRegData(19) = '0' AND rising_edge(LA), RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLK_WENeg_sy, Violation => Tviol_CLK_WENeg_sy ); 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 ); VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_RESETNeg, Violation => Tviol_OENeg_RESETNeg ); ----------------------- --pulse width checkers ------------------------ -- PulseWidth Check for REset VitalPeriodPulseCheck ( TestSignal => RESETNeg, TestSignalName => "RESETNeg", PulseWidthLow => tpw_RESETNeg_negedge, CheckEnabled => TRUE,--FLASh selected HeaderMsg => InstancePath & PartID, PeriodData => PD_RESETNeg, Violation => Pviol_RESETNeg ); -- PulseWidth Check for AVD VitalPeriodPulseCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", PulseWidthLow => tpw_AVDNeg_negedge, --tAVDP CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_AVDNeg, Violation => Pviol_AVDNeg ); -- PulseWidth Check for WE VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WENeg", PulseWidthHigh => tpw_WENeg_posedge, PulseWidthLow => tpw_WENeg_negedge, CheckEnabled => TRUE,--FLASh selected HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); Violation := Tviol_A0_AVDNeg OR Tviol_A0_CLK_r OR Tviol_A0_CLK_f OR Tviol_A0_WENeg OR Tviol_DQ0_CLK_r OR Tviol_DQ0_CLK_f OR Tviol_RDY_CLK_r OR Tviol_RDY_CLK_f OR Tviol_CENeg_CLK_r OR Tviol_CENeg_CLK_f OR Tviol_AVDNeg_CLK_r OR Tviol_AVDNeg_CLK_f OR Tviol_OENeg_WENeg OR Tviol_DQ0_WENeg OR Tviol_CLK_AVDNeg OR Tviol_CLK_WENeg_as OR Tviol_AVDNeg_WENeg OR Tviol_CLK_WENeg_sy OR Tviol_CENeg_RESETNeg OR Tviol_OENeg_RESETNeg OR Pviol_RESETNeg OR Pviol_AVDNeg 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_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; --------------------------------------------------------------------------- --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 write control signals" SEVERITY warning; END IF; END PROCESS PulseWatch; ---------------------------------------------------------------------------- --FLASH ---------------------------------------------------------------------------- --latch address on rising edge and data on falling edge of write write_dc: PROCESS (gWE_n, gCE_n, gOE_n, 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 <= 'X'; END IF; END IF; IF ((gWE_n = '1') AND (gCE_n = '0') AND (gOE_n = '0')) THEN read <= '1'; ELSE read <= '0'; END IF; END PROCESS write_dc; --------------------------------------------------------------------------- --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, reseted, Whole_addr, AVDNeg, CLK_active) VARIABLE A_tmp : NATURAL RANGE 0 TO 16#7FF#; VARIABLE SA_tmp : NATURAL RANGE 0 TO SecNum; VARIABLE A_tmp1 : NATURAL RANGE 0 TO SecSize_L; VARIABLE CR_Addr_tmp : std_logic_vector(HiConfBit downto 0) := (OTHERS => '0'); VARIABLE LA_TMP : std_logic; VARIABLE i : NATURAL; BEGIN IF reseted='1' THEN IF CENeg = '0' THEN --------------------- --asynh address latch ---------------------- IF (ConfRegData(19) = '1') THEN -- WE falling LA IF ( (falling_edge(WENeg) AND AVDNeg = '0') OR (falling_edge(WENeg) AND falling_edge(AVDNeg))) --OR see CE LATCH ADDRESSES AND LA = '0' THEN LA <= '1'; Whole_addr <= A; -- AVD rising LA ELSIF rising_edge(AVDNeg) AND LA = '0' THEN LA <= '1', '0' AFTER 1 ns; Whole_addr <= A; -- latch is open ELSIF LA = '0' AND AVDNeg = '0' THEN Whole_addr <= A; END IF; ELSE --------------------- --burst address latch ---------------------- -- CLK active LA IF AVDNeg = '0' AND rising_edge(CLk_active) AND LA ='0' THEN LA <= '1'; Whole_addr <= A; -- AVD rising LA ELSIF rising_edge(AVDNeg) AND LA = '0' THEN LA <= '1', '0' AFTER 1 ns; Whole_addr <= A; END IF; END IF; END IF; --CE LATCH ADDRESS IF ( falling_edge(CENeg) AND AVDNeg = '0' AND WENeg ='0' AND ConfRegData(19) = '1') THEN IF LA = '0' THEN LA <= '1' ; Whole_addr <= A; END IF; END IF; -- deassert LA IF rising_edge(CENeg) THEN LA <= '0'; ELSIF AVDNeg = '1' AND CENeg = '0' AND LA = '1' THEN LA <= '0' ; END IF; A_tmp := to_nat( Whole_Addr(10 downto 0) ); RestoreSectAddr(Whole_Addr, SA_tmp, A_tmp1); --Data Latch IF (rising_edge(WENeg) OR rising_edge(CENeg))--If rising_edge CEneg latches data AND write = '1' THEN D_tmp0 <= to_nat(Din(15 downto 0)); END IF; IF rising_edge(write) OR rising_edge(LA) OR falling_edge(OENeg) OR ((Whole_addr'EVENT ) AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN BA <= ResolveBank(SA_tmp); SecAddr <= SA_tmp; Address <= A_tmp1; CR_Addr(HiConfBit downto LoConfBit) <= Whole_Addr(HiConfBit downto Loconfbit); Addr <= A_tmp; END IF; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Program/ Write Buffer Program Operations -- start/ suspend/ resume --------------------------------------------------------------------------- ProgTime :PROCESS(PSTART, ESP_ACT, reseted) VARIABLE duration : time; VARIABLE pow : time; BEGIN IF LongTimming THEN IF ULBYPASS = '1' THEN pow := tdevice_POU; ELSE pow := tdevice_POW; END IF; ELSE pow := tdevice_POW / 1; 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 (Sec_Prot(SA) = '0' AND (Ers_queue(SA) = '0' OR ESP_ACT = '0'))THEN duration := pow; PDONE <= '0', '1' AFTER duration; 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, Ers_Queue, reseted)--Ers_Sub_Queue, VARIABLE cnt : NATURAL RANGE 0 TO SecNum:= 0; VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE seo : time; VARIABLE bank0 : BOOLEAN; VARIABLE bank1 : BOOLEAN; VARIABLE bank2 : BOOLEAN; VARIABLE bank3 : BOOLEAN; BEGIN bank0 := FALSE; bank1 := FALSE; bank2 := FALSE; bank3 := FALSE; IF LongTimming THEN seo := tdevice_SEO; ELSE seo := tdevice_SEO/scale; END IF; 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; FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND Sec_Prot(i) /= '1' THEN cnt := cnt +1; bank0 := bank0 OR ResolveBAnk(i) = 0; bank1 := bank1 OR ResolveBAnk(i) = 1; bank2 := bank2 OR ResolveBAnk(i) = 2; bank3 := bank3 OR ResolveBAnk(i) = 3; 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; -- if all sectors from one bank are protected --bannki = FALSE IF NOT bank0 AND BankLockedForErs(LB_ei, 0) THEN EERR0 <= '1', '0' AFTER 100 us; END IF; IF NOT bank1 AND BankLockedForErs(LB_ei, 1) THEN EERR1 <= '1', '0' AFTER 100 us; END IF; IF NOT bank2 AND BankLockedForErs(LB_ei, 2) THEN EERR2 <= '1', '0' AFTER 100 us; END IF; IF NOT bank3 AND BankLockedForErs(LB_ei, 3) THEN EERR3 <= '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; --Hardware Write Protection ACC_WP_CTRL: PROCESS(ACC, WPNeg) VARIABLE Sec_Prot_reg : std_logic_vector(SecNum downto 0) := (OTHERS => '0'); VARIABLE Sec_Prot_reg0 : std_logic := '0'; VARIABLE Sec_Prot_reg1 : std_logic := '0'; BEGIN IF falling_edge(ACC) THEN --lock all sectors except 'first_prot' and 'first_prot +1' FOR i IN 0 TO SecNum LOOP IF (i /= first_prot) AND i /= (first_prot +1) THEN Sec_Prot_reg(i) := Sec_Prot(i); Sec_Prot(i) := '1'; END IF; END LOOP; ELSIF rising_edge(ACC) THEN --unlock all sectors except 'first_prot' and 'first_prot +1' FOR i IN 0 TO SecNum LOOP IF (i /= first_prot) AND i /= (first_prot +1) THEN Sec_Prot(i) := Sec_Prot_reg(i); END IF; END LOOP; END IF; IF (falling_edge(WPNeg) AND rising_edge(ACC)) OR (falling_edge(ACC) AND (rising_edge(WPNEg))) OR (WPNeg = '0' AND ACC'EVENT AND NOT WPNeg'EVENT ) OR (ACC = '0' AND WPNeg'EVENT AND NOT ACC'EVENT ) THEN --don't update Sec_Prot_reg0, Sec_Prot_reg1 ELSIF (falling_edge(WPNeg) AND falling_edge(ACC)) OR (falling_edge(WPNeg) AND ACC = '1') OR (falling_edge(ACC) AND WPNeg = '1') THEN Sec_Prot_reg0 := Sec_Prot(first_prot); Sec_Prot_reg1 := Sec_Prot(first_prot+1); Sec_Prot(first_prot) := '1'; Sec_Prot(first_prot+1) := '1'; ELSIF (rising_edge(WPNeg) AND rising_edge(ACC)) OR (rising_edge(WPNeg) AND ACC = '1') OR (rising_edge(ACC) AND WPNeg = '1') THEN Sec_Prot(first_prot) := Sec_Prot_reg0; Sec_Prot(first_prot+1) := Sec_Prot_reg1; END IF; END PROCESS ACC_WP_CTRL; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(write, Addr, D_tmp0, ULBYPASS, PDONE, EDONE, HANG, CTMOUT_out, START_T1_out, reseted, READY_out, PERR, EERR) VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; 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#) AND (ULBYPASS = '0')) OR (ULBYPASS = '1'); 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; ELSIF (DataLo = 16#60#) THEN next_state <= SLU_Z001; ELSE next_state <= RESET; END IF; END IF; WHEN SLU_Z001 => IF falling_edge(write) THEN IF (DataLo = 16#60#) THEN next_state <= SLU_PREL; ELSE next_state <= RESET; END IF; END IF; WHEN SLU_PREL => IF falling_edge(write) THEN IF (DataLo = 16#60#) THEN next_state <= SLU; ELSE next_state <= RESET; END IF; END IF; WHEN SLU => IF falling_edge(write) THEN IF (DataLo = 16#F0#) THEN 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#20#)) THEN next_state <= PREL_ULBYPASS; ELSIF (A_PAT_1 AND (DataLo = 16#90#)) THEN --lock bank LB_A 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; ELSE next_state <= RESET; END IF; END IF; WHEN PREL_ULBYPASS => IF falling_edge(write) THEN IF (A_PAT_1 AND (DataLo = 16#90#)) THEN --unlock bypass reset --lock bankk LB_A 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_PREL; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; WHEN CFI => IF falling_edge(write) THEN IF (Addr = 16#55#) AND (DataLo = 16#98#) THEN next_state <= CFI; ELSIF (DataLo = 16#F0#) THEN next_state <= RESET; ELSE next_state <= CFI; END IF; END IF; WHEN AS => IF falling_edge(write) THEN IF (DataLo = 16#F0#) THEN --unlock LB_A next_state <= RESET; ELSIF (Addr = 16#55#) AND (DataLo = 16#98#) THEN next_state <= AS_CFI; ELSE next_state <= AS; END IF; END IF; WHEN A0SEEN => IF falling_edge(write) THEN --lock LB_P 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 --lock bank LB_Ei 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; WHEN SERS => IF (CTMOUT_out = '1' AND CTMOUT_out'EVENT)THEN next_state <= SERS_EXEC; ELSIF falling_edge(write) THEN IF (DataLo = 16#B0# AND BankLockedForErs(LB_Ei, BA) = TRUE) THEN next_state <= ESPS; -- ESP according to datasheet ELSIF (DataLo = 16#30#) THEN next_state <= SERS; ELSIF ULBYPASS = '1' THEN --ResetBankForErs next_state <= PREL_ULBYPASS; ELSE --ResetBankForErs next_state <= RESET; END IF; END IF; WHEN ESPS => IF (START_T1_out = '1') THEN next_state <= ESP; END IF; WHEN SERS_EXEC => IF rising_edge(EDONE) OR falling_edge(EERR) THEN --ResetBankForErs 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 BankLockedForErs(LB_Ei, BA) = TRUE) THEN next_state <= ESPS; END IF; END IF; END IF; WHEN ESP => IF falling_edge(write) THEN IF (DataLo = 16#30# AND BankLockedForErs(LB_Ei, BA) = TRUE) THEN next_state <= SERS_EXEC; ELSIF ULBYPASS = '1' THEN IF DataLo = 16#20# THEN null; ELSIF A_PAT_1 AND DataLo = 16#A0# THEN next_state <= ESP_A0SEEN; ELSIF A_PAT_1 AND DataLo = 16#90# THEN --exit unlock bypass --lock LB_A next_state <= ESP_AS; END IF; 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_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#20# THEN next_state <= ESP; ELSIF A_PAT_1 AND DataLo = 16#A0# THEN next_state <= ESP_A0SEEN; ELSIF A_PAT_1 AND DataLo = 16#90# THEN --lock LB_A next_state <= ESP_AS; ELSE next_state <= ESP; END IF; END IF; WHEN ESP_CFI => IF falling_edge(write) THEN IF Addr = 16#55# AND DataLo = 16#98# THEN null; ELSIF DataLo = 16#F0# THEN next_state <= ESP; ELSIF (DataLo = 16#30# AND BankLockedForErs(LB_Ei, BA)) THEN next_state <= SERS_EXEC; ELSE next_state <= ESP; END IF; END IF; WHEN ESP_A0SEEN => IF falling_edge(write) THEN next_state <= PGMS; --set ESP --lock LB_P END IF; WHEN ESP_AS => IF falling_edge(write) THEN IF DataLo = 16#F0# THEN -- resret ULBYPASS --unlock LB_A next_state <= ESP; 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 IF ESP_ACT = '1' THEN next_state <= ESP_AS; ELSE next_state <= AS; END IF; END IF; END IF; WHEN PGMS => IF rising_edge(PDONE) OR falling_edge(PERR) THEN --unlock LB_P IF ESP_ACT = '1' THEN next_state <= ESP; 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, Addr, D_tmp0, Address, SecAddr, PDONE, PERR, EDONE, EERR, EERR0, EERR1, EERR2, EERR3, HANG, START_T1_out, CTMOUT_out, RST, reseted, READY_out, gOE_n, gCE_n, current_state, PoweredUp, Addr_cnt) VARIABLE WData : INTEGER RANGE -1 TO MaxData := 0;--n VARIABLE WAddr : NATURAL RANGE 0 TO SecSize_L := 0;--n 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(7 downto 0) := (OTHERS=>'0'); FILE mem_file : text is mem_file_name; VARIABLE ind : NATURAL RANGE 0 TO MemSize := 0; VARIABLE buf : line; VARIABLE i : INTEGER; 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 wr_cnt : NATURAL RANGE 0 TO 31; VARIABLE tmp_addr : std_logic_vector(15 downto 0); VARIABLE DataLo : NATURAL RANGE 0 TO MaxData := 0; VARIABLE temp : std_logic_vector(7 downto 0); --tmp: lock/unlock sector VARIABLE lock : std_logic; --bank of internal address counter VARIABLE BurstBA : INTEGER RANGE -1 TO BankNum := -1; --sector of internal address counter VARIABLE BurstSa : INTEGER RANGE -1 TO SecNum := -1; 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#)AND (ULBYPASS = '0')) OR (ULBYPASS = '1'); END IF; oe:= ( ------------- --asyn read ------------ (burst_mode = FALSE AND ( rising_edge(read) OR (read = '1' AND (Address'EVENT OR SecAddr'EVENT )))) OR ------------- --burst read ------------- (burst_mode = TRUE AND read = '1' AND Addr_cnt'EVENT) ); BurstBA := ResolveBankFromAddr(Addr_cnt); BurstSA := ResolveSectFromAddr(Addr_cnt); IF PoweredUp = '0' THEN Sec_Prot := (OTHERS => '1'); END IF; IF rising_edge(reseted) THEN LB_P <= -1; -- reset latched banks upon reset LB_A <= -1; ResetBankForErs(LB_Ei); ConfRegData <= "11100101000000000000"; ELSIF reseted = '1' THEN CASE current_state IS WHEN RESET => ESP_ACT <= '0'; IF falling_edge(write) THEN null; ELSIF oe THEN MemRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; WHEN SLU_Z001 => null; WHEN SLU_PREL => IF falling_edge(write) THEN IF (DataLo = 16#60#) THEN --set sector protect tmp_addr := to_slv(Address,16); IF (tmp_addr(6) = '0') THEN lock := '1'; ELSE lock := '0'; END IF; Sec_Prot(SecAddr) := lock; END IF; END IF; WHEN SLU => IF falling_edge(write) THEN IF (DataLo = 16#60#) THEN --set sector protect tmp_addr := to_slv(Address,16); IF (tmp_addr(6) = '0') THEN lock := '1'; ELSE lock := '0'; END IF; Sec_Prot(SecAddr) := lock; END IF; END IF; WHEN Z001 => null; WHEN PREL_SETBWB => IF falling_edge(write) THEN IF (A_PAT_1 AND (DataLo = 16#20#)) THEN ULBYPASS <= '1'; ELSIF (A_PAT_1 AND (DataLo = 16#90#)) THEN ULBYPASS <= '0';--ULBYPAS is already 0 here LB_A <= BA; --LockB(SecAddr); ELSIF (A_PAT_1 AND (DataLo = 16#C0#)) THEN --write configuration register ConfRegData <= CR_Addr; END IF; END IF; WHEN PREL_ULBYPASS => IF falling_edge(write) THEN IF (DataLo = 16#20#) THEN ULBYPASS <= '1'; ELSIF (A_PAT_1 AND (DataLo = 16#90#)) THEN LB_A <= BA; --LockB(SecAddr); --ULBYPASS <= '0';changed in AS END IF; END IF; WHEN CFI => IF falling_edge(write) THEN null; ELSIF oe THEN CfiRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; WHEN AS => IF falling_edge(write) THEN IF (DataLo = 16#F0#) THEN LB_A <= -1; --UnLockB(SecAddr); ULBYPASS <= '0'; ELSIF (Addr = 16#55#) AND (DataLo = 16#98#) THEN null; END IF; ELSIF oe THEN IF (NOT burst_mode AND LB_A = BA) OR (burst_mode AND Addr_cnt >= bsa(LB_A) AND Addr_cnt <= bea(LB_A)) THEN AsRead(Address, Addr_cnt, reduced_hnd, vs, SecAddr, Dout_zd); ELSE MemRead(SecAddr, Address, Addr_cnt, Dout_zd); END IF; END IF; WHEN A0SEEN => IF falling_edge(write) THEN LB_P <= BA; --LockB(SecAddr); PSTART <= '1', '0' AFTER 1 ns; WData := DataLo; WAddr := Address; SA <= SecAddr; temp := to_slv(DataLo, 8); Status(7) := NOT temp(7); END IF; WHEN C8 => IF falling_edge(write) THEN null; END IF; WHEN C8_Z001 => IF falling_edge(write) THEN END IF; WHEN C8_PREL => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo = 16#10# THEN --Start Chip Erase FOR i IN 0 TO BankNum LOOP LB_Ei(i) <= i; END LOOP; ESTART <= '1', '0' AFTER 1 ns; ESUSP <= '0'; ERES <= '0'; Ers_Queue <= (OTHERS => '1'); Status := "00001000"; ELSIF DataLo = 16#30# THEN AddBankForErs(BA, LB_Ei); --put selected sector to sec. ers. queue --start timeout Ers_Queue <= (OTHERS => '0'); Ers_Queue(SecAddr) <= '1'; CTMOUT_in <= '0', '1' AFTER 1 ns; END IF; END IF; WHEN ERS => IF oe THEN ----------------------------------------------------------- -- read status / embeded erase algorithm - Chip Erase ----------------------------------------------------------- Status(7) := '0'; Status(6) := NOT Status(6); --toggle Status(5) := '0'; Status(3) := '1'; Status(2) := NOT Status(2); --toggle DOut_zd(7 downto 0) <= Status; Dout_zd(15 downto 8) <= (OTHERS=> 'Z'); END IF; IF rising_edge(EDONE) OR falling_edge(EERR) THEN ResetBankForErs(LB_Ei); END IF; IF EERR /= '1' THEN FOR i IN 0 TO SecNum LOOP IF Sec_Prot(i) /= '1' THEN Mem((sssa(i)) TO (ssea(i)) ) := (OTHERS => -1); END IF; END LOOP; IF EDONE = '1' THEN FOR i IN 0 TO SecNum LOOP IF Sec_Prot(i) /= '1' THEN Mem(sssa(i) TO ssea(i)) := (OTHERS => MaxData); END IF; END LOOP; END IF; END IF; WHEN SERS => IF (CTMOUT_out = '1' AND CTMOUT_out'EVENT)THEN CTMOUT_in <= '0'; START_T1_in <= '0'; ESTART <= '1', '0' AFTER 1 ns; ESUSP <= '0'; ERES <= '0'; --next_state <= SERS_EXEC; ELSIF falling_edge(write) THEN IF (DataLo = 16#B0# AND BankLockedForErs(LB_Ei, BA) = TRUE) THEN --next_state <= ESPS; -- ESP according to datasheet --need to start erase process prior to suspend ESTART <= '1', '0' AFTER 1 ns; ESUSP <= '0'; ERES <= '0'; --suspend timeout (should be 0 according to datasheet) START_T1_in <= '1'; ELSIF (DataLo = 16#30# ) THEN AddBankForErs(BA, LB_Ei); CTMOUT_in <= '0', '1' AFTER 1 ns; Ers_Queue(SecAddr) <= '1'; ELSE ResetBankForErs(LB_Ei); END IF; ELSIF oe THEN IF (NOT burst_mode AND BankLockedForErs(LB_Ei, BA)) OR (burst_mode AND BankLockedForErs(LB_Ei, BurstBA)) THEN ----------------------------------------------------------- --read status - sector erase timeout ----------------------------------------------------------- Status(3) := '0'; DOut_zd(7 downto 0) <= Status; Dout_zd(15 downto 8) <= (OTHERS=> 'Z'); ELSE MemRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; END IF; WHEN ESPS => ESUSP <= '1';--, '0' AFTER 1 ns; CTMOUT_in <= '0'; IF (START_T1_out = '1') THEN ESP_ACT <= '1'; START_T1_in <= '0'; ELSIF oe THEN IF (NOT burst_mode AND BankLockedForErs(LB_Ei, BA)) OR (burst_mode AND BankLockedForErs(LB_Ei, BurstBA)) THEN ----------------------------------------------------------- --read status / erase suspend timeout - stil erasing ----------------------------------------------------------- Status(7) := '0'; Status(6) := NOT Status(6); --toggle Status(5) := '0'; Status(3) := '1'; IF ((NOT burst_mode AND Ers_Queue(SecAddr) = '1') OR (burst_mode AND BurstSA > -1 AND Ers_Queue(BurstSA) = '1')) THEN Status(2) := NOT Status(2); --toggle END IF; DOut_zd(7 downto 0) <= Status; Dout_zd(15 downto 8) <= (OTHERS=> 'Z'); ELSE MemRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; END IF; WHEN SERS_EXEC => IF oe THEN IF (NOT burst_mode AND BankLockedForErs(LB_Ei, BA)) OR (burst_mode AND BankLockedForErs(LB_Ei, BurstBA)) THEN ----------------------------------------------------------- --read status Erase Busy ----------------------------------------------------------- Status(7) := '0'; Status(6) := NOT Status(6); --toggle Status(5) := '0'; Status(3) := '1'; IF ((NOT burst_mode AND Ers_Queue(SecAddr) = '1') OR (burst_mode AND BurstSA > -1 AND Ers_Queue(BurstSA) = '1')) THEN Status(2) := NOT Status(2); --toggle END IF; DOut_zd(7 downto 0) <= Status; Dout_zd(15 downto 8) <= (OTHERS=> 'Z'); ELSE MemRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; END IF; IF rising_edge(EDONE) OR falling_edge(EERR) THEN ResetBankForErs(LB_Ei); ELSE IF falling_edge(EERR0) THEN ResetBankForErs(LB_Ei, 0); END IF; IF falling_edge(EERR1) THEN ResetBankForErs(LB_Ei, 1); END IF; IF falling_edge(EERR2) THEN ResetBankForErs(LB_Ei, 2); END IF; IF falling_edge(EERR3) THEN ResetBankForErs(LB_Ei, 3); END IF; END IF; IF EERR /= '1' THEN FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND Sec_Prot(i) /= '1' THEN Mem(sssa(i) TO ssea(i)) := (OTHERS => -1); END IF; END LOOP; IF EDONE = '1' THEN FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND Sec_Prot(i) /= '1' THEN Mem(sssa(i) TO ssea(i)):= (OTHERS => MaxData); END IF; END LOOP; ELSIF falling_edge(write) THEN IF (DataLo = 16#B0# AND BankLockedForErs(LB_Ei, BA) = TRUE) THEN START_T1_in <= '1'; END IF; END IF; END IF; WHEN ESP => ESUSP <= '0';-- IF falling_edge(write) THEN IF (DataLo = 16#30# AND BankLockedForErs(LB_Ei, BA) = TRUE) THEN --resume erase ERES <= '1', '0' AFTER 1 ns; ELSIF ULBYPASS = '1' THEN IF DataLo = 16#20# THEN null; ELSIF A_PAT_1 AND DataLo = 16#90# THEN LB_A <= BA; --LockB(LB_A); END IF; END IF; ELSIF oe THEN ----------------------------------------------------------- --read ----------------------------------------------------------- IF ((NOT burst_mode AND Ers_Queue(SecAddr) = '1') OR (burst_mode AND BurstSA > -1 AND Ers_Queue(BurstSA) = '1')) THEN ------------------------------------------------------- --read status ------------------------------------------------------- Status(7) := '1'; -- Status(6) No toggle Status(5) := '0'; Status(2) := NOT Status(2); --toggle DOut_zd(7 downto 0) <= Status; Dout_zd(15 downto 8) <= (OTHERS=> 'Z'); ELSE --MemRead(SecAddr, Address, BYTENeg, DOut_zd); MemRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; END IF; WHEN ESP_Z001 => null; WHEN ESP_PREL => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo = 16#20# THEN ULBYPASS <= '1'; ELSIF A_PAT_1 AND DataLo = 16#90# THEN LB_A <= BA;--LockB(); END IF; END IF; WHEN ESP_CFI => IF falling_edge(write) THEN IF Addr = 16#55# AND DataLo = 16#98# THEN null; ELSIF DataLo = 16#F0# THEN ESP_ACT <= '1'; ELSIF (DataLo = 16#30# AND BankLockedForErs(LB_Ei, BA)) THEN --resume erase ERES <= '1', '0' AFTER 1 ns; ELSE ESP_ACT <= '1'; END IF; ELSIF oe THEN CfiRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; WHEN ESP_A0SEEN => IF falling_edge(write) THEN LB_P <= BA; ESP_ACT <= '1'; PSTART <= '1', '0' AFTER 1 ns; WData := DataLo; WAddr := Address; SA <= SecAddr; temp := to_slv(DataLo, 8); Status(7) := NOT temp(7); END IF; WHEN ESP_AS => IF falling_edge(write) THEN IF DataLo = 16#F0# THEN -- resret ULBYPASS ULBYPASS <= '0'; LB_A <= -1; END IF; ELSIF oe THEN IF (NOT burst_mode AND LB_A = BA) OR (burst_mode AND Addr_cnt >= bsa(LB_A) AND Addr_cnt <= bea(LB_A)) THEN AsRead(Address,Addr_cnt, reduced_hnd, vs, SecAddr, Dout_zd); ELSIF (Ers_Queue(SecAddr) /= '1') THEN MemRead(SecAddr, Address, Addr_cnt, DOut_zd); ELSE ------------------------------------------------------- -- if addressed sector is selected for erasure --read status ------------------------------------------------------- Status(7) := '1'; -- Status(6) No toggle Status(5) := '0'; Status(2) := NOT Status(2); --toggle DOut_zd(7 downto 0) <= Status; DOut_zd(15 downto 8) <= (OTHERS => 'Z'); END IF; END IF; WHEN AS_CFI => --this is CFI state, only CFI codes are visable IF falling_edge(write) THEN IF DataLo = 16#F0# THEN null; END IF; ELSIF oe THEN CfiRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; WHEN PGMS => IF oe THEN IF (NOT burst_mode AND LB_P = BA) OR (burst_mode AND LB_P = BurstBA) THEN ------------------------------------------------------- --read status ------------------------------------------------------- Status(6) := NOT Status(6); --toggle Status(5) := '0'; --Status(2) no toggle Status(1) := '0'; DOut_zd(7 downto 0) <= Status; DOut_zd(15 downto 8) <= (OTHERS => 'Z'); ELSIF ( ESP_ACT = '1' AND ((NOT burst_mode AND Ers_Queue(SecAddr)='1') OR (burst_mode AND BurstSA > -1 AND Ers_Queue(BurstSA) = '1'))) THEN Status(7) := '1'; -- Status(6) No toggle Status(5) := '0'; Status(2) := NOT Status(2); --toggle DOut_zd(7 downto 0) <= Status; DOut_zd(15 downto 8) <= (OTHERS => 'Z'); ELSE MemRead(SecAddr, Address, Addr_cnt, DOut_zd); END IF; END IF; IF rising_edge(PDONE) OR falling_edge(PERR) THEN LB_P <= -1; END IF; IF PERR/='1' AND NOT PERR'EVENT THEN new_int:= WData; old_int:=Mem(sssa(SA) + WAddr); 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; Mem(sssa(SA) + WAddr) := -1; IF HANG /= '1' AND PDONE = '1' AND (NOT PERR'EVENT) THEN Mem(sssa(SA) + WAddr) := WData; WData:= -1; END IF; END IF; END CASE; END IF; --Output Disable Control IF (gCE_n = '1') OR (gOE_n = '1') OR (RESETNeg = '0' AND RST = '0') THEN DOut_zd <= (OTHERS=>'Z'); END IF; IF NOW = 0 ns THEN ------------------------------------------------------------------------------- -----am29bds640g memory preload file format ----------------------------------- ------------------------------------------------------------------------------- -- / - comment -- @aaaaaa - stands for address within sector -- dddd - is word to be written at Mem(aaaaaa++) -- (aaaaaa is incremented at every load) -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! ------------------------------------------------------------------------------- IF (mem_file_name /= "none" AND UserPreload ) THEN ind := 0; Mem := (OTHERS => MaxData); WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '/' THEN --comment NEXT; ELSIF buf(1) = '@' THEN --address ind := h(buf(2 to 7)); ELSE IF ind <= MemSize THEN-- MemSize = 16#3FFFFF#; Mem(ind) := h(buf(1 to 4)); END IF; IF ind < MemSize THEN ind := ind + 1; END IF; END IF; END LOOP; END IF; ------------------------------------------------------------------- --CFI array data / am29bds640g !!! DEVICE SPECIFIC ------------------------------------------------------------------- --CFI query identification string -- !!!!!! WORD ADDRESSES (x16) 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#17#; CFI_array(16#1C#) := 16#19#; 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#09#; CFI_array(16#22#) := 16#00#; CFI_array(16#23#) := 16#04#; 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#17#; 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#03#; CFI_array(16#2D#) := 16#03#; CFI_array(16#2E#) := 16#00#; CFI_array(16#2F#) := 16#40#; CFI_array(16#30#) := 16#00#; CFI_array(16#31#) := 16#7D#; CFI_array(16#32#) := 16#00#; CFI_array(16#33#) := 16#00#; CFI_array(16#34#) := 16#01#; CFI_array(16#35#) := 16#03#; CFI_array(16#36#) := 16#00#; CFI_array(16#37#) := 16#40#; CFI_array(16#38#) := 16#00#; CFI_array(16#39#) := 16#00#; CFI_array(16#3A#) := 16#00#; CFI_array(16#3B#) := 16#00#; CFI_array(16#3C#) := 16#00#; --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#33#; CFI_array(16#45#) := 16#04#; CFI_array(16#46#) := 16#02#; CFI_array(16#47#) := 16#01#; CFI_array(16#48#) := 16#00#; CFI_array(16#49#) := 16#05#; CFI_array(16#4A#) := 16#63#; CFI_array(16#4B#) := 16#01#; CFI_array(16#4C#) := 16#00#; CFI_array(16#4D#) := 16#B5#; CFI_array(16#4E#) := 16#C5#; IF TImingMOdel(12) = 't' THEN CFI_array(16#4F#) := 16#02#; ELSE CFI_array(16#4F#) := 16#03#; END IF; CFI_array(16#50#) := 16#00#; CFI_array(16#57#) := 16#04#; CFI_array(16#58#) := 16#23#; CFI_array(16#59#) := 16#20#; CFI_array(16#5A#) := 16#20#; CFI_array(16#5B#) := 16#23#; END IF; END PROCESS Functional; AddressValid: PROCESS(A) BEGIN Addr_Valid := (AVDNeg = '0'); END PROCESS AddressValid; OutputDelay: PROCESS(DOut_zd) VARIABLE tOD : time := 0 ns; VARIABLE tCD : time := 0 ns; VARIABLE tAD : time := 0 ns; BEGIN IF NOT burst_mode THEN IF DOut_zd(0) /= 'Z' THEN tpd_from_OE := FALSE; tpd_from_CE := FALSE; Open3state := TRUE; tOD := -gOE_n'LAST_EVENT + tpd_OENeg_DQ0(trz1); tCD := -gCE_n'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 Addr_Valid AND tAD >= 0 ns AND ((tAD >= tOD AND tpd_from_OE = TRUE) OR (tAD >= tCD AND tpd_from_CE = TRUE)) THEN Dout_z <= "XXXXXXXXXXXXXXXX", Dout_zd AFTER tAD; ELSE Dout_z <= Dout_zd; END IF; ELSE Open3state := FALSE; Dout_z <= Dout_zd; END IF; ELSE Dout_z <= Dout_zd; END IF; END PROCESS OutputDelay; ----------------------------------------------------------------------- -- Path Delay Section ----------------------------------------------------------------------- RDY_OUT: PROCESS(RDY_zd) VARIABLE RDY_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => RDY, OutSignalName => "RDY", OutTemp => RDY_zd, Mode => VitalTransport, GlitchData => RDY_GlitchData, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => TRUE), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => TRUE), 2 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_DQ0), PathCondition => CLK = ConfRegData(17) AND burst_mode) ) ); END PROCESS RDY_Out; D_Out_15_0_PathDelay_Gen : FOR i IN 0 TO 15 GENERATE PROCESS(DOut_z(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_z(i), GlitchData => D0_GlitchData, IgnoreDefaultDelay => TRUE, Mode => VitalTransport, RejectFastPath => false, Paths => ( --FLASH 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => (burst_mode OR (NOT open3state OR (open3state AND tpd_from_CE))) --open3state ), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => (burst_mode OR(NOT open3state OR (open3state AND tpd_from_OE))) ), 2 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => DOut_z(i) /= 'X'), 3 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_DQ0), PathCondition => CLK = ConfRegData(17) AND burst_mode) ) ); END PROCESS; END GENERATE D_Out_15_0_PathDelay_Gen; LoadConfigReg: PROCESS(ConfRegData) --reseted BEGIN IF ConfRegData(19) = '0' THEN burst_mode := TRUE; ELSE burst_mode := FALSE; END IF; END PROCESS LoadConfigReg; CLK_active_edge: PROCESS(CLK) BEGIN IF ConfRegData(17) = '1' THEN CLK_active <= CLK; ELSE CLK_active <= NOT CLK; END IF; END PROCESS CLK_active_edge; RDY_gen_proc: PROCESS(tIACC_cnt_dwn, Addr_cnt, gOE_n, gCE_n) VARIABLE active_algo : BOOLEAN := FALSE; VARIABLE i : INTEGER := 0; VARIABLE burstSA : INTEGER := -1; BEGIN IF gOE_n = '0' AND gCE_n = '0' THEN --RDY active with data IF ConfRegData(18) = '1' AND burst_mode AND gCE_n = '0' AND tIACC_cnt_dwn >0 THEN RDY_zd <= '0'; --RDY active before data ELSIF ConfRegData(18) = '0' AND burst_mode AND gCe_n = '0' THEN --17.02 BurstSA := ResolveSectFromAddr((Addr_cnt+1)MOD(MemSize+1)); ActiveAlgo(active_algo,((Addr_cnt+1)MOD(MemSize+1)), BurstSA); IF -- in next bank embedded algor. active ConfRegData(16 downto 15) = "00" AND tIACC_cnt_dwn = 0 AND (Addr_cnt MOD 16#40#) = 16#3F# AND active_algo THEN RDY_zd <= '0'; ELSIF tIACC_cnt_dwn > 1 OR --0x40 boundary crossing ((Addr_cnt MOD 16#40#) = 16#3E# AND (to_nat(Whole_Addr) MOD 16#40#) /= 16#3E# AND (to_nat(Whole_Addr) MOD 16#40#) /= 16#3F# AND ConfRegData(16 downto 15) = "00") OR ((Addr_cnt MOD 16#40#) = 16#3E# AND TimingModel(14) = '9' AND (to_nat(Whole_Addr) MOD 16#40#) = 16#3E# AND ConfRegData(16 downto 15) = "00") THEN RDY_zd <= '0'; ELSE RDY_zd <= '1'; END IF; ELSE RDY_zd <= '1'; END IF; END IF; --Output Disable Control IF (gOE_n = '1') OR (gCE_n = '1') OR (RESETNeg = '0' AND RST = '0') THEN RDY_zd <= 'Z'; END IF; END PROCESS RDY_gen_proc; tiACC_cnt_dwn_proc: PROCESS(LA, CLK_active, bound_cross, bound_cross_active) --starting burst address VARIABLE Latched_Addr : std_logic_vector(HiAddrBit downto 0); VARIABLE bound_cross_loc : BOOLEAN; VARIABLE bound_cross_loc_active : BOOLEAN; BEGIN IF burst_mode = TRUE THEN IF rising_edge(LA) THEN --load counter Latched_Addr := Whole_Addr; bound_cross_loc := FALSE; bound_cross_loc_active := FALSE; LoadtIACC(Latched_Addr, ConfRegData, bound_cross_loc, bound_cross_loc_active, tIACC_cnt_dwn); ELSIF rising_edge(bound_cross) THEN --load counter bound_cross_loc := TRUE; bound_cross_loc_active := FALSE; LoadtIACC(Latched_Addr, ConfRegData, bound_cross_loc, bound_cross_loc_active, tIACC_cnt_dwn); ELSIF rising_edge(bound_cross_active) THEN --load counter bound_cross_loc := FALSE; bound_cross_loc_active := TRUE; LoadtIACC(Latched_Addr, ConfRegData, bound_cross_loc, bound_cross_loc_active, tIACC_cnt_dwn); ELSE IF rising_edge(CLK_active) AND tIACC_cnt_dwn /= 0 THEN --count down tIACC_cnt_dwn <= tIACC_cnt_dwn - 1; END IF; END IF; END IF; END PROCESS tiACC_cnt_dwn_proc; burst_read_proc: PROCESS(LA, tIACC_cnt_dwn, read, CLK_active, gCE_n) VARIABLE Addr_cnt_l : NATURAL; VARIABLE Start_Addr : NATURAL; VARIABLE active_algo : BOOLEAN := FALSE; VARIABLE i : INTEGER := 0; VARIABLE burstSA : INTEGER := -1; BEGIN IF burst_mode = TRUE THEN IF rising_edge(LA) THEN Addr_cnt_l := to_nat(Whole_Addr); --load A(21..0) Start_Addr := to_nat(Whole_Addr); max_wrap_thr := 0; ELSE IF read = '1' AND tiACC_cnt_dwn = 0 THEN --sta ako read dodje pre tIACC_cnt _dwn /= 0?? IF rising_edge(CLK_active) AND enable_cnt = '1' THEN IncrAddr_cnt(Addr_cnt_l, Start_Addr); IF ((Addr_cnt_l mod 16#40#) = 16#3F#) THEN bound_cross <= '1', '0' AFTER 1 ns; END IF; --17.02 BurstSA := ResolveSectFromAddr((Addr_cnt+1) MOD (MemSize+1)); ActiveAlgo(active_algo, ((Addr_cnt+1)MOD(MemSize+1)), BurstSA); IF active_algo THEN bound_cross_active <= '1', '0' AFTER 1 ns; Addr_cnt <= -1; ELSE Addr_cnt <= Addr_cnt_l; END IF; ELSE Addr_cnt <= Addr_cnt_l; END IF; END IF; IF read = '0' THEN Addr_cnt <= -1; END IF; END IF; END IF; END PROCESS burst_read_proc; enable_addr_cnt: PROCESS(Addr_cnt, lb_p, LA) VARIABLE active_algo : BOOLEAN := FALSE; VARIABLE i : INTEGER := 0; VARIABLE burstSA : INTEGER := -1; BEGIN BurstSA := ResolveSectFromAddr(Addr_cnt); ActiveAlgo(active_algo,Addr_cnt, BurstSA); IF active_algo THEN enable_cnt <= '0'; END IF; IF rising_edge(LA) THEN enable_cnt <= '1'; END IF; END PROCESS enable_addr_cnt; ModelTimming: PROCESS BEGIN WAIT FOR 2880020 ms; IF tdevice_POW = 5 us THEN REPORT "Timming model: min timings"; ELSIF tdevice_POW = 11.5 us THEN REPORT "Timming model: typ timings"; ELSIF tdevice_POW = 210 us THEN REPORT "Timming model: max timings" SEV