-------------------------------------------------------------------------------- -- File name : fs29sl800.vhd -------------------------------------------------------------------------------- -- Copyright (C) 2006 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 M.Milanovic 06 Feb 03 Initial release -- -------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: Flasys -- Technology: Flash Memory -- Part: FS29SL800 -- -- Description: 8 Mbit (512K x 16 or 1M x 8) dual supply (1.8Vand 3.3V) -- non-volatile Flash memory -- -------------------------------------------------------------------------------- -- Known Bugs: -- -------------------------------------------------------------------------------- -- Comments : -- For correct simulation, simulator resolution should be set to 1ps -- -------------------------------------------------------------------------------- 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 fs29sl800 IS GENERIC ( -- tipd delays: interconnect path delays tipd_A0 : VitalDelayType01 := VitalZeroDelay01; tipd_A1 : VitalDelayType01 := VitalZeroDelay01; tipd_A2 : VitalDelayType01 := VitalZeroDelay01; tipd_A3 : VitalDelayType01 := VitalZeroDelay01; tipd_A4 : VitalDelayType01 := VitalZeroDelay01; tipd_A5 : VitalDelayType01 := VitalZeroDelay01; tipd_A6 : VitalDelayType01 := VitalZeroDelay01; tipd_A7 : VitalDelayType01 := VitalZeroDelay01; tipd_A8 : VitalDelayType01 := VitalZeroDelay01; tipd_A9 : VitalDelayType01 := VitalZeroDelay01; tipd_A10 : VitalDelayType01 := VitalZeroDelay01; tipd_A11 : VitalDelayType01 := VitalZeroDelay01; tipd_A12 : VitalDelayType01 := VitalZeroDelay01; tipd_A13 : VitalDelayType01 := VitalZeroDelay01; tipd_A14 : VitalDelayType01 := VitalZeroDelay01; tipd_A15 : VitalDelayType01 := VitalZeroDelay01; tipd_A16 : VitalDelayType01 := VitalZeroDelay01; tipd_A17 : VitalDelayType01 := VitalZeroDelay01; tipd_A18 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01; --(tAA,tAA) tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(-,-,tCHZ,tCE,tCHZ,tCE) tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(-,-,tOHZ,tOE,tOHZ,tOE) tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(-,-,0,-,0,-) tpd_BYTENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(-,-,tBLQZ,tBHQV,tBLQZ,tBHQV) --tsetup values tsetup_A0_WENeg : VitalDelayType := UnitDelay; --tAS edge \ tsetup_DQ0_WENeg : VitalDelayType := UnitDelay; --tDS edge / --thold values thold_CENeg_RESETNeg : VitalDelayType := UnitDelay; --tRH edge / thold_A0_WENeg : VitalDelayType := UnitDelay; --tAH edge \ thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / thold_BYTENeg_CENeg : VitalDelayType := UnitDelay; --tCLBL,tCLBH edge \ thold_BYTENeg_WENeg : VitalDelayType := UnitDelay; --tBH edge \ --tpw values: pulse width tpw_RESETNeg_negedge : VitalDelayType := UnitDelay; --tRP tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCPH tpw_A0_negedge : VitalDelayType := UnitDelay; --tRC,tWC tpw_A0_posedge : VitalDelayType := UnitDelay; --tRC,tWC --period values tperiod_CENeg_posedge: VitalDelayType := UnitDelay; --tRC -- tdevice values: values for internal delays --Byte Program Time tBPGM tdevice_POB : VitalDelayType := 40 us; --Word Program Time tWPGM tdevice_POW : VitalDelayType := 40 us; --Sector Erase Time tSER tdevice_SEO : VitalDelayType := 500 ms; --Chip Erase Time tCER tdevice_CEO : VitalDelayType := 1.5 sec; --device ready after Hardware reset(during embeded algorithm) tdevice_READY : VitalDelayType := 100.05 us; --tRH + tRP --Internal information access and exit time tdevice_INTEXIT : VitalDelayType := 100 ns; --tIA -- 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"; otp_file_name : string := "none"; UserPreload : boolean := FALSE; LongTimming : boolean := TRUE; -- For FMF SDF technology file usage TimingModel : string := DefaultTimingModel ); PORT ( A0 : IN std_ulogic := 'U'; -- A1 : IN std_ulogic := 'U'; -- A2 : IN std_ulogic := 'U'; -- A3 : IN std_ulogic := 'U'; -- A4 : IN std_ulogic := 'U'; -- A5 : IN std_ulogic := 'U'; -- A6 : IN std_ulogic := 'U'; -- A7 : IN std_ulogic := 'U'; -- A8 : IN std_ulogic := 'U'; -- address A9 : IN std_ulogic := 'U'; -- lines A10 : IN std_ulogic := 'U'; -- A11 : IN std_ulogic := 'U'; -- A12 : IN std_ulogic := 'U'; -- A13 : IN std_ulogic := 'U'; -- A14 : IN std_ulogic := 'U'; -- A15 : IN std_ulogic := 'U'; -- A16 : IN std_ulogic := 'U'; -- A17 : IN std_ulogic := 'U'; -- A18 : IN std_ulogic := 'U'; -- DQ0 : INOUT std_ulogic := 'U'; -- DQ1 : INOUT std_ulogic := 'U'; -- DQ2 : INOUT std_ulogic := 'U'; -- DQ3 : INOUT std_ulogic := 'U'; -- DQ4 : INOUT std_ulogic := 'U'; -- DQ5 : INOUT std_ulogic := 'U'; -- DQ6 : INOUT std_ulogic := 'U'; -- data DQ7 : INOUT std_ulogic := 'U'; -- lines DQ8 : INOUT std_ulogic := 'U'; -- DQ9 : INOUT std_ulogic := 'U'; -- DQ10 : INOUT std_ulogic := 'U'; -- DQ11 : INOUT std_ulogic := 'U'; -- DQ12 : INOUT std_ulogic := 'U'; -- DQ13 : INOUT std_ulogic := 'U'; -- DQ14 : INOUT std_ulogic := 'U'; -- DQ15 : INOUT std_ulogic := 'U'; -- DQ15/A-1 CENeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RESETNeg : IN std_ulogic := 'U'; BYTENeg : IN std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 OF fs29sl800 : ENTITY IS TRUE; END fs29sl800; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral OF fs29sl800 IS ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : string := "FS29SL800"; CONSTANT MaxData : natural := 16#FF#; --255; CONSTANT SecSize : natural := 16#FFFF#; --65535 CONSTANT OTPSize : natural := 63; --64 bytes(32 words) CONSTANT SecNum : natural := 18; CONSTANT HiAddrBit : natural := 18; CONSTANT MemSize : natural := (SecNum - 2)*(SecSize + 1)-1; -- interconnect path delay signals SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL A2_ipd : std_ulogic := 'U'; SIGNAL A3_ipd : std_ulogic := 'U'; SIGNAL A4_ipd : std_ulogic := 'U'; SIGNAL A5_ipd : std_ulogic := 'U'; SIGNAL A6_ipd : std_ulogic := 'U'; SIGNAL A7_ipd : std_ulogic := 'U'; SIGNAL A8_ipd : std_ulogic := 'U'; SIGNAL A9_ipd : std_ulogic := 'U'; SIGNAL A10_ipd : std_ulogic := 'U'; SIGNAL A11_ipd : std_ulogic := 'U'; SIGNAL A12_ipd : std_ulogic := 'U'; SIGNAL A13_ipd : std_ulogic := 'U'; SIGNAL A14_ipd : std_ulogic := 'U'; SIGNAL A15_ipd : std_ulogic := 'U'; SIGNAL A16_ipd : std_ulogic := 'U'; SIGNAL A17_ipd : std_ulogic := 'U'; SIGNAL A18_ipd : std_ulogic := 'U'; SIGNAL DQ0_ipd : std_ulogic := 'U'; SIGNAL DQ1_ipd : std_ulogic := 'U'; SIGNAL DQ2_ipd : std_ulogic := 'U'; SIGNAL DQ3_ipd : std_ulogic := 'U'; SIGNAL DQ4_ipd : std_ulogic := 'U'; SIGNAL DQ5_ipd : std_ulogic := 'U'; SIGNAL DQ6_ipd : std_ulogic := 'U'; SIGNAL DQ7_ipd : std_ulogic := 'U'; SIGNAL DQ8_ipd : std_ulogic := 'U'; SIGNAL DQ9_ipd : std_ulogic := 'U'; SIGNAL DQ10_ipd : std_ulogic := 'U'; SIGNAL DQ11_ipd : std_ulogic := 'U'; SIGNAL DQ12_ipd : std_ulogic := 'U'; SIGNAL DQ13_ipd : std_ulogic := 'U'; SIGNAL DQ14_ipd : std_ulogic := 'U'; SIGNAL DQ15_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL RESETNeg_ipd : std_ulogic := 'U'; SIGNAL BYTENeg_ipd : std_ulogic := 'U'; --- internal delays SIGNAL POB_in : std_ulogic := '0'; SIGNAL POB_out : std_ulogic := '0'; SIGNAL POW_in : std_ulogic := '0'; SIGNAL POW_out : std_ulogic := '0'; SIGNAL SEO_in : std_ulogic := '0'; SIGNAL SEO_out : std_ulogic := '0'; SIGNAL CEO_in : std_ulogic := '0'; SIGNAL CEO_out : std_ulogic := '0'; SIGNAL INT_in : std_ulogic := '0'; SIGNAL INT_out : std_ulogic := '0'; SIGNAL READY_in : std_ulogic := '0'; SIGNAL READY_out : std_ulogic := '0'; BEGIN ---------------------------------------------------------------------------- -- Internal Delays ---------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays POB :VitalBuf(POB_out, POB_in, (tdevice_POB ,UnitDelay)); POW :VitalBuf(POW_out, POW_in, (tdevice_POW ,UnitDelay)); SEO :VitalBuf(SEO_out, SEO_in, (tdevice_SEO ,UnitDelay)); CEO :VitalBuf(CEO_out, CEO_in, (tdevice_CEO ,UnitDelay)); INTEXIT:VitalBuf(INT_out, INT_in, (tdevice_INTEXIT ,UnitDelay)); READY :VitalBuf(READY_out, READY_in, (tdevice_READY ,UnitDelay)); ---------------------------------------------------------------------------- -- Wire Delays ---------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_2 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_3 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_4 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_5 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_6 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_7 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_8 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_9 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_10 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_11 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_12 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_13 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_14 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_15 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_16 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_17 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_18 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_19 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_20 : VitalWireDelay (DQ0_ipd, DQ0, tipd_DQ0); w_21 : VitalWireDelay (DQ1_ipd, DQ1, tipd_DQ1); w_22 : VitalWireDelay (DQ2_ipd, DQ2, tipd_DQ2); w_23 : VitalWireDelay (DQ3_ipd, DQ3, tipd_DQ3); w_24 : VitalWireDelay (DQ4_ipd, DQ4, tipd_DQ4); w_25 : VitalWireDelay (DQ5_ipd, DQ5, tipd_DQ5); w_26 : VitalWireDelay (DQ6_ipd, DQ6, tipd_DQ6); w_27 : VitalWireDelay (DQ7_ipd, DQ7, tipd_DQ7); w_28 : VitalWireDelay (DQ8_ipd, DQ8, tipd_DQ8); w_29 : VitalWireDelay (DQ9_ipd, DQ9, tipd_DQ9); w_30 : VitalWireDelay (DQ10_ipd, DQ10, tipd_DQ10); w_31 : VitalWireDelay (DQ11_ipd, DQ11, tipd_DQ11); w_32 : VitalWireDelay (DQ12_ipd, DQ12, tipd_DQ12); w_33 : VitalWireDelay (DQ13_ipd, DQ13, tipd_DQ13); w_34 : VitalWireDelay (DQ14_ipd, DQ14, tipd_DQ14); w_35 : VitalWireDelay (DQ15_ipd, DQ15, tipd_DQ15); w_36 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); w_37 : VitalWireDelay (OENeg_ipd, OENeg, tipd_OENeg); w_38 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_39 : VitalWireDelay (RESETNeg_ipd, RESETNeg, tipd_RESETNeg); w_40 : VitalWireDelay (BYTENeg_ipd, BYTENeg, tipd_BYTENeg); 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'; BYTENeg : IN std_ulogic := 'U' ); PORT MAP ( A(0) => A0_ipd, A(1) => A1_ipd, A(2) => A2_ipd, A(3) => A3_ipd, A(4) => A4_ipd, A(5) => A5_ipd, A(6) => A6_ipd, A(7) => A7_ipd, A(8) => A8_ipd, A(9) => A9_ipd, A(10) => A10_ipd, A(11) => A11_ipd, A(12) => A12_ipd, A(13) => A13_ipd, A(14) => A14_ipd, A(15) => A15_ipd, A(16) => A16_ipd, A(17) => A17_ipd, A(18) => A18_ipd, DIn(0) => DQ0_ipd, DIn(1) => DQ1_ipd, DIn(2) => DQ2_ipd, DIn(3) => DQ3_ipd, DIn(4) => DQ4_ipd, DIn(5) => DQ5_ipd, DIn(6) => DQ6_ipd, DIn(7) => DQ7_ipd, DIn(8) => DQ8_ipd, DIn(9) => DQ9_ipd, DIn(10) => DQ10_ipd, DIn(11) => DQ11_ipd, DIn(12) => DQ12_ipd, DIn(13) => DQ13_ipd, DIn(14) => DQ14_ipd, DIn(15) => DQ15_ipd, DOut(0) => DQ0, DOut(1) => DQ1, DOut(2) => DQ2, DOut(3) => DQ3, DOut(4) => DQ4, DOut(5) => DQ5, DOut(6) => DQ6, DOut(7) => DQ7, DOut(8) => DQ8, DOut(9) => DQ9, DOut(10) => DQ10, DOut(11) => DQ11, DOut(12) => DQ12, DOut(13) => DQ13, DOut(14) => DQ14, DOut(15) => DQ15, CENeg => CENeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, RESETNeg => RESETNeg_ipd, BYTENeg => BYTENeg_ipd ); -- State Machine : State_Type TYPE state_type IS ( RESET, Z001, PREL_SETBWB, C8, C8_Z001, C8_PREL, ERS, SERS_EXEC, HARD_PROT_PREL, SOFT_PROT, SOFT_PROT_EXIT_01, SOFT_PROT_EXIT_02, SOFT_UNPROT, SOFT_UNPROT_EXIT_01, SOFT_UNPROT_EXIT_02, AS, AS_EXIT_01, AS_EXIT_02, CFI, CFI_EXIT_01, CFI_EXIT_02, A0SEEN, PGMS, OTP_READ, OTP_EXIT_01, OTP_EXIT_02, OTP_WRITE, HARD_PROT_Z001, HARD_PROT ); --Flash Memory Array TYPE SecType IS ARRAY (0 TO SecSize) OF integer RANGE -1 TO MaxData; TYPE MemArray IS ARRAY (0 TO SecNum-3) OF SecType; --Common Flash Interface Query codes TYPE CFItype IS ARRAY (16#10# TO 16#3C#) OF natural RANGE 0 TO 16#FF#; --OTP Area TYPE OTPType IS ARRAY (0 TO OTPSize) OF integer RANGE -1 TO MaxData; TYPE WDataType IS ARRAY (0 TO 1) OF integer RANGE -1 TO MaxData; TYPE WAddrType IS ARRAY (0 TO 1) OF integer; -- 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 OTP_ACT : std_logic := '0'; --OTP access SIGNAL HW_ACT : std_logic := '0'; --Hard Write programing SIGNAL PSTART : std_logic := '0'; --Start Programming SIGNAL PDONE : std_logic := '1'; --Prog. Done SIGNAL AS_Exit : std_logic := '1'; --exit CFI, autoselect, --security read, Soft protect SIGNAL AS_Ent : std_logic := '0'; --enter CFI, autoselect, --security read --Program location is in protected sector SIGNAL PERR : std_logic := '0'; SIGNAL EDONE : std_logic := '1'; --Ers. Done SIGNAL ESTART : std_logic := '0'; --Start Erase --All sectors selected for erasure are protected SIGNAL EERR : std_logic := '0'; --Sectors selected for erasure SIGNAL ERS_QUEUE : std_logic_vector(SecNum DOWNTO 0):= (OTHERS => '0'); --Command Register SIGNAL write : std_logic := '0'; SIGNAL read : std_logic := '0'; --Sector Address SIGNAL SecAddr : natural RANGE 0 TO SecNum-3 := 0; SIGNAL SecAddr_exact : natural RANGE 0 TO SecNum := 0; SIGNAL SA : natural RANGE 0 TO SecNum-3 := 0; SIGNAL SA_exact : natural RANGE 0 TO SecNum := 0; --Address within sector SIGNAL Address : natural RANGE 0 TO SecSize := 0; SIGNAL D_tmp0 : natural RANGE 0 TO MaxData; SIGNAL D_tmp1 : natural RANGE 0 TO MaxData; --A18:A15 Don't Care SIGNAL Addr : natural RANGE 0 TO 16#FFFF# := 0; --glitch protection SIGNAL gWE_n : std_logic := '1'; SIGNAL gCE_n : std_logic := '1'; SIGNAL gOE_n : std_logic := '1'; SIGNAL add_lt : std_logic; SIGNAL RST : std_logic := '1'; SIGNAL reseted : std_logic := '0'; SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); SHARED VARIABLE OTP : OTPType :=(OTHERS=>0); SHARED VARIABLE WBData : WDataType :=(OTHERS=>0); SHARED VARIABLE WBAddr : WAddrType :=(OTHERS=>-1); --Sector Protection Status SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum DOWNTO 0) := (OTHERS => '0'); --Hardware sectors protected SHARED VARIABLE H_Sec_Prot : std_logic_vector(SecNum DOWNTO 0) := (OTHERS => '0'); SHARED VARIABLE SEC_LOCK : std_logic; SHARED VARIABLE OTP_GROUP : natural RANGE 0 TO 3; SHARED VARIABLE OTP_Prot : std_logic_vector(3 DOWNTO 0) := (OTHERS => '0'); -- timing check violation SIGNAL Viol : X01 := '0'; -- Access time variables SHARED VARIABLE OPENLATCH : boolean; SHARED VARIABLE FROMCE : boolean; SHARED VARIABLE FROMOE : boolean; SHARED VARIABLE ADDR_event : time := 0 ns; SHARED VARIABLE readpolling : std_logic := '1'; -- for dummy reads SHARED VARIABLE E : std_logic := '0'; --reset timming error BEGIN ---------------------------------------------------------------------------- --Power Up time 110 us; ---------------------------------------------------------------------------- PoweredUp <= '1' AFTER 110 us; --tVDHPH + TRH RST <= RESETNeg AFTER 50 ns; ---------------------------------------------------------------------------- -- VITAL Timing Checks Procedures ---------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A, DIn, CENeg, OENeg, WENeg, RESETNeg, BYTENeg) -- Timing Check Variables VARIABLE Tviol_A0_CENeg : X01 := '0'; VARIABLE TD_A0_CENeg : VitalTimingDataType; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ15_WENeg : X01 := '0'; VARIABLE TD_DQ15_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE Tviol_DQ15_CENeg : X01 := '0'; VARIABLE TD_DQ15_CENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_OENeg_RESETNeg : X01 := '0'; VARIABLE TD_OENeg_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_OENeg_CENeg : X01 := '0'; VARIABLE TD_OENeg_CENeg : VitalTimingDataType; VARIABLE Tviol_BYTENeg_CENeg: X01 := '0'; VARIABLE TD_BYTENeg_CENeg : VitalTimingDataType; VARIABLE Tviol_BYTENeg_WENeg: X01 := '0'; VARIABLE TD_BYTENeg_WENeg : VitalTimingDataType; VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType :=VitalPeriodDataInit; VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType :=VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType :=VitalPeriodDataInit; VARIABLE Pviol_A0 : X01 := '0'; VARIABLE PD_A0 : VitalPeriodDataType :=VitalPeriodDataInit; VARIABLE Pviol_CENeg1 : X01 := '0'; VARIABLE PD_CENeg1 : VitalPeriodDataType :=VitalPeriodDataInit; 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_WENeg, SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, HoldLow => thold_A0_WENeg, CheckEnabled => WENeg = '0' AND OENeg = '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CENeg, Violation => Tviol_A0_CENeg ); -- Setup/Hold Check between A and WENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_A0_WENeg, SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, HoldLow => thold_A0_WENeg, CheckEnabled => CENeg = '0' AND OENeg = '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); -- Setup/Hold Check between DQ and CENeg VitalSetupHoldCheck ( TestSignal => DIn(14 DOWNTO 0), TestSignalName => "DQ", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => WENeg = '0' AND OENeg = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CENeg, Violation => Tviol_DQ0_CENeg ); -- Setup/Hold Check between DQ15 and CENeg VitalSetupHoldCheck ( TestSignal => DIn(15), TestSignalName => "DQ(15)", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => WENeg = '0' AND OENeg = '1' AND BYTENeg /= '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ15_CENeg, Violation => Tviol_DQ15_CENeg ); -- Setup/Hold Check between DQ and WENeg VitalSetupHoldCheck ( TestSignal => DIn(14 DOWNTO 0), TestSignalName => "DQ", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => CENeg = '0' AND OENeg = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_WENeg, Violation => Tviol_DQ0_WENeg ); -- Setup/Hold Check between DQ15 and WENeg VitalSetupHoldCheck ( TestSignal => DIn(15), TestSignalName => "DQ(15)", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => CENeg = '0' AND OENeg = '1' AND BYTENeg /= '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ15_WENeg, Violation => Tviol_DQ15_WENeg ); -- Hold Check between CENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => RESETNeg, RefSignalName => "RESET#", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => E = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RESETNeg, Violation => Tviol_CENeg_RESETNeg ); -- Hold Check between OENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => RESETNeg, RefSignalName => "RESET#", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => E = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_RESETNeg, Violation => Tviol_OENeg_RESETNeg ); -- Hold Check between WENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => RESETNeg, RefSignalName => "RESET#", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => E = '0', 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 => PDONE = '0' OR EDONE = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg, Violation => Tviol_OENeg_WENeg ); -- Hold Check between OENeg and CENeg VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => CENeg, RefSignalName => "CE#", HoldHigh => thold_OENeg_WENeg, CheckEnabled => PDONE = '0' OR EDONE = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg, Violation => Tviol_OENeg_WENeg ); -- Setup/Hold Check between BYTENeg and CENeg VitalSetupHoldCheck ( TestSignal => BYTENeg, TestSignalName => "BYTE#", RefSignal => CENeg, RefSignalName => "CE#", HoldHigh => thold_BYTENeg_CENeg, HoldLow => thold_BYTENeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_BYTENeg_CENeg, Violation => Tviol_BYTENeg_CENeg ); -- Setup/Hold Check between BYTENeg and WENeg VitalSetupHoldCheck ( TestSignal => BYTENeg, TestSignalName => "BYTE#", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_BYTENeg_WENeg, HoldLow => thold_BYTENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_BYTENeg_WENeg, Violation => Tviol_BYTENeg_WENeg ); -- 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 => CENeg = '0', HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); -- PulseWidth Check for CENeg VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CE#", PulseWidthHigh => tpw_CENeg_posedge, PulseWidthLow => tpw_CENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CENeg, Violation => Pviol_CENeg ); -- 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 ); -- Period Check for CENeg VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CE#", Period => tperiod_CENeg_posedge, CheckEnabled => PDONE = '0' OR EDONE = '0', HeaderMsg => InstancePath & PartID, PeriodData => PD_CENeg1, Violation => Pviol_CENeg1 ); Violation := Tviol_A0_CENeg OR Tviol_A0_WENeg OR Tviol_DQ0_WENeg OR Tviol_DQ15_WENeg OR Tviol_DQ0_CENeg OR Tviol_DQ15_CENeg OR Tviol_CENeg_RESETNeg OR Tviol_OENeg_RESETNeg OR Tviol_WENeg_RESETNeg OR Tviol_OENeg_WENeg OR Tviol_OENeg_CENeg OR Tviol_BYTENeg_CENeg OR Tviol_BYTENeg_WENeg OR Pviol_RESETNeg OR Pviol_CENeg OR Pviol_WENeg OR Pviol_A0 OR Pviol_CENeg1; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; ---------------------------------------------------------------------------- -- sequential process for reset control and FSM state transition ---------------------------------------------------------------------------- StateTransition : PROCESS(next_state, RESETNeg, RST, READY_out, PDone, EDone, PoweredUp) VARIABLE R : std_logic := '0'; --prog or erase in progress BEGIN IF PoweredUp='1' THEN --Hardware reset timing control IF falling_edge(RESETNeg) THEN E := '0'; IF (PDONE = '0' OR EDONE = '0') THEN --if program or erase in progress READY_in <= '1'; R := '1'; ELSE READY_in <= '0'; R := '0'; --prog or erase not in progress END IF; ELSIF rising_edge(RESETNeg) AND RST = '1' THEN --RESET# pulse < tRP READY_in <= '0'; R := '0'; E := '1'; END IF; IF RESETNeg = '1' AND ( R = '0' OR (R = '1' AND READY_out = '1')) THEN current_state <= next_state; READY_in <= '0'; R := '0'; reseted <= '1'; ELSIF (R = '0' AND RESETNeg = '0' AND RST = '0')OR (R = '1' AND RESETNeg = '0' AND RST = '0' AND READY_out = '0')OR (R = '1' AND RESETNeg = '1' AND RST = '0' AND READY_out = '0')OR (R = '1' AND RESETNeg = '1' AND RST = '1' AND READY_out = '0')THEN current_state <= RESET; --reset start reseted <= '0'; Sec_Prot := (OTHERS => '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; address_event: PROCESS(A, DIn(15), add_lt) VARIABLE ADDR_event2 : time := 0 ns; BEGIN IF A'EVENT OR (BYTENeg = '0' AND DIn(15)'EVENT) THEN ADDR_event2 := NOW; add_lt <= '0', '1' AFTER 5 ns; END IF; IF rising_edge(add_lt) THEN ADDR_event := ADDR_event2; END IF; END PROCESS address_event; --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) BEGIN IF (WENeg'EVENT AND (gWE_n = WENeg)) OR (CENeg'EVENT AND (gCE_n = CENeg)) OR (OENeg'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, BYTENeg, reseted, add_lt) VARIABLE A_tmp : natural RANGE 0 TO 16#FFFF#; VARIABLE SA_tmp : natural RANGE 0 TO SecNum-3; VARIABLE A_tmp1 : natural RANGE 0 TO SecSize; VARIABLE tmp : std_logic_vector(HiAddrBit DOWNTO 0); FUNCTION sec_exact(in_sec : IN natural RANGE 0 TO SecNum-3; in_addr : IN natural RANGE 0 TO SecSize) RETURN natural IS VARIABLE out_sec : natural RANGE 0 TO SecNum; BEGIN IF TimingModel(10) = 'T' THEN IF in_sec <= SecNum-4 THEN out_sec := in_sec; ELSIF in_addr < (SecSize+1)/2 THEN out_sec := SecNum-3; ELSIF in_addr < 5*(SecSize+1)/8 THEN out_sec := SecNum-2; ELSIF in_addr < 3*(SecSize+1)/4 THEN out_sec := SecNum-1; ELSE out_sec := SecNum; END IF; ELSE IF in_sec > 0 THEN out_sec := in_sec+3; ELSIF in_addr < (SecSize+1)/4 THEN out_sec := 0; ELSIF in_addr < 3*(SecSize+1)/8 THEN out_sec := 1; ELSIF in_addr < (SecSize+1)/2 THEN out_sec := 2; ELSE out_sec := 3; END IF; END IF; RETURN out_sec; END sec_exact; 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 ((rising_edge(add_lt)OR BYTENeg'EVENT)AND WENeg = '1' AND CENeg = '0' AND OENeg = '0')THEN SA_tmp := to_nat(A(HiAddrBit DOWNTO 15)); tmp := A; IF (BYTENeg = '0') THEN A_tmp1 := to_nat(A(14 DOWNTO 0) & Din(15)); A_tmp := to_nat(A(14 DOWNTO 0) & Din(15)); ELSE A_tmp1 := to_nat(A(14 DOWNTO 0) & '0'); A_tmp := to_nat(A(14 DOWNTO 0)); END IF; ELSIF (rising_edge(WENeg) OR rising_edge(CENeg))AND write = '1' THEN D_tmp0 <= to_nat(DIn(7 DOWNTO 0)); IF BYTENeg = '1' THEN D_tmp1 <= to_nat(DIn(15 DOWNTO 8)); END IF; END IF; IF rising_edge(write) OR falling_edge(OENeg) OR ((rising_edge(add_lt)OR BYTENeg'EVENT) AND WENeg = '1' AND CENeg = '0' AND OENeg = '0')THEN SecAddr <= SA_tmp; SecAddr_exact <= sec_exact(SA_tmp, A_tmp1); Address <= A_tmp1; Addr <= A_tmp; OTP_GROUP := to_nat(tmp(4 DOWNTO 3)); SEC_LOCK := tmp(5); END IF; END IF; END PROCESS BusCycleDecode; ---------------------------------------------------------------------------- -- Timing control for the Program Operations ---------------------------------------------------------------------------- ProgTime :PROCESS(PSTART, BYTENeg, OTP_ACT, reseted) VARIABLE duration : time; VARIABLE pob : time; VARIABLE pow : time; BEGIN pob := tdevice_POB / 100; pow := tdevice_POW / 100; IF LongTimming THEN pob := tdevice_POB; pow := tdevice_POW; END IF; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programing terminated ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE = '1' THEN IF ((Sec_Prot(SA_exact) = '0' AND H_Sec_Prot(SA_exact) = '0' AND OTP_ACT = '0' AND HW_ACT = '0') OR (OTP_Prot(OTP_GROUP) = '0' AND OTP_ACT = '1') OR (H_Sec_Prot(SA_exact) = '0' AND HW_ACT = '1')) THEN IF HW_ACT = '1' THEN duration := pob - 5 ns; ELSIF BYTENeg = '1' THEN duration := pow - 5 ns; ELSE duration := pob - 5 ns; END IF; PDONE <= '0', '1' AFTER duration; readpolling := '0'; ELSE PERR <= '1', '0' AFTER 995 ns; END IF; END IF; END IF; END PROCESS ProgTime; ---------------------------------------------------------------------------- -- Timing control for the Erase Operations ---------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, Ers_Queue, reseted) VARIABLE cnt : natural RANGE 0 TO SecNum; VARIABLE duration : time; VARIABLE seo : time; VARIABLE ceo : time; BEGIN seo := tdevice_SEO / 1000; ceo := tdevice_CEO / 1000; IF LongTimming THEN seo := tdevice_SEO; ceo := tdevice_CEO; END IF; IF rising_edge(reseted) THEN EDONE <= '1'; -- reset done, ERASE terminated ELSIF reseted = '1' THEN IF rising_edge(ESTART) AND EDONE = '1' THEN cnt := 0; FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND Sec_Prot(i) /= '1' AND H_Sec_Prot(i) /= '1' THEN cnt := cnt +1; END IF; END LOOP; IF cnt > 0 THEN IF next_state = SERS_EXEC THEN duration := seo - 5 ns; ELSIF next_state = ERS THEN duration := ceo - 5 ns; END IF; EDONE <= '0', '1' AFTER duration; readpolling := '0'; ELSE EERR <= '1', '0' AFTER 99995 ns; END IF; END IF; END IF; END PROCESS; ---------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation ---------------------------------------------------------------------------- StateGen :PROCESS(write, Addr, D_tmp0, PDONE, EDONE, reseted, READY_out, PERR, EERR, AS_Exit) VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; --DATA High Byte VARIABLE DataHi : natural RANGE 0 TO MaxData := 0; --DATA Low Byte VARIABLE DataLo : natural RANGE 0 TO MaxData := 0; BEGIN ------------------------------------------------------------------------ -- Functionality Section ------------------------------------------------------------------------ IF falling_edge(write) THEN DataLo := D_tmp0; DataHi := D_tmp1; IF BYTENeg = '1' THEN PATTERN_1 := Addr = 16#5555# AND DataLo = 16#AA# AND DataHi = 16#00#; PATTERN_2 := Addr = 16#2AAA# AND DataLo = 16#55# AND DataHi = 16#00#; A_PAT_1 := Addr = 16#5555#; ELSE PATTERN_1 := Addr = 16#AAAA# AND DataLo = 16#AA#; PATTERN_2 := Addr = 16#5555# AND DataLo = 16#55#; A_PAT_1 := Addr = 16#AAAA#; END IF; END IF; IF reseted /= '1' THEN next_state <= current_state; ELSE CASE current_state IS WHEN RESET => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= Z001; ELSE next_state <= RESET; END IF; END IF; WHEN Z001 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= PREL_SETBWB; ELSE next_state <= RESET; END IF; END IF; WHEN PREL_SETBWB => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo = 16#60# THEN next_state <= HARD_PROT_PREL; ELSIF A_PAT_1 AND DataLo = 16#51# THEN next_state <= SOFT_PROT; ELSIF A_PAT_1 AND DataLo = 16#52# THEN next_state <= SOFT_UNPROT; ELSIF A_PAT_1 AND DataLo = 16#90# THEN next_state <= AS; ELSIF A_PAT_1 AND DataLo = 16#98# THEN next_state <= CFI; ELSIF A_PAT_1 AND DataLo = 16#A0# THEN next_state <= A0SEEN; ELSIF A_PAT_1 AND DataLo = 16#41# THEN next_state <= OTP_WRITE; ELSIF A_PAT_1 AND DataLo = 16#40# THEN next_state <= OTP_READ; ELSIF A_PAT_1 AND DataLo = 16#80# THEN next_state <= C8; ELSE next_state <= RESET; END IF; END IF; WHEN SOFT_PROT => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= SOFT_PROT_EXIT_01; ELSE next_state <= SOFT_PROT; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN SOFT_PROT_EXIT_01 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= SOFT_PROT_EXIT_02; ELSE next_state <= SOFT_PROT; END IF; END IF; WHEN SOFT_PROT_EXIT_02 => IF falling_edge(write) THEN IF NOT(A_PAT_1 AND DataLo = 16#F0#) THEN next_state <= SOFT_PROT; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN SOFT_UNPROT => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= SOFT_UNPROT_EXIT_01; ELSE next_state <= SOFT_UNPROT; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN SOFT_UNPROT_EXIT_01 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= SOFT_UNPROT_EXIT_02; ELSE next_state <= SOFT_UNPROT; END IF; END IF; WHEN SOFT_UNPROT_EXIT_02 => IF falling_edge(write) THEN IF NOT(A_PAT_1 AND DataLo = 16#F0#) THEN next_state <= SOFT_UNPROT; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN HARD_PROT_PREL => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= HARD_PROT_Z001; ELSE next_state <= RESET; END IF; END IF; WHEN HARD_PROT_Z001 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= HARD_PROT; ELSE next_state <= RESET; END IF; END IF; WHEN HARD_PROT => IF falling_edge(write) THEN IF DataLo = 16#61# THEN next_state <= PGMS; ELSE next_state <= RESET; END IF; END IF; WHEN AS => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= AS_EXIT_01; ELSE next_state <= AS; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN AS_EXIT_01 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= AS_EXIT_02; ELSE next_state <= AS; END IF; END IF; WHEN AS_EXIT_02 => IF falling_edge(write) THEN IF NOT(A_PAT_1 AND DataLo = 16#F0#) THEN next_state <= AS; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN CFI => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= CFI_EXIT_01; ELSE next_state <= CFI; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN CFI_EXIT_01 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= CFI_EXIT_02; ELSE next_state <= CFI; END IF; END IF; WHEN CFI_EXIT_02 => IF falling_edge(write) THEN IF NOT(A_PAT_1 AND DataLo = 16#F0#) THEN next_state <= CFI; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN OTP_READ => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= OTP_EXIT_01; ELSE next_state <= OTP_READ; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN OTP_EXIT_01 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= OTP_EXIT_02; ELSE next_state <= OTP_READ; END IF; END IF; WHEN OTP_EXIT_02 => IF falling_edge(write) THEN IF NOT(A_PAT_1 AND DataLo = 16#F0#) THEN next_state <= OTP_READ; END IF; ELSIF rising_edge(AS_Exit) THEN next_state <= RESET; END IF; WHEN A0SEEN => IF falling_edge(write) THEN next_state <= PGMS; END IF; WHEN OTP_WRITE => IF falling_edge(write) THEN next_state <= PGMS; END IF; WHEN C8 => IF falling_edge(write) THEN IF PATTERN_1 THEN next_state <= C8_Z001; ELSE next_state <= RESET; END IF; END IF; WHEN C8_Z001 => IF falling_edge(write) THEN IF PATTERN_2 THEN next_state <= C8_PREL; ELSE next_state <= RESET; END IF; END IF; WHEN C8_PREL => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo = 16#10# THEN next_state <= ERS; ELSIF DataLo = 16#30# THEN next_state <= SERS_EXEC; ELSE next_state <= RESET; END IF; END IF; WHEN ERS | SERS_EXEC => IF rising_edge(EDONE) OR falling_edge(EERR) THEN next_state <= RESET; END IF; WHEN PGMS => IF rising_edge(PDONE) OR falling_edge(PERR) THEN next_state <= RESET; END IF; END CASE; END IF; END PROCESS StateGen; ---------------------------------------------------------------------------- --FSM Output generation and general funcionality ---------------------------------------------------------------------------- Functional : PROCESS(write, read, Addr, D_tmp0, D_tmp1, Address, SecAddr, PDONE, EDONE, RST, READY_out, gOE_n, gCE_n, reseted, current_state) VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE A_PAT_1 : boolean := FALSE; VARIABLE oe : boolean := FALSE; --Status reg. VARIABLE Status : std_logic_vector(7 DOWNTO 0) := (OTHERS=>'0'); VARIABLE dummyreadsts : std_logic_vector(7 DOWNTO 0) := (OTHERS=>'0'); VARIABLE old_bit : std_logic_vector(7 DOWNTO 0); VARIABLE new_bit : std_logic_vector(7 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 1; --DATA High Byte VARIABLE DataHi : natural RANGE 0 TO MaxData := 0; --DATA Low Byte VARIABLE DataLo : natural RANGE 0 TO MaxData := 0; VARIABLE temp : std_logic_vector(7 DOWNTO 0); PROCEDURE set_sector(in_sec : IN natural RANGE 0 TO SecNum; in_data: IN integer RANGE -1 TO MaxData) IS BEGIN IF TimingModel(10) = 'T' THEN IF in_sec <= SecNum-4 THEN Mem(in_sec) := (OTHERS => in_data); ELSIF in_sec = SecNum-3 THEN FOR I IN 0 TO (SecSize+1)/2-1 LOOP Mem(SecNum-3)(I) := in_data; END LOOP; ELSIF in_sec = SecNum-2 THEN FOR I IN (SecSize+1)/2 TO 5*(SecSize+1)/8-1 LOOP Mem(SecNum-3)(I) := in_data; END LOOP; ELSIF in_sec = SecNum-1 THEN FOR I IN 5*(SecSize+1)/8 TO 3*(SecSize+1)/4-1 LOOP Mem(SecNum-3)(I) := in_data; END LOOP; ELSE FOR I IN 3*(SecSize+1)/4-1 TO SecSize LOOP Mem(SecNum-3)(I) := in_data; END LOOP; END IF; ELSE IF in_sec >= 4 THEN Mem(in_sec-3) := (OTHERS => in_data); ELSIF in_sec = 0 THEN FOR I IN 0 TO (SecSize+1)/4-1 LOOP Mem(0)(I) := in_data; END LOOP; ELSIF in_sec = 1 THEN FOR I IN (SecSize+1)/4 TO 3*(SecSize+1)/8-1 LOOP Mem(0)(I) := in_data; END LOOP; ELSIF in_sec = 2 THEN FOR I IN 3*(SecSize+1)/8 TO (SecSize+1)/2-1 LOOP Mem(0)(I) := in_data; END LOOP; ELSE FOR I IN (SecSize+1)/2 TO SecSize LOOP Mem(0)(I) := in_data; END LOOP; END IF; END IF; END set_sector; ---------------------------------------------------------------------------- --Read procedures ---------------------------------------------------------------------------- PROCEDURE MemRead IS BEGIN IF Mem(SecAddr)(Address) = -1 THEN DOut_zd(7 downto 0) <= (OTHERS => 'X'); ELSE DOut_zd(7 downto 0) <= to_slv(Mem(SecAddr)(Address),8); END IF; IF BYTENeg='1' THEN IF Mem(SecAddr)(Address + 1) = -1 THEN DOut_zd(15 downto 8) <= (OTHERS => 'X'); ELSE DOut_zd(15 downto 8) <= to_slv(Mem(SecAddr)(Address + 1),8); END IF; END IF; END; PROCEDURE ASRead IS VARIABLE AsAddress : natural; BEGIN AsAddress := Address; IF BYTENeg = '1' THEN AsAddress := AsAddress / 2; AsAddress := AsAddress MOD 16#100#; IF AsAddress = 0 THEN DOut_zd(15 DOWNTO 0) <= to_slv(16#7F7F#,16); ELSIF AsAddress = 1 THEN IF TimingModel(10) = 'T' THEN DOut_zd(15 DOWNTO 0) <= to_slv(16#B975#,16); ELSE DOut_zd(15 DOWNTO 0) <= to_slv(16#B976#,16); END IF; ELSIF AsAddress = 4 THEN DOut_zd(15 DOWNTO 0) <= to_slv(16#7FA7#,16); ELSIF AsAddress = 2 THEN IF H_Sec_Prot(SecAddr_exact) = '1' THEN DOut_zd(7 DOWNTO 4) <= to_slv(16#1#,4); ELSIF Sec_Prot(SecAddr_exact) = '1' THEN DOut_zd(7 DOWNTO 0) <= to_slv(16#01#,8); ELSE DOut_zd(7 DOWNTO 0) <= to_slv(16#00#,8); END IF; END IF; ELSE AsAddress := AsAddress MOD 16#100#; IF AsAddress = 0 OR AsAddress = 1 THEN DOut_zd(7 DOWNTO 0) <= to_slv(16#7F#,8); ELSIF AsAddress = 8 THEN DOut_zd(7 DOWNTO 0) <= to_slv(16#A7#,8); ELSIF AsAddress = 9 THEN DOut_zd(7 DOWNTO 0) <= to_slv(16#7F#,8); ELSIF AsAddress = 2 THEN IF TimingModel(10) = 'T' THEN DOut_zd(7 DOWNTO 0) <= to_slv(16#75#,8); ELSE DOut_zd(7 DOWNTO 0) <= to_slv(16#76#,8); END IF; ELSIF AsAddress = 3 THEN DOut_zd(7 DOWNTO 0) <= to_slv(16#B9#,8); ELSIF AsAddress = 4 THEN IF H_Sec_Prot(SecAddr_exact) = '1' THEN DOut_zd(7 DOWNTO 4) <= to_slv(16#1#,4); ELSIF Sec_Prot(SecAddr_exact) = '1' THEN DOut_zd(7 DOWNTO 0) <= to_slv(16#01#,8); ELSE DOut_zd(7 DOWNTO 0) <= to_slv(16#00#,8); END IF; END IF; END IF; END ; PROCEDURE CFIRead IS VARIABLE CFIAddress : natural; BEGIN CFIAddress := Address; IF BYTENeg = '1' THEN CFIAddress := CFIAddress / 2; END IF; CFIAddress := CFIAddress MOD 16#100#; IF Addr >= 16#10# AND Addr <= 16#3C# THEN IF BYTENeg = '0' THEN DOut_zd(15 DOWNTO 8) <= (OTHERS => 'Z'); ELSE DOut_zd(15 DOWNTO 8) <= (OTHERS => '0'); END IF; DOut_zd(7 DOWNTO 0) <= to_slv(CFI_array(Addr),8); ELSE ASSERT FALSE REPORT "Invalid CFI query address" SEVERITY warning; END IF; END; BEGIN ------------------------------------------------------------------------ -- Functionality Section ------------------------------------------------------------------------ IF falling_edge(write) THEN DataLo := D_tmp0; DataHi := D_tmp1; IF BYTENeg = '1' THEN PATTERN_1 := Addr = 16#5555# AND DataLo = 16#AA# AND DataHi = 16#00#; PATTERN_2 := Addr = 16#2AAA# AND DataLo = 16#55# AND DataHi = 16#00#; A_PAT_1 := Addr = 16#5555#; ELSE PATTERN_1 := Addr = 16#AAAA# AND DataLo = 16#AA#; PATTERN_2 := Addr = 16#5555# AND DataLo = 16#55#; A_PAT_1 := Addr = 16#AAAA#; END IF; END IF; oe:= rising_edge(read) OR (read = '1' AND (Address'EVENT OR SecAddr'EVENT)); IF reseted = '1' THEN CASE current_state IS WHEN RESET => OTP_ACT <= '0'; HW_ACT <= '0'; IF oe THEN IF readpolling = '1' THEN MemRead; ELSE DOut_zd(7 DOWNTO 0) <= dummyreadsts; readpolling := '1'; END IF; END IF; WHEN Z001 => readpolling := '1'; WHEN PREL_SETBWB => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo = 16#41# THEN OTP_ACT <= '1'; ELSIF (A_PAT_1 AND DataLo = 16#90#) OR (A_PAT_1 AND DataLo = 16#98#) OR (A_PAT_1 AND DataLo = 16#40#) THEN AS_Ent <= '0', '1' AFTER tdevice_INTEXIT; END IF; END IF; WHEN SOFT_PROT => IF falling_edge(write) THEN IF DataLo = 16#50# AND H_Sec_Prot(SecAddr_exact) /= '1' THEN Sec_Prot(SecAddr_exact) := '1'; ELSIF DataLo = 16#F0# THEN AS_Exit <= '0', '1' AFTER tdevice_INTEXIT; END IF; END IF; WHEN SOFT_UNPROT => IF falling_edge(write) THEN IF DataLo = 16#50# THEN Sec_Prot(SecAddr_exact) := '0'; ELSIF DataLo = 16#F0# THEN AS_Exit <= '0', '1' AFTER tdevice_INTEXIT; END IF; END IF; WHEN HARD_PROT => IF falling_edge(write) THEN IF DataLo = 16#61# THEN HW_ACT <= '1'; PSTART <= '1', '0' AFTER 1 ns; Status := "10000000"; SA <= SecAddr; SA_exact <= SecAddr_exact; END IF; END IF; WHEN AS => IF falling_edge(write) THEN IF DataLo = 16#F0# THEN AS_Exit <= '0', '1' AFTER tdevice_INTEXIT; END IF; ELSIF oe THEN IF AS_Ent = '1' THEN ASRead; END IF; END IF; WHEN CFI => IF falling_edge(write) THEN IF DataLo = 16#F0# THEN AS_Exit <= '0', '1' AFTER tdevice_INTEXIT; END IF; ELSIF oe THEN IF AS_Ent = '1' THEN CFIRead; END IF; END IF; WHEN OTP_READ => IF falling_edge(write) THEN IF DataLo = 16#F0# THEN AS_Exit <= '0', '1' AFTER tdevice_INTEXIT; END IF; ELSIF oe THEN IF AS_Ent = '1' THEN IF SEC_LOCK = '1' THEN DOut_zd(3 DOWNTO 0) <= OTP_Prot; ELSE IF OTP(Address MOD (OTPSize + 1)) = -1 THEN DOut_zd(7 DOWNTO 0) <= (OTHERS => 'X'); ELSE DOut_zd(7 DOWNTO 0) <= to_slv(OTP(Address MOD (OTPSize + 1)),8); END IF; IF BYTENeg = '1' THEN IF OTP((Address+1) MOD (OTPSize+1)) = -1 THEN DOut_zd(15 DOWNTO 8) <= (OTHERS => 'X'); ELSE DOut_zd(15 DOWNTO 8) <= to_slv(OTP((Address+1) MOD (OTPSize+1)),8); END IF; END IF; END IF; END IF; END IF; WHEN A0SEEN => IF falling_edge(write) THEN PSTART <= '1', '0' AFTER 1 ns; WBData(0) := -1; WBData(1) := -1; IF Viol = '0' THEN WBData(0) := D_tmp0; WBData(1) := D_tmp1; END IF; WBAddr(0) := Address; SA <= SecAddr; SA_exact <= SecAddr_exact; temp := to_slv(DataLo, 8); Status(7) := NOT temp(7); IF BYTENeg = '1' THEN WBAddr(1) := WBAddr(0) + 1; ELSE WBAddr(1) := -1; END IF; END IF; WHEN OTP_WRITE => IF falling_edge(write) THEN OTP_ACT <= '1'; ------------------------------------------------------------ --OTP programming ------------------------------------------------------------ PSTART <= '1', '0' AFTER 1 ns; WBData(0) := -1; WBData(1) := -1; IF Viol = '0' THEN WBData(0) := D_tmp0; WBData(1) := D_tmp1; END IF; WBAddr(0) := Address MOD (OTPSize + 1); temp := to_slv(DataLo, 8); Status(7) := NOT temp(7); IF BYTENeg = '1' THEN WBAddr(1) := WBAddr(0) + 1; ELSE WBAddr(1) := -1; END IF; END IF; WHEN C8_PREL => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo=16#10# THEN --Start Chip Erase ESTART <= '1', '0' AFTER 1 ns; Ers_Queue <= (OTHERS => '1'); Status := (OTHERS => '0'); ELSIF DataLo=16#30# THEN ESTART <= '1', '0' AFTER 1 ns; Ers_Queue <= (OTHERS => '0'); Ers_Queue(SecAddr_exact) <= '1'; Status := (OTHERS => '0'); END IF; END IF; WHEN ERS => IF oe THEN ------------------------------------------------------------ -- read status / embeded erase algorithm - Chip Erase ------------------------------------------------------------ Status(7) := '0'; Status(6) := NOT Status(6); --toggle DOut_zd(7 DOWNTO 0) <= Status; readpolling := '1'; dummyreadsts(7) := '1'; END IF; IF EERR /= '1' THEN FOR i IN 0 TO SecNum LOOP IF Sec_Prot(i) /= '1' AND H_Sec_Prot(i) /= '1' AND NOT(RESETNeg = '0' AND RST = '0') THEN set_sector(i, -1); END IF; END LOOP; IF EDONE = '1' THEN FOR i IN 0 TO SecNum LOOP IF Sec_Prot(i) /= '1' AND H_Sec_Prot(i) /= '1' THEN set_sector(i, MaxData); END IF; END LOOP; END IF; END IF; WHEN SERS_EXEC => IF oe THEN ------------------------------------------------------------ --read status Erase Busy ------------------------------------------------------------ Status(7) := '0'; Status(6) := NOT Status(6); --toggle DOut_zd(7 DOWNTO 0) <= Status; readpolling := '1'; dummyreadsts(7) := '1'; END IF; IF EERR /= '1' THEN FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND Sec_Prot(i) /= '1' AND H_Sec_Prot(i) /= '1' THEN set_sector(i, -1); END IF; END LOOP; IF EDONE = '1' THEN FOR i IN Ers_Queue'RANGE LOOP IF Ers_Queue(i) = '1' AND Sec_Prot(i) /= '1' AND H_Sec_Prot(i) /= '1' THEN set_sector(i, MaxData); END IF; END LOOP; END IF; END IF; WHEN PGMS => IF oe THEN ------------------------------------------------------------ --read status ------------------------------------------------------------ Status(6) := NOT Status(6); --toggle IF HW_ACT = '1' OR (OTP_ACT = '1' AND SEC_LOCK = '1') THEN Status(7) := '1'; END IF; DOut_zd(7 DOWNTO 0) <= Status; readpolling := '1'; dummyreadsts(7) := NOT Status(7); END IF; IF HW_ACT = '0' THEN IF PERR /='1' THEN IF OTP_ACT = '1' AND SEC_LOCK = '1' THEN OTP_Prot := to_slv(DataLo MOD 16#10#,4); ELSE IF WBAddr(1) < 0 THEN wr_cnt := 0; ELSE wr_cnt := 1; END IF; FOR i IN wr_cnt DOWNTO 0 LOOP new_int:= WBData(i); IF OTP_ACT /= '1' THEN --mem write old_int:=Mem(SA)(WBAddr(i)); ELSE old_int:=OTP(WBAddr(i)); END IF; IF new_int>-1 THEN new_bit:=to_slv(new_int,8); IF old_int>-1 THEN old_bit:=to_slv(old_int,8); FOR j IN 0 TO 7 LOOP IF old_bit(j) = '0' THEN new_bit(j):='0'; END IF; END LOOP; new_int:=to_nat(new_bit); END IF; WBData(i):= new_int; ELSE WBData(i):= -1; END IF; END LOOP; FOR i IN wr_cnt DOWNTO 0 LOOP IF OTP_ACT /= '1' THEN --mem write Mem(SA)(WBAddr(i)) := -1; ELSE OTP(WBAddr(i)) := -1; END IF; END LOOP; IF PDONE = '1' AND (NOT PERR'EVENT) THEN FOR i IN wr_cnt DOWNTO 0 LOOP IF OTP_ACT /= '1' THEN --mem write Mem(SA)(WBAddr(i)) := WBData(i); ELSE OTP(WBAddr(i)) := WBData(i); END IF; WBData(i):= -1; END LOOP; END IF; END IF; END IF; ELSIF PDONE = '1' THEN H_Sec_Prot(SA_exact) := '1'; HW_ACT <= '0'; END IF; WHEN SOFT_PROT_EXIT_02 | SOFT_UNPROT_EXIT_02 | AS_EXIT_02 | CFI_EXIT_02 | OTP_EXIT_02 => IF falling_edge(write) THEN IF A_PAT_1 AND DataLo = 16#F0# THEN AS_Exit <= '0', '1' AFTER tdevice_INTEXIT; END IF; END IF; WHEN C8 | C8_Z001 | HARD_PROT_PREL | SOFT_PROT_EXIT_01 | SOFT_UNPROT_EXIT_01 | AS_EXIT_01 | CFI_EXIT_01 | OTP_EXIT_01 | HARD_PROT_Z001 => null; END CASE; END IF; --Output Disable Control IF gOE_n = '1' OR gCE_n = '1' OR (RESETNeg = '0' AND RST = '0') THEN DOut_zd <= (OTHERS => 'Z'); ELSE IF (BYTENeg = '0') THEN DOut_zd(15 DOWNTO 8) <= (OTHERS =>'Z'); END IF; END IF; --Preload Control ------------------------------------------------------------------------ -- File Read Section ------------------------------------------------------------------------ ------------------------------------------------------------------------ --CFI array data ------------------------------------------------------------------------ --CFI Query Identification String CFI_array(16#10#) := 16#51#; CFI_array(16#11#) := 16#52#; CFI_array(16#12#) := 16#59#; CFI_array(16#13#) := 16#02#; CFI_array(16#14#) := 16#00#; CFI_array(16#15#) := 16#00#; CFI_array(16#16#) := 16#00#; CFI_array(16#17#) := 16#00#; CFI_array(16#18#) := 16#00#; CFI_array(16#19#) := 16#00#; CFI_array(16#1A#) := 16#00#; --System Interface Information CFI_array(16#1B#) := 16#16#; CFI_array(16#1C#) := 16#20#; CFI_array(16#1D#) := 16#00#; CFI_array(16#1E#) := 16#00#; CFI_array(16#1F#) := 16#04#; CFI_array(16#20#) := 16#04#; CFI_array(16#21#) := 16#06#; CFI_array(16#22#) := 16#09#; CFI_array(16#23#) := 16#02#; CFI_array(16#24#) := 16#02#; CFI_array(16#25#) := 16#03#; CFI_array(16#26#) := 16#02#; --Device Geometry Definition CFI_array(16#27#) := 16#14#; CFI_array(16#28#) := 16#02#; CFI_array(16#29#) := 16#00#; CFI_array(16#2A#) := 16#01#; CFI_array(16#2B#) := 16#00#; CFI_array(16#2C#) := 16#04#; CFI_array(16#2D#) := 16#00#; CFI_array(16#2E#) := 16#00#; CFI_array(16#2F#) := 16#40#; CFI_array(16#30#) := 16#00#; CFI_array(16#31#) := 16#01#; CFI_array(16#32#) := 16#00#; CFI_array(16#33#) := 16#20#; CFI_array(16#34#) := 16#00#; CFI_array(16#35#) := 16#00#; CFI_array(16#36#) := 16#00#; CFI_array(16#37#) := 16#80#; CFI_array(16#38#) := 16#00#; CFI_array(16#39#) := 16#0E#; CFI_array(16#3A#) := 16#00#; CFI_array(16#3B#) := 16#00#; CFI_array(16#3C#) := 16#01#; END PROCESS Functional; ---------------------------------------------------------------------------- ---- File Read Section - Preload Control ---------------------------------------------------------------------------- MemPreload : PROCESS -- text file input variables FILE mem_file : text IS mem_file_name; FILE otp_file : text IS otp_file_name; VARIABLE ind : natural RANGE 0 TO MemSize:= 0; VARIABLE ind_sect : natural RANGE 0 TO SecNum-3:= 0; VARIABLE ind_addr : natural RANGE 0 TO SecSize:= 0; VARIABLE buf : line; PROCEDURE RestoreSectAddr ( VARIABLE A : IN natural RANGE 0 TO MemSize; VARIABLE SectAddr : INOUT natural RANGE 0 TO SecNum-3; VARIABLE A_tmp : INOUT natural RANGE 0 TO SecSize ) IS BEGIN FOR I IN 0 TO SecNum-3 LOOP IF A >= I*(SecSize+1) AND A <= I*(SecSize+1) + SecSize THEN SectAddr := I; A_tmp := A - I*(SecSize + 1); END IF; END LOOP; END RestoreSectAddr; BEGIN -------------------------------------------------------------------------------- -----fs29sl800_otp preload file format------------------------------------------ -------------------------------------------------------------------------------- -- / - comment -- @aa - stands for address -- dd -
is byte to be written at OTP(aa++) -- (aa is incremented at every load) -- only first 1-3 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! -------------------------------------------------------------------------------- IF (otp_file_name /= "none" AND UserPreload ) THEN OTP := (OTHERS => MaxData); ind := 0; WHILE (NOT ENDFILE (OTP_file)) LOOP READLINE (OTP_file, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 TO 3)); --address ELSE IF ind <= OTPSize THEN OTP(ind) := h(buf(1 TO 2)); ind := ind + 1; END IF; END IF; END LOOP; END IF; -------------------------------------------------------------------------------- -----fs29sl800 memory preload file format -------------------------------------- -------------------------------------------------------------------------------- -- / - comment -- @aaaaa - stands for address -- dd -
is byte to be written at Mem(aaaaa++) -- (aaaaa is incremented at every load) -- only first 1-6 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! -------------------------------------------------------------------------------- IF (mem_file_name /= "none" AND UserPreload ) THEN ind := 0; Mem := (OTHERS => (OTHERS => MaxData)); WHILE (NOT ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '/' THEN --comment NEXT; ELSIF buf(1) = '@' THEN --address ind := h(buf(2 TO 6)); ELSE IF ind <= MemSize THEN RestoreSectAddr(ind, ind_sect, ind_addr); Mem(ind_sect)(ind_addr) := h(buf(1 TO 2)); ELSE ASSERT FALSE REPORT " Memory address out of range" SEVERITY warning; END IF; IF ind < MemSize THEN ind := ind + 1; END IF; END IF; END LOOP; END IF; WAIT; END PROCESS MemPreload; 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 := ADDR_event - NOW + tpd_A0_DQ0(tr01); FROMOE := (OEDQ_t >= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t > OEDQ_t) AND (CEDQ_t > 0 ns); IF BYTENeg = '0' THEN ValidData := "ZZZZZZZZXXXXXXXX"; ELSE ValidData := "XXXXXXXXXXXXXXXX"; END IF; 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 CEDQ_t := -CENeg'LAST_EVENT + tpd_CENeg_DQ0(tr0z); OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_DQ0(tr0z); FROMOE := (OEDQ_t <= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t < OEDQ_t) AND (CEDQ_t > 0 ns); OPENLATCH := FALSE; DOut_Pass <= DOut_zd; END IF; END PROCESS DOutPassThrough; ---------------------------------------------------------------------------- -- Path Delay Section for DOut signal ---------------------------------------------------------------------------- D_Out_PathDelay_Gen : FOR i IN 0 TO 7 GENERATE PROCESS(DOut_Pass(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_Pass(i), GlitchData => D0_GlitchData, IgnoreDefaultDelay => TRUE, Mode => VitalTransport, RejectFastPath => FALSE, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => (NOT OPENLATCH AND NOT FROMOE) OR (OPENLATCH AND FROMCE)), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => (NOT OPENLATCH AND NOT FROMCE) OR (OPENLATCH AND FROMOE)), 2 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => NOT FROMOE AND NOT FROMCE), 3 => (InputChangeTime => Din(15)'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => BYTENeg = '0' AND DOut_pass(i) /= 'X'), 4 => (InputChangeTime => BYTENeg'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_BYTENeg_DQ0), PathCondition => BYTENeg = '1'), 5 => (InputChangeTime => RESETNeg'LAST_EVENT, PathDelay => tpd_RESETNeg_DQ0, PathCondition => RESETNeg = '0') ) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; ---------------------------------------------------------------------------- -- Path Delay Section for DOut signal ---------------------------------------------------------------------------- D_Out_15_7_PathDelay_Gen : FOR i IN 8 TO 15 GENERATE PROCESS(DOut_Pass(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_Pass(i), GlitchData => D0_GlitchData, IgnoreDefaultDelay => TRUE, Mode => VitalTransport, RejectFastPath => FALSE, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => (NOT OPENLATCH AND NOT FROMOE) OR (OPENLATCH AND FROMCE)), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => (NOT OPENLATCH AND NOT FROMCE) OR (OPENLATCH AND FROMOE)), 2 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => NOT FROMOE AND NOT FROMCE), 3 => (InputChangeTime => Din(15)'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => BYTENeg = '0' AND DOut_pass(i) /= 'X'), 4 => (InputChangeTime => BYTENeg'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_BYTENeg_DQ0), PathCondition => BYTENeg = '1'), 5 => (InputChangeTime => RESETNeg'LAST_EVENT, PathDelay => tpd_RESETNeg_DQ0, PathCondition => RESETNeg='0'), 6 => (InputChangeTime => BYTENeg'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_BYTENeg_DQ0), PathCondition => BYTENeg = '0') ) ); END PROCESS; END GENERATE D_Out_15_7_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral;