------------------------------------------------------------------------------- -- File name : s29gl04gs.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2011 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 H. Dimitrijevic 11 March 17 Initial release -- V1.1 H. Dimitrijevic 11 April 01 Clear Status command in -- static architecture corrected -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH -- Technology: Flash Memory -- Part: S29GL04GS -- -- Description: 4 Gbit(512MByte) CMOS 3.0 Volt core with Non-volatile Flash -- Memory,65nm MirrorBit Technology, x16 data bus -- ------------------------------------------------------------------------------- -- 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 s29gl04gs IS GENERIC ( -- tipd delays: interconnect path delays tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A22 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A23 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A24 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A25 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A26 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A27 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(tCE,tCE,tDF,-,tDF,-) tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(tOE,tOE,tDF,-,tDF,-) tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --tsetup values tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / tsetup_CENeg_WENeg : VitalDelayType := UnitDelay; --tCS edge \ --thold values thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / thold_CENeg_WENeg : VitalDelayType := UnitDelay; --tCH edge / --tpw values: pulse width tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC,tRC tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH -- tdevice values: values for internal delays --Write Buffer Program Operation tWHWH1 tdevice_WBPB : VitalDelayType := 340 us; --max=750u --Effective Write Buffer Program Operation tWHWH1 tdevice_WBPBW : VitalDelayType := 1.3 us; -- per word --Program Operation tdevice_POW : VitalDelayType := 150 us;-- per word --Sector Erase Operation tWHWH2 tdevice_SEO : VitalDelayType := 900 ms; -- Blank Check tdevice_BC :VitalDelayType := 17 ms; --device ready after Hardware reset(during embeded algorithm) tdevice_READY : VitalDelayType := 30 us; --tRPH -- 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";--"s29gl04gs.mem"; UserPreload : BOOLEAN := FALSE; LongTimming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING ); PORT ( A27 : IN std_ulogic := 'U'; -- A26 : IN std_ulogic := 'U'; -- A25 : IN std_ulogic := 'U'; -- A24 : IN std_ulogic := 'U'; -- A23 : IN std_ulogic := 'U'; -- A22 : IN std_ulogic := 'U'; -- A21 : IN std_ulogic := 'U'; -- A20 : IN std_ulogic := 'U'; -- A19 : IN std_ulogic := 'U'; -- A18 : IN std_ulogic := 'U'; -- A17 : IN std_ulogic := 'U'; -- A16 : IN std_ulogic := 'U'; -- A15 : IN std_ulogic := 'U'; -- A14 : IN std_ulogic := 'U'; -- A13 : IN std_ulogic := 'U'; --address A12 : IN std_ulogic := 'U'; --lines A11 : IN std_ulogic := 'U'; -- A10 : IN std_ulogic := 'U'; -- A9 : IN std_ulogic := 'U'; -- A8 : IN std_ulogic := 'U'; -- A7 : IN std_ulogic := 'U'; -- A6 : IN std_ulogic := 'U'; -- A5 : IN std_ulogic := 'U'; -- A4 : IN std_ulogic := 'U'; -- A3 : IN std_ulogic := 'U'; -- A2 : IN std_ulogic := 'U'; -- A1 : IN std_ulogic := 'U'; -- A0 : IN std_ulogic := 'U'; -- DQ15 : INOUT std_logic := 'U'; -- DQ14 : INOUT std_logic := 'U'; -- DQ13 : INOUT std_logic := 'U'; -- DQ12 : INOUT std_logic := 'U'; -- DQ11 : INOUT std_logic := 'U'; -- DQ10 : INOUT std_logic := 'U'; -- DQ9 : INOUT std_logic := 'U'; -- data DQ8 : INOUT std_logic := 'U'; -- lines DQ7 : INOUT std_logic := 'U'; -- DQ6 : INOUT std_logic := 'U'; -- DQ5 : INOUT std_logic := 'U'; -- DQ4 : INOUT std_logic := 'U'; -- DQ3 : INOUT std_logic := 'U'; -- DQ2 : INOUT std_logic := 'U'; -- DQ1 : INOUT std_logic := 'U'; -- DQ0 : INOUT std_logic := 'U'; -- CENeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RESETNeg : IN std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of s29gl04gs : ENTITY IS TRUE; END s29gl04gs; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral_dynamic_memory_allocation of s29gl04gs IS ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral_dynamic_memory_allocation : ARCHITECTURE IS TRUE; --------------------------------------------------------------------------- -- CONSTANT AND SIGNAL DECLARATION --------------------------------------------------------------------------- --Declaration of constants - memory characteristics -- The constant declared here are used to enable the creation of models -- of memories within a family with a minimum amount of editing CONSTANT PartID : STRING := "S29GL04GS11WPS0028"; CONSTANT MaxData : NATURAL := 16#FFFF#; CONSTANT SecSize : NATURAL := 16#1FFFF#; --256KB CONSTANT SecNum : NATURAL := 2047; CONSTANT HiAddrBit : NATURAL := 27; CONSTANT AddrRANGE : NATURAL := 16#FFFFFFF#; -- interconnect path delay signals SIGNAL A27_ipd : std_ulogic := 'U'; SIGNAL A26_ipd : std_ulogic := 'U'; SIGNAL A25_ipd : std_ulogic := 'U'; SIGNAL A24_ipd : std_ulogic := 'U'; SIGNAL A23_ipd : std_ulogic := 'U'; SIGNAL A22_ipd : std_ulogic := 'U'; SIGNAL A21_ipd : std_ulogic := 'U'; SIGNAL A20_ipd : std_ulogic := 'U'; SIGNAL A19_ipd : std_ulogic := 'U'; SIGNAL A18_ipd : std_ulogic := 'U'; SIGNAL A17_ipd : std_ulogic := 'U'; SIGNAL A16_ipd : std_ulogic := 'U'; SIGNAL A15_ipd : std_ulogic := 'U'; SIGNAL A14_ipd : std_ulogic := 'U'; SIGNAL A13_ipd : std_ulogic := 'U'; SIGNAL A12_ipd : std_ulogic := 'U'; SIGNAL A11_ipd : std_ulogic := 'U'; SIGNAL A10_ipd : std_ulogic := 'U'; SIGNAL A9_ipd : std_ulogic := 'U'; SIGNAL A8_ipd : std_ulogic := 'U'; SIGNAL A7_ipd : std_ulogic := 'U'; SIGNAL A6_ipd : std_ulogic := 'U'; SIGNAL A5_ipd : std_ulogic := 'U'; SIGNAL A4_ipd : std_ulogic := 'U'; SIGNAL A3_ipd : std_ulogic := 'U'; SIGNAL A2_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL DQ15_ipd : std_ulogic := 'U'; SIGNAL DQ14_ipd : std_ulogic := 'U'; SIGNAL DQ13_ipd : std_ulogic := 'U'; SIGNAL DQ12_ipd : std_ulogic := 'U'; SIGNAL DQ11_ipd : std_ulogic := 'U'; SIGNAL DQ10_ipd : std_ulogic := 'U'; SIGNAL DQ9_ipd : std_ulogic := 'U'; SIGNAL DQ8_ipd : std_ulogic := 'U'; SIGNAL DQ7_ipd : std_ulogic := 'U'; SIGNAL DQ6_ipd : std_ulogic := 'U'; SIGNAL DQ5_ipd : std_ulogic := 'U'; SIGNAL DQ4_ipd : std_ulogic := 'U'; SIGNAL DQ3_ipd : std_ulogic := 'U'; SIGNAL DQ2_ipd : std_ulogic := 'U'; SIGNAL DQ1_ipd : std_ulogic := 'U'; SIGNAL DQ0_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL RESETNeg_ipd : std_ulogic := 'U'; --- internal delays -------------------------------------------------------- SIGNAL WBPO_in : std_ulogic := '0'; SIGNAL WBPO_out : std_ulogic := '0'; SIGNAL WBPOW_in : std_ulogic := '0'; SIGNAL WBPOW_out : std_ulogic := '0'; SIGNAL PO_in : std_ulogic := '0'; SIGNAL PO_out : std_ulogic := '0'; SIGNAL SEO_in : std_ulogic := '0'; SIGNAL SEO_out : std_ulogic := '0'; SIGNAL BC_in : std_ulogic := '0'; SIGNAL BC_out : std_ulogic := '0'; SIGNAL READY_in : std_ulogic := '0'; SIGNAL sREADY : std_ulogic := '0'; -- Device ready after reset SIGNAL READY_int : std_ulogic := '0'; SIGNAL sREADYt : std_ulogic := '0'; -- Device ready after reset ----------------------------------------------------------- BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays WBPBW :VitalBuf(WBPOW_out,WBPOW_in, (tdevice_WBPBW ,UnitDelay)); WBPB :VitalBuf(WBPO_out,WBPO_in, (tdevice_WBPB ,UnitDelay)); POW :VitalBuf(PO_out, PO_in, (tdevice_POW ,UnitDelay)); SEO :VitalBuf(SEO_out, SEO_in, (tdevice_SEO ,UnitDelay)); BC :VitalBUF(BC_out, BC_in, (tdevice_BC ,UnitDelay)); READY :VitalBuf(sREADYt, READY_int, (tdevice_READY ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (A27_ipd, A27, tipd_A27); w_2 : VitalWireDelay (A26_ipd, A26, tipd_A26); w_3 : VitalWireDelay (A25_ipd, A25, tipd_A25); w_4 : VitalWireDelay (A24_ipd, A24, tipd_A24); w_5 : VitalWireDelay (A23_ipd, A23, tipd_A23); w_6 : VitalWireDelay (A22_ipd, A22, tipd_A22); w_7 : VitalWireDelay (A21_ipd, A21, tipd_A21); w_8 : VitalWireDelay (A20_ipd, A20, tipd_A20); w_9 : VitalWireDelay (A19_ipd, A19, tipd_A19); w_10 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_11 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_12 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_13 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_14 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_15 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_16 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_17 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_18 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_19 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_20 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_21 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_22 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_23 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_24 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_25 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_26 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_27 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_28 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_29 : VitalWireDelay (DQ15_ipd, DQ15, tipd_DQ15); w_30 : VitalWireDelay (DQ14_ipd, DQ14, tipd_DQ14); w_31 : VitalWireDelay (DQ13_ipd, DQ13, tipd_DQ13); w_32 : VitalWireDelay (DQ12_ipd, DQ12, tipd_DQ12); w_33 : VitalWireDelay (DQ11_ipd, DQ11, tipd_DQ11); w_34 : VitalWireDelay (DQ10_ipd, DQ10, tipd_DQ10); w_35 : VitalWireDelay (DQ9_ipd, DQ9, tipd_DQ9); w_36 : VitalWireDelay (DQ8_ipd, DQ8, tipd_DQ8); w_37 : VitalWireDelay (DQ7_ipd, DQ7, tipd_DQ7); w_38 : VitalWireDelay (DQ6_ipd, DQ6, tipd_DQ6); w_39 : VitalWireDelay (DQ5_ipd, DQ5, tipd_DQ5); w_40 : VitalWireDelay (DQ4_ipd, DQ4, tipd_DQ4); w_41 : VitalWireDelay (DQ3_ipd, DQ3, tipd_DQ3); w_42 : VitalWireDelay (DQ2_ipd, DQ2, tipd_DQ2); w_43 : VitalWireDelay (DQ1_ipd, DQ1, tipd_DQ1); w_44 : VitalWireDelay (DQ0_ipd, DQ0, tipd_DQ0); w_45 : VitalWireDelay (OENeg_ipd, OENeg, tipd_OENeg); w_46 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_47 : VitalWireDelay (RESETNeg_ipd, RESETNeg, tipd_RESETNeg); w_48 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); 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' ); PORT MAP ( A(27) => A27_ipd, A(26) => A26_ipd, A(25) => A25_ipd, A(24) => A24_ipd, A(23) => A23_ipd, A(22) => A22_ipd, A(21) => A21_ipd, A(20) => A20_ipd, A(19) => A19_ipd, A(18) => A18_ipd, A(17) => A17_ipd, A(16) => A16_ipd, A(15) => A15_ipd, A(14) => A14_ipd, A(13) => A13_ipd, A(12) => A12_ipd, A(11) => A11_ipd, A(10) => A10_ipd, A(9) => A9_ipd, A(8) => A8_ipd, A(7) => A7_ipd, A(6) => A6_ipd, A(5) => A5_ipd, A(4) => A4_ipd, A(3) => A3_ipd, A(2) => A2_ipd, A(1) => A1_ipd, A(0) => A0_ipd, DIn(15) => DQ15_ipd, DIn(14) => DQ14_ipd, DIn(13) => DQ13_ipd, DIn(12) => DQ12_ipd, DIn(11) => DQ11_ipd, DIn(10) => DQ10_ipd, DIn(9) => DQ9_ipd, DIn(8) => DQ8_ipd, DIn(7) => DQ7_ipd, DIn(6) => DQ6_ipd, DIn(5) => DQ5_ipd, DIn(4) => DQ4_ipd, DIn(3) => DQ3_ipd, DIn(2) => DQ2_ipd, DIn(1) => DQ1_ipd, DIn(0) => DQ0_ipd, DOut(15) => DQ15, DOut(14) => DQ14, DOut(13) => DQ13, DOut(12) => DQ12, DOut(11) => DQ11, DOut(10) => DQ10, DOut(9) => DQ9, DOut(8) => DQ8, DOut(7) => DQ7, DOut(6) => DQ6, DOut(5) => DQ5, DOut(4) => DQ4, DOut(3) => DQ3, DOut(2) => DQ2, DOut(1) => DQ1, DOut(0) => DQ0, CENeg => CENeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, RESETNeg => RESETNeg_ipd ); -- State Machine : State_Type TYPE state_type IS ( RESET, READUL1, --2nd bus write cycle READUL2, --3rd bus write cycle READSR, BLCK, BLCKSR, CUL1, ER, -- erase ERUL1, --2nd bus write cycle for erase ERUL2, --3rd bus write cycle SER, --sector erase ERSR, PG, PGSR, WBPGMS_WBCNT, WBPGMS_WBLSTA, WBPGMS_WBLOAD, WBPGMS_CONFB, AS, --Autoselect ECC_ENTRY ); -- 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 DOut_Pass : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); --FSM control signals SIGNAL CHECK_ACT : std_logic := '0'; SIGNAL STAT_ACT : std_logic := '0'; SIGNAL PDONE : std_logic := '1'; --Prog. Done SIGNAL PSTART : std_logic := '0'; --Start Programming SIGNAL LCNT : NATURAL RANGE 0 TO 255:= 0; --Load Counter --number of location to be writen in Write Buffer: 0-255 word. --if 256 word programming SIGNAL PCNT : NATURAL RANGE 0 TO 256:= 0; SIGNAL EDONE : std_logic := '1'; --Ers. Done SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL BCSTART : std_logic := '0'; --Blank Check Start SIGNAL BCDONE : std_logic := '1'; --Blank Check Done --flags for corrupted sectors SIGNAL corrupt_flags : 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; SIGNAL WBPage : NATURAL; --Address within sector SIGNAL Address : NATURAL RANGE 0 TO SecSize := 0; SIGNAL D_tmp : NATURAL RANGE 0 TO MaxData; SIGNAL D_tmp1 : NATURAL RANGE 0 TO 16#FFF#; --A24:A11 Don't Care SIGNAL Addr : NATURAL RANGE 0 TO 16#FFF# := 0; SIGNAL Addr1 : NATURAL RANGE 0 TO 16#FFFFFFF# := 0; SIGNAL WPage : NATURAL RANGE 0 TO 16#FFF# := 0; SIGNAL RPage : NATURAL RANGE 0 TO 16#2000# := 0; SIGNAL RPChange : boolean := true; --glitch protection SIGNAL gWE_n : std_logic := 'U'; SIGNAL gCE_n : std_logic := 'U'; SIGNAL gOE_n : std_logic := 'U'; SIGNAL RST : std_logic := '1'; SIGNAL reseted : std_logic := '0'; -- timing check violation SIGNAL Viol : X01 := '0'; -- Access time variables SHARED VARIABLE OPENLATCH : BOOLEAN; SHARED VARIABLE FROMCE : BOOLEAN; SHARED VARIABLE FROMOE : BOOLEAN; -- --------------------------------------------------------------------- -- Memory data initial value. -- Default value may be overridden by conigure_memory procedure -- --------------------------------------------------------------------- SHARED VARIABLE max_data : NATURAL := 16#FFFF#; -- --------------------------------------------------------------------- -- Data types required to implement link list structure -- --------------------------------------------------------------------- TYPE mem_data_t; TYPE mem_data_pointer_t IS ACCESS mem_data_t; TYPE mem_data_t IS RECORD key_address : INTEGER; val_data : INTEGER; successor : mem_data_pointer_t; END RECORD; -- --------------------------------------------------------------------- -- Array of linked lists. -- Support memory region partitioning for faster access. -- --------------------------------------------------------------------- TYPE mem_data_pointer_array_t IS ARRAY(NATURAL RANGE <>) OF mem_data_pointer_t; -- --------------------------------------------------------------------- -- Override mechanism provided for default parameter values -- --------------------------------------------------------------------- PROCEDURE configure_memory( max_data_c : IN INTEGER) IS BEGIN max_data := max_data_c; END PROCEDURE configure_memory; -- --------------------------------------------------------------------- -- Create linked listed -- --------------------------------------------------------------------- PROCEDURE create_list( key_address : IN INTEGER; val_data : IN INTEGER; root : INOUT mem_data_pointer_t) IS BEGIN root := NEW mem_data_t; root.successor := NULL; root.key_address := key_address; root.val_data := val_data; END PROCEDURE create_list; -- -------------------------------------------------------------------- -- Iterate through linked listed comapring key values -- Stop when key value greater or equal -- -------------------------------------------------------------------- PROCEDURE position_list( key_address : IN INTEGER; root : INOUT mem_data_pointer_t; found : INOUT mem_data_pointer_t; prev : INOUT mem_data_pointer_t) IS BEGIN found := root; prev := NULL; WHILE ((found /= NULL) AND (found.key_address < key_address)) LOOP prev := found; found := found.successor; END LOOP; END PROCEDURE position_list; -- ------------------------------------------------------------------- -- Add new element to a linked list -- ------------------------------------------------------------------- PROCEDURE insert_list( key_address : IN INTEGER; val_data : IN INTEGER; root : INOUT mem_data_pointer_t) IS VARIABLE new_element : mem_data_pointer_t; VARIABLE found : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; BEGIN position_list(key_address, root, found, prev); -- Insert at list tail IF (found = NULL) THEN prev.successor := NEW mem_data_t; prev.successor.key_address := key_address; prev.successor.val_data := val_data; prev.successor.successor := NULL; ELSE -- Element exists, update memory data value IF (found.key_address = key_address) THEN found.val_data := val_data; ELSE -- No element found, allocate and link new_element := NEW mem_data_t; new_element.key_address := key_address; new_element.val_data := val_data; new_element.successor := found; -- Possible root position IF (prev /= NULL) THEN prev.successor := new_element; ELSE root := new_element; END IF; END IF; END IF; END PROCEDURE insert_list; -- -------------------------------------------------------------------- -- Remove element from a linked list -- -------------------------------------------------------------------- PROCEDURE remove_list( key_address : IN INTEGER; root : INOUT mem_data_pointer_t) IS VARIABLE found : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; BEGIN position_list(key_address, root, found, prev); IF (found /= NULL) THEN -- Key value match IF (found.key_address = key_address) THEN -- Handle root position removal IF (prev /= NULL) THEN prev.successor := found.successor; ELSE root := found.successor; END IF; DEALLOCATE(found); END IF; END IF; END PROCEDURE remove_list; -- ------------------------------------------------------------------- -- Remove range of elements from a linked list -- Higher performance than one-by-one removal -- ------------------------------------------------------------------- PROCEDURE remove_list_range( address_low : IN INTEGER; address_high : IN INTEGER; root : INOUT mem_data_pointer_t) IS VARIABLE iter : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; VARIABLE link_element : mem_data_pointer_t; BEGIN iter := root; prev := NULL; -- Find first linked list element belonging to -- a specified address range [address_low, address_high] WHILE ((iter /= NULL) AND NOT ( (iter.key_address >= address_low) AND (iter.key_address <= address_high))) LOOP prev := iter; iter := iter.successor; END LOOP; -- Continue until address_high reached -- Deallocate linked list elements pointed by iterator IF (iter /= NULL) THEN WHILE ((iter /= NULL) AND (iter.key_address >= address_low) AND (iter.key_address <= address_high)) LOOP link_element := iter.successor; DEALLOCATE(iter); iter := link_element; END LOOP; -- Handle possible root value change IF prev /= NULL THEN prev.successor := link_element; ELSE root := link_element; END IF; END IF; END PROCEDURE remove_list_range; -- --------------------------------------------------------------------- -- Address range to be erased -- --------------------------------------------------------------------- PROCEDURE erase_mem( address_low : IN INTEGER; address_high : IN INTEGER; linked_list : INOUT mem_data_pointer_t) IS BEGIN remove_list_range( address_low, address_high, linked_list ); END PROCEDURE erase_mem; -- -------------------------------------------------------------------- -- Memory READ operation performed above dynamically allocated space -- -------------------------------------------------------------------- PROCEDURE read_mem( linked_list : INOUT mem_data_pointer_t; data : INOUT INTEGER; address : IN INTEGER) IS VARIABLE found : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; VARIABLE mem_data : INTEGER; BEGIN IF (linked_list = NULL) THEN -- Not allocated, not written, initial value mem_data := max_data ; ELSE position_list(address, linked_list, found, prev); IF (found /= NULL) THEN IF found.key_address = address THEN -- Allocated, val_data stored mem_data := found.val_data; ELSE -- Not allocated, not written, initial value mem_data := max_data ; END IF; ELSE -- Not allocated, not written, initial value mem_data := max_data ; END IF; END IF; data := mem_data; END PROCEDURE read_mem; -- ------------------------------------------------------------------ -- Memory WRITE operation performed above dynamically allocated space -- ------------------------------------------------------------------ PROCEDURE write_mem( linked_list : INOUT mem_data_pointer_t; address : IN INTEGER; data : IN INTEGER) IS BEGIN IF (data /= max_data ) THEN -- Handle possible root value update IF (linked_list /= NULL) THEN insert_list(address, data, linked_list); ELSE create_list(address, data, linked_list); END IF; ELSE -- Deallocate if initial value written -- No linked list, NOP, initial value implicit IF (linked_list /= NULL) THEN remove_list(address, linked_list); END IF; END IF; END PROCEDURE write_mem; ------------------------------------------------------------------- -- Handle dynamic memory allocation ------------------------------------------------------------------- -- Partition dynamically allocated space for performance CONSTANT list_num : INTEGER := 2047; CONSTANT list_size : INTEGER := 16#20000#; -- Access dynamically allocated space SHARED VARIABLE linked_list : mem_data_pointer_array_t(0 TO list_num); SHARED VARIABLE list_id_v : NATURAL; -- Asure proper initialization PROCEDURE initialize IS VARIABLE I : INTEGER; BEGIN FOR I IN 0 TO list_num LOOP linked_list(I) := NULL; END LOOP; END PROCEDURE initialize; FUNCTION READMEM(Data : INTEGER RANGE -1 TO MaxData+1; Flags : STD_LOGIC_VECTOR(SecNum downto 0); Sec : NATURAL RANGE 0 TO SecNum) RETURN STD_LOGIC_VECTOR IS VARIABLE ReadData : STD_LOGIC_VECTOR(15 downto 0); BEGIN IF Data = -1 THEN ReadData := (OTHERS=>'X'); ELSE IF Flags(Sec) = '1' THEN ReadData := (OTHERS=>'X'); ELSE ReadData := to_slv(Data,16); END IF; END IF; RETURN ReadData; END READMEM; BEGIN --------------------------------------------------------------------------- --Power Up time 300 us; --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 300 us; RST <= RESETNeg AFTER 200 ns; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A, Din, CENeg, OENeg, WENeg, RESETNeg) -- Timing Check Variables --Setup/Hold Check Variables VARIABLE Tviol_A0_CENeg_F : X01 := '0'; VARIABLE TD_A0_CENeg_F : VitalTimingDataType; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_F : X01 := '0'; VARIABLE TD_CENeg_WENeg_F : VitalTimingDataType; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_WENeg_RESETNeg : X01 := '0'; VARIABLE TD_WENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg : X01 := '0'; VARIABLE TD_OENeg_WENeg : VitalTimingDataType; VARIABLE Tviol_WENeg_OENeg : X01 := '0'; VARIABLE TD_WENeg_OENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_R : X01 := '0'; VARIABLE TD_CENeg_WENeg_R : VitalTimingDataType; --Pulse Width and Period Check Variables VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_A0 : X01 := '0'; VARIABLE PD_A0 : VitalPeriodDataType := VitalPeriodDataInit; --Functionality Results Variables --(used to OR all individual violations) VARIABLE Violation : X01 := '0'; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between A and CENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_A0_CENeg, SetupLow => tsetup_A0_CENeg, HoldHigh => thold_A0_CENeg, HoldLow => thold_A0_CENeg, CheckEnabled => WENeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CENeg_F, Violation => Tviol_A0_CENeg_F ); -- Setup/Hold Check between A and WENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_A0_CENeg, SetupLow => tsetup_A0_CENeg, HoldHigh => thold_A0_CENeg, HoldLow => thold_A0_CENeg, CheckEnabled => CENeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); -- Setup/Hold Check between DQ and CENeg VitalSetupHoldCheck ( TestSignal => DQ0, TestSignalName => "DQ", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_DQ0_CENeg, SetupLow => tsetup_DQ0_CENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => DIn(15 downto 0)/=DOut_zd(15 downto 0), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CENeg, Violation => Tviol_DQ0_CENeg ); -- Setup/Hold Check between DQ and WENeg VitalSetupHoldCheck ( TestSignal => DQ0, TestSignalName => "DQ", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_DQ0_CENeg, SetupLow => tsetup_DQ0_CENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => DIn(15 downto 0)/=DOut_zd(15 downto 0), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_WENeg, Violation => Tviol_DQ0_WENeg ); -- Setup Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_F, Violation => Tviol_CENeg_WENeg_F ); -- Hold Check between CENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => RESETNeg, RefSignalName => "RESET#", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RESETNeg, Violation => Tviol_CENeg_RESETNeg ); -- Hold Check between WENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => RESETNeg, RefSignalName => "RESET#", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_RESETNeg, Violation => Tviol_WENeg_RESETNeg ); -- Hold Check between OENeg and WENeg VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_OENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg, Violation => Tviol_OENeg_WENeg ); -- Hold Check between WENeg and OENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => OENeg, RefSignalName => "OE#", HoldHigh => thold_WENeg_OENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_OENeg, Violation => Tviol_WENeg_OENeg ); -- Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_R, Violation => Tviol_CENeg_WENeg_R ); -- PulseWidth Check for RESETNeg VitalPeriodPulseCheck ( TestSignal => RESETNeg, TestSignalName => "RESET#", PulseWidthLow => tpw_RESETNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RESETNeg, Violation => Pviol_RESETNeg ); -- PulseWidth Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WE#", PulseWidthHigh => tpw_WENeg_posedge, PulseWidthLow => tpw_WENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); -- PulseWidth Check for A VitalPeriodPulseCheck ( TestSignal => A(0), TestSignalName => "A", PulseWidthHigh => tpw_A0_negedge, PulseWidthLow => tpw_A0_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_A0, Violation => Pviol_A0 ); Violation := Tviol_A0_CENeg_F OR Tviol_A0_WENeg OR Tviol_DQ0_CENeg OR Tviol_DQ0_WENeg OR Tviol_CENeg_WENeg_F OR Tviol_CENeg_RESETNeg OR Tviol_WENeg_RESETNeg OR Tviol_OENeg_WENeg OR Tviol_WENeg_OENeg OR Tviol_CENeg_WENeg_R OR Pviol_RESETNeg OR Pviol_WENeg OR Pviol_A0 ; 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, sREADY, 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 sREADY = '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 sREADY = '0') OR (R = '1' AND RESETNeg = '1' AND RST = '0' AND sREADY = '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, 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; --------------------------------------------------------------------------- --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 (gWE_n'EVENT AND (gWE_n /= WENeg)) OR (gCE_n'EVENT AND (gCE_n /= CENeg)) OR (gOE_n'EVENT AND (gOE_n /= OENeg)) THEN ASSERT false REPORT "Glitch detected on write 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, reseted, read) VARIABLE A_tmp : NATURAL RANGE 0 TO 16#FFF#; VARIABLE SA_tmp : NATURAL RANGE 0 TO SecNum; VARIABLE A_tmp1 : NATURAL RANGE 0 TO SecSize; VARIABLE A_tmp2 : NATURAL RANGE 0 TO 16#FFFFFFF#; VARIABLE CE : std_logic; BEGIN IF reseted = '1' THEN IF (falling_edge(WENeg) AND CENeg ='0' AND OENeg = '1') OR (falling_edge(CENeg) AND WENeg/= OENeg ) OR (falling_edge(OENeg) AND WENeg ='1' AND CENeg = '0') OR (A'EVENT AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN A_tmp := to_nat(A(11 downto 0)); SA_tmp := to_nat(A(HiAddrBit downto 17)); A_tmp1 := to_nat(A(16 downto 0)); A_tmp2 := to_nat(A(HiAddrBit downto 0)); ELSIF (rising_edge(WENeg) OR rising_edge(CENeg)) AND write = '1' THEN D_tmp <= to_nat(Din(15 downto 0)); D_tmp1 <= to_nat(Din(7 downto 0)); END IF; IF rising_edge(write) OR rising_edge(read) OR falling_edge(OENeg) OR (A'EVENT AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN SecAddr <= SA_tmp; Address <= A_tmp1; WPage <= A_tmp1 / 256; IF (RPage /= (A_tmp1 / 16)) OR (CENeg /= CE) THEN RPchange <= true; ELSE RPchange <= false; END IF; RPage <= A_tmp1 / 16; CE := CENeg; Addr <= A_tmp; Addr1 <= A_tmp2; END IF; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Program/ Write Buffer Program Operations -- start/ suspend/ resume --------------------------------------------------------------------------- ProgTime : PROCESS(PSTART, reseted) VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE pow : time; VARIABLE wbpb : time; BEGIN IF LongTimming THEN pow := tdevice_POW; wbpb := tdevice_WBPBW;--per word ELSE pow := tdevice_POW; wbpb := tdevice_WBPBW; --per word END IF; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programing immediately terminated ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE = '1' THEN IF PCNT < 256 THEN --buffer cnt := PCNT + 1; duration := cnt * wbpb; END IF; elapsed := 0 ns; PDONE <= '0', '1' AFTER duration; start := NOW; END IF; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Blank Check --------------------------------------------------------------------------- BCTime :PROCESS(BCSTART, reseted) VARIABLE bco : time; BEGIN IF LongTimming THEN bco := tdevice_BC; ELSE bco := tdevice_BC / 1000; END IF; IF reseted = '1' THEN IF rising_edge(BCSTART) AND BCDONE = '1' THEN BCDONE <= '0', '1' AFTER bco; END IF; END IF; END PROCESS; --------------------------------------------------------------------------- -- Timing control for the Erase Operations --------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, reseted) VARIABLE duration : time; VARIABLE seo : time; BEGIN IF LongTimming THEN seo := tdevice_SEO; ELSE seo := tdevice_SEO / 10; END IF; IF rising_edge(reseted) THEN EDONE <= '1'; -- reset done, ERASE immediately terminated ELSIF reseted = '1' THEN IF rising_edge(ESTART) AND EDONE = '1' THEN duration := seo; EDONE <= '0', '1' AFTER duration; END IF; END IF; END PROCESS; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(write, STAT_ACT, Addr, D_tmp1, PDONE, EDONE, BCDONE, reseted, sREADY, RST ) VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; VARIABLE Continuity_Check_1: boolean := FALSE; VARIABLE Continuity_Check_2: boolean := FALSE; --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO 16#FFF# := 0; --DATA WORD VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(write) THEN DataLo := D_tmp1; Data := D_tmp; PATTERN_1 := (Addr=16#555#) AND (DataLo = 16#AA#) ; PATTERN_2 := (Addr=16#2AA#) AND (DataLo = 16#55#) ; A_PAT_1 := (Addr=16#555#); Continuity_Check_1 := (Addr1=16#5555555#) AND (Data=16#5555#); Continuity_Check_2 := (Addr1=16#AAAAAAA#) AND (Data=16#AAAA#); 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) AND (NOT Continuity_Check_1)) THEN next_state <= READUL1; ELSIF (A_PAT_1 AND (DataLo=16#70#)) THEN next_state <= READSR; ELSIF (A_PAT_1 AND (DataLo=16#33#)) THEN next_state <= BLCK; ELSIF (Continuity_Check_1) THEN next_state <= CUL1; ELSE next_state <= RESET; END IF; END IF; WHEN READUL1 => IF falling_edge(write) THEN IF (PATTERN_2) THEN next_state <= READUL2; ELSIF DataLo = 16#F0# THEN next_state <= RESET; ELSE next_state <= RESET; END IF; END IF; WHEN READUL2 => IF falling_edge(write) THEN IF (DataLo=16#25#) THEN next_state <= WBPGMS_WBCNT; ELSIF (A_PAT_1 AND (DataLo=16#80#)) THEN next_state <= ER; ELSIF (A_PAT_1 AND (DataLo=16#90#)) THEN next_state <= AS; ELSIF (A_PAT_1 AND (DataLo=16#75#)) THEN next_state <= ECC_ENTRY; ELSIF DataLo = 16#F0# THEN next_state <= RESET; ELSE next_state <= RESET; END IF; END IF; WHEN READSR => IF (STAT_ACT = '0') THEN next_state <= RESET; ELSE next_state <= READSR; END IF; WHEN BLCK => IF (falling_edge(write) AND (A_PAT_1 AND (DataLo=16#70#))) THEN next_state <= BLCKSR; ELSIF rising_edge(BCDONE) THEN next_state <= RESET; END IF; WHEN BLCKSR => IF (STAT_ACT = '0') THEN IF (BCDONE= '0') THEN next_state <= BLCK; ELSE next_state <= RESET; END IF; ELSE next_state <= BLCKSR; END IF; WHEN CUL1 => IF falling_edge(write) THEN IF (Continuity_Check_2) THEN next_state <= RESET; ELSIF DataLo = 16#F0# THEN next_state <= RESET; ELSE next_state <= RESET; END IF; END IF; WHEN AS => IF falling_edge(write) THEN IF (DataLo=16#F0#) THEN next_state <= RESET; ELSE next_state <= AS; END IF; END IF; WHEN ER => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= ERUL1; ELSE next_state <= RESET; END IF; END IF; WHEN ERUL1 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= ERUL2; ELSE next_state <= RESET; END IF; END IF; WHEN ERUL2 => IF falling_edge(write) THEN IF DataLo=16#30# THEN next_state <= SER; ELSE next_state <= RESET; END IF; END IF; WHEN SER => IF (falling_edge(write) AND (A_PAT_1 AND (DataLo=16#70#))) THEN next_state <= ERSR; ELSIF rising_edge(EDONE) THEN next_state <= RESET; END IF; WHEN ERSR => IF (STAT_ACT = '0') THEN IF (EDONE= '0') THEN next_state <= SER; ELSE next_state <= RESET; END IF; ELSE next_state <= ERSR; END IF; WHEN WBPGMS_WBCNT => IF falling_edge(write) THEN IF (SecAddr = SA) AND Data < 256 THEN next_state <= WBPGMS_WBLSTA; ELSE next_state <= RESET; END IF; END IF; WHEN WBPGMS_WBLSTA => IF falling_edge(write) THEN IF (SecAddr = SA) THEN -- fix WriteBufferPage WBPage IF (LCNT > 0) THEN next_state <= WBPGMS_WBLOAD; ELSE next_state <= WBPGMS_CONFB; END IF; ELSE next_state <= RESET; END IF; END IF; WHEN WBPGMS_WBLOAD => IF falling_edge(write) THEN IF (WPage = WBPage) THEN IF (LCNT > 0) THEN next_state <= WBPGMS_WBLOAD; ELSE next_state <= WBPGMS_CONFB; END IF; ELSE next_state <= RESET; END IF; END IF; WHEN WBPGMS_CONFB => IF falling_edge(write) THEN IF (SecAddr = SA) AND (DataLo = 16#29#) THEN next_state <= PG; --WBPGMS ELSE next_state <= RESET; END IF; END IF; WHEN PG => IF (falling_edge(write) AND (A_PAT_1 AND (DataLo=16#70#))) THEN next_state <= PGSR; ELSIF rising_edge(PDONE) THEN next_state <= RESET; END IF; WHEN PGSR => IF (STAT_ACT = '0') THEN IF (PDONE= '0') THEN next_state <= PG; ELSE next_state <= RESET; END IF; ELSE next_state <= PGSR; END IF; WHEN ECC_ENTRY => IF (falling_edge(write) AND (DataLo = 16#F0#)) THEN next_state <= RESET; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general functionality --------------------------------------------------------------------------- Functional : PROCESS(write, read, Addr, Addr1, D_tmp, D_tmp1, Address, SecAddr,EDONE, RST, reseted, BCDONE, PDONE, sREADY, gOE_n, current_state) --Flash Memory Array TYPE SecType IS ARRAY (0 TO SecSize) OF INTEGER RANGE -1 TO MaxData; --WriteBuffer TYPE WBDataType IS ARRAY ( 0 TO 256) OF INTEGER RANGE -1 TO MaxData; TYPE WBAddrType IS ARRAY ( 0 TO 256) OF INTEGER RANGE -1 TO 256; -- ECC ASO VARIABLE ECC_array : std_logic_vector(16#FFFFFF# downto 0) :=(OTHERS => '0'); -- ECC Write Buffer temporary VARIABLE ECC_WB_array: std_logic_vector(16#FFFFFF# downto 0) :=(OTHERS => '0'); VARIABLE WBData : WBDataType:= (OTHERS => 0); VARIABLE WBAddr : WBAddrType:= (OTHERS => -1); VARIABLE BaseLoc : NATURAL RANGE 0 TO SecSize := 0; VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; VARIABLE Continuity_Check_1: boolean := FALSE; VARIABLE Continuity_Check_2: boolean := FALSE; VARIABLE oe : boolean := FALSE; --Status reg. VARIABLE StatusReg : std_logic_vector(15 downto 0) := "0000000010000000"; -- text file input variables FILE mem_file : text is mem_file_name; VARIABLE S_ind : NATURAL RANGE 0 TO SecNum := 0; VARIABLE ind : NATURAL := 0; VARIABLE index : NATURAL RANGE 0 TO SecSize:=0; VARIABLE buf : line; 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 256; --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO 16#FF# := 0; --DATA WORD VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE mem_data : INTEGER; VARIABLE PR_FLAG : BOOLEAN := FALSE; VARIABLE ER_FLAG : BOOLEAN := FALSE; VARIABLE temp : std_logic_vector(15 downto 0); VARIABLE ECCPage : NATURAL; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(write) THEN DataLo := D_tmp1; Data := D_tmp; PATTERN_1 := (Addr=16#555#) AND (DataLo=16#AA#) ; PATTERN_2 := (Addr=16#2AA#) AND (DataLo=16#55#) ; A_PAT_1 := (Addr=16#555#); Continuity_Check_1 := (Addr1=16#5555555#) AND (Data=16#5555#) ; Continuity_Check_2 := (Addr1=16#AAAAAAA#) AND (Data=16#AAAA#) ; END IF; oe := rising_edge(read) OR (read = '1' AND Address'EVENT); IF falling_edge(RST) AND RESETNeg = '0' THEN STAT_ACT <= '0'; StatusReg(7) := '1'; StatusReg(6 DOWNTO 0) := (OTHERS => '0'); END IF; IF reseted = '1' THEN CASE current_state IS WHEN RESET => StatusReg(7) := '1'; IF falling_edge(write) THEN IF (A_PAT_1 AND (DataLo=16#70#)) AND STAT_ACT = '0' THEN STAT_ACT <= '1'; ELSIF (A_PAT_1 AND (DataLo=16#71#)) THEN StatusReg(5 DOWNTO 4) := "00"; StatusReg(0) := '0'; STAT_ACT <= '0'; ELSIF (A_PAT_1 AND (DataLo = 16#33#)) THEN BCSTART <= '1', '0' AFTER 1 ns; StatusReg (7) := '0'; StatusReg (5) := '0'; SA <= SecAddr; STAT_ACT <= '0'; ELSIF Continuity_Check_1 THEN CHECK_ACT <= '1'; END IF; END IF; IF oe THEN read_mem( linked_list(SecAddr), mem_data, SecAddr * (SecSize+1) + Address); DOut_zd(15 downto 0) <= READMEM(mem_data,corrupt_flags,SecAddr); END IF; WHEN READUL1 => null; WHEN READUL2 => IF falling_edge(write) THEN IF (DataLo=16#25#) THEN --fix Sector Address SA SA <= SecAddr; END IF; END IF; WHEN READSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; WHEN BLCK => IF falling_edge(write) AND ((A_PAT_1) AND (DataLo = 16#70#) AND (STAT_ACT = '0')) THEN STAT_ACT <= '1'; END IF; IF oe THEN DOut_zd(15 downto 0) <= (OTHERS => 'X'); END IF; IF rising_edge(BCDONE) THEN StatusReg(7) := '1'; StatusReg(5) := '0'; FOR j IN 0 TO SecSize LOOP read_mem( linked_list(SA), mem_data, SA * (SecSize+1) + j); IF mem_data /= MaxData THEN StatusReg (5) := '1'; END IF; END LOOP; STAT_ACT <= '0'; END IF; WHEN BLCKSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; WHEN CUL1 => IF falling_edge(write) THEN IF Continuity_Check_2 AND CHECK_ACT = '1' THEN StatusReg(0) := '1'; CHECK_ACT <= '0'; END IF; END IF; WHEN AS => IF oe THEN --ID READ IF Addr=16#00# THEN DOut_zd(15 downto 0) <= to_slv(16#0001#,16); ELSIF Addr=16#01# THEN DOut_zd(15 downto 0) <= to_slv(16#227E#,16); ELSIF Addr=16#02# THEN DOut_zd(15 downto 0) <= to_slv(0,16); ELSIF Addr=16#03# THEN DOut_zd(15 downto 0) <= to_slv(16#FFFF#,16); ELSIF Addr>=16#04# and Addr<=16#0B# THEN DOut_zd(15 downto 0) <= to_slv(16#FFFF#,16); ELSIF Addr=16#0C# THEN DOut_zd(15 downto 4) <= to_slv(0,12); DOut_zd(3 downto 2 ) <= to_slv(0,2);--Classic cmd set DOut_zd(1) <= '0';--DQ bit polling not supported DOut_zd(0) <= '1';--Status register supported ELSIF Addr = 16#0D# THEN DOut_zd(15 downto 0) <= to_slv(0,16); ELSIF Addr = 16#0E# THEN DOut_zd(15 downto 0) <= to_slv(16#225E#,16); ELSIF Addr = 16#0F# THEN DOut_zd(15 downto 0) <= to_slv(16#2201#,16); ELSIF Addr>=16#0010# and Addr<=16#1FFF# THEN DOut_zd(15 downto 0) <= to_slv(16#FFFF#,16); END IF; END IF; WHEN ER => NULL; WHEN ERUL1 => NULL; WHEN ERUL2 => IF falling_edge(write) THEN ESTART <= '1', '0' AFTER 1 ns; StatusReg(7 downto 0) := "00000000"; SA <= SecAddr; ER_FLAG := FALSE; END IF; WHEN SER => IF falling_edge(write) AND ((A_PAT_1) AND (DataLo = 16#70#) AND (STAT_ACT = '0')) THEN STAT_ACT <= '1'; END IF; IF NOT ER_FLAG THEN ER_FLAG:= TRUE; erase_mem( SA * (SecSize + 1), SA * (SecSize + 1) + SecSize, linked_list(SA)); corrupt_flags(SA) <= '1'; END IF; IF EDONE = '1' THEN ER_FLAG:= FALSE; erase_mem( SA * (SecSize + 1), SA * (SecSize + 1) + SecSize, linked_list(SA)); corrupt_flags(SA) <= '0'; FOR j IN 0 TO SecSize LOOP ECCPage := (SA * (SecSize+1) + j)/16#10#; ECC_array(ECCPage) := '0'; ECC_WB_array(ECCPage) := '0'; END LOOP; StatusReg(7) := '1'; END IF; WHEN ERSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; IF EDONE = '1' THEN ER_FLAG:= FALSE; erase_mem( SA * (SecSize + 1), SA * (SecSize + 1) + SecSize, linked_list(SA)); corrupt_flags(SA) <= '0'; FOR j IN 0 TO SecSize LOOP ECCPage := (SA * (SecSize+1) + j)/16#10#; ECC_array(ECCPage) := '0'; ECC_WB_array(ECCPage) := '0'; END LOOP; StatusReg(7) := '1'; END IF; WHEN WBPGMS_WBCNT => IF falling_edge(write) THEN IF (SecAddr = SA) AND Data < 256 THEN cnt := Data; PCNT <= cnt; LCNT <= cnt; ELSE StatusReg(4) := '1'; END IF; END IF; WHEN WBPGMS_WBLSTA => IF falling_edge(write) THEN IF (SecAddr = SA) THEN -- fix WriteBufferPage WBPage WBData(cnt) := -1; IF Viol = '0' THEN WBData(cnt) := Data; END IF; WBAddr(cnt) := Address MOD 256; IF cnt > 0 THEN cnt := cnt -1; END IF; WBPage <= WPage; END IF; LCNT <= cnt; END IF; WHEN WBPGMS_WBLOAD => IF falling_edge(write) THEN IF (WPage = WBPage)THEN WBData(cnt) := -1; IF Viol = '0' THEN WBData(cnt) := Data; END IF; WBAddr(cnt) := Address MOD 256; IF cnt > 0 THEN cnt := cnt - 1; END IF; ELSE StatusReg(4) := '1'; END IF; LCNT <= cnt; END IF; WHEN WBPGMS_CONFB => IF falling_edge(write) THEN IF (SecAddr = SA) AND (DataLo = 16#29#) THEN PSTART <= '1', '0' AFTER 1 ns; StatusReg(7) := '0'; PR_FLAG := FALSE; ELSE StatusReg(4) := '1'; END IF; END IF; WHEN PG => IF falling_edge(write) AND ((A_PAT_1) AND (DataLo = 16#70#) AND (STAT_ACT = '0')) THEN STAT_ACT <= '1'; END IF; IF NOT PR_FLAG THEN PR_FLAG:=TRUE; BaseLoc := WBPage * 256; wr_cnt := PCNT; FOR i IN wr_cnt downto 0 LOOP new_int := WBData(i); IF WBAddr(i) < 0 THEN old_int := -1; ELSE --mem write read_mem( linked_list(SA), mem_data, SA * (SecSize+1) + BaseLoc+WBAddr(i)); IF corrupt_flags(SA) = '1' THEN old_int := -1; ELSE old_int := mem_data; END IF; END IF; IF new_int > -1 THEN new_bit := to_slv(new_int,16); IF (old_int>-1) THEN old_bit := to_slv(old_int,16); FOR j IN 0 TO 15 LOOP IF old_bit(j) = '0' THEN new_bit(j) := '0'; END IF; END LOOP; ELSE new_bit(0) := 'X'; END IF; IF new_bit(0)/='X' THEN new_int := to_nat(new_bit); WBData(i) := new_int; ELSE WBData(i) := -1; END IF; ELSE WBData(i) := -1; END IF; END LOOP; FOR i IN wr_cnt downto 0 LOOP write_mem( linked_list(SA), SA * (SecSize+1) + BaseLoc+WBAddr(i), -1); END LOOP; END IF; IF PDONE = '1' THEN PR_FLAG :=FALSE; FOR i IN wr_cnt downto 0 LOOP IF WBAddr(i) > -1 AND WBdata(i) > -1 THEN --mem write write_mem( linked_list(SA), SA*(SecSize+1) + BaseLoc+WBAddr(i), WBData(i)); ECCPage := (SA * (SecSize+1) + (BaseLoc + WBAddr(i)))/16#10#; IF ECC_WB_array(ECCPage) = '1' THEN ECC_array(ECCPage) := '1'; END IF; ECC_WB_array(ECCPage) := '1'; END IF; WBData(i) := -1; END LOOP; END IF; IF rising_edge(PDONE) THEN StatusReg(7) := '1'; END IF; WHEN PGSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; IF PDONE = '1' THEN PR_FLAG :=FALSE; FOR i IN wr_cnt downto 0 LOOP IF WBAddr(i) > -1 AND WBdata(i) > -1 THEN --mem write write_mem( linked_list(SA), SA*(SecSize+1) + BaseLoc+WBAddr(i), WBData(i)); ECCPage := (SA * (SecSize+1) + (BaseLoc + WBAddr(i)))/16#10#; IF ECC_WB_array(ECCPage) = '1' THEN ECC_array(ECCPage) := '1'; END IF; ECC_WB_array(ECCPage) := '1'; END IF; WBData(i) := -1; END LOOP; END IF; IF rising_edge(PDONE) THEN StatusReg(7) := '1'; END IF; WHEN ECC_ENTRY => IF oe THEN ECCPage := (SecAddr * (SecSize+1) + Address)/16#10#; DOut_zd(15 downto 0) <= (OTHERS => '0'); DOut_zd(0) <= ECC_array(ECCPage); END IF; END CASE; END IF; --Output Disable Control IF (gOE_n = '1') OR (RESETNeg = '0'AND RST = '0') THEN DOut_zd <= (OTHERS => 'Z'); END IF; --Preload Control ------------------------------------------------------------------------------- -- File Read Section ------------------------------------------------------------------------------- IF NOW = 0 ns THEN configure_memory(16#FFFF#); initialize; corrupt_flags <= ( OTHERS => '0'); ------------------------------------------------------------------------------- -----s29gl04gs memory preload file format ----------------------------------- ------------------------------------------------------------------------------- -- / - comment -- @aaaaaaa - stands for address within sector -- dd -
is byte to be written at Mem(*)(aaaaaaa++) -- (aaaaaaa is incremented at every load) -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! ------------------------------------------------------------------------------- IF (mem_file_name /= "none" ) THEN ind := 0; S_ind := 0; -- load sector 0 WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 to 8)); --address ELSE IF ind=0 THEN S_ind := 0; index := 0; write_mem( linked_list(S_ind), S_ind * (SecSize+1) + index, h(buf(1 to 4))); ind := ind + 1; ELSIF ind < SecSize+1 THEN S_ind := 0; index := ind; write_mem( linked_list(S_ind), S_ind * (SecSize+1) + index, h(buf(1 to 4))); ind := ind + 1; ELSIF ind <= AddrRANGE THEN S_ind := NATURAL(ind / (SecSize +1)); index := ind - S_ind*(SecSize+1); write_mem( linked_list(S_ind), S_ind * (SecSize+1) + index, h(buf(1 to 4))); ind := ind + 1; ELSE REPORT " Memory address out of range" SEVERITY warning; END IF; END IF; END LOOP; END IF; END IF; END PROCESS Functional; ------------------------------------------------------------------------------- -----***timing processes*** ------------------------------------------------------------------------------- READY_time : PROCESS (READY_in) BEGIN IF rising_edge ( READY_in ) THEN IF LongTimming = TRUE THEN sREADY <= '0', '1' AFTER (tdevice_READY - 1 ns); ELSE sREADY <= '0', '1' AFTER (tdevice_READY - 1 ns)/10; END IF; ELSE sREADY <= '0'; END IF; END PROCESS READY_time; ------------------------------------------------------------------------------- --- ------------------------------------------------------------------------------- DOutPassThrough : PROCESS(DOut_zd) VARIABLE ValidData : std_logic_vector(15 downto 0); VARIABLE CEDQ_t : TIME; VARIABLE OEDQ_t : TIME; VARIABLE ADDRDQ_t : TIME; BEGIN IF DOut_zd(0) /= 'Z' THEN OPENLATCH := TRUE; CEDQ_t := -CENeg'LAST_EVENT + tpd_CENeg_DQ0(trz0); OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_DQ0(trz0); ADDRDQ_t := -A'LAST_EVENT + tpd_A0_DQ0(tr01);-- FROMOE := (OEDQ_t >= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t > OEDQ_t) AND (CEDQ_t > 0 ns); ValidData := "XXXXXXXXXXXXXXXX"; IF ((ADDRDQ_t > 0 ns) AND (((ADDRDQ_t > CEDQ_t) AND FROMCE) OR ((ADDRDQ_t > OEDQ_t) AND FROMOE))) THEN DOut_Pass <= ValidData, DOut_zd AFTER ADDRDQ_t; ELSE DOut_Pass <= DOut_zd; END IF; ELSE OPENLATCH := FALSE; DOut_Pass <= DOut_zd; END IF; END PROCESS DOutPassThrough; ----------------------------------------------------------------------- -- Path Delay Section ----------------------------------------------------------------------- -- Path Delay Section for DOut signal D_Out_PathDelay_Gen : FOR i IN DOut_Pass'RANGE GENERATE PROCESS(DOut_Pass(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_Pass(i), GlitchData => D0_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMCE)), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMOE)), 2 => (InputChangeTime => RESETNeg'LAST_EVENT, PathDelay => tpd_RESETNeg_DQ0, PathCondition => RESETNeg='0'), 3 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => DOut_pass(i) /= 'X' AND RPchange), 4 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ1), PathCondition => DOut_pass(i)/= 'X' AND (NOT RPchange)) ) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral_dynamic_memory_allocation; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral_static_memory_allocation of s29gl04gs IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral_static_memory_allocation : ARCHITECTURE IS TRUE; --------------------------------------------------------------------------- -- CONSTANT AND SIGNAL DECLARATION --------------------------------------------------------------------------- --Declaration of constants - memory characteristics -- The constant declared here are used to enable the creation of models -- of memories within a family with a minimum amount of editing CONSTANT PartID : STRING := "S29GL04GS11WPS0028"; CONSTANT MaxData : NATURAL := 16#FFFF#; CONSTANT SecSize : NATURAL := 16#1FFFF#; --256KB CONSTANT SecNum : NATURAL := 2047; CONSTANT HiAddrBit : NATURAL := 27; CONSTANT AddrRANGE : NATURAL := 16#FFFFFFF#; -- interconnect path delay signals SIGNAL A27_ipd : std_ulogic := 'U'; SIGNAL A26_ipd : std_ulogic := 'U'; SIGNAL A25_ipd : std_ulogic := 'U'; SIGNAL A24_ipd : std_ulogic := 'U'; SIGNAL A23_ipd : std_ulogic := 'U'; SIGNAL A22_ipd : std_ulogic := 'U'; SIGNAL A21_ipd : std_ulogic := 'U'; SIGNAL A20_ipd : std_ulogic := 'U'; SIGNAL A19_ipd : std_ulogic := 'U'; SIGNAL A18_ipd : std_ulogic := 'U'; SIGNAL A17_ipd : std_ulogic := 'U'; SIGNAL A16_ipd : std_ulogic := 'U'; SIGNAL A15_ipd : std_ulogic := 'U'; SIGNAL A14_ipd : std_ulogic := 'U'; SIGNAL A13_ipd : std_ulogic := 'U'; SIGNAL A12_ipd : std_ulogic := 'U'; SIGNAL A11_ipd : std_ulogic := 'U'; SIGNAL A10_ipd : std_ulogic := 'U'; SIGNAL A9_ipd : std_ulogic := 'U'; SIGNAL A8_ipd : std_ulogic := 'U'; SIGNAL A7_ipd : std_ulogic := 'U'; SIGNAL A6_ipd : std_ulogic := 'U'; SIGNAL A5_ipd : std_ulogic := 'U'; SIGNAL A4_ipd : std_ulogic := 'U'; SIGNAL A3_ipd : std_ulogic := 'U'; SIGNAL A2_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL DQ15_ipd : std_ulogic := 'U'; SIGNAL DQ14_ipd : std_ulogic := 'U'; SIGNAL DQ13_ipd : std_ulogic := 'U'; SIGNAL DQ12_ipd : std_ulogic := 'U'; SIGNAL DQ11_ipd : std_ulogic := 'U'; SIGNAL DQ10_ipd : std_ulogic := 'U'; SIGNAL DQ9_ipd : std_ulogic := 'U'; SIGNAL DQ8_ipd : std_ulogic := 'U'; SIGNAL DQ7_ipd : std_ulogic := 'U'; SIGNAL DQ6_ipd : std_ulogic := 'U'; SIGNAL DQ5_ipd : std_ulogic := 'U'; SIGNAL DQ4_ipd : std_ulogic := 'U'; SIGNAL DQ3_ipd : std_ulogic := 'U'; SIGNAL DQ2_ipd : std_ulogic := 'U'; SIGNAL DQ1_ipd : std_ulogic := 'U'; SIGNAL DQ0_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL RESETNeg_ipd : std_ulogic := 'U'; --- internal delays -------------------------------------------------------- SIGNAL WBPO_in : std_ulogic := '0'; SIGNAL WBPO_out : std_ulogic := '0'; SIGNAL WBPOW_in : std_ulogic := '0'; SIGNAL WBPOW_out : std_ulogic := '0'; SIGNAL PO_in : std_ulogic := '0'; SIGNAL PO_out : std_ulogic := '0'; SIGNAL SEO_in : std_ulogic := '0'; SIGNAL SEO_out : std_ulogic := '0'; SIGNAL BC_in : std_ulogic := '0'; SIGNAL BC_out : std_ulogic := '0'; SIGNAL READY_in : std_ulogic := '0'; SIGNAL sREADY : std_ulogic := '0'; -- Device ready after reset SIGNAL READY_int : std_ulogic := '0'; SIGNAL sREADYt : std_ulogic := '0'; -- Device ready after reset ----------------------------------------------------------- BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays WBPBW :VitalBuf(WBPOW_out,WBPOW_in, (tdevice_WBPBW ,UnitDelay)); WBPB :VitalBuf(WBPO_out,WBPO_in, (tdevice_WBPB ,UnitDelay)); POW :VitalBuf(PO_out, PO_in, (tdevice_POW ,UnitDelay)); SEO :VitalBuf(SEO_out, SEO_in, (tdevice_SEO ,UnitDelay)); BC :VitalBUF(BC_out, BC_in, (tdevice_BC ,UnitDelay)); READY :VitalBuf(sREADYt, READY_int, (tdevice_READY ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (A27_ipd, A27, tipd_A27); w_2 : VitalWireDelay (A26_ipd, A26, tipd_A26); w_3 : VitalWireDelay (A25_ipd, A25, tipd_A25); w_4 : VitalWireDelay (A24_ipd, A24, tipd_A24); w_5 : VitalWireDelay (A23_ipd, A23, tipd_A23); w_6 : VitalWireDelay (A22_ipd, A22, tipd_A22); w_7 : VitalWireDelay (A21_ipd, A21, tipd_A21); w_8 : VitalWireDelay (A20_ipd, A20, tipd_A20); w_9 : VitalWireDelay (A19_ipd, A19, tipd_A19); w_10 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_11 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_12 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_13 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_14 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_15 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_16 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_17 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_18 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_19 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_20 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_21 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_22 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_23 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_24 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_25 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_26 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_27 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_28 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_29 : VitalWireDelay (DQ15_ipd, DQ15, tipd_DQ15); w_30 : VitalWireDelay (DQ14_ipd, DQ14, tipd_DQ14); w_31 : VitalWireDelay (DQ13_ipd, DQ13, tipd_DQ13); w_32 : VitalWireDelay (DQ12_ipd, DQ12, tipd_DQ12); w_33 : VitalWireDelay (DQ11_ipd, DQ11, tipd_DQ11); w_34 : VitalWireDelay (DQ10_ipd, DQ10, tipd_DQ10); w_35 : VitalWireDelay (DQ9_ipd, DQ9, tipd_DQ9); w_36 : VitalWireDelay (DQ8_ipd, DQ8, tipd_DQ8); w_37 : VitalWireDelay (DQ7_ipd, DQ7, tipd_DQ7); w_38 : VitalWireDelay (DQ6_ipd, DQ6, tipd_DQ6); w_39 : VitalWireDelay (DQ5_ipd, DQ5, tipd_DQ5); w_40 : VitalWireDelay (DQ4_ipd, DQ4, tipd_DQ4); w_41 : VitalWireDelay (DQ3_ipd, DQ3, tipd_DQ3); w_42 : VitalWireDelay (DQ2_ipd, DQ2, tipd_DQ2); w_43 : VitalWireDelay (DQ1_ipd, DQ1, tipd_DQ1); w_44 : VitalWireDelay (DQ0_ipd, DQ0, tipd_DQ0); w_45 : VitalWireDelay (OENeg_ipd, OENeg, tipd_OENeg); w_46 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_47 : VitalWireDelay (RESETNeg_ipd, RESETNeg, tipd_RESETNeg); w_48 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); 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' ); PORT MAP ( A(27) => A27_ipd, A(26) => A26_ipd, A(25) => A25_ipd, A(24) => A24_ipd, A(23) => A23_ipd, A(22) => A22_ipd, A(21) => A21_ipd, A(20) => A20_ipd, A(19) => A19_ipd, A(18) => A18_ipd, A(17) => A17_ipd, A(16) => A16_ipd, A(15) => A15_ipd, A(14) => A14_ipd, A(13) => A13_ipd, A(12) => A12_ipd, A(11) => A11_ipd, A(10) => A10_ipd, A(9) => A9_ipd, A(8) => A8_ipd, A(7) => A7_ipd, A(6) => A6_ipd, A(5) => A5_ipd, A(4) => A4_ipd, A(3) => A3_ipd, A(2) => A2_ipd, A(1) => A1_ipd, A(0) => A0_ipd, DIn(15) => DQ15_ipd, DIn(14) => DQ14_ipd, DIn(13) => DQ13_ipd, DIn(12) => DQ12_ipd, DIn(11) => DQ11_ipd, DIn(10) => DQ10_ipd, DIn(9) => DQ9_ipd, DIn(8) => DQ8_ipd, DIn(7) => DQ7_ipd, DIn(6) => DQ6_ipd, DIn(5) => DQ5_ipd, DIn(4) => DQ4_ipd, DIn(3) => DQ3_ipd, DIn(2) => DQ2_ipd, DIn(1) => DQ1_ipd, DIn(0) => DQ0_ipd, DOut(15) => DQ15, DOut(14) => DQ14, DOut(13) => DQ13, DOut(12) => DQ12, DOut(11) => DQ11, DOut(10) => DQ10, DOut(9) => DQ9, DOut(8) => DQ8, DOut(7) => DQ7, DOut(6) => DQ6, DOut(5) => DQ5, DOut(4) => DQ4, DOut(3) => DQ3, DOut(2) => DQ2, DOut(1) => DQ1, DOut(0) => DQ0, CENeg => CENeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, RESETNeg => RESETNeg_ipd ); -- State Machine : State_Type TYPE state_type IS ( RESET, READUL1, --2nd bus write cycle READUL2, --3rd bus write cycle READSR, BLCK, BLCKSR, CUL1, ER, -- erase ERUL1, --2nd bus write cycle for erase ERUL2, --3rd bus write cycle SER, --sector erase ERSR, PG, PGSR, WBPGMS_WBCNT, WBPGMS_WBLSTA, WBPGMS_WBLOAD, WBPGMS_CONFB, AS, --Autoselect ECC_ENTRY ); -- 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 DOut_Pass : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); --FSM control signals SIGNAL CHECK_ACT : std_logic := '0'; SIGNAL STAT_ACT : std_logic := '0'; SIGNAL PDONE : std_logic := '1'; --Prog. Done SIGNAL PSTART : std_logic := '0'; --Start Programming SIGNAL LCNT : NATURAL RANGE 0 TO 255:= 0; --Load Counter --number of location to be writen in Write Buffer: 0-255 word. --if 256 word programming SIGNAL PCNT : NATURAL RANGE 0 TO 256:= 0; SIGNAL EDONE : std_logic := '1'; --Ers. Done SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL BCSTART : std_logic := '0'; --Blank Check Start SIGNAL BCDONE : std_logic := '1'; --Blank Check Done --flags for corrupted sectors SIGNAL corrupt_flags : 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; SIGNAL WBPage : NATURAL; --Address within sector SIGNAL Address : NATURAL RANGE 0 TO SecSize := 0; SIGNAL D_tmp : NATURAL RANGE 0 TO MaxData; SIGNAL D_tmp1 : NATURAL RANGE 0 TO 16#FFF#; --A24:A11 Don't Care SIGNAL Addr : NATURAL RANGE 0 TO 16#FFF# := 0; SIGNAL Addr1 : NATURAL RANGE 0 TO 16#FFFFFFF# := 0; SIGNAL WPage : NATURAL RANGE 0 TO 16#FFF# := 0; SIGNAL RPage : NATURAL RANGE 0 TO 16#2000# := 0; SIGNAL RPChange : boolean := true; --glitch protection SIGNAL gWE_n : std_logic := 'U'; SIGNAL gCE_n : std_logic := 'U'; SIGNAL gOE_n : std_logic := 'U'; SIGNAL RST : std_logic := '1'; SIGNAL reseted : std_logic := '0'; -- timing check violation SIGNAL Viol : X01 := '0'; -- Access time variables SHARED VARIABLE OPENLATCH : BOOLEAN; SHARED VARIABLE FROMCE : BOOLEAN; SHARED VARIABLE FROMOE : BOOLEAN; FUNCTION READMEM(Data : INTEGER RANGE -1 TO MaxData) RETURN STD_LOGIC_VECTOR IS VARIABLE ReadData : STD_LOGIC_VECTOR(15 downto 0); BEGIN IF Data = -1 THEN ReadData := (OTHERS=>'X'); ELSE ReadData := to_slv(Data,16); END IF; RETURN ReadData; END READMEM; BEGIN --------------------------------------------------------------------------- --Power Up time 300 us; --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 300 us; RST <= RESETNeg AFTER 200 ns; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A, Din, CENeg, OENeg, WENeg, RESETNeg) -- Timing Check Variables --Setup/Hold Check Variables VARIABLE Tviol_A0_CENeg_F : X01 := '0'; VARIABLE TD_A0_CENeg_F : VitalTimingDataType; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_F : X01 := '0'; VARIABLE TD_CENeg_WENeg_F : VitalTimingDataType; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_WENeg_RESETNeg : X01 := '0'; VARIABLE TD_WENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg : X01 := '0'; VARIABLE TD_OENeg_WENeg : VitalTimingDataType; VARIABLE Tviol_WENeg_OENeg : X01 := '0'; VARIABLE TD_WENeg_OENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_R : X01 := '0'; VARIABLE TD_CENeg_WENeg_R : VitalTimingDataType; --Pulse Width and Period Check Variables VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_A0 : X01 := '0'; VARIABLE PD_A0 : VitalPeriodDataType := VitalPeriodDataInit; --Functionality Results Variables --(used to OR all individual violations) VARIABLE Violation : X01 := '0'; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between A and CENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_A0_CENeg, SetupLow => tsetup_A0_CENeg, HoldHigh => thold_A0_CENeg, HoldLow => thold_A0_CENeg, CheckEnabled => WENeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CENeg_F, Violation => Tviol_A0_CENeg_F ); -- Setup/Hold Check between A and WENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_A0_CENeg, SetupLow => tsetup_A0_CENeg, HoldHigh => thold_A0_CENeg, HoldLow => thold_A0_CENeg, CheckEnabled => CENeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); -- Setup/Hold Check between DQ and CENeg VitalSetupHoldCheck ( TestSignal => DQ0, TestSignalName => "DQ", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_DQ0_CENeg, SetupLow => tsetup_DQ0_CENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => DIn(15 downto 0)/=DOut_zd(15 downto 0), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CENeg, Violation => Tviol_DQ0_CENeg ); -- Setup/Hold Check between DQ and WENeg VitalSetupHoldCheck ( TestSignal => DQ0, TestSignalName => "DQ", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_DQ0_CENeg, SetupLow => tsetup_DQ0_CENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => DIn(15 downto 0)/=DOut_zd(15 downto 0), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_WENeg, Violation => Tviol_DQ0_WENeg ); -- Setup Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_F, Violation => Tviol_CENeg_WENeg_F ); -- Hold Check between CENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => RESETNeg, RefSignalName => "RESET#", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RESETNeg, Violation => Tviol_CENeg_RESETNeg ); -- Hold Check between WENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => RESETNeg, RefSignalName => "RESET#", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_RESETNeg, Violation => Tviol_WENeg_RESETNeg ); -- Hold Check between OENeg and WENeg VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_OENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg, Violation => Tviol_OENeg_WENeg ); -- Hold Check between WENeg and OENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => OENeg, RefSignalName => "OE#", HoldHigh => thold_WENeg_OENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_OENeg, Violation => Tviol_WENeg_OENeg ); -- Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_R, Violation => Tviol_CENeg_WENeg_R ); -- PulseWidth Check for RESETNeg VitalPeriodPulseCheck ( TestSignal => RESETNeg, TestSignalName => "RESET#", PulseWidthLow => tpw_RESETNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RESETNeg, Violation => Pviol_RESETNeg ); -- PulseWidth Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WE#", PulseWidthHigh => tpw_WENeg_posedge, PulseWidthLow => tpw_WENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); -- PulseWidth Check for A VitalPeriodPulseCheck ( TestSignal => A(0), TestSignalName => "A", PulseWidthHigh => tpw_A0_negedge, PulseWidthLow => tpw_A0_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_A0, Violation => Pviol_A0 ); Violation := Tviol_A0_CENeg_F OR Tviol_A0_WENeg OR Tviol_DQ0_CENeg OR Tviol_DQ0_WENeg OR Tviol_CENeg_WENeg_F OR Tviol_CENeg_RESETNeg OR Tviol_WENeg_RESETNeg OR Tviol_OENeg_WENeg OR Tviol_WENeg_OENeg OR Tviol_CENeg_WENeg_R OR Pviol_RESETNeg OR Pviol_WENeg OR Pviol_A0 ; 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, sREADY, 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 sREADY = '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 sREADY = '0') OR (R = '1' AND RESETNeg = '1' AND RST = '0' AND sREADY = '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, 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; --------------------------------------------------------------------------- --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 (gWE_n'EVENT AND (gWE_n /= WENeg)) OR (gCE_n'EVENT AND (gCE_n /= CENeg)) OR (gOE_n'EVENT AND (gOE_n /= OENeg)) THEN ASSERT false REPORT "Glitch detected on write 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, reseted, read) VARIABLE A_tmp : NATURAL RANGE 0 TO 16#FFF#; VARIABLE SA_tmp : NATURAL RANGE 0 TO SecNum; VARIABLE A_tmp1 : NATURAL RANGE 0 TO SecSize; VARIABLE A_tmp2 : NATURAL RANGE 0 TO 16#FFFFFFF#; VARIABLE CE : std_logic; BEGIN IF reseted = '1' THEN IF (falling_edge(WENeg) AND CENeg ='0' AND OENeg = '1') OR (falling_edge(CENeg) AND WENeg/= OENeg ) OR (falling_edge(OENeg) AND WENeg ='1' AND CENeg = '0') OR (A'EVENT AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN A_tmp := to_nat(A(11 downto 0)); SA_tmp := to_nat(A(HiAddrBit downto 17)); A_tmp1 := to_nat(A(16 downto 0)); A_tmp2 := to_nat(A(HiAddrBit downto 0)); ELSIF (rising_edge(WENeg) OR rising_edge(CENeg)) AND write = '1' THEN D_tmp <= to_nat(Din(15 downto 0)); D_tmp1 <= to_nat(Din(7 downto 0)); END IF; IF rising_edge(write) OR rising_edge(read) OR falling_edge(OENeg) OR (A'EVENT AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN SecAddr <= SA_tmp; Address <= A_tmp1; WPage <= A_tmp1 / 256; IF (RPage /= (A_tmp1 / 16)) OR (CENeg /= CE) THEN RPchange <= true; ELSE RPchange <= false; END IF; RPage <= A_tmp1 / 16; CE := CENeg; Addr <= A_tmp; Addr1 <= A_tmp2; END IF; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Program/ Write Buffer Program Operations -- start/ suspend/ resume --------------------------------------------------------------------------- ProgTime : PROCESS(PSTART, reseted) VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE pow : time; VARIABLE wbpb : time; BEGIN IF LongTimming THEN pow := tdevice_POW; wbpb := tdevice_WBPBW;--per word ELSE pow := tdevice_POW; wbpb := tdevice_WBPBW; --per word END IF; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programing immediately terminated ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE = '1' THEN IF PCNT < 256 THEN --buffer cnt := PCNT + 1; duration := cnt * wbpb; END IF; elapsed := 0 ns; PDONE <= '0', '1' AFTER duration; start := NOW; END IF; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Blank Check --------------------------------------------------------------------------- BCTime :PROCESS(BCSTART, reseted) VARIABLE bco : time; BEGIN IF LongTimming THEN bco := tdevice_BC; ELSE bco := tdevice_BC / 1000; END IF; IF reseted = '1' THEN IF rising_edge(BCSTART) AND BCDONE = '1' THEN BCDONE <= '0', '1' AFTER bco; END IF; END IF; END PROCESS; --------------------------------------------------------------------------- -- Timing control for the Erase Operations --------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, reseted) VARIABLE duration : time; VARIABLE seo : time; BEGIN IF LongTimming THEN seo := tdevice_SEO; ELSE seo := tdevice_SEO / 10; END IF; IF rising_edge(reseted) THEN EDONE <= '1'; -- reset done, ERASE immediately terminated ELSIF reseted = '1' THEN IF rising_edge(ESTART) AND EDONE = '1' THEN duration := seo; EDONE <= '0', '1' AFTER duration; END IF; END IF; END PROCESS; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(write,STAT_ACT, Addr, D_tmp1, PDONE, EDONE, BCDONE, reseted, sREADY, RST ) VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; VARIABLE Continuity_Check_1: boolean := FALSE; VARIABLE Continuity_Check_2: boolean := FALSE; --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO 16#FFF# := 0; --DATA WORD VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(write) THEN DataLo := D_tmp1; Data := D_tmp; PATTERN_1 := (Addr=16#555#) AND (DataLo = 16#AA#) ; PATTERN_2 := (Addr=16#2AA#) AND (DataLo = 16#55#) ; A_PAT_1 := (Addr=16#555#); Continuity_Check_1 := (Addr1=16#5555555#) AND (Data=16#5555#); Continuity_Check_2 := (Addr1=16#AAAAAAA#) AND (Data=16#AAAA#); 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) AND (NOT Continuity_Check_1)) THEN next_state <= READUL1; ELSIF (A_PAT_1 AND (DataLo=16#70#)) THEN next_state <= READSR; ELSIF (A_PAT_1 AND (DataLo=16#33#)) THEN next_state <= BLCK; ELSIF (Continuity_Check_1) THEN next_state <= CUL1; ELSE next_state <= RESET; END IF; END IF; WHEN READUL1 => IF falling_edge(write) THEN IF (PATTERN_2) THEN next_state <= READUL2; ELSIF DataLo = 16#F0# THEN next_state <= RESET; ELSE next_state <= RESET; END IF; END IF; WHEN READUL2 => IF falling_edge(write) THEN IF (DataLo=16#25#) THEN next_state <= WBPGMS_WBCNT; ELSIF (A_PAT_1 AND (DataLo=16#80#)) THEN next_state <= ER; ELSIF (A_PAT_1 AND (DataLo=16#90#)) THEN next_state <= AS; ELSIF (A_PAT_1 AND (DataLo=16#75#)) THEN next_state <= ECC_ENTRY; ELSIF DataLo = 16#F0# THEN next_state <= RESET; ELSE next_state <= RESET; END IF; END IF; WHEN READSR => IF (STAT_ACT = '0') THEN next_state <= RESET; ELSE next_state <= READSR; END IF; WHEN BLCK => IF (falling_edge(write) AND (A_PAT_1 AND (DataLo=16#70#))) THEN next_state <= BLCKSR; ELSIF rising_edge(BCDONE) THEN next_state <= RESET; END IF; WHEN BLCKSR => IF (STAT_ACT = '0') THEN IF (BCDONE= '0') THEN next_state <= BLCK; ELSE next_state <= RESET; END IF; ELSE next_state <= BLCKSR; END IF; WHEN CUL1 => IF falling_edge(write) THEN IF (Continuity_Check_2) THEN next_state <= RESET; ELSIF DataLo = 16#F0# THEN next_state <= RESET; ELSE next_state <= RESET; END IF; END IF; WHEN AS => IF falling_edge(write) THEN IF (DataLo=16#F0#) THEN next_state <= RESET; ELSE next_state <= AS; END IF; END IF; WHEN ER => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= ERUL1; ELSE next_state <= RESET; END IF; END IF; WHEN ERUL1 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= ERUL2; ELSE next_state <= RESET; END IF; END IF; WHEN ERUL2 => IF falling_edge(write) THEN IF DataLo=16#30# THEN next_state <= SER; ELSE next_state <= RESET; END IF; END IF; WHEN SER => IF (falling_edge(write) AND (A_PAT_1 AND (DataLo=16#70#))) THEN next_state <= ERSR; ELSIF rising_edge(EDONE) THEN next_state <= RESET; END IF; WHEN ERSR => IF (STAT_ACT = '0') THEN IF (EDONE= '0') THEN next_state <= SER; ELSE next_state <= RESET; END IF; ELSE next_state <= ERSR; END IF; WHEN WBPGMS_WBCNT => IF falling_edge(write) THEN IF (SecAddr = SA) AND Data < 256 THEN next_state <= WBPGMS_WBLSTA; ELSE next_state <= RESET; END IF; END IF; WHEN WBPGMS_WBLSTA => IF falling_edge(write) THEN IF (SecAddr = SA) THEN -- fix WriteBufferPage WBPage IF (LCNT > 0) THEN next_state <= WBPGMS_WBLOAD; ELSE next_state <= WBPGMS_CONFB; END IF; ELSE next_state <= RESET; END IF; END IF; WHEN WBPGMS_WBLOAD => IF falling_edge(write) THEN IF (WPage = WBPage) THEN IF (LCNT > 0) THEN next_state <= WBPGMS_WBLOAD; ELSE next_state <= WBPGMS_CONFB; END IF; ELSE next_state <= RESET; END IF; END IF; WHEN WBPGMS_CONFB => IF falling_edge(write) THEN IF (SecAddr = SA) AND (DataLo = 16#29#) THEN next_state <= PG; --WBPGMS ELSE next_state <= RESET; END IF; END IF; WHEN PG => IF (falling_edge(write) AND (A_PAT_1 AND (DataLo=16#70#))) THEN next_state <= PGSR; ELSIF rising_edge(PDONE) THEN next_state <= RESET; END IF; WHEN PGSR => IF (STAT_ACT = '0') THEN IF (PDONE= '0') THEN next_state <= PG; ELSE next_state <= RESET; END IF; ELSE next_state <= PGSR; END IF; WHEN ECC_ENTRY => IF (falling_edge(write) AND (DataLo = 16#F0#)) THEN next_state <= RESET; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general functionality --------------------------------------------------------------------------- Functional : PROCESS(write, read, Addr, Addr1, D_tmp, D_tmp1, Address, SecAddr,EDONE, RST, reseted, BCDONE, PDONE, sREADY, gOE_n, current_state) --Flash Memory Array TYPE SecType IS ARRAY (0 TO SecSize) OF INTEGER RANGE -1 TO MaxData; TYPE MemArray IS ARRAY (0 TO SecNum) OF SecType; --WriteBuffer TYPE WBDataType IS ARRAY ( 0 TO 256) OF INTEGER RANGE -1 TO MaxData; TYPE WBAddrType IS ARRAY ( 0 TO 256) OF INTEGER RANGE -1 TO 256; -- Mem(SecAddr)(Address).... VARIABLE Mem : MemArray := (OTHERS => (OTHERS => MaxData)); -- ECC ASO VARIABLE ECC_array : std_logic_vector(16#FFFFFF# downto 0) :=(OTHERS => '0'); -- ECC Write Buffer temporary VARIABLE ECC_WB_array: std_logic_vector(16#FFFFFF# downto 0) :=(OTHERS => '0'); VARIABLE WBData : WBDataType:= (OTHERS => 0); VARIABLE WBAddr : WBAddrType:= (OTHERS => -1); VARIABLE BaseLoc : NATURAL RANGE 0 TO SecSize := 0; VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; VARIABLE Continuity_Check_1: boolean := FALSE; VARIABLE Continuity_Check_2: boolean := FALSE; VARIABLE oe : boolean := FALSE; --Status reg. VARIABLE StatusReg : std_logic_vector(15 downto 0) := "0000000010000000"; -- text file input variables FILE mem_file : text is mem_file_name; VARIABLE S_ind : NATURAL RANGE 0 TO SecNum := 0; VARIABLE ind : NATURAL := 0; VARIABLE index : NATURAL RANGE 0 TO SecSize:=0; VARIABLE buf : line; 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 256; --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO 16#FF# := 0; --DATA WORD VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE mem_data : INTEGER; VARIABLE PR_FLAG : BOOLEAN := FALSE; VARIABLE ER_FLAG : BOOLEAN := FALSE; VARIABLE temp : std_logic_vector(15 downto 0); VARIABLE ECCPage : NATURAL; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(write) THEN DataLo := D_tmp1; Data := D_tmp; PATTERN_1 := (Addr=16#555#) AND (DataLo=16#AA#) ; PATTERN_2 := (Addr=16#2AA#) AND (DataLo=16#55#) ; A_PAT_1 := (Addr=16#555#); Continuity_Check_1 := (Addr1=16#5555555#) AND (Data=16#5555#) ; Continuity_Check_2 := (Addr1=16#AAAAAAA#) AND (Data=16#AAAA#) ; END IF; oe := rising_edge(read) OR (read = '1' AND Address'EVENT); IF falling_edge(RST) AND RESETNeg = '0' THEN STAT_ACT <= '0'; StatusReg(7) := '1'; StatusReg(6 DOWNTO 0) := (OTHERS => '0'); END IF; IF reseted = '1' THEN CASE current_state IS WHEN RESET => StatusReg(7) := '1'; IF falling_edge(write) THEN IF (A_PAT_1 AND (DataLo=16#70#)) AND STAT_ACT = '0' THEN STAT_ACT <= '1'; ELSIF (A_PAT_1 AND (DataLo=16#71#)) THEN StatusReg(5 DOWNTO 4) := "00"; StatusReg(0) := '0'; STAT_ACT <= '0'; ELSIF (A_PAT_1 AND (DataLo = 16#33#)) THEN BCSTART <= '1', '0' AFTER 1 ns; StatusReg (7) := '0'; StatusReg (5) := '0'; SA <= SecAddr; STAT_ACT <= '0'; ELSIF Continuity_Check_1 THEN CHECK_ACT <= '1'; END IF; END IF; IF oe THEN DOut_zd(15 downto 0) <= READMEM(Mem(SecAddr)(Address)); END IF; WHEN READUL1 => null; WHEN READUL2 => IF falling_edge(write) THEN IF (DataLo=16#25#) THEN --fix Sector Address SA SA <= SecAddr; END IF; END IF; WHEN READSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; WHEN BLCK => IF falling_edge(write) AND ((A_PAT_1) AND (DataLo = 16#70#) AND (STAT_ACT = '0')) THEN STAT_ACT <= '1'; END IF; IF oe THEN DOut_zd(15 downto 0) <= (OTHERS => 'X'); END IF; IF rising_edge(BCDONE) THEN StatusReg(7) := '1'; StatusReg(5) := '0'; FOR j IN 0 TO SecSize LOOP IF Mem(SA)(j) /= MaxData THEN StatusReg (5) := '1'; END IF; END LOOP; STAT_ACT <= '0'; END IF; WHEN BLCKSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; IF BCDONE = '1' THEN StatusReg(7) := '1'; StatusReg(5) := '0'; FOR j IN 0 TO SecSize LOOP IF Mem(SA)(j) /= MaxData THEN StatusReg (5) := '1'; END IF; END LOOP; STAT_ACT <= '0'; END IF; WHEN CUL1 => IF falling_edge(write) THEN IF Continuity_Check_2 AND CHECK_ACT = '1' THEN StatusReg(0) := '1'; CHECK_ACT <= '0'; END IF; END IF; WHEN AS => IF oe THEN --ID READ IF Addr=16#00# THEN DOut_zd(15 downto 0) <= to_slv(16#0001#,16); ELSIF Addr=16#01# THEN DOut_zd(15 downto 0) <= to_slv(16#227E#,16); ELSIF Addr=16#02# THEN DOut_zd(15 downto 0) <= to_slv(0,16); ELSIF Addr=16#03# THEN DOut_zd(15 downto 0) <= to_slv(16#FFFF#,16); ELSIF Addr>=16#04# and Addr<=16#0B# THEN DOut_zd(15 downto 0) <= to_slv(16#FFFF#,16); ELSIF Addr=16#0C# THEN DOut_zd(15 downto 4) <= to_slv(0,12); DOut_zd(3 downto 2 ) <= to_slv(0,2);--Classic cmd set DOut_zd(1) <= '0';--DQ bit polling not supported DOut_zd(0) <= '1';--Status register supported ELSIF Addr = 16#0D# THEN DOut_zd(15 downto 0) <= to_slv(0,16); ELSIF Addr = 16#0E# THEN DOut_zd(15 downto 0) <= to_slv(16#225E#,16); ELSIF Addr = 16#0F# THEN DOut_zd(15 downto 0) <= to_slv(16#2201#,16); ELSIF Addr>=16#0010# and Addr<=16#1FFF# THEN DOut_zd(15 downto 0) <= to_slv(16#FFFF#,16); END IF; END IF; WHEN ER => NULL; WHEN ERUL1 => NULL; WHEN ERUL2 => IF falling_edge(write) THEN ESTART <= '1', '0' AFTER 1 ns; StatusReg(7 downto 0) := "00000000"; SA <= SecAddr; ER_FLAG := FALSE; END IF; WHEN SER => IF falling_edge(write) AND ((A_PAT_1) AND (DataLo = 16#70#) AND (STAT_ACT = '0')) THEN STAT_ACT <= '1'; END IF; IF NOT ER_FLAG THEN ER_FLAG:= TRUE; FOR i IN 0 TO SecSize LOOP Mem(SA)(i) := -1; END LOOP; END IF; IF EDONE = '1' THEN ER_FLAG:= FALSE; FOR i IN 0 TO SecSize LOOP Mem(SA)(i) := MaxData; END LOOP; FOR j IN 0 TO SecSize LOOP ECCPage := (SA * (SecSize+1) + j)/16#10#; ECC_array(ECCPage) := '0'; ECC_WB_array(ECCPage) := '0'; END LOOP; StatusReg(7) := '1'; END IF; WHEN ERSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; IF EDONE = '1' THEN ER_FLAG:= FALSE; FOR i IN 0 TO SecSize LOOP Mem(SA)(i) := MaxData; END LOOP; FOR j IN 0 TO SecSize LOOP ECCPage := (SA * (SecSize+1) + j)/16#10#; ECC_array(ECCPage) := '0'; ECC_WB_array(ECCPage) := '0'; END LOOP; StatusReg(7) := '1'; END IF; WHEN WBPGMS_WBCNT => IF falling_edge(write) THEN IF (SecAddr = SA) AND Data < 256 THEN cnt := Data; PCNT <= cnt; LCNT <= cnt; ELSE StatusReg(4) := '1'; END IF; END IF; WHEN WBPGMS_WBLSTA => IF falling_edge(write) THEN IF (SecAddr = SA) THEN -- fix WriteBufferPage WBPage WBData(cnt) := -1; IF Viol = '0' THEN WBData(cnt) := Data; END IF; WBAddr(cnt) := Address MOD 256; IF cnt > 0 THEN cnt := cnt -1; END IF; WBPage <= WPage; END IF; LCNT <= cnt; END IF; WHEN WBPGMS_WBLOAD => IF falling_edge(write) THEN IF (WPage = WBPage)THEN WBData(cnt) := -1; IF Viol = '0' THEN WBData(cnt) := Data; END IF; WBAddr(cnt) := Address MOD 256; IF cnt > 0 THEN cnt := cnt - 1; END IF; ELSE StatusReg(4) := '1'; END IF; LCNT <= cnt; END IF; WHEN WBPGMS_CONFB => IF falling_edge(write) THEN IF (SecAddr = SA) AND (DataLo = 16#29#) THEN PSTART <= '1', '0' AFTER 1 ns; StatusReg(7) := '0'; PR_FLAG := FALSE; ELSE StatusReg(4) := '1'; END IF; END IF; WHEN PG => IF falling_edge(write) AND ((A_PAT_1) AND (DataLo = 16#70#) AND (STAT_ACT = '0')) THEN STAT_ACT <= '1'; END IF; IF NOT PR_FLAG THEN PR_FLAG:=TRUE; BaseLoc := WBPage * 256; wr_cnt := PCNT; FOR i IN wr_cnt downto 0 LOOP new_int := WBData(i); IF WBAddr(i) < 0 THEN old_int := -1; ELSE --mem write old_int := Mem(SA)(BaseLoc+WBAddr(i)); END IF; IF new_int > -1 THEN new_bit := to_slv(new_int,16); IF (old_int>-1) THEN old_bit := to_slv(old_int,16); FOR j IN 0 TO 15 LOOP IF old_bit(j) = '0' THEN new_bit(j) := '0'; END IF; END LOOP; ELSE new_bit(0) := 'X'; END IF; IF new_bit(0)/='X' THEN new_int := to_nat(new_bit); WBData(i) := new_int; ELSE WBData(i) := -1; END IF; ELSE WBData(i) := -1; END IF; END LOOP; FOR i IN wr_cnt downto 0 LOOP --mem write Mem(SA)(BaseLoc + WBAddr(i)) := -1; END LOOP; END IF; IF PDONE = '1' THEN PR_FLAG :=FALSE; FOR i IN wr_cnt downto 0 LOOP IF WBAddr(i) > -1 AND WBdata(i) > -1 THEN --mem write Mem(SA)(BaseLoc + WBAddr(i)) := WBData(i); ECCPage := (SA * (SecSize+1) + (BaseLoc + WBAddr(i)))/16#10#; IF ECC_WB_array(ECCPage) = '1' THEN ECC_array(ECCPage) := '1'; END IF; ECC_WB_array(ECCPage) := '1'; END IF; WBData(i) := -1; END LOOP; END IF; IF rising_edge(PDONE) THEN StatusReg(7) := '1'; END IF; WHEN PGSR => IF (oe AND STAT_ACT = '1') THEN DOut_zd(15 downto 0) <= StatusReg; STAT_ACT <= '0'; END IF; IF PDONE = '1' THEN PR_FLAG :=FALSE; FOR i IN wr_cnt downto 0 LOOP IF WBAddr(i) > -1 AND WBdata(i) > -1 THEN --mem write Mem(SA)(BaseLoc + WBAddr(i)) := WBData(i); ECCPage := (SA * (SecSize+1) + (BaseLoc + WBAddr(i)))/16#10#; IF ECC_WB_array(ECCPage) = '1' THEN ECC_array(ECCPage) := '1'; END IF; ECC_WB_array(ECCPage) := '1'; END IF; WBData(i) := -1; END LOOP; END IF; IF rising_edge(PDONE) THEN StatusReg(7) := '1'; END IF; WHEN ECC_ENTRY => IF oe THEN ECCPage := (SecAddr * (SecSize+1) + Address)/16#10#; DOut_zd(15 downto 0) <= (OTHERS => '0'); DOut_zd(0) <= ECC_array(ECCPage); END IF; END CASE; END IF; --Output Disable Control IF (gOE_n = '1') OR (RESETNeg = '0'AND RST = '0') THEN DOut_zd <= (OTHERS => 'Z'); END IF; --Preload Control ------------------------------------------------------------------------------- -- File Read Section ------------------------------------------------------------------------------- IF NOW = 0 ns THEN ------------------------------------------------------------------------------- -----s29gl04gs memory preload file format ----------------------------------- ------------------------------------------------------------------------------- -- / - comment -- @aaaaaaa - stands for address within sector -- dd -
is byte to be written at Mem(*)(aaaaaaa++) -- (aaaaaaa is incremented at every load) -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! ------------------------------------------------------------------------------- IF (mem_file_name /= "none" ) THEN ind := 0; S_ind := 0; Mem := (OTHERS => (OTHERS => MaxData)); -- load sector 0 WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 to 8)); --address ELSE IF ind=0 THEN S_ind := 0; index := 0; Mem(S_ind)(index) := h(buf(1 to 4)); ind := ind + 1; ELSIF ind < SecSize+1 THEN S_ind := 0; index := ind; Mem(S_ind)(index) := h(buf(1 to 4)); ind := ind + 1; ELSIF ind <= AddrRANGE THEN S_ind := NATURAL(ind / (SecSize +1)); index := ind - S_ind*(SecSize+1); Mem(S_ind)(index) := h(buf(1 to 4)); ind := ind + 1; ELSE REPORT " Memory address out of range" SEVERITY warning; END IF; END IF; END LOOP; END IF; END IF; END PROCESS Functional; ------------------------------------------------------------------------------- -----***timing processes*** ------------------------------------------------------------------------------- READY_time : PROCESS (READY_in) BEGIN IF rising_edge ( READY_in ) THEN IF LongTimming = TRUE THEN sREADY <= '0', '1' AFTER (tdevice_READY - 1 ns); ELSE sREADY <= '0', '1' AFTER (tdevice_READY - 1 ns)/10; END IF; ELSE sREADY <= '0'; END IF; END PROCESS READY_time; ------------------------------------------------------------------------------- --- ------------------------------------------------------------------------------- DOutPassThrough : PROCESS(DOut_zd) VARIABLE ValidData : std_logic_vector(15 downto 0); VARIABLE CEDQ_t : TIME; VARIABLE OEDQ_t : TIME; VARIABLE ADDRDQ_t : TIME; BEGIN IF DOut_zd(0) /= 'Z' THEN OPENLATCH := TRUE; CEDQ_t := -CENeg'LAST_EVENT + tpd_CENeg_DQ0(trz0); OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_DQ0(trz0); ADDRDQ_t := -A'LAST_EVENT + tpd_A0_DQ0(tr01);-- FROMOE := (OEDQ_t >= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t > OEDQ_t) AND (CEDQ_t > 0 ns); ValidData := "XXXXXXXXXXXXXXXX"; IF ((ADDRDQ_t > 0 ns) AND (((ADDRDQ_t > CEDQ_t) AND FROMCE) OR ((ADDRDQ_t > OEDQ_t) AND FROMOE))) THEN DOut_Pass <= ValidData, DOut_zd AFTER ADDRDQ_t; ELSE DOut_Pass <= DOut_zd; END IF; ELSE OPENLATCH := FALSE; DOut_Pass <= DOut_zd; END IF; END PROCESS DOutPassThrough; ----------------------------------------------------------------------- -- Path Delay Section ----------------------------------------------------------------------- -- Path Delay Section for DOut signal D_Out_PathDelay_Gen : FOR i IN DOut_Pass'RANGE GENERATE PROCESS(DOut_Pass(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_Pass(i), GlitchData => D0_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMCE)), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMOE)), 2 => (InputChangeTime => RESETNeg'LAST_EVENT, PathDelay => tpd_RESETNeg_DQ0, PathCondition => RESETNeg='0'), 3 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => DOut_pass(i) /= 'X' AND RPchange), 4 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ1), PathCondition => DOut_pass(i)/= 'X' AND (NOT RPchange)) ) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral_static_memory_allocation;