-------------------------------------------------------------------------------- -- File name : s29xs256r.vhd -------------------------------------------------------------------------------- -- Copyright (C) 2008 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 B.Colakovic 08 Sep 29 Initial Release -------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH -- Technology: FLASH MEMORY -- Part: s29xs256r -- -- Description: 256 Megabit (16M x 16 bit) 1.8 V -- Burst Simultaneous Read/Write -- Multiplexed MirrorBit Flash Memory -------------------------------------------------------------------------------- -- Comments : -- For correct simulation, simulator resolution should be set to 1 ps -- 16th character in TimingModel determines whether top or bottom boot -- architecture is used -------------------------------------------------------------------------------- -- 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 s29xs256r IS GENERIC( --tipd delays: interconnect path delays 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_ADQ0 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ1 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ2 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ3 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ4 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ5 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ6 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ7 :VitalDelayType01 := VitalZeroDelay01; --data tipd_ADQ8 :VitalDelayType01 := VitalZeroDelay01; --lines tipd_ADQ9 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ10 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ11 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ12 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ13 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ14 :VitalDelayType01 := VitalZeroDelay01; -- tipd_ADQ15 :VitalDelayType01 := VitalZeroDelay01; -- tipd_CLK :VitalDelayType01 := VitalZeroDelay01; -- tipd_CENeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_OENeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_WENeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_RESETNeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_AVDNeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_VPP :VitalDelayType01 := VitalZeroDelay01; -- --tpd delays tpd_RESETNeg_ADQ0 :VitalDelayType01Z := UnitDelay01Z; tpd_A16_ADQ0 :VitalDelayType01 := UnitDelay01; -- tacc tpd_CENeg_ADQ0_SYN_EQ_0 :VitalDelayType01Z := UnitDelay01Z; -- tce, tcez tpd_CENeg_ADQ0_SYN_EQ_1 :VitalDelayType01Z := UnitDelay01Z; -- tce, tcez tpd_OENeg_ADQ0_SYN_EQ_0 :VitalDelayType01Z := UnitDelay01Z; -- toe, toez tpd_OENeg_ADQ0_SYN_EQ_1 :VitalDelayType01Z := UnitDelay01Z; -- toe, toez tpd_CLK_ADQ0 :VitalDelayType01 := UnitDelay01; -- tbacc tpd_CENeg_RDY_SYN_EQ_0 :VitalDelayType01Z := UnitDelay01Z; -- tcr, tcez tpd_CENeg_RDY_SYN_EQ_1 :VitalDelayType01Z := UnitDelay01Z; -- tcr, tcez tpd_OENeg_RDY :VitalDelayType01 := UnitDelay01; -- toe tpd_CLK_RDY :VitalDelayType01 := UnitDelay01; -- tracc --tsetup values tsetup_CENeg_CLK :VitalDelayType := UnitDelay; -- tces edge / tsetup_ADQ0_CLK :VitalDelayType := UnitDelay; -- tacs edge / tsetup_ADQ0_AVDNeg :VitalDelayType := UnitDelay; -- tas edge / tsetup_AVDNeg_CLK :VitalDelayType := UnitDelay; -- tavc edge / tsetup_ADQ0_WENeg :VitalDelayType := UnitDelay; -- tawes edge \ tsetup_AVDNeg_WENeg :VitalDelayType := UnitDelay; -- tds edge / tsetup_AVDNeg_OENeg :VitalDelayType := UnitDelay; -- tavdo edge \ tsetup_WENeg_AVDNeg :VitalDelayType := UnitDelay; -- twea edge \ tsetup_OENeg_WENeg :VitalDelayType := UnitDelay; -- tweh edge \ tsetup_WENeg_OENeg :VitalDelayType := UnitDelay; -- tweh edge \ tsetup_CENeg_WENeg :VitalDelayType := UnitDelay; -- tcs edge \ tsetup_RESETNeg_CENeg:VitalDelayType := UnitDelay; -- trh edge \ --thold values thold_CENeg_RESETNeg :VitalDelayType := UnitDelay; -- trph edge \ thold_ADQ0_CLK :VitalDelayType := UnitDelay; -- tach edge / thold_ADQ0_AVDNeg :VitalDelayType :=UnitDelay; -- taavdh edge / thold_AVDNeg_CLK :VitalDelayType := UnitDelay; -- tavd edge / --tpw values: pulse width tpw_RESETNeg_negedge :VitalDelayType := UnitDelay; -- trp tpw_AVDNeg_negedge :VitalDelayType := UnitDelay; -- tavdp tpw_WENeg_negedge :VitalDelayType := UnitDelay; -- twp tpw_WENeg_posedge :VitalDelayType := UnitDelay; -- twph tpw_CLK_negedge :VitalDelayType := UnitDelay; -- tcl tpw_CLK_posedge :VitalDelayType := UnitDelay; -- tch --tperiod values tperiod_WENeg :VitalDelayType := UnitDelay; --twc tperiod_CLK :VitalDelayType := UnitDelay; --tclk --tdevice values: values for internal delays --Write Buffer Program tdevice_WRBO :VitalDelayType := 9.4 us; -- Sector Erase Operation -- 64 Kword sector tdevice_SEO64 :VitalDelayType := 1.3 sec; -- 16 Kword sector tdevice_SEO16 :VitalDelayType := 0.6 sec; -- Initial access delay tIA tdevice_IACC :VitalDelayType := 75 ns; -- Program/Erase Suspend Timeout tESL, tPSL tdevice_START :VitalDelayType := 30 us; -- Blank Check Time tdevice_BCHECK :VitalDelayType := 1 ms; -- 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"; secsi_file_name : STRING := "none"; UserPreload : BOOLEAN := FALSE; LongTiming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING ); PORT ( A16 :IN std_ulogic := 'U'; -- A17 :IN std_ulogic := 'U'; -- A18 :IN std_ulogic := 'U'; -- A19 :IN std_ulogic := 'U'; -- A20 :IN std_ulogic := 'U'; -- A21 :IN std_ulogic := 'U'; -- A22 :IN std_ulogic := 'U'; -- A23 :IN std_ulogic := 'U'; -- ADQ15 : INOUT std_ulogic := 'U'; -- ADQ14 : INOUT std_ulogic := 'U'; -- ADQ13 : INOUT std_ulogic := 'U'; -- ADQ12 : INOUT std_ulogic := 'U'; -- ADQ11 : INOUT std_ulogic := 'U'; -- ADQ10 : INOUT std_ulogic := 'U'; -- ADQ9 : INOUT std_ulogic := 'U'; -- data ADQ8 : INOUT std_ulogic := 'U'; -- lines ADQ7 : INOUT std_ulogic := 'U'; -- ADQ6 : INOUT std_ulogic := 'U'; -- ADQ5 : INOUT std_ulogic := 'U'; -- ADQ4 : INOUT std_ulogic := 'U'; -- ADQ3 : INOUT std_ulogic := 'U'; -- ADQ2 : INOUT std_ulogic := 'U'; -- ADQ1 : INOUT std_ulogic := 'U'; -- ADQ0 : INOUT std_ulogic := 'U'; -- CLK :IN std_ulogic := 'U'; -- RESETNeg :IN std_ulogic := 'U'; -- CENeg :IN std_ulogic := 'U'; -- OENeg :IN std_ulogic := 'U'; -- WENeg :IN std_ulogic := 'U'; -- AVDNeg :IN std_ulogic := 'U'; -- VPP :IN std_ulogic := 'U'; -- RDY :OUT std_ulogic := 'U' -- ); ATTRIBUTE VITAL_LEVEL0 of s29xs256r : ENTITY IS TRUE; END s29xs256r; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of s29xs256r IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID :STRING := "s29xs256r"; CONSTANT MaxData :NATURAL := 16#FFFF#; CONSTANT MemSize :NATURAL := 16#FFFFFF#; CONSTANT SecNum :NATURAL := 258; CONSTANT BankNum :NATURAL := 7; CONSTANT SecGroupNum :NATURAL := 1; CONSTANT SecSize64 :NATURAL := 16#FFFF#; CONSTANT SecSize16 :NATURAL := 16#3FFF#; CONSTANT BankSize :NATURAL := 16#1FFFFF#; CONSTANT HiAddrBit :NATURAL := 23; CONSTANT WrBuffLength :NATURAL := 31; CONSTANT WrBuffPgNum :NATURAL := 16#7FFFF#; CONSTANT Reserved0 :STD_LOGIC := '0'; CONSTANT Reserved1 :STD_LOGIC := '1'; -- interconnect path delay signals 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 ADQ15_ipd :std_ulogic := 'U'; SIGNAL ADQ14_ipd :std_ulogic := 'U'; SIGNAL ADQ13_ipd :std_ulogic := 'U'; SIGNAL ADQ12_ipd :std_ulogic := 'U'; SIGNAL ADQ11_ipd :std_ulogic := 'U'; SIGNAL ADQ10_ipd :std_ulogic := 'U'; SIGNAL ADQ9_ipd :std_ulogic := 'U'; SIGNAL ADQ8_ipd :std_ulogic := 'U'; SIGNAL ADQ7_ipd :std_ulogic := 'U'; SIGNAL ADQ6_ipd :std_ulogic := 'U'; SIGNAL ADQ5_ipd :std_ulogic := 'U'; SIGNAL ADQ4_ipd :std_ulogic := 'U'; SIGNAL ADQ3_ipd :std_ulogic := 'U'; SIGNAL ADQ2_ipd :std_ulogic := 'U'; SIGNAL ADQ1_ipd :std_ulogic := 'U'; SIGNAL ADQ0_ipd :std_ulogic := 'U'; SIGNAL CLK_ipd :std_ulogic := 'U'; SIGNAL RESETNeg_ipd :std_ulogic := 'U'; SIGNAL CENeg_ipd :std_ulogic := 'U'; SIGNAL OENeg_ipd :std_ulogic := 'U'; SIGNAL WENeg_ipd :std_ulogic := 'U'; SIGNAL AVDNeg_ipd :std_ulogic := 'U'; SIGNAL VPP_ipd :std_ulogic := 'U'; -- internal delays SIGNAL IACC_in :std_ulogic := '0';-- Initial access delay SIGNAL IACC_out :std_ulogic := '0';-- SIGNAL START_in :std_ulogic := '0';-- Program/Erase Suspend SIGNAL START_out :std_ulogic := '0';-- Timeout -- Annotate SIGNAL P1_in : std_ulogic := '0'; SIGNAL P1_out : std_ulogic := '0'; SIGNAL P2_in : std_ulogic := '0'; SIGNAL P2_out : std_ulogic := '0'; SIGNAL P3_in : std_ulogic := '0'; SIGNAL P3_out : std_ulogic := '0'; SIGNAL P4_in : std_ulogic := '0'; SIGNAL P4_out : std_ulogic := '0'; SIGNAL P5_in : std_ulogic := '0'; SIGNAL P5_out : std_ulogic := '0'; SIGNAL P6_in : std_ulogic := '0'; SIGNAL P6_out : std_ulogic := '0'; BEGIN ---------------------------------------------------------------------------- -- INTERNAL DELAYS ---------------------------------------------------------------------------- -- VITAL primitives which incorporate internal delays WRBO :VitalBUF(P1_out, P1_in,tpd_a_q=>(tdevice_WRBO,UnitDelay)); SEO64 :VitalBUF(P2_out, P2_in,tpd_a_q=>(tdevice_SEO64,UnitDelay)); SEO16 :VitalBUF(P3_out, P3_in,tpd_a_q=>(tdevice_SEO16,UnitDelay)); IACC :VitalBuf(P4_out, P4_in,tpd_a_q=>(tdevice_IACC,UnitDelay)); START :VitalBUF(P5_out, P5_in,tpd_a_q=>(tdevice_START,UnitDelay)); BCHECK :VitalBUF(P6_out, P6_in,tpd_a_q=>(tdevice_BCHECK,UnitDelay)); ---------------------------------------------------------------------------- -- WIRE DELAYS ---------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay( A23_ipd,A23,tipd_A23 ); w_2 : VitalWireDelay( A22_ipd,A22,tipd_A22 ); w_3 : VitalWireDelay( A21_ipd,A21,tipd_A21 ); w_4 : VitalWireDelay( A20_ipd,A20,tipd_A20 ); w_5 : VitalWireDelay( A19_ipd,A19,tipd_A19 ); w_6 : VitalWireDelay( A18_ipd,A18,tipd_A18 ); w_7 : VitalWireDelay( A17_ipd,A17,tipd_A17 ); w_8 : VitalWireDelay( A16_ipd,A16,tipd_A16 ); w_9: VitalWireDelay( ADQ15_ipd,ADQ15,tipd_ADQ15 ); w_10: VitalWireDelay( ADQ14_ipd,ADQ14,tipd_ADQ14 ); w_11: VitalWireDelay( ADQ13_ipd,ADQ13,tipd_ADQ13 ); w_12: VitalWireDelay( ADQ12_ipd,ADQ12,tipd_ADQ12 ); w_13: VitalWireDelay( ADQ11_ipd,ADQ11,tipd_ADQ11 ); w_14: VitalWireDelay( ADQ10_ipd,ADQ10,tipd_ADQ10 ); w_15: VitalWireDelay( ADQ9_ipd,ADQ9,tipd_ADQ9 ); w_16: VitalWireDelay( ADQ8_ipd,ADQ8,tipd_ADQ8 ); w_17: VitalWireDelay( ADQ7_ipd,ADQ7,tipd_ADQ7 ); w_18: VitalWireDelay( ADQ6_ipd,ADQ6,tipd_ADQ6 ); w_19: VitalWireDelay( ADQ5_ipd,ADQ5,tipd_ADQ5 ); w_20: VitalWireDelay( ADQ4_ipd,ADQ4,tipd_ADQ4 ); w_21: VitalWireDelay( ADQ3_ipd,ADQ3,tipd_ADQ3 ); w_22: VitalWireDelay( ADQ2_ipd,ADQ2,tipd_ADQ2 ); w_23: VitalWireDelay( ADQ1_ipd,ADQ1,tipd_ADQ1 ); w_24: VitalWireDelay( ADQ0_ipd,ADQ0,tipd_ADQ0 ); w_25: VitalWireDelay( CLK_ipd,CLK,tipd_CLK ); w_26: VitalWireDelay( RESETNeg_ipd,RESETNeg,tipd_RESETNeg ); w_27: VitalWireDelay( CENeg_ipd,CENeg,tipd_CENeg ); w_28: VitalWireDelay( OENeg_ipd,OENeg,tipd_OENeg ); w_29: VitalWireDelay( WENeg_ipd,WENeg,tipd_WENeg ); w_30: VitalWireDelay( AVDNeg_ipd,AVDNeg,tipd_AVDNeg ); w_31: VitalWireDelay( VPP_ipd,VPP,tipd_VPP ); END BLOCK WireDelay; ---------------------------------------------------------------------------- -- 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'); CLK :IN std_ulogic := 'U'; -- RESETNeg :IN std_ulogic := 'U'; -- CENeg :IN std_ulogic := 'U'; -- OENeg :IN std_ulogic := 'U'; -- WENeg :IN std_ulogic := 'U'; -- AVDNeg :IN std_ulogic := 'U'; -- VPP :IN std_ulogic := 'U'; -- RDY :OUT std_ulogic := 'U' -- ); PORT MAP ( 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) => ADQ15_ipd, A(14) => ADQ14_ipd, A(13) => ADQ13_ipd, A(12) => ADQ12_ipd, A(11) => ADQ11_ipd, A(10) => ADQ10_ipd, A(9) => ADQ9_ipd, A(8) => ADQ8_ipd, A(7) => ADQ7_ipd, A(6) => ADQ6_ipd, A(5) => ADQ5_ipd, A(4) => ADQ4_ipd, A(3) => ADQ3_ipd, A(2) => ADQ2_ipd, A(1) => ADQ1_ipd, A(0) => ADQ0_ipd, DIn(15) => ADQ15_ipd, DIn(14) => ADQ14_ipd, DIn(13) => ADQ13_ipd, DIn(12) => ADQ12_ipd, DIn(11) => ADQ11_ipd, DIn(10) => ADQ10_ipd, DIn(9) => ADQ9_ipd, DIn(8) => ADQ8_ipd, DIn(7) => ADQ7_ipd, DIn(6) => ADQ6_ipd, DIn(5) => ADQ5_ipd, DIn(4) => ADQ4_ipd, DIn(3) => ADQ3_ipd, DIn(2) => ADQ2_ipd, DIn(1) => ADQ1_ipd, DIn(0) => ADQ0_ipd, DOut(15) => ADQ15, DOut(14) => ADQ14, DOut(13) => ADQ13, DOut(12) => ADQ12, DOut(11) => ADQ11, DOut(10) => ADQ10, DOut(9) => ADQ9, DOut(8) => ADQ8, DOut(7) => ADQ7, DOut(6) => ADQ6, DOut(5) => ADQ5, DOut(4) => ADQ4, DOut(3) => ADQ3, DOut(2) => ADQ2, DOut(1) => ADQ1, DOut(0) => ADQ0, CLK => CLK_ipd, RESETNeg => RESETNeg_ipd, CENeg => CENeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, AVDNeg => AVDNeg_ipd, VPP => VPP_ipd, RDY => RDY ); -- State Machine : State_Type TYPE state_type IS (IDLE_RST, ERASE_ENTRY, ID_CFI_ENTRY, SL_ENTRY, SSR_LOCK_ENTRY, SecSi_ENTRY, CR_ENTRY, W2B_ENTRY, BC_ENTRY, CERS, SERS, SL_Change, W2B_WC, SERS_SL, LOCK_RANGE, W2BUF_PG, WB_LOADED, SERS_SUS, PGM, PGM_SL, PGM_SUS); TYPE RD_MODE_type IS( SYNCR, NOSYNC, LINEAR, CONTINUOUS ); --Flash Memory Array TYPE SecGroupAddr IS ARRAY (0 TO SecGroupNum) OF NATURAL; TYPE MemArr IS ARRAY (0 TO MemSize) OF INTEGER RANGE -1 TO MaxData; --SecSi Memory Array TYPE SecSiArr IS ARRAY (0 TO 16#FF# ) OF INTEGER RANGE -1 TO MaxData; --CFI Array TYPE CFIArr IS ARRAY (16#10# TO 16#67#) OF INTEGER RANGE -1 TO MaxData; --Write Buffer Array TYPE WrBuffDataArr IS ARRAY (0 TO WrBuffLength) OF INTEGER RANGE -1 TO MaxData; TYPE WrBuffAddrArr IS ARRAY (0 TO WrBuffLength) OF INTEGER RANGE -1 TO MemSize; -- states SIGNAL current_state : state_type; SIGNAL next_state : state_type; SIGNAL RD_MODE : RD_MODE_type; -- powerup SIGNAL PoweredUp : std_logic := '0'; SHARED VARIABLE SYN : std_logic := '0'; --Synchronous mode --FSM control signals SIGNAL ESP_ACT : std_logic := '0'; SIGNAL PGM_ACT : std_logic := '0'; SIGNAL LOCK_ACT : std_logic := '0'; SIGNAL CR_ACT : std_logic := '0'; SIGNAL SecSi : std_logic := '0'; SIGNAL STAT_ACT : std_logic := '0'; SIGNAL PDONE : std_logic := '1'; --Programming Done SIGNAL PSTART : std_logic := '0'; --Start Programming SIGNAL PSUSP : std_logic := '0'; --Suspend Programming SIGNAL PRES : std_logic := '0'; --Resume Programming SIGNAL EDONE : std_logic := '1'; --Erase Done SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL ESUSP : std_logic := '0'; --Suspend Erase SIGNAL ERES : std_logic := '0'; --Resume Erase SIGNAL BCDONE : std_logic := '1'; --Blank Check Done SIGNAL CEDONE : std_logic := '1'; --Chip Erase Done SIGNAL WRITE : std_logic := '1'; SIGNAL READ : std_logic := '1'; SIGNAL BURST : std_logic := '1'; SIGNAL ReadINIT : std_logic := '1'; SIGNAL DOut_zd : std_logic_vector(15 downto 0) := (OTHERS=>'Z'); SIGNAL DOut_Pass : std_logic_vector(15 downto 0) := (OTHERS=>'Z'); SIGNAL RDY_zd : std_logic := 'Z'; SHARED VARIABLE OutputD : std_logic_vector(15 downto 0); SHARED VARIABLE UpperAddress : std_logic_vector(15 downto 0):=(OTHERS=>'0'); SIGNAL PrevAddr : INTEGER RANGE -1 TO MemSize := -1; SHARED VARIABLE LockRangeDone : BOOLEAN:=FALSE; -- Access time variables SHARED VARIABLE FROMCE : BOOLEAN:=FALSE; SHARED VARIABLE FROMOE : BOOLEAN:=FALSE; SHARED VARIABLE FROMADDR : BOOLEAN:=FALSE; SHARED VARIABLE OPENLATCH : BOOLEAN; SHARED VARIABLE AddrTime : TIME; --Address SIGNAL Addr : INTEGER RANGE -1 TO MemSize := -1; --Sector Address SIGNAL SecAddr : INTEGER RANGE -1 TO SecNum := -1; --Bank Address SIGNAL BankID : INTEGER RANGE -1 TO BankNum := -1; -- Write page buffer address SIGNAL BuffPageAddr : INTEGER RANGE -1 TO WrBuffPgNum; CONSTANT sgsaT : SecGroupAddr := (16#000000#,16#FF0000#); CONSTANT sgsaB : SecGroupAddr := (16#000000#,16#010000#); --Data SIGNAL D_tmp : INTEGER RANGE -1 TO MaxData; SIGNAL BA_ERS : INTEGER RANGE -1 TO BankNum; SIGNAL BA_PGM : INTEGER RANGE -1 TO BankNum; SIGNAL BA_BC : INTEGER RANGE -1 TO BankNum; SIGNAL SA_ERS : INTEGER RANGE -1 TO SecNum; SIGNAL SA_SSR : INTEGER RANGE -1 TO SecNum; SIGNAL SA_SecSi : INTEGER RANGE -1 TO SecNum; SIGNAL SA_CR : INTEGER RANGE -1 TO SecNum; SIGNAL SA_PGM : INTEGER RANGE -1 TO SecNum; SIGNAL SA_SR : INTEGER RANGE -1 TO SecNum; SIGNAL SA_ID_CFI : INTEGER RANGE -1 TO SecNum; SIGNAL SA_BC : INTEGER RANGE -1 TO SecNum; SIGNAL SL_REG : INTEGER RANGE -2 TO SecNum; SIGNAL PA_PGM : INTEGER RANGE -1 TO WrBuffPgNum; --glitch protection SIGNAL gWE_n : std_logic := '1'; SIGNAL gCE_n : std_logic := '1'; SIGNAL gOE_n : std_logic := '1'; SIGNAL gAVD_n : std_logic := '1'; SIGNAL AddrREF : std_logic := '0'; SIGNAL CLKMerge : std_logic := '0'; SHARED VARIABLE IN_W_ELAPSED: BOOLEAN; SHARED VARIABLE DATA_DELAY : BOOLEAN; --reset timing SIGNAL RST : std_logic := '0'; SIGNAL reseted : std_logic := '0'; -- Mem(Address) SHARED VARIABLE Mem : MemArr := (OTHERS => MaxData); -- SecSi Sector SHARED VARIABLE SecSiMem: SecSiArr := (OTHERS => MaxData); -- CFI Sector SHARED VARIABLE CFIMem : CFIArr; SHARED VARIABLE ConfReg0 : std_logic_vector(15 downto 0) := "1101111101001000"; SHARED VARIABLE SSR_LOCK_REG : std_logic_vector(15 downto 0) := "1111111111111101"; -- Write Buffer Signals SIGNAL WrBuffData : WrBuffDataArr := ( OTHERS => -1); SIGNAL WrBuffAddr : WrBuffAddrArr := ( OTHERS => -1); SIGNAL WrBuffCnt : NATURAL RANGE 0 TO WrBuffLength; SIGNAL WC : NATURAL RANGE 0 TO WrBuffLength; SIGNAL RDY_temp : std_logic; SHARED VARIABLE BurstDelay : NATURAL; SHARED VARIABLE WS_Initial : NATURAL; SHARED VARIABLE BurstStarted : boolean; SHARED VARIABLE Check_freq : boolean; FUNCTION ReturnAddr(ADDR : NATURAL; SADDR : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; BEGIN IF SADDR <= 3 AND TimingModel(16) = '1' THEN result := ADDR MOD (SecSize16+1); ELSIF TimingModel(16) = '1' THEN result := ADDR MOD (SecSize64+1); ELSIF SADDR < (SecNum-3) AND TimingModel(16) = '0' THEN result := ADDR MOD (SecSize64+1); ELSE result := ADDR MOD (SecSize16+1); END IF; RETURN result; END ReturnAddr; FUNCTION ReturnSectorID(ADDR : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; VARIABLE conv : NATURAL; BEGIN conv := ADDR / (SecSize64+1); IF conv = 0 AND TimingModel(16) = '1' THEN result := (ADDR - sgsaB(0)) / (SecSize16+1); ELSIF TimingModel(16) = '1' THEN result := 3 + conv; ELSIF conv = SecNum - 3 AND TimingModel(16) = '0' THEN result := SecNum - 3 + (ADDR - sgsaT(1))/(SecSize16+1); ELSE result := conv; END IF; RETURN result; END ReturnSectorID; FUNCTION ReturnBuffPage(ADDR : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; BEGIN result := ADDR / (WrBuffLength+1); RETURN result; END ReturnBuffPage; FUNCTION ReturnBank(ADDR : NATURAL) RETURN NATURAL IS VARIABLE BankResult : NATURAL; BEGIN BankResult := ADDR/(BankSize+1); RETURN BankResult; END ReturnBank; BEGIN ---------------------------------------------------------------------------- --Power Up time tVCS ---------------------------------------------------------------------------- PoweredUp <= '1' AFTER 300 us; RSTtiming: PROCESS(RESETNeg) BEGIN IF falling_edge(RESETNeg) THEN RST <= '0' AFTER 50 ns; ELSIF rising_edge(RESETNeg) THEN RST <= '1'; END IF; END PROCESS; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck:PROCESS(A, DIn, CENeg, OENeg, WENeg, RESETNeg, CLK, AVDNeg) -- Timing Check Variables VARIABLE Tviol_CENeg_CLK : X01 := '0'; VARIABLE TD_CENeg_CLK : VitalTimingDataType; VARIABLE Tviol_A_CLK : X01 := '0'; VARIABLE TD_A_CLK : VitalTimingDataType; VARIABLE Tviol_AVDNeg_CLK : X01 := '0'; VARIABLE TD_AVDNeg_CLK : VitalTimingDataType; VARIABLE Tviol_A_AVDNeg : X01 := '0'; VARIABLE TD_A_AVDNeg : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg : X01 := '0'; VARIABLE TD_OENeg_WENeg : VitalTimingDataType; VARIABLE Tviol_WENeg_OENeg : X01 := '0'; VARIABLE TD_WENeg_OENeg : VitalTimingDataType; VARIABLE Tviol_AVDNeg_WENeg : X01 := '0'; VARIABLE TD_AVDNeg_WENeg : VitalTimingDataType; VARIABLE Tviol_AVDNeg_OENeg : X01 := '0'; VARIABLE TD_AVDNeg_OENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg : X01 := '0'; VARIABLE TD_CENeg_WENeg : VitalTimingDataType; VARIABLE Tviol_WENeg_CENeg : X01 := '0'; VARIABLE TD_WENeg_CENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_RESETNeg : X01 := '0'; VARIABLE TD_OENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_CENeg_AVDNeg : X01 := '0'; VARIABLE TD_CENeg_AVDNeg : VitalTimingDataType; VARIABLE Tviol_WENeg_AVDNeg : X01 := '0'; VARIABLE TD_WENeg_AVDNeg : VitalTimingDataType; VARIABLE Tviol_RESETNeg_OENeg : X01 := '0'; VARIABLE TD_RESETNeg_OENeg : VitalTimingDataType; VARIABLE Tviol_RESETNeg_CENeg : X01 := '0'; VARIABLE TD_RESETNeg_CENeg : VitalTimingDataType; VARIABLE Pviol_AVDNeg : X01 := '0'; VARIABLE PD_AVDNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE PViol_CLK : X01 := '0'; VARIABLE PD_CLK : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup Check between CENeg and CLK VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_CENeg_CLK, CheckEnabled => ConfReg0(15) = '0' AND AVDNeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLK, Violation => Tviol_CENeg_CLK ); -- Setup/Hold Check between A and CLK VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_ADQ0_CLK, SetupHigh => tsetup_ADQ0_CLK, HoldHigh => thold_ADQ0_CLK, HoldLow => thold_ADQ0_CLK, CheckEnabled => ConfReg0(15) = '0' AND AVDNeg = '0' AND CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A_CLK, Violation => Tviol_A_CLK ); --- Setup/Hold Check between AVDNeg and CLK VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_AVDNeg_CLK, HoldLow => thold_AVDNeg_CLK, CheckEnabled => ConfReg0(15) = '0' AND CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_CLK, Violation => Tviol_AVDNeg_CLK ); -- Setup/Hold Check between A and AVDNeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => AVDNeg, RefSignalName => "AVD#", SetupLow => tsetup_ADQ0_AVDNeg, SetupHigh => tsetup_ADQ0_AVDNeg, HoldHigh => thold_ADQ0_AVDNeg, HoldLow => thold_ADQ0_AVDNeg, CheckEnabled => ConfReg0(15) = '0' AND CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A_AVDNeg, Violation => Tviol_A_AVDNeg ); -- Setup Check between DATA and WENeg VitalSetupHoldCheck ( TestSignal => DIn, TestSignalName => "DIn", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_ADQ0_WENeg, SetupLow => tsetup_ADQ0_WENeg, CheckEnabled => CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_WENeg, Violation => Tviol_DQ0_WENeg ); -- Setup Check between DATA and CENeg VitalSetupHoldCheck ( TestSignal => DIn, TestSignalName => "DIn", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_ADQ0_WENeg, SetupLow => tsetup_ADQ0_WENeg, CheckEnabled => WENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CENeg, Violation => Tviol_DQ0_CENeg ); -- Setup Check between AVDNeg and WENeg VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_AVDNeg_WENeg, CheckEnabled => CENeg='0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_WENeg, Violation => Tviol_AVDNeg_WENeg ); -- Setup Check between AVDNeg and OENeg VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => OENeg, RefSignalName => "OENeg", SetupHigh => tsetup_AVDNeg_OENeg, CheckEnabled => CENeg='0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_OENeg, Violation => Tviol_AVDNeg_OENeg ); -- Setup Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg, Violation => Tviol_CENeg_WENeg ); -- Setup Check between WENeg and CENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CENeg, RefSignalName => "CENeg", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg, Violation => Tviol_WENeg_CENeg ); -- Setup Check between OENeg and WENeg VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_OENeg_WENeg, CheckEnabled => CENeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg, Violation => TViol_OENeg_WENeg ); -- Setup Check between WENeg and OENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => OENeg, RefSignalName => "OE#", SetupHigh => tsetup_WENeg_OENeg, CheckEnabled => CENeg = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_OENeg, Violation => TViol_WENeg_OENeg ); -- Hold Check between OENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_RESETNeg, Violation => Tviol_OENeg_RESETNeg ); -- Hold Check between CENeg and RESETNeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RESETNeg, Violation => Tviol_CENeg_RESETNeg ); -- Setup Check between CENeg and AVDNeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupLow => tpw_AVDNeg_negedge, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_AVDNeg, Violation => Tviol_CENeg_AVDNeg ); -- Setup Check between WENeg and AVDNeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupHigh => tsetup_WENeg_AVDNeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_AVDNeg, Violation => Tviol_WENeg_AVDNeg ); -- Setup Check between RESETNeg and OENeg VitalSetupHoldCheck ( TestSignal => RESETNeg, TestSignalName => "RESETNeg", RefSignal => OENeg, RefSignalName => "OENeg", SetupHigh => tsetup_RESETNeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_RESETNeg_OENeg, Violation => Tviol_RESETNeg_OENeg ); -- Setup Check between RESETNeg and CENeg VitalSetupHoldCheck ( TestSignal => RESETNeg, TestSignalName => "RESETNeg", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_RESETNeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_RESETNeg_CENeg, Violation => Tviol_RESETNeg_CENeg ); -- PulseWidth Check for AVDNeg VitalPeriodPulseCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", PulseWidthLow => tpw_AVDNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_AVDNeg, Violation => Pviol_AVDNeg ); -- PulseWidth Check for RESETNeg VitalPeriodPulseCheck ( TestSignal => RESETNeg, TestSignalName => "RESETNeg", PulseWidthLow => tpw_RESETNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RESETNeg, Violation => Pviol_RESETNeg ); -- PulseWidth, Period Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WENeg", PulseWidthLow => tpw_WENeg_negedge, PulseWidthHigh => tpw_WENeg_posedge, Period => tperiod_WENeg, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); -- PulseWidth, Period Check for CENeg VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CENeg", PulseWidthLow => tpw_WENeg_negedge, PulseWidthHigh => tpw_WENeg_posedge, Period => tperiod_WENeg, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CENeg, Violation => Pviol_CENeg ); -- PulseWidth, Period Check for CLK VitalPeriodPulseCheck ( TestSignal => CLK, TestSignalName => "CLK", PulseWidthLow => tpw_CLK_negedge, PulseWidthHigh => tpw_CLK_posedge, Period => tperiod_CLK, CheckEnabled => ConfReg0(15) = '0', HeaderMsg => InstancePath & PartID, PeriodData => PD_CLK, Violation => PViol_CLK ); Violation := Tviol_CENeg_CLK OR Tviol_A_CLK OR Tviol_AVDNeg_CLK OR Tviol_A_AVDNeg OR Tviol_DQ0_WENeg OR Tviol_DQ0_CENeg OR Tviol_OENeg_WENeg OR Tviol_WENeg_OENeg OR Tviol_AVDNeg_WENeg OR Tviol_AVDNeg_OENeg OR Tviol_CENeg_WENeg OR Tviol_WENeg_CENeg OR Tviol_OENeg_RESETNeg OR Tviol_CENeg_RESETNeg OR Tviol_CENeg_AVDNeg OR Tviol_WENeg_AVDNeg OR Tviol_RESETNeg_OENeg OR Tviol_RESETNeg_CENeg OR Pviol_AVDNeg OR Pviol_RESETNeg OR Pviol_WENeg OR Pviol_CENeg OR PViol_CLK; 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, RST, PoweredUp) BEGIN IF PoweredUp = '1' THEN IF RESETNeg = '1' THEN IF next_state'EVENT THEN current_state <= next_state; END IF; reseted <= '1'; ELSIF RESETNeg = '0' AND RST = '0' THEN --no state transition while RESET# low current_state <= IDLE_RST; reseted <= '0'; END IF; ELSE current_state <= IDLE_RST; reseted <= '0'; END IF; END PROCESS StateTransition; ---------------------------------------------------------------------------- --Glitch Protection: Inertial Delay does not Propagate Pulses < 3 ns ---------------------------------------------------------------------------- gWE_n <= WENeg AFTER 3 ns WHEN WENeg = '0' ELSE WENeg; gCE_n <= CENeg AFTER 3 ns WHEN CENeg = '0' ELSE CENeg; gOE_n <= OENeg AFTER 3 ns WHEN OENeg = '0' ELSE OENeg; gAVD_n<= AVDNeg AFTER 3 ns WHEN AVDNeg = '0' ELSE AVDNeg; --------------------------------------------------------------------------- -- Clock active edge --> CLKMerge rising edge, needed for burst sequences --------------------------------------------------------------------------- CLKGen : PROCESS(CLK) BEGIN IF rising_edge(CLK) THEN CLKMerge <= '1', '0' AFTER 1 ns; END IF; END PROCESS CLKGen; Start_time : PROCESS (START_in) BEGIN IF rising_edge (START_in) THEN IF LongTiming = TRUE THEN START_out <= '0', '1' AFTER tdevice_START; ELSE START_out <= '0', '1' AFTER tdevice_START/1; END IF; ELSE START_out <= '0'; END IF; END PROCESS Start_time; TIACCB : PROCESS(IACC_in) BEGIN IF IACC_in = '0' THEN IACC_out <= '0'; ELSE IACC_out <= '1' AFTER (tdevice_IACC - 1 ns); END IF; END PROCESS TIACCB; --------------------------------------------------------------------------- -- Address Latch and Bus Cycle Decode ---------------------------------------------------------------------------- BusCycleDecode: PROCESS(A, gWE_n, gCE_n, gOE_n, gAVD_n, WENeg, CENeg, OENeg, reseted, AVDNeg, CLK) VARIABLE AddressLatched : NATURAL RANGE 0 TO MemSize; VARIABLE WrAddressLatched : NATURAL RANGE 0 TO MemSize; VARIABLE READCYCLE : BOOLEAN := TRUE; VARIABLE LATCHED : BOOLEAN := TRUE; VARIABLE HiAddr : std_logic_vector((HiAddrBit-16) downto 0); BEGIN -- Write address latch IF (rising_edge(AVDNeg) AND CENeg = '0') THEN IF WENeg = '1' AND OENeg = '0' THEN UpperAddress := DIn; END IF; IF OENeg = '1' THEN WrAddressLatched := to_nat(UpperAddress & DIn); END IF; END IF; IF RESETNeg /= '0' AND ((rising_edge(gWE_n) AND gCE_n = '0') OR (rising_edge(gCE_n) AND gWE_n = '0') OR (rising_edge(gWE_n) AND rising_edge(gCE_n))) AND OENeg = '1' AND AVDNeg = '1' THEN -- WRITE operation SecAddr <= ReturnSectorID(WrAddressLatched); BankID <= ReturnBank(WrAddressLatched); Addr <= WrAddressLatched; BuffPageAddr <= ReturnBuffPage(WrAddressLatched); D_tmp <= to_nat(Din(15 downto 0)); WRITE <= '0', '1' AFTER 1 ns; END IF; IF reseted='1' AND ConfReg0(15) = '1' THEN -- Asynchronous Mode address latch IF ( (falling_edge(AVDNeg) OR (A'EVENT AND AVDNeg = '0') OR (DIn'EVENT AND AVDNeg = '0')) AND WENeg = '1') THEN -- tACC count AddrREF <= NOT AddrREF; END IF; IF (rising_edge(AVDNeg) AND CENeg = '0') THEN IF WENeg = '1' AND OENeg = '0' THEN UpperAddress := DIn; END IF; IF OENeg = '1' THEN AddressLatched := to_nat(UpperAddress & DIn); END IF; END IF; IF ((falling_edge(OENeg) OR falling_edge(CENeg)) AND WENeg = '1' AND CENeg = '0' AND OENeg = '0' AND AVDNeg = '1') THEN -- Initiate READ SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr <= ReturnBuffPage(AddressLatched); Addr <= AddressLatched ; READ <= '0', '1' AFTER 1 ns; END IF; ELSIF reseted = '1' AND ConfReg0(15) = '0' THEN IF falling_edge(AVDNeg) THEN LATCHED := FALSE; READCYCLE := FALSE; END IF; IF rising_edge(CLK) AND READCYCLE THEN READCYCLE := FALSE; IACC_in <= '1' AFTER 1 ns; BURST <= '0', '1' AFTER 2 ns; Check_freq := TRUE; BurstStarted := FALSE; END IF; -- Synchronous CLK active edge address latch IF rising_edge(CLK) AND WENeg = '1' AND OENeg = '0' AND CENeg = '0' AND AVDNeg = '0' AND NOT LATCHED THEN UpperAddress := DIn; END IF; IF rising_edge(CLK) AND WENeg = '1' AND OENeg = '1' AND CENeg = '0' AND AVDNeg = '0' AND NOT LATCHED THEN READCYCLE := TRUE; LATCHED := TRUE; AddressLatched := to_nat(UpperAddress & DIn); SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr<= ReturnBuffPage(AddressLatched); Addr <= AddressLatched; BurstDelay := 0; IACC_in <= '0', '1' AFTER 1 ns; AddrREF <= NOT AddrREF; BurstStarted := TRUE; END IF; IF (falling_edge(gWE_n) OR falling_edge(gCE_n)) AND gCE_n = '0' AND gWE_n = '0' AND gOE_n = '1' THEN READCYCLE := FALSE; END IF; -- Inititate READ, Synchronous mode IF (falling_edge(OENeg) AND WENeg = '1' AND CENeg = '0') THEN -- Initiate READ IF LATCHED = TRUE THEN SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr<= ReturnBuffPage(AddressLatched); Addr <= AddressLatched; READ <= '0', '1' AFTER 1 ns; END IF; END IF; END IF; END PROCESS BusCycleDecode; ---------------------------------------------------------------------------- -- Timing control for the Write Buffer Program Operation -- start/ suspend/ resume ---------------------------------------------------------------------------- ProgTime :PROCESS(PSTART, PSUSP, PRES, reseted) VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE wrbo : time; BEGIN IF LongTiming THEN wrbo := tdevice_WRBO; ELSE wrbo := tdevice_WRBO / 1; END IF; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programing terminated ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE='1' THEN start := NOW; elapsed := 0 ns; duration := (WrBuffCnt+1)* wrbo; PDONE <= '0', '1' AFTER duration; ELSIF rising_edge(PSUSP) AND PDONE = '0' THEN elapsed := NOW - start; duration := duration - elapsed; PDONE <= '0'; ELSIF rising_edge(PRES) AND PDONE = '0' THEN start := NOW; PDONE <= '0', '1' AFTER duration; END IF; END IF; END PROCESS ProgTime; ---------------------------------------------------------------------------- -- Timing control for the Sector Erase Operation ---------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, ESUSP, ERES, reseted) VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE seo16 : time; VARIABLE seo64 : time; BEGIN IF LongTiming THEN seo16 := tdevice_SEO16; seo64 := tdevice_SEO64; ELSE seo16 := tdevice_SEO16 / 1000; seo64 := tdevice_SEO64 / 1000; 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 start := NOW; elapsed := 0 ns; IF (SA_ERS <= 3 AND TimingModel(16) = '1') OR (SA_ERS >= SecNum - 3 AND TimingModel(16) = '0') THEN duration := seo16; ELSE duration := seo64; END IF; elapsed := 0 ns; EDONE <= '0', '1' AFTER duration; start := NOW; ELSIF rising_edge(ESUSP) AND EDONE = '0' THEN elapsed := NOW - start; duration := duration - elapsed; EDONE <= '0'; ELSIF rising_edge(ERES) AND EDONE = '0' THEN start := NOW; EDONE <= '0', '1' AFTER duration; END IF; END IF; END PROCESS ErsTime; ---------------------------------------------------------------------------- -- Process that determines clock frequency ---------------------------------------------------------------------------- CLK_FREQ :PROCESS(CLK) VARIABLE CLK_PER : time := 0 ns; VARIABLE LAST_CLK : time := 0 ns; BEGIN IF rising_edge(CLK) THEN CLK_PER := NOW - LAST_CLK; LAST_CLK := NOW; IF ConfReg0(15) = '0' AND Check_freq THEN IF (CLK_PER < 37.037 ns AND WS_Initial < 4) OR (CLK_PER < 25.00 ns AND WS_Initial < 5) OR (CLK_PER < 18.518 ns AND WS_Initial < 6) OR (CLK_PER < 15.151 ns AND WS_Initial < 7) OR (CLK_PER < 12.50 ns AND WS_Initial < 8) OR (CLK_PER < 10.526 ns AND WS_Initial < 9) OR (CLK_PER < 9.615 ns AND WS_Initial < 10) OR (CLK_PER < 8.333 ns AND WS_Initial < 11) OR (CLK_PER < 7.462 ns AND WS_Initial < 12) THEN ASSERT FALSE REPORT "More wait states are required for " & "this clock frequency value" SEVERITY warning; END IF; END IF; Check_freq := FALSE; END IF; END PROCESS CLK_FREQ; ---------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation ---------------------------------------------------------------------------- StateGen :PROCESS(WRITE, PDONE, EDONE, BCDONE, CEDONE, START_out, reseted) VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE DataLo : NATURAL RANGE 0 TO 16#FF# := 0; VARIABLE AddrCom : NATURAL RANGE 0 TO 16#FFF# := 0; BEGIN ------------------------------------------------------------------------ -- Functionality Section ------------------------------------------------------------------------ IF falling_edge(WRITE) THEN Data := D_tmp; DataLo := D_tmp MOD 16#100#; AddrCom := Addr MOD 16#1000#; END IF; IF reseted /= '1' THEN next_state <= current_state; ELSE CASE current_state IS WHEN IDLE_RST => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#80# THEN next_state <= ERASE_ENTRY; ELSIF AddrCom = 16#555# AND DataLo = 16#60# THEN next_state <= SL_ENTRY; ELSIF AddrCom = 16#555# AND DataLo = 16#40# THEN next_state <= SSR_LOCK_ENTRY; ELSIF AddrCom = 16#555# AND DataLo = 16#88# THEN next_state <= SecSi_ENTRY; ELSIF AddrCom = 16#555# AND DataLo = 16#D0# THEN next_state <= CR_ENTRY; ELSIF AddrCom = 16#555# AND DataLo = 16#25# THEN next_state <= W2B_ENTRY; ELSIF (AddrCom MOD 16#100# = 16#55#) AND (DataLo = 16#98# OR DataLo = 16#90#) AND (BankID = 0) THEN next_state <= ID_CFI_ENTRY; ELSIF AddrCom = 16#555# AND DataLo = 16#33# THEN next_state <= BC_ENTRY; END IF; END IF; WHEN ERASE_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#2AA# AND DataLo = 16#10# AND SecAddr = SA_ERS AND (SL_REG = 0 OR SL_REG = -2) AND VPP /= '0' AND NOT LockRangeDone THEN next_state <= CERS; ELSIF AddrCom = 16#2AA# AND DataLo = 16#30# AND SecAddr = SA_ERS AND (SecAddr = SL_REG OR SL_REG = -2) AND VPP /= '0' THEN next_state <= SERS; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE next_state <= IDLE_RST; END IF; END IF; WHEN ID_CFI_ENTRY => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= IDLE_RST; END IF; END IF; WHEN SL_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#2AA# AND DataLo = 16#60# THEN next_state <= SL_Change; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSIF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF PGM_ACT = '1' THEN next_state <= PGM_SUS; ELSE next_state <= IDLE_RST; END IF; END IF; WHEN SSR_LOCK_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#25# AND SecAddr = SA_SSR THEN next_state <= W2B_ENTRY; ELSIF DataLo = 16#F0# THEN next_state <= IDLE_RST; END IF; END IF; WHEN SecSi_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#25# AND SecAddr = SA_SecSi THEN next_state <= W2B_ENTRY; ELSIF DataLo = 16#F0# THEN next_state <= IDLE_RST; END IF; END IF; WHEN CR_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#25# AND SecAddr = SA_CR THEN next_state <= W2B_ENTRY; ELSIF DataLo = 16#F0# THEN next_state <= IDLE_RST; END IF; END IF; WHEN W2B_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#2AA# AND SecAddr = SA_PGM AND (((SecAddr = SL_REG OR SL_REG = -2) AND VPP /= '0') OR (SecSi = '1' AND VPP /= '0') OR LOCK_ACT = '1' OR CR_ACT = '1') AND NOT (SecSi = '1' AND SSR_LOCK_REG(0) = '0') AND NOT (LOCK_ACT = '1' AND DataLo > 0) AND NOT (CR_ACT = '1' AND DataLo > 0) AND NOT (ESP_ACT = '1' AND SecAddr = SA_ERS) THEN next_state <= W2B_WC; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSIF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF LOCK_ACT = '1' THEN next_state <= SSR_LOCK_ENTRY; ELSIF SecSi = '1' THEN next_state <= SecSi_ENTRY; ELSIF CR_ACT ='1' THEN next_state <= CR_ENTRY; ELSE next_state <= IDLE_RST; END IF; END IF; WHEN BC_ENTRY => IF rising_edge(BCDONE) THEN next_state <= IDLE_RST; END IF; WHEN CERS => IF rising_edge(CEDONE) THEN next_state <= IDLE_RST; END IF; WHEN SERS => IF rising_edge(EDONE) THEN next_state <= IDLE_RST; ELSIF falling_edge(WRITE) THEN IF DataLo = 16#B0# THEN next_state <= SERS_SL; END IF; END IF; WHEN SL_Change => IF falling_edge(WRITE) THEN IF DataLo = 16#61# THEN next_state <= LOCK_RANGE; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSIF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF PGM_ACT = '1' THEN next_state <= PGM_SUS; ELSE next_state <= IDLE_RST; END IF; END IF; WHEN W2B_WC => IF falling_edge(WRITE) THEN IF SecAddr = SA_PGM AND NOT (SecSi = '1' AND (ReturnAddr(Addr,SA_SecSi) < 128 OR ReturnAddr(Addr,SA_SecSi) > 255)) AND NOT (LOCK_ACT = '1' AND (AddrCom MOD 16#100# /= 0)) AND NOT (CR_ACT = '1' AND (AddrCom MOD 16#100# > 0)) AND WC = 0 THEN next_state <= WB_LOADED; ELSIF SecAddr = SA_PGM AND NOT (SecSi = '1' AND (ReturnAddr(Addr,SA_SecSi) < 128 OR ReturnAddr(Addr,SA_SecSi) > 255)) AND NOT ((Addr + WC) / (WrBuffLength +1) > Addr / (WrBuffLength +1)) AND LOCK_ACT = '0' AND CR_ACT = '0'THEN next_state <= W2BUF_PG; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSIF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF LOCK_ACT = '1' THEN next_state <= SSR_LOCK_ENTRY; ELSIF CR_ACT = '1' THEN next_state <= CR_ENTRY; ELSIF SecSi = '1' THEN next_state <= SecSi_ENTRY; ELSE next_state <= IDLE_RST; END IF; END IF; WHEN SERS_SL => IF rising_edge(START_out) THEN next_state <= SERS_SUS; END IF; WHEN LOCK_RANGE => IF falling_edge(WRITE) THEN IF DataLo MOD 16#10# = 16#C# THEN NULL; ELSIF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF PGM_ACT = '1' THEN next_state <= PGM_SUS; ELSE next_state <= IDLE_RST; END IF; END IF; WHEN W2BUF_PG => IF falling_edge(WRITE) THEN IF NOT (Addr = PrevAddr + 1) THEN IF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF SecSi = '1' THEN next_state <= SecSi_ENTRY; ELSE next_state <= IDLE_RST; END IF; ELSIF WC = 0 THEN next_state <= WB_LOADED; END IF; END IF; WHEN WB_LOADED => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#29# AND SecAddr = SA_PGM AND CR_ACT = '0' AND (WrBuffAddr(WrBuffCnt)/32 = WrBuffAddr(0)/32) THEN next_state <= PGM; ELSIF AddrCom = 16#555# AND DataLo = 16#29# AND SecAddr = SA_PGM AND CR_ACT = '1' AND (WrBuffAddr(WrBuffCnt)/32 = WrBuffAddr(0)/32) THEN next_state <= CR_ENTRY; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSIF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF LOCK_ACT = '1' THEN next_state <= SSR_LOCK_ENTRY; ELSIF CR_ACT = '1' THEN next_state <= CR_ENTRY; ELSIF SecSi = '1' THEN next_state <= SecSi_ENTRY; ELSE next_state <= IDLE_RST; END IF; END IF; WHEN SERS_SUS => IF falling_edge(WRITE) THEN IF AddrCom = 16#000# AND DataLo = 16#30# THEN next_state <= SERS; ELSIF AddrCom = 16#555# AND DataLo = 16#60# THEN next_state <= SL_ENTRY; ELSIF AddrCom = 16#555# AND DataLo = 16#25# THEN next_state <= W2B_ENTRY; END IF; END IF; WHEN PGM => IF rising_edge(PDONE) THEN IF ESP_ACT = '1' THEN next_state <= SERS_SUS; ELSIF LOCK_ACT = '1' THEN next_state <= SSR_LOCK_ENTRY; ELSIF SecSi = '1' THEN next_state <= SecSi_ENTRY; ELSE next_state <= IDLE_RST; END IF; ELSIF falling_edge(WRITE) THEN IF DataLo = 16#51# THEN next_state <= PGM_SL; END IF; END IF; WHEN PGM_SL => IF rising_edge(START_out) THEN next_state <= PGM_SUS; END IF; WHEN PGM_SUS => IF falling_edge(WRITE) THEN IF AddrCom = 16#000# AND DataLo = 16#50# THEN next_state <= PGM; ELSIF AddrCom = 16#555# AND DataLo = 16#60# THEN next_state <= SL_ENTRY; END IF; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for Read Mode Generation --------------------------------------------------------------------------- ReadModeGen :PROCESS(gWE_n, BURST, gCE_n, AVDNeg, RST) VARIABLE BURST_TR : BOOLEAN; VARIABLE SYNCREAD : BOOLEAN; BEGIN BURST_TR := FALSE; SYNCREAD := FALSE; IF falling_edge(RST) AND RESETNeg = '0' THEN RD_MODE <= NOSYNC; END IF; IF reseted = '1' THEN CASE current_state IS WHEN IDLE_RST => IF falling_edge(BURST) THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ERASE_ENTRY => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN SL_ENTRY => IF falling_edge(BURST) THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (PGM_ACT = '1' AND BuffPageAddr = PA_PGM) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN SSR_LOCK_ENTRY => IF falling_edge(BURST) THEN IF SecAddr = SA_SSR THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN SecSi_ENTRY => IF falling_edge(BURST) THEN IF SecAddr = SA_SecSi AND ReturnAddr(Addr,SA_SecSi) > 16#FF# THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN CR_ENTRY => IF falling_edge(BURST) THEN IF SecAddr = SA_CR THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN W2B_ENTRY => IF falling_edge(BURST) THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (LOCK_ACT = '1' AND SecAddr = SA_SSR) OR (CR_ACT = '1' AND SecAddr = SA_CR) OR (SecSi = '1' AND SecAddr = SA_SecSi AND Addr > 16#FF#) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ID_CFI_ENTRY => IF falling_edge(BURST) THEN IF SecAddr = SA_ID_CFI AND (ReturnAddr(Addr,SA_ID_CFI) > 16#67#) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN BC_ENTRY => IF falling_edge(BURST) THEN IF BankID = BA_BC OR (STAT_ACT = '1' AND SecAddr = SA_SR) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN CERS => IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN SERS => IF falling_edge(BURST) THEN IF BankID = BA_ERS OR (STAT_ACT = '1' AND SecAddr = SA_SR) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN SL_Change => IF falling_edge(BURST) THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (PGM_ACT = '1' AND BuffPageAddr = PA_PGM) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN W2B_WC => IF falling_edge(BURST) THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (LOCK_ACT = '1' AND SecAddr = SA_SSR) OR (CR_ACT = '1' AND SecAddr = SA_CR) OR (SecSi = '1' AND SecAddr = SA_SecSi AND Addr > 16#FF#) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN SERS_SL => IF falling_edge(BURST) THEN IF BankID = BA_ERS OR (STAT_ACT = '1' AND SecAddr = SA_SR) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN LOCK_RANGE => IF falling_edge(BURST) THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (PGM_ACT = '1' AND BuffPageAddr = PA_PGM) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN W2BUF_PG => IF falling_edge(BURST) THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (SecSi = '1' AND SecAddr = SA_SecSi AND Addr > 16#FF#) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN WB_LOADED => IF falling_edge(BURST) THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (LOCK_ACT = '1' AND SecAddr = SA_SSR) OR (CR_ACT = '1' AND SecAddr = SA_CR) OR (SecSi = '1' AND SecAddr = SA_SecSi AND Addr > 16#FF#) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN SERS_SUS => IF falling_edge(BURST) THEN IF SecAddr = SA_ERS OR (STAT_ACT = '1' AND SecAddr = SA_SR) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PGM => IF falling_edge(BURST) THEN IF BankID = BA_PGM OR (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (STAT_ACT = '1' AND SecAddr = SA_SR) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PGM_SL => IF falling_edge(BURST) THEN IF BankID = BA_PGM OR (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (STAT_ACT = '1' AND SecAddr = SA_SR) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PGM_SUS => IF falling_edge(BURST) THEN IF BuffPageAddr = PA_PGM OR (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (LOCK_ACT = '1' AND SecAddr = SA_SSR) OR (CR_ACT = '1' AND SecAddr = SA_CR) OR (SecSi = '1' AND SecAddr = SA_SecSi AND Addr > 16#FF#) OR (STAT_ACT = '1' AND SecAddr = SA_SR) THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; END CASE; IF(rising_edge(gCE_n) OR falling_edge(AVDNeg) OR falling_edge(gWE_n))AND (RD_MODE /= NOSYNC) THEN RD_MODE <= NOSYNC; END IF; IF BURST_TR THEN IF ConfReg0(2 downto 0) = "000" THEN RD_MODE <= CONTINUOUS; ELSE RD_MODE <= LINEAR; END IF; ReadINIT <= '0', '1' AFTER 2 ns; ELSIF SYNCREAD THEN RD_MODE <= SYNCR; ReadINIT <= '0', '1' AFTER 2 ns; END IF; END IF; END PROCESS ReadModeGen; ---------------------------------------------------------------------------- --FSM Output generation and general funcionality ---------------------------------------------------------------------------- Functional : PROCESS(WRITE, READ, BURST, AVDNeg, ReadINIT, PDONE, EDONE, CEDONE, BCDONE, START_out, RST, gOE_n, OENeg, CENeg, WENeg, CLKMerge, IACC_out) VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE DataLo : NATURAL RANGE 0 TO 16#FF# := 0; VARIABLE AddrCom : NATURAL RANGE 0 TO 16#FFF# := 0; VARIABLE Status : std_logic_vector(15 downto 0) := "0000000010000000"; VARIABLE oe : BOOLEAN:=FALSE; 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; -- Burst variables VARIABLE BurstAddr : INTEGER RANGE -1 TO MemSize := -1; VARIABLE BurstSec : INTEGER RANGE -1 TO SecNum := -1; VARIABLE LatencyAddr : INTEGER RANGE -1 TO MemSize := -1; VARIABLE BurstLength : NATURAL RANGE 0 TO 32; VARIABLE RdCnt : NATURAL RANGE 0 TO 32; VARIABLE DOut_burst : std_logic_vector(15 downto 0) := (OTHERS=>'Z'); VARIABLE SecAddr1 : INTEGER := 0; VARIABLE mem_data : INTEGER := -1; VARIABLE WS_Latency : NATURAL RANGE 0 TO 7; VARIABLE WS_Boundary : NATURAL RANGE 0 TO 4; VARIABLE DelayCyc_CNT : INTEGER; VARIABLE DelayCycSwitch: NATURAL RANGE 0 TO 5; VARIABLE BoundarySwitch: NATURAL RANGE 0 TO 3; VARIABLE BusyBound : boolean; -- Burst mode control VARIABLE INITIAL : boolean; VARIABLE BOUNDARY_CROSS : boolean; VARIABLE NO_PROGRESS : boolean; VARIABLE BURST_END : boolean; VARIABLE PR_FLAG : BOOLEAN := FALSE; VARIABLE ER_FLAG : BOOLEAN := FALSE; VARIABLE SLA_Lo : integer RANGE -1 TO SecNum; VARIABLE SLA_Hi : integer RANGE -1 TO SecNum; VARIABLE SLA_temp: integer RANGE -1 TO SecNum; VARIABLE LockRange : boolean; VARIABLE A6Lock : boolean; TYPE ReadTargetType IS (Mem_T, SS_T, ID_CFI_T); VARIABLE ReadTarget : ReadTargetType; PROCEDURE READMEM(Address :IN INTEGER; SecAddr :IN INTEGER; Targ :IN ReadTargetType)IS VARIABLE ReadData : STD_LOGIC_VECTOR(15 downto 0); BEGIN CASE Targ IS WHEN Mem_T => IF Mem(Address) /= -1 THEN ReadData := to_slv(Mem(Address),16); ELSE ReadData := ( OTHERS =>'X'); END IF; WHEN SS_T => IF Address <= 16#FF# THEN IF SecSiMem(Address) /= -1 THEN ReadData := to_slv(SecSiMem(Address),16); ELSE ReadData := ( OTHERS =>'X'); END IF; ELSE ReadData := (OTHERS => '0'); END IF; WHEN ID_CFI_T => IF Address >= 16#10# AND Address <= 16#67# THEN ReadData := to_slv(CFIMem(Address),16); ELSIF Address = 16#00# THEN ReadData := to_slv(16#0001#,16); ELSIF Address = 16#01# THEN ReadData := to_slv(16#007E#,16); ELSIF Address = 16#03# THEN ReadData := to_slv(16#0000#,16); ELSIF Address = 16#06# THEN ReadData := to_slv(16#0010#,16); ELSIF Address = 16#0C# THEN ReadData := to_slv(16#05#,16); ELSIF Address = 16#0E# THEN IF TimingModel(16) = '1' THEN ReadData := to_slv(16#0066#,16); ELSIF TimingModel(16) = '0' THEN ReadData := to_slv(16#0064#,16); END IF; ELSIF Address = 16#0F# THEN ReadData := to_slv(16#0001#,16); ELSE ReadData(7 DOWNTO 0) := (OTHERS => Reserved1); ReadData(15 DOWNTO 8) := (OTHERS => Reserved0); END IF; END CASE; OutputD := ReadData; END READMEM; PROCEDURE READ_BURST_DATA( BAddr:IN INTEGER; BSec :IN INTEGER; Targ :IN ReadTargetType) IS VARIABLE mem_data : INTEGER; BEGIN CASE Targ IS WHEN Mem_T => DOut_burst := ( OTHERS =>'X'); IF Mem(BAddr)/=-1 THEN DOut_burst := to_slv(Mem(BAddr),16); END IF; WHEN SS_T => DOut_burst := ( OTHERS =>'X'); IF SecSiMem(ReturnAddr(BAddr,SA_SecSi))/=-1 THEN DOut_burst := to_slv(SecSiMem(ReturnAddr(BAddr,SA_SecSi)),16); END IF; WHEN ID_CFI_T => IF ReturnAddr(BAddr,SA_ID_CFI) >= 16#10# AND ReturnAddr(BAddr,SA_ID_CFI) <= 16#67# THEN DOut_burst := to_slv(CFIMem(ReturnAddr(BAddr,SA_ID_CFI)),16); ELSIF ReturnAddr(BAddr,SA_ID_CFI) = 16#00# THEN DOut_burst := to_slv(16#0001#,16); ELSIF ReturnAddr(BAddr,SA_ID_CFI) = 16#01# THEN DOut_burst := to_slv(16#007E#,16); ELSIF ReturnAddr(BAddr,SA_ID_CFI) = 16#03# THEN DOut_burst := to_slv(16#0000#,16); ELSIF ReturnAddr(BAddr,SA_ID_CFI) = 16#06# THEN DOut_burst := to_slv(16#0010#,16); ELSIF ReturnAddr(BAddr,SA_ID_CFI) = 16#0C# THEN DOut_burst := to_slv(16#05#,16); ELSIF ReturnAddr(BAddr,SA_ID_CFI) = 16#0E# THEN IF TimingModel(16) = '1' THEN DOut_burst := to_slv(16#0066#,16); ELSIF TimingModel(16) = '0' THEN DOut_burst := to_slv(16#0064#,16); END IF; ELSIF ReturnAddr(BAddr,SA_ID_CFI) = 16#0F# THEN DOut_burst := to_slv(16#0001#,16); ELSE DOut_burst(7 DOWNTO 0) := (OTHERS => Reserved1); DOut_burst(15 DOWNTO 8) := (OTHERS => Reserved0); END IF; END CASE; END READ_BURST_DATA; PROCEDURE NEXT_ADDR_LIN( BAddr :INOUT INTEGER; Length :IN INTEGER RANGE 0 TO 16 ) IS BEGIN BAddr := BAddr + 1; IF BAddr MOD Length = 0 THEN BAddr:= BAddr - Length; END IF; END NEXT_ADDR_LIN; PROCEDURE CHECK_END( CNT :INOUT INTEGER; BEnd :OUT BOOLEAN ) IS BEGIN CNT:=CNT-1; IF CNT= 0 THEN BEnd := TRUE; ELSE BEnd := FALSE; END IF; END CHECK_END; PROCEDURE NEXT_ADDR( BAddr:INOUT INTEGER; BSec :INOUT INTEGER; Targ :IN ReadTargetType ) IS BEGIN CASE Targ IS WHEN Mem_T => IF BAddr = MemSize THEN BAddr := 0; BSec := 0; ELSE BAddr:=BAddr+1; IF (BSec < (SecNum-3) AND TimingModel(16) = '0') OR (BSec > 3 AND TimingModel(16) = '1') THEN IF (BAddr MOD (SecSize64+1) = 0) THEN BSec:= BSec + 1; END IF; ELSE IF (BAddr MOD (SecSize16+1) = 0) THEN BSec := BSec+1; END IF; END IF; END IF; WHEN SS_T => IF BAddr MOD 256 = 255 THEN BAddr := BAddr-255; ELSE BAddr := BAddr+1; END IF; WHEN ID_CFI_T => IF BAddr MOD 16#80# = 16#67# THEN BAddr := BAddr-16#67#; ELSE BAddr := BAddr+1; END IF; END CASE; END NEXT_ADDR; PROCEDURE CheckBoundary(BusyBound : INOUT BOOLEAN; BurstAddr : IN NATURAL) IS VARIABLE BankCHECK : NATURAL; VARIABLE SectorCHECK : NATURAL; VARIABLE PageCHECK : NATURAL; BEGIN BankCHECK := ReturnBank((BurstAddr+1) mod (MemSize+1)); SectorCHECK := ReturnSectorID((BurstAddr+1) mod (MemSize+1)); PageCHECK := ReturnBuffPage((BurstAddr+1) mod (MemSize+1)); BusyBOUND := FALSE; IF (current_state = IDLE_RST AND STAT_ACT = '1' AND SectorCHECK = SA_SR) OR (current_state = SL_ENTRY AND ((ESP_ACT='1' AND SectorCHECK = SA_ERS) OR (PGM_ACT = '1' AND PageCHECK = PA_PGM))) OR (current_state = SSR_LOCK_ENTRY AND SectorCHECK = SA_SSR) OR (current_state = SecSi_ENTRY AND SectorCHECK = SA_SecSi) OR (current_state = CR_ENTRY AND SectorCHECK = SA_CR) OR (current_state = W2B_ENTRY AND ((ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (LOCK_ACT = '1' AND SectorCHECK = SA_SSR) OR (CR_ACT = '1' AND SectorCHECK = SA_CR) OR (SecSi = '1' AND SectorCHECK = SA_SecSi))) OR (current_state = ID_CFI_ENTRY AND SectorCHECK = SA_ID_CFI) OR (current_state = BC_ENTRY AND (BankCHECK = BA_BC OR (STAT_ACT = '1' AND SectorCHECK = SA_SR))) OR (current_state = SERS AND (BankCHECK = BA_ERS OR (STAT_ACT = '1' AND SectorCHECK = SA_SR))) OR (current_state = SL_Change AND ((ESP_ACT='1' AND SectorCHECK = SA_ERS) OR (PGM_ACT = '1' AND PageCHECK = PA_PGM))) OR (current_state = W2B_WC AND ((ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (LOCK_ACT = '1' AND SectorCHECK = SA_SSR) OR (CR_ACT = '1' AND SectorCHECK = SA_CR) OR (SecSi = '1' AND SectorCHECK = SA_SecSi))) OR (current_state = SERS_SL AND (BankCHECK = BA_ERS OR (STAT_ACT = '1' AND SectorCHECK = SA_SR))) OR (current_state = LOCK_RANGE AND ((ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (PGM_ACT = '1' AND PageCHECK = PA_PGM))) OR (current_state = W2BUF_PG AND ((ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (SecSi = '1' AND SectorCHECK = SA_SecSi))) OR (current_state = WB_LOADED AND ((ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (LOCK_ACT = '1' AND SectorCHECK = SA_SSR) OR (CR_ACT = '1' AND SectorCHECK = SA_CR) OR (SecSi = '1' AND SectorCHECK = SA_SecSi))) OR (current_state = SERS_SUS AND (SectorCHECK = SA_ERS OR (STAT_ACT = '1' AND SectorCHECK = SA_SR))) OR (current_state = PGM AND (BankCHECK = BA_PGM OR (ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (STAT_ACT = '1' AND SectorCHECK = SA_SR))) OR (current_state = PGM_SL AND (BankCHECK = BA_PGM OR (ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (STAT_ACT = '1' AND SectorCHECK = SA_SR))) OR (current_state = PGM_SUS AND (PageCHECK = PA_PGM OR (ESP_ACT = '1' AND SectorCHECK = SA_ERS) OR (LOCK_ACT = '1' AND SectorCHECK = SA_SSR) OR (CR_ACT = '1' AND SectorCHECK = SA_CR) OR (SecSi = '1' AND SectorCHECK = SA_SecSi) OR (STAT_ACT = '1' AND SectorCHECK = SA_SR))) THEN BusyBOUND := TRUE; END IF; BusyBOUND := BusyBOUND AND (ReturnBank(BurstAddr) /= BankCHECK OR ReturnSectorID(BurstAddr) /= SectorCHECK OR ReturnBuffPage(BurstAddr) /= PageCHECK); END PROCEDURE CheckBoundary; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(WRITE) THEN Data := D_tmp; DataLo := D_tmp mod 16#100#; AddrCom := Addr mod 16#1000#; END IF; oe := falling_edge(READ); IF falling_edge(RST) AND RESETNeg='0' THEN ESP_ACT <= '0'; PGM_ACT <= '0'; LOCK_ACT <= '0'; CR_ACT <= '0'; SecSi <= '0'; ConfReg0 := "1101111101001000"; START_in <= '0'; BCDONE <= '1'; CEDONE <= '1'; STAT_ACT <= '0'; Status(7 DOWNTO 0) := "10000000"; UpperAddress := (OTHERS => '0'); END IF; IF falling_edge(AVDNeg) THEN RDY_temp <= '1'; END IF; IF falling_edge(BURST) THEN INITIAL := TRUE; DelayCycSwitch := 0; BurstAddr := Addr; BurstSec := SecAddr; IF (to_nat(ConfReg0(2 DOWNTO 0)) = 2) THEN BurstLength := 8; ELSIF (to_nat(ConfReg0(2 DOWNTO 0)) = 3)THEN BurstLength := 16; ELSE BurstLength := 0; END IF; RdCnt := BurstLength; WS_Initial := 13; IF to_nat(ConfReg0(14 downto 11)) < 11 AND to_nat(ConfReg0(14 downto 11)) > 0 THEN WS_Initial := to_nat(ConfReg0(14 downto 11)) + 2; END IF; BurstDelay := BurstDelay + WS_Initial -1; -- Set WS_Latency according to WS_Initial IF WS_Initial >= 8 THEN WS_Latency := 7; ELSE WS_Latency := WS_Initial - 1; END IF; -- Set WS_Boundary according to WS_Initial IF WS_Initial >= 10 THEN WS_Boundary := 2; ELSIF WS_Initial = 9 THEN WS_Boundary := 1; ELSE WS_Boundary := 0; END IF; IN_W_ELAPSED := FALSE; DATA_DELAY := FALSE; BOUNDARY_CROSS := FALSE; BURST_END := FALSE; NO_PROGRESS := FALSE; BusyBound := FALSE; DelayCyc_CNT := BurstAddr MOD 8; IF DelayCyc_CNT - (7 - WS_Latency) > 0 THEN DelayCyc_CNT := DelayCyc_CNT - (7 - WS_Latency); ELSE DelayCyc_CNT := 0; END IF; IF BurstLength=8 OR (BurstLength=16 AND BurstAddr MOD 16 >= 8) THEN DelayCyc_CNT := 0; END IF; LatencyAddr := ((BurstAddr / 8)*8) + 7; IF current_state = ID_CFI_ENTRY AND BurstSec = SA_ID_CFI THEN ReadTarget := ID_CFI_T; ELSIF SecSi = '1' AND BurstSec = SA_SecSi THEN ReadTarget := SS_T; ELSE ReadTarget := Mem_T; END IF; END IF; IF reseted = '1' THEN CASE current_state IS WHEN IDLE_RST => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#80# THEN SA_ERS <= SecAddr; BA_ERS <= BankID; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#40# THEN SA_SSR <= SecAddr; LOCK_ACT <= '1'; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#88# THEN SA_SecSi <= SecAddr; SecSi <= '1'; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#D0# THEN SA_CR <= SecAddr; CR_ACT <= '1'; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#25# THEN SA_PGM <= SecAddr; BA_PGM <= BankID; STAT_ACT <= '0'; ELSIF (AddrCom MOD 16#100# = 16#55#) AND (DataLo = 16#98# OR DataLo = 16#90#) AND (BankID = 0) THEN SA_ID_CFI <= SecAddr; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF AddrCom = 16#555# AND DataLo = 16#71# THEN Status(7 DOWNTO 0) := "10000000"; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#33# THEN SA_BC <= SecAddr; BA_BC <= BankID; IF LongTiming THEN BCDONE <= '0', '1' AFTER tdevice_BCHECK; ELSE BCDONE <= '0', '1' AFTER tdevice_BCHECK/1; END IF; Status(7) := '0'; STAT_ACT <= '0'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN Status(0) := '0'; DOut_zd <= Status; STAT_ACT <= '0'; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN ERASE_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#2AA# AND DataLo = 16#10# THEN IF SecAddr = SA_ERS AND (SL_REG = 0 OR SL_REG = -2) AND VPP /= '0' AND NOT LockRangeDone THEN IF LongTiming THEN CEDONE <= '0', '1' AFTER (SecNum-3)*tdevice_SEO64+4*tdevice_SEO16; ELSE CEDONE <= '0', '1' AFTER ((SecNum-3)*tdevice_SEO64+4*tdevice_SEO16)/1000; END IF; Status(7) := '0'; Status(5) := '0'; Status(1) := '0'; ER_FLAG := FALSE; ELSE Status(5) := '1'; IF SecAddr = SA_ERS THEN Status(1) := '1'; ELSE Status(1) := '0'; END IF; END IF; ELSIF AddrCom = 16#2AA# AND DataLo = 16#30# THEN IF SecAddr = SA_ERS AND VPP /= '0' AND (SecAddr = SL_REG OR SL_REG = -2) THEN ESTART <= '1','0' AFTER 1 ns; Status(7) := '0'; Status(5) := '0'; Status(1) := '0'; ER_FLAG := FALSE; ELSE Status(5) := '1'; IF SecAddr = SA_ERS THEN Status(1) := '1'; ELSE Status(1) := '0'; END IF; END IF; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE Status(5) := '1'; END IF; END IF; IF oe THEN READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; WHEN SL_ENTRY => IF oe THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (PGM_ACT = '1' AND BuffPageAddr = PA_PGM) THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN SSR_LOCK_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#25# AND SecAddr = SA_SSR THEN SA_PGM <= SecAddr; BA_PGM <= BankID; ELSIF DataLo = 16#F0# THEN LOCK_ACT <= '0'; END IF; END IF; IF oe THEN IF SecAddr = SA_SSR THEN DOut_zd <= SSR_LOCK_REG; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN SecSi_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#25# AND SecAddr = SA_SecSi THEN SA_PGM <= SecAddr; BA_PGM <= BankID; ELSIF DataLo = 16#F0# THEN SecSi <= '0'; END IF; END IF; IF oe THEN IF SecAddr = SA_SecSi THEN READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); DOut_zd <= OutputD; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN CR_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#25# AND SecAddr = SA_CR THEN SA_PGM <= SecAddr; BA_PGM <= BankID; ELSIF DataLo = 16#F0# THEN CR_ACT <= '0'; END IF; END IF; IF oe THEN IF SecAddr = SA_CR THEN IF Addr MOD 16#100# = 0 THEN DOut_zd <= ConfReg0; ELSE DOut_zd <= (OTHERS => '0'); END IF; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN W2B_ENTRY => IF falling_edge(WRITE) THEN IF AddrCom = 16#2AA# THEN IF SecAddr = SA_PGM AND (((SecAddr = SL_REG OR SL_REG = -2) AND VPP /= '0') OR (SecSi = '1' AND VPP /= '0') OR LOCK_ACT = '1' OR CR_ACT = '1') AND NOT (SecSi = '1' AND SSR_LOCK_REG(0) = '0') AND NOT (LOCK_ACT = '1' AND DataLo > 0) AND NOT (CR_ACT = '1' AND DataLo > 0) AND NOT (ESP_ACT = '1' AND SecAddr = SA_ERS) THEN WC <= DataLo MOD (WrBuffLength +1); WrBuffCnt <= DataLo MOD (WrBuffLength +1); ELSE Status(4) := '1'; IF SecAddr = SA_PGM AND LOCK_ACT = '0' AND CR_ACT = '0' AND NOT (ESP_ACT = '1' AND SecAddr = SA_ERS) THEN Status(1) := '1'; ELSE Status(1) := '0'; END IF; END IF; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE Status(4) := '1'; END IF; END IF; IF oe THEN IF ESP_ACT = '1' AND SecAddr = SA_ERS THEN DOut_zd <= (OTHERS => '0'); ELSIF LOCK_ACT = '1' AND SecAddr = SA_SSR THEN DOut_zd <= SSR_LOCK_REG; ELSIF CR_ACT = '1' AND SecAddr = SA_CR THEN IF Addr MOD 16#100# = 0 THEN DOut_zd <= ConfReg0; ELSE DOut_zd <= (OTHERS => '0'); END IF; ELSIF SecSi = '1' AND SecAddr = SA_SecSi THEN READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); DOut_zd <= OutputD; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN ID_CFI_ENTRY => IF oe THEN IF SecAddr = SA_ID_CFI THEN READMEM(ReturnAddr(Addr,SecAddr),SecAddr,ID_CFI_T); DOut_zd <= OutputD; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN BC_ENTRY => IF rising_edge(BCDONE) THEN Status(7) := '1'; Status(5) := '0'; IF SA_BC <= 3 AND TimingModel(16) = '1' THEN FOR j IN SA_BC*(SecSize16+1) + sgsaB(0) TO SA_BC*(SecSize16+1) + sgsaB(0)+SecSize16 LOOP IF Mem(j) /= MaxData THEN Status(5) := '1'; END IF; END LOOP; ELSIF TimingModel(16) = '1' THEN FOR j IN (SA_BC-4)*(SecSize64+1) + sgsaB(1) TO (SA_BC-4)*(SecSize64+1) + sgsaB(1)+SecSize64 LOOP IF Mem(j) /= MaxData THEN Status(5) := '1'; END IF; END LOOP; ELSIF SA_BC < SecNum-3 AND TimingModel(16) = '0' THEN FOR j IN SA_BC*(SecSize64+1) + sgsaT(0) TO SA_BC*(SecSize64+1) + sgsaT(0)+SecSize64 LOOP IF Mem(j) /= MaxData THEN Status(5) := '1'; END IF; END LOOP; ELSIF TimingModel(16) = '0' THEN FOR j IN (SA_BC-(SecNum-3))*(SecSize16+1)+sgsaT(1) TO (SA_BC-(SecNum-3))*(SecSize16+1)+sgsaT(1)+SecSize16 LOOP IF Mem(j) /= MaxData THEN Status(5) := '1'; END IF; END LOOP; END IF; STAT_ACT <= '0'; END IF; IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN IF BankID = BA_BC THEN Status(0) := '0'; ELSE Status(0) := '1'; END IF; DOut_zd <= Status; STAT_ACT <= '0'; ELSE DOut_zd <= (OTHERS => 'X'); END IF; END IF; WHEN CERS => IF NOT ER_FLAG THEN ER_FLAG := TRUE; Mem := (OTHERS => -1); END IF; IF rising_edge(CEDONE) THEN Mem := (OTHERS => MaxData); Status(7) := '1'; STAT_ACT <= '0'; END IF; IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN Status(0) := '0'; DOut_zd <= Status; STAT_ACT <= '0'; ELSE DOut_zd <= (OTHERS => '0'); END IF; END IF; WHEN SERS => IF NOT ER_FLAG THEN ER_FLAG := TRUE; IF SA_ERS <= 3 AND TimingModel(16) = '1' THEN FOR j IN SA_ERS*(SecSize16+1) + sgsaB(0) TO SA_ERS*(SecSize16+1) + sgsaB(0)+SecSize16 LOOP Mem(j) := -1; END LOOP; ELSIF TimingModel(16) = '1' THEN FOR j IN (SA_ERS-4)*(SecSize64+1) + sgsaB(1) TO (SA_ERS-4)*(SecSize64+1) + sgsaB(1)+SecSize64 LOOP Mem(j) := -1; END LOOP; ELSIF SA_ERS < SecNum-3 AND TimingModel(16) = '0' THEN FOR j IN SA_ERS*(SecSize64+1) + sgsaT(0) TO SA_ERS*(SecSize64+1) + sgsaT(0)+SecSize64 LOOP Mem(j) := -1; END LOOP; ELSE FOR j IN (SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT(1) TO (SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT(1)+SecSize16 LOOP Mem(j) := -1; END LOOP; END IF; END IF; IF rising_edge(EDONE) THEN IF SA_ERS <= 3 AND TimingModel(16) = '1' THEN FOR j IN SA_ERS*(SecSize16+1) + sgsaB(0) TO SA_ERS*(SecSize16+1) + sgsaB(0)+SecSize16 LOOP Mem(j) := MaxData; END LOOP; ELSIF TimingModel(16) = '1' THEN FOR j IN (SA_ERS-4)*(SecSize64+1) + sgsaB(1) TO (SA_ERS-4)*(SecSize64+1) + sgsaB(1)+SecSize64 LOOP Mem(j) := MaxData; END LOOP; ELSIF SA_ERS < SecNum-3 AND TimingModel(16) = '0' THEN FOR j IN SA_ERS*(SecSize64+1) + sgsaT(0) TO SA_ERS*(SecSize64+1) + sgsaT(0)+SecSize64 LOOP Mem(j) := MaxData; END LOOP; ELSE FOR j IN (SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT(1) TO (SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT(1)+SecSize16 LOOP Mem(j) := MaxData; END LOOP; END IF; Status(7) := '1'; STAT_ACT <= '0'; END IF; IF falling_edge(WRITE) THEN IF DataLo = 16#B0# THEN ESUSP <= '1', '0' AFTER 1 ns; START_in <= '1'; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN IF BankID = BA_ERS THEN Status(0) := '0'; ELSE Status(0) := '1'; END IF; DOut_zd <= Status; STAT_ACT <= '0'; ELSIF BankID = BA_ERS THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN SL_Change => IF falling_edge(WRITE) THEN IF DataLo = 16#60# AND (Addr MOD 16#80#)/16#40# = 0 AND (SecAddr = SL_REG OR SL_REG = -2) THEN SL_REG <= -1; ELSIF DataLo = 16#60# AND (Addr MOD 16#80#)/16#40# = 1 AND SL_REG = -1 AND (SecAddr < SLA_Lo OR SecAddr > SLA_Hi) THEN SL_REG <= SecAddr; ELSIF DataLo = 16#61# AND NOT LockRangeDone THEN LockRange := TRUE; SLA_temp := SecAddr; A6Lock := (Addr MOD 16#80#)/16#40# = 0; ELSIF DataLo = 16#61# THEN LockRange := FALSE; END IF; END IF; IF oe THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (PGM_ACT = '1' AND BuffPageAddr = PA_PGM) THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN W2B_WC => IF falling_edge(WRITE) THEN IF SecAddr = SA_PGM AND NOT (SecSi = '1' AND (ReturnAddr(Addr,SA_SecSi) < 128 OR ReturnAddr(Addr,SA_SecSi) > 255)) AND NOT (LOCK_ACT = '1' AND (AddrCom MOD 16#100# /= 0)) AND NOT (CR_ACT = '1' AND (AddrCom MOD 16#100# > 0)) AND WC = 0 THEN PrevAddr <= Addr AFTER 1 ns; WrBuffAddr(0) <= Addr; WrBuffData(0) <= Data; PA_PGM <= BuffPageAddr; ELSIF SecAddr = SA_PGM AND NOT (SecSi = '1' AND (ReturnAddr(Addr,SA_SecSi) < 128 OR ReturnAddr(Addr,SA_SecSi) > 255)) AND NOT ((Addr + WC) / (WrBuffLength +1) > Addr / (WrBuffLength +1)) AND LOCK_ACT = '0' AND CR_ACT = '0'THEN PrevAddr <= Addr AFTER 1 ns; WrBuffAddr(WC) <= Addr; WrBuffData(WC) <= Data; WC <= WC - 1; PA_PGM <= BuffPageAddr; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE Status(4) := '1'; END IF; END IF; IF oe THEN IF ESP_ACT = '1' AND SecAddr = SA_ERS THEN DOut_zd <= (OTHERS => '0'); ELSIF LOCK_ACT = '1' AND SecAddr = SA_SSR THEN DOut_zd <= SSR_LOCK_REG; ELSIF CR_ACT = '1' AND SecAddr = SA_CR THEN IF Addr MOD 16#100# = 0 THEN DOut_zd <= ConfReg0; ELSE DOut_zd <= (OTHERS => '0'); END IF; ELSIF SecSi = '1' AND SecAddr = SA_SecSi THEN READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); DOut_zd <= OutputD; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN SERS_SL => IF rising_edge(START_out) THEN START_in <= '0'; ESP_ACT <= '1'; Status(7) := '1'; Status(6) := '1'; STAT_ACT <= '0'; END IF; IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN IF BankID = BA_ERS THEN Status(0) := '0'; ELSE Status(0) := '1'; END IF; DOut_zd <= Status; STAT_ACT <= '0'; ELSIF BankID = BA_ERS THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN LOCK_RANGE => IF falling_edge(WRITE) THEN IF DataLo=16#61# AND LockRange AND SecAddr >= SLA_temp AND A6Lock AND (Addr MOD 16#80#)/16#40# = 0 THEN LockRangeDone := TRUE; SLA_Lo := SLA_temp; SLA_Hi := SecAddr; IF SLA_Lo <= 3 AND TimingModel(16) = '1' THEN SLA_Lo := 0; END IF; IF SLA_Hi < 3 AND TimingModel(16) = '1' THEN SLA_Hi := 3; END IF; IF SLA_Lo > (SecNum-3) AND TimingModel(16) = '0' THEN SLA_Lo := SecNum-3; END IF; IF SLA_Hi >= (SecNum-3) AND TimingModel(16) = '0' THEN SLA_Hi := SecNum; END IF; IF SL_REG >= SLA_Lo AND SL_REG <= SLA_Hi THEN SL_REG <= -1; END IF; END IF; END IF; IF oe THEN IF (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (PGM_ACT = '1' AND BuffPageAddr = PA_PGM) THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN W2BUF_PG => IF falling_edge(WRITE) THEN IF Addr = PrevAddr + 1 THEN WrBuffAddr(WC) <= Addr; WrBuffData(WC) <= Data; PrevAddr <= Addr AFTER 1 ns; IF WC > 0 THEN WC <= WC - 1; END IF; ELSE Status(4) := '1'; END IF; END IF; IF oe THEN IF ESP_ACT = '1' AND SecAddr = SA_ERS THEN DOut_zd <= (OTHERS => '0'); ELSIF SecSi = '1' AND SecAddr = SA_SecSi THEN READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); DOut_zd <= OutputD; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN WB_LOADED => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#29# AND SecAddr = SA_PGM AND CR_ACT = '1' AND (WrBuffAddr(0) MOD 16#100# = 0) AND(WrBuffAddr(WrBuffCnt)/32 = WrBuffAddr(0)/32) THEN ConfReg0 := to_slv(WrBuffData(0), 16); ELSIF AddrCom = 16#555# AND DataLo = 16#29# AND SecAddr = SA_PGM AND CR_ACT = '0' AND (WrBuffAddr(WrBuffCnt)/32 = WrBuffAddr(0)/32) THEN PSTART <= '1', '0' AFTER 1 ns; Status(7) := '0'; Status(4) := '0'; PR_FLAG := FALSE; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE Status(4) := '1'; END IF; END IF; IF oe THEN IF ESP_ACT = '1' AND SecAddr = SA_ERS THEN DOut_zd <= (OTHERS => '0'); ELSIF LOCK_ACT = '1' AND SecAddr = SA_SSR THEN DOut_zd <= SSR_LOCK_REG; ELSIF CR_ACT = '1' AND SecAddr = SA_CR THEN IF Addr MOD 16#100# = 0 THEN DOut_zd <= ConfReg0; ELSE DOut_zd <= (OTHERS => '0'); END IF; ELSIF SecSi = '1' AND SecAddr = SA_SecSi THEN READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); DOut_zd <= OutputD; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN SERS_SUS => IF falling_edge(WRITE) THEN IF AddrCom = 16#000# AND DataLo = 16#30# THEN ERES <= '1', '0' AFTER 1 ns; ESP_ACT <= '0'; STAT_ACT <= '0'; Status(7) := '0'; Status(6) := '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#25# THEN SA_PGM <= SecAddr; BA_PGM <= BankID; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF AddrCom = 16#555# AND DataLo = 16#71# THEN Status(7) := '1'; Status(5 DOWNTO 3) := "000"; Status(1 DOWNTO 0) := "00"; STAT_ACT <= '0'; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN Status(0) := '0'; DOut_zd <= Status; STAT_ACT <= '0'; ELSIF SecAddr = SA_ERS THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN PGM => IF NOT PR_FLAG THEN PR_FLAG := TRUE; IF LOCK_ACT = '0' AND CR_ACT = '0' THEN FOR i IN WrBuffCnt DOWNTO 0 LOOP new_int:= WrBuffData(i); old_int:= -1; IF SecSi='1' THEN old_int:=SecSiMem(ReturnAddr(WrBuffAddr(i), SA_SecSi)); ELSE old_int:=Mem(WrBuffAddr(i)); END IF; WrBuffData(i)<= -1; IF new_int>-1 THEN new_bit:=to_slv(new_int,16); IF old_int>-1 THEN old_bit:=to_slv(old_int,16); FOR j IN 0 TO 15 LOOP IF old_bit(j) = '0' THEN new_bit(j):='0'; END IF; END LOOP; new_int:=to_nat(new_bit); END IF; WrBuffData(i)<= new_int; END IF; END LOOP; END IF; IF LOCK_ACT='1' AND SSR_LOCK_REG(0)='1' AND (WrBuffData(0) MOD 2 = 0) THEN SSR_LOCK_REG(0) := 'X'; ELSE FOR i IN WrBuffCnt downto 0 LOOP IF SecSi = '1' THEN SecSiMem(ReturnAddr(WrBuffAddr(i),SA_SecSi)) := -1; ELSE Mem(WrBuffAddr(i)) := -1; END IF; END LOOP; END IF; END IF; IF rising_edge(PDONE) THEN IF LOCK_ACT='1' AND SSR_LOCK_REG(0)='X' THEN SSR_LOCK_REG(0) := '0'; ELSE FOR i IN WrBuffCnt downto 0 LOOP IF SecSi = '1' THEN SecSiMem(ReturnAddr(WrBuffAddr(i),SA_SecSi)) := WrBuffData(i); ELSE Mem(WrBuffAddr(i)) := WrBuffData(i); END IF; WrBuffData(i)<= -1; END LOOP; END IF; Status(7) := '1'; STAT_ACT <= '0'; END IF; IF falling_edge(WRITE) THEN IF DataLo = 16#51# THEN PSUSP <= '1', '0' AFTER 1 ns; START_in <= '1'; STAT_ACT <= '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN IF BankID = BA_PGM THEN Status(0) := '0'; ELSE Status(0) := '1'; END IF; DOut_zd <= Status; STAT_ACT <= '0'; ELSIF BankID = BA_PGM OR (ESP_ACT = '1' AND SecAddr = SA_ERS) THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN PGM_SL => IF rising_edge(START_out) THEN START_in <= '0'; PGM_ACT <= '1'; Status(7) := '1'; Status(2) := '1'; STAT_ACT <= '0'; END IF; IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN IF BankID = BA_PGM THEN Status(0) := '0'; ELSE Status(0) := '1'; END IF; DOut_zd <= Status; STAT_ACT <= '0'; ELSIF BankID = BA_PGM OR (ESP_ACT = '1' AND SecAddr = SA_ERS) THEN DOut_zd <= (OTHERS => '0'); ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; WHEN PGM_SUS => IF falling_edge(WRITE) THEN IF AddrCom = 16#000# AND DataLo = 16#50# THEN PRES <= '1', '0' AFTER 1 ns; PGM_ACT <= '0'; STAT_ACT <= '0'; Status(7) := '0'; Status(2) := '0'; ELSIF AddrCom = 16#555# AND DataLo = 16#70# AND STAT_ACT = '0' THEN SA_SR <= SecAddr; STAT_ACT <= '1'; ELSIF AddrCom = 16#555# AND DataLo = 16#71# THEN Status(7) := '1'; Status(5 DOWNTO 3) := "000"; Status(1 DOWNTO 0) := "00"; STAT_ACT <= '0'; ELSIF DataLo MOD 16#10# = 16#C# THEN NULL; ELSE STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' AND SecAddr = SA_SR THEN Status(0) := '0'; DOut_zd <= Status; STAT_ACT <= '0'; ELSIF BuffPageAddr = PA_PGM OR (ESP_ACT = '1' AND SecAddr = SA_ERS) OR (LOCK_ACT = '1' AND SecAddr = SA_SSR) OR (CR_ACT = '1' AND SecAddr = SA_CR) THEN DOut_zd <= (OTHERS => '0'); ELSIF SecSi = '1' AND SecAddr = SA_SecSi THEN READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); DOut_zd <= OutputD; ELSE READMEM(Addr,SecAddr,Mem_T); DOut_zd <= OutputD; END IF; END IF; END CASE; END IF; CASE RD_MODE IS WHEN LINEAR => -- linear mode only implemented IF (rising_edge(CLKMerge) OR falling_edge(ReadINIT)) THEN IF BurstDelay > 0 THEN BurstDelay := BurstDelay - 1; IF (OENeg = '0') THEN RDY_temp <= '0'; END IF; IF BurstDelay = 1 THEN IF ConfReg0(8) ='0' THEN RDY_temp <= '1'; BurstStarted := TRUE; END IF; END IF; IF BurstDelay = 0 THEN RDY_temp <= '1'; BurstStarted := TRUE; END IF; END IF; IF BurstDelay = 0 THEN IF (IACC_out = '1' OR NOT IN_W_ELAPSED) THEN IF BURST_END THEN RDY_temp <= '0'; ELSIF INITIAL THEN IF DelayCycSwitch = 0 AND BurstAddr /= LatencyAddr THEN RDY_temp <= '1'; READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RDCnt,BURST_END); IF BurstAddr = LatencyAddr THEN IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 4; ELSE DelayCycSwitch := 1; END IF; END IF; ELSIF DelayCycSwitch=0 AND BurstAddr=LatencyAddr THEN IF DelayCyc_CNT > 0 THEN RDY_temp <= ConfReg0(8); ELSE RDY_temp <= '1'; END IF; READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); IF DelayCyc_CNT = 0 THEN INITIAL := FALSE; NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RDCnt,BURST_END); DelayCycSwitch := 0; ELSE DelayCyc_CNT := DelayCyc_CNT -1; IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 3; ELSE DelayCycSwitch := 2; END IF; END IF; ELSIF DelayCycSwitch = 1 THEN RDY_temp <= ConfReg0(8); READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); DelayCyc_CNT := DelayCyc_CNT -1; IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 3; ELSE DelayCycSwitch := 2; END IF; ELSIF DelayCycSwitch = 2 THEN RDY_temp <= '0'; READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); DelayCyc_CNT := DelayCyc_CNT -1; IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 3; END IF; ELSIF DelayCycSwitch = 3 THEN READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RDCnt,BURST_END); RDY_temp <= NOT ConfReg0(8); DelayCycSwitch := 4; ELSE --DelayCycSwitch = 4 INITIAL := FALSE; DelayCycSwitch := 0; RDY_temp <= '1'; READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RDCnt,BURST_END); END IF; IF (BURST_END) THEN RDY_temp <= ConfReg0(8); END IF; ELSE -- READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RDCnt,BURST_END); IF (NOT BURST_END ) THEN RDY_temp <= '1'; ELSE RDY_temp <= ConfReg0(8); END IF; END IF; ELSE IF OENeg = '0' THEN REPORT " More wait states should be programmed " severity warning; END IF; END IF; IF IN_W_ELAPSED THEN DATA_DELAY := TRUE; END IF; IN_W_ELAPSED := TRUE; END IF; END IF; WHEN CONTINUOUS => -- continuous mode IF (rising_edge(CLKMerge) OR falling_edge(ReadINIT)) THEN IF BurstDelay > 0 THEN BurstDelay := BurstDelay - 1; IF (OENeg = '0') THEN RDY_temp <= '0'; END IF; IF BurstDelay = 1 THEN IF ConfReg0(8) ='0' THEN RDY_temp <= '1'; BurstStarted := TRUE; END IF; END IF; IF BurstDelay = 0 THEN RDY_temp <= '1'; BurstStarted := TRUE; END IF; END IF; IF BurstDelay = 0 THEN IF (IACC_out = '1' OR NOT IN_W_ELAPSED) THEN IF INITIAL THEN IF DelayCycSwitch = 0 AND BurstAddr /= LatencyAddr THEN RDY_temp <= '1'; READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); NEXT_ADDR(BurstAddr,BurstSec,ReadTarget); IF BurstAddr = LatencyAddr THEN IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 4; ELSE DelayCycSwitch := 1; END IF; END IF; ELSIF DelayCycSwitch=0 AND BurstAddr=LatencyAddr THEN RDY_temp <= ConfReg0(8); READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); DelayCyc_CNT := DelayCyc_CNT -1; IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 3; ELSE DelayCycSwitch := 2; END IF; ELSIF DelayCycSwitch = 1 THEN RDY_temp <= ConfReg0(8); READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); DelayCyc_CNT := DelayCyc_CNT -1; IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 3; ELSE DelayCycSwitch := 2; END IF; ELSIF DelayCycSwitch = 2 THEN RDY_temp <= '0'; READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); DelayCyc_CNT := DelayCyc_CNT -1; IF DelayCyc_CNT = 0 THEN DelayCycSwitch := 3; END IF; ELSIF DelayCycSwitch = 3 THEN READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); IF BurstAddr MOD 16#80# = 16#7F# THEN IF WS_Boundary > 0 THEN RDY_temp <= '0'; ELSE IF ReadTarget = Mem_T THEN CheckBoundary(BusyBOUND,BurstAddr); END IF; NEXT_ADDR(BurstAddr,BurstSec, ReadTarget); IF BusyBOUND THEN RDY_temp <= '0'; ELSE RDY_temp <= NOT ConfReg0(8); END IF; END IF; INITIAL := FALSE; BOUNDARY_CROSS := TRUE; BoundarySwitch := 0; ELSE NEXT_ADDR(BurstAddr,BurstSec,ReadTarget); RDY_temp <= NOT ConfReg0(8); DelayCycSwitch := 4; END IF; ELSE --DelayCycSwitch = 4 INITIAL := FALSE; DelayCycSwitch := 0; READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); IF BurstAddr MOD 16#80# = 16#7F# THEN IF WS_Boundary > 0 THEN RDY_temp <= ConfReg0(8); ELSE IF ReadTarget = Mem_T THEN CheckBoundary(BusyBOUND,BurstAddr); END IF; NEXT_ADDR(BurstAddr,BurstSec, ReadTarget); RDY_temp <= '1'; END IF; BOUNDARY_CROSS := TRUE; BoundarySwitch := 0; ELSE RDY_temp <= '1'; NEXT_ADDR(BurstAddr,BurstSec,ReadTarget); END IF; END IF; ELSIF BOUNDARY_CROSS THEN IF BoundarySwitch = 0 THEN IF WS_Boundary > 0 THEN READ_BURST_DATA(BurstAddr,BurstSec, ReadTarget); WS_Boundary := WS_Boundary - 1; IF WS_Boundary > 0 THEN RDY_temp <= '0'; BoundarySwitch := 1; ELSE IF ReadTarget = Mem_T THEN CheckBoundary(BusyBOUND,BurstAddr); END IF; IF BusyBOUND THEN RDY_temp <= '0'; ELSE RDY_temp <= NOT ConfReg0(8); END IF; NEXT_ADDR(BurstAddr,BurstSec, ReadTarget); BoundarySwitch := 2; END IF; ELSE BoundarySwitch := 3; END IF; ELSIF BoundarySwitch = 1 THEN READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); WS_Boundary := WS_Boundary - 1; IF ReadTarget = Mem_T THEN CheckBoundary(BusyBOUND,BurstAddr); END IF; IF BusyBOUND THEN RDY_temp <= '0'; ELSE RDY_temp <= NOT ConfReg0(8); END IF; NEXT_ADDR(BurstAddr,BurstSec,ReadTarget); BoundarySwitch := 2; ELSE -- Boundary switch=2 BoundarySwitch:=3; END IF; IF BoundarySwitch = 3 THEN IF BusyBOUND THEN NO_PROGRESS := TRUE; DOut_burst := (OTHERS => '0'); RDY_temp <= '0'; ELSE RDY_temp <= '1'; READ_BURST_DATA(BurstAddr,BurstSec, ReadTarget); NEXT_ADDR(BurstAddr,BurstSec,ReadTarget); END IF; BOUNDARY_CROSS := FALSE; END IF; ELSIF NO_PROGRESS THEN RDY_temp <= '0'; ELSE READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); IF BurstAddr MOD 16#80# = 16#7F# THEN IF WS_Boundary > 0 THEN RDY_temp <= ConfReg0(8); ELSE IF ReadTarget = Mem_T THEN CheckBoundary(BusyBOUND,BurstAddr); END IF; NEXT_ADDR(BurstAddr,BurstSec,ReadTarget); RDY_temp <= '1'; END IF; BOUNDARY_CROSS := TRUE; BoundarySwitch := 0; ELSE NEXT_ADDR(BurstAddr,BurstSec,ReadTarget); RDY_temp <= '1'; END IF; END IF; ELSE IF OENeg = '0' THEN REPORT " More wait states should be programmed " severity warning; END IF; END IF; IF IN_W_ELAPSED THEN DATA_DELAY := TRUE; END IF; IN_W_ELAPSED := TRUE; END IF; END IF; WHEN SYNCR => IF (rising_edge(CLKMerge) OR falling_edge(ReadINIT)) THEN IF BurstDelay > 0 THEN BurstDelay := BurstDelay - 1; IF (OENeg = '0') THEN RDY_temp <= '0'; END IF; IF BurstDelay = 1 THEN IF ConfReg0(8) ='0' THEN RDY_temp <= '1'; BurstStarted := TRUE; END IF; END IF; END IF; IF BurstDelay = 0 THEN RDY_temp <= '1'; BurstStarted := TRUE; END IF; END IF; WHEN NOSYNC => NULL; END CASE; IF RD_MODE /= NOSYNC AND IN_W_ELAPSED AND OENeg='0' THEN DOut_zd <= DOut_burst; END IF; IF falling_edge (OENeg) AND NOT BurstStarted THEN RDY_temp <= '0'; END IF; IF rising_edge(CENeg) THEN RDY_temp <= '1'; END IF; --Output Disable Control IF rising_edge(CENeg) OR (falling_edge(RST) AND RESETNeg = '0') OR ( rising_edge(OENeg) AND (RD_MODE = NOSYNC OR RD_MODE = SYNCR OR INITIAL))THEN DOut_zd <= (OTHERS=>'Z'); END IF; END PROCESS Functional; ---------------------------------------------------------------------------- ---- CFI Preload Process ---------------------------------------------------------------------------- CFIPreload : PROCESS(PoweredUp) BEGIN IF (PoweredUp = '1' ) THEN CFIMem := (OTHERS => 0); --CFI Query Identification String CFIMem(16#10#) := 16#0051#; CFIMem(16#11#) := 16#0052#; CFIMem(16#12#) := 16#0059#; CFIMem(16#13#) := 16#0002#; CFIMem(16#14#) := 16#0000#; CFIMem(16#15#) := 16#0040#; CFIMem(16#16#) := 16#0000#; CFIMem(16#17#) := 16#0000#; CFIMem(16#18#) := 16#0000#; CFIMem(16#19#) := 16#0000#; CFIMem(16#1A#) := 16#0000#; --System Interface String CFIMem(16#1B#) := 16#0017#; CFIMem(16#1C#) := 16#0019#; CFIMem(16#1D#) := 16#0000#; CFIMem(16#1E#) := 16#0000#; CFIMem(16#1F#) := 16#0008#; CFIMem(16#20#) := 16#0009#; CFIMem(16#21#) := 16#000A#; CFIMem(16#22#) := 16#0012#; CFIMem(16#23#) := 16#0003#; CFIMem(16#24#) := 16#0003#; CFIMem(16#25#) := 16#0003#; CFIMem(16#26#) := 16#0003#; --Device Geometry Definition CFIMem(16#27#) := 16#0019#; CFIMem(16#28#) := 16#0001#; CFIMem(16#29#) := 16#0000#; CFIMem(16#2A#) := 16#0006#; CFIMem(16#2B#) := 16#0000#; CFIMem(16#2C#) := 16#0002#; IF TimingModel(16) = '0' THEN CFIMem(16#2D#) := 16#00FE#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#2D#) := 16#0003#; END IF; CFIMem(16#2E#) := 16#0000#; IF TimingModel(16) = '0' THEN CFIMem(16#2F#) := 16#0000#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#2F#) := 16#0080#; END IF; IF TimingModel(16) = '0' THEN CFIMem(16#30#) := 16#0002#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#30#) := 16#0000#; END IF; IF TimingModel(16) = '0' THEN CFIMem(16#31#) := 16#0003#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#31#) := 16#00FE#; END IF; CFIMem(16#32#) := 16#0000#; IF TimingModel(16) = '0' THEN CFIMem(16#33#) := 16#0080#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#33#) := 16#0000#; END IF; IF TimingModel(16) = '0' THEN CFIMem(16#34#) := 16#0000#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#34#) := 16#0002#; END IF; --Primary Algorithm-Specific Extended Query CFIMem(16#40#) := 16#0050#; CFIMem(16#41#) := 16#0052#; CFIMem(16#42#) := 16#0049#; CFIMem(16#43#) := 16#0031#; CFIMem(16#44#) := 16#0034#; CFIMem(16#45#) := 16#0020#; CFIMem(16#46#) := 16#0002#; CFIMem(16#47#) := 16#0001#; CFIMem(16#48#) := 16#0000#; CFIMem(16#49#) := 16#0009#; CFIMem(16#4A#) := 16#00E0#; CFIMem(16#4B#) := 16#0001#; CFIMem(16#4C#) := 16#0000#; CFIMem(16#4D#) := 16#0085#; CFIMem(16#4E#) := 16#0095#; IF TimingModel(16) = '0' THEN CFIMem(16#4F#) := 16#0003#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#4F#) := 16#0002#; END IF; CFIMem(16#50#) := 16#0001#; CFIMem(16#51#) := 16#0000#; CFIMem(16#52#) := 16#0007#; CFIMem(16#53#) := 16#000E#; CFIMem(16#54#) := 16#000E#; CFIMem(16#55#) := 16#0008#; CFIMem(16#56#) := 16#0008#; CFIMem(16#57#) := 16#0008#; IF TimingModel(16) = '0' THEN CFIMem(16#58#) := 16#0020#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#58#) := 16#0023#; END IF; CFIMem(16#59#) := 16#0020#; CFIMem(16#5A#) := 16#0020#; CFIMem(16#5B#) := 16#0020#; CFIMem(16#5C#) := 16#0020#; CFIMem(16#5D#) := 16#0020#; CFIMem(16#5E#) := 16#0020#; IF TimingModel(16) = '0' THEN CFIMem(16#5F#) := 16#0023#; ELSIF TimingModel(16) = '1' THEN CFIMem(16#5F#) := 16#0020#; END IF; END IF; END PROCESS CFIPreload; ---------------------------------------------------------------------------- ---- File Read Section - Preload Control ---------------------------------------------------------------------------- MemPreload : PROCESS(PoweredUp) -- text file input variables FILE mem_file : text is mem_file_name; FILE secsi_file : text is secsi_file_name; VARIABLE buf : line; VARIABLE ind : NATURAL; VARIABLE addr_ind : NATURAL; VARIABLE secsi_ind : NATURAL; VARIABLE reported : NATURAL RANGE 0 TO 1 := 0; VARIABLE mem_data : INTEGER; VARIABLE SecAddr : INTEGER; BEGIN IF (PoweredUp = '1') THEN IF (mem_file_name /= "none" AND UserPreload ) THEN -- s29xs256r memory file -- // - comment -- @aaaaaa - stands for address -- dddd - is word to be written at Mem(aaaaaa++) -- (aaaaaa is incremented at every load) -- only first 1-7 columns are loaded. -- NO EMPTY LINES addr_ind := 0; reported := 0; Mem := (OTHERS => MaxData); WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '/' THEN --comment NEXT; ELSIF buf(1) = '@' THEN --address addr_ind := h(buf(2 to 7)); ELSE IF addr_ind <= MemSize THEN Mem(addr_ind) := h(buf(1 to 4)); addr_ind := addr_ind + 1; ELSIF reported = 0 THEN REPORT " Memory address out of range" SEVERITY warning; reported := 1; END IF; END IF; END LOOP; END IF; IF (secsi_file_name /= "none" AND UserPreload ) THEN --s29xs256r_secsi memory file --// - comment --@aa - stands for address within SecSi region --dddd - is word to be written at SecSi(aa++) -- (aa is incremented at every load) -- only first 1-4 columns are loaded. NO empty lines ! secsi_ind := 0; SecSiMem := (OTHERS => MaxData); reported := 0; WHILE (not ENDFILE (SecSi_file)) LOOP READLINE (SecSi_file, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN secsi_ind := h(buf(2 to 3)); --address ELSE IF secsi_ind <= 16#FF# THEN SecSiMem(secsi_ind) := h(buf(1 TO 4)); secsi_ind := secsi_ind + 1; ELSIF reported = 0 THEN REPORT " SecSi area address out of range" SEVERITY warning; reported := 1; END IF; END IF; END LOOP; END IF; END IF; END PROCESS MemPreload; ---------------------------------------------------------------------------- -- Process for RDY generation ---------------------------------------------------------------------------- RDYGenerate : PROCESS(RDY_temp, CENeg, reseted) BEGIN IF CENeg = '0' AND ConfReg0(15)='0' AND reseted = '1' THEN IF ConfReg0(10) = '1' THEN RDY_zd <= RDY_temp; ELSE RDY_zd <= NOT RDY_temp; END IF; ELSIF CENeg = '0' AND reseted = '1' THEN RDY_zd <= '1'; ELSE RDY_zd <= 'Z'; END IF; END PROCESS RDYGenerate; ---------------------------------------------------------------------------- -- Process for Dout generation ---------------------------------------------------------------------------- DQValueGen : 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 IF ConfReg0(15) = '1' THEN CEDQ_t := tpd_CENeg_ADQ0_SYN_EQ_0(trz0)-CENeg'LAST_EVENT; OEDQ_t := tpd_OENeg_ADQ0_SYN_EQ_0(trz0)-OENeg'LAST_EVENT; ELSE CEDQ_t := tpd_CENeg_ADQ0_SYN_EQ_1(trz0)-CENeg'LAST_EVENT; OEDQ_t := tpd_OENeg_ADQ0_SYN_EQ_1(trz0)-OENeg'LAST_EVENT; END IF; IF ConfReg0(15) = '1' THEN ADDRDQ_t:= -AddrRef'LAST_EVENT + tpd_A16_ADQ0(tr01);--tacc ELSE ADDRDQ_t:= -AddrREF'LAST_EVENT + tdevice_IACC; END IF; FROMOE := (OEDQ_t >= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t > OEDQ_t) AND (CEDQ_t > 0 ns); FROMADDR := NOT FROMOE AND NOT FROMCE; 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 IF ConfReg0(15) = '1' THEN CEDQ_t := tpd_CENeg_ADQ0_SYN_EQ_0(tr0z)-CENeg'LAST_EVENT; OEDQ_t := tpd_OENeg_ADQ0_SYN_EQ_0(tr0z)-OENeg'LAST_EVENT; ELSE CEDQ_t := tpd_CENeg_ADQ0_SYN_EQ_1(tr0z)-CENeg'LAST_EVENT; OEDQ_t := tpd_OENeg_ADQ0_SYN_EQ_1(tr0z)-OENeg'LAST_EVENT; END IF; FROMOE:= ((OEDQ_t <= CEDQ_t) AND (OEDQ_t > 0 ns)) OR (CEDQ_t< 0 ns); FROMCE := ((CEDQ_t < OEDQ_t) AND (CEDQ_t > 0 ns)) OR (OEDQ_t< 0 ns); DOut_Pass <= DOut_zd; END IF; END PROCESS DQValueGen; ---------------------------------------------------------------------------- -- Path Delay Section ---------------------------------------------------------------------------- PROCESS(RDY_zd) VARIABLE RDY_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => RDY, OutSignalName => "RDY", OutTemp => RDY_zd, GlitchData => RDY_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_RDY_SYN_EQ_0, PathCondition => ConfReg0(15) = '1'), 1 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_RDY_SYN_EQ_1, PathCondition => ConfReg0(15) = '0'), 2 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => VitalExtendToFillDelay (tpd_OENeg_RDY), PathCondition => CENeg = '0' AND ConfReg0(15) = '0'), 3 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => VitalExtendToFillDelay (tpd_CLK_RDY), PathCondition => CENeg = '0' AND ConfReg0(15) = '0' AND CLK = '1' AND RDY_zd /= 'Z'), 4 => (InputChangeTime => RESETNeg'LAST_EVENT, PathDelay => tpd_RESETNeg_ADQ0, PathCondition => RESETNeg='0' ) ) ); END PROCESS; --------------------------------------------------------------------------- -- Path Delay Section for DOut signal --------------------------------------------------------------------------- D_Out_PathDelay_Gen : FOR i IN 0 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, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_ADQ0_SYN_EQ_0, PathCondition => FROMOE AND ConfReg0(15) = '1'), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_ADQ0_SYN_EQ_1, PathCondition => FROMOE AND ConfReg0(15) = '0'), 2 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_ADQ0_SYN_EQ_0, PathCondition => (FROMCE OR DOut_Pass(0)='X') AND ConfReg0(15) = '1'), 3 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_ADQ0_SYN_EQ_1, PathCondition => (FROMCE OR DOut_Pass(0)='X') AND ConfReg0(15) = '0'), 4 => (InputChangeTime => AddrREF'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A16_ADQ0), PathCondition => FROMADDR AND ConfReg0(15) = '0'), 5 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_ADQ0), PathCondition => CENeg = '0' AND ConfReg0(15) = '0' AND IN_W_ELAPSED AND CLK = '1' AND (RD_MODE = CONTINUOUS OR RD_MODE = LINEAR)), 6 => (InputChangeTime => RESETNeg'LAST_EVENT, PathDelay => tpd_RESETNeg_ADQ0, PathCondition => RESETNeg='0' ) ) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; END BLOCK Behavior; END vhdl_behavioral;