-------------------------------------------------------------------------------- -- File Name: i28f256j3.vhd -------------------------------------------------------------------------------- -- Copyright (C) 2004 Free Model Foundry; http://www.FreeModelFoundry.com -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2 as -- published by the Free Software Foundation. -- -- MODIFICATION HISTORY: -- -- version: | author: | mod date: | changes made: -- V1.0 M.Stojsavljevic 04 APR 22 Initial release -- V1.1 M.Stojsavljevic 04 MAY 21 FSM change-state process modified: -- no longer triggered by CEXNeg; -- read/write decode modified: -- formed signals Read/Write which -- are set/reset on OENeg,CEXNEg,A -- /WENeg, CEXNeg -- sts_configure states reduced: -- data sheet explicitly rejects a -- possibility of sts configuration -- while busy or suspended -- programming data flow modified: -- WDone setting -- in order to encrease code coverage, -- merged identical-changing-state -- cases to one WHEN statement -- also in order to encrease code -- coverage, modified CASE for FSM -- transitions: FSM changes state to -- RESET_POWER_DOWN on RSTNeg low no -- matter which state is current -- state; -- The conditions for some of the -- Vital timing procedures are changed -------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH MEMORY -- Technology: CMOS -- Part: I28F256J3 -- -- Description: 256Mbit Advanced+ Boot Block Intel Flash memory -- -------------------------------------------------------------------------------- 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 i28f256j3 IS GENERIC ( -- tipd delays: interconnect path delays tipd_A0 : VitalDelayType01 := VitalZeroDelay01; tipd_A1 : VitalDelayType01 := VitalZeroDelay01; tipd_A2 : VitalDelayType01 := VitalZeroDelay01; tipd_A3 : VitalDelayType01 := VitalZeroDelay01; tipd_A4 : VitalDelayType01 := VitalZeroDelay01; tipd_A5 : VitalDelayType01 := VitalZeroDelay01; tipd_A6 : VitalDelayType01 := VitalZeroDelay01; tipd_A7 : VitalDelayType01 := VitalZeroDelay01; tipd_A8 : VitalDelayType01 := VitalZeroDelay01; tipd_A9 : VitalDelayType01 := VitalZeroDelay01; tipd_A10 : VitalDelayType01 := VitalZeroDelay01; tipd_A11 : VitalDelayType01 := VitalZeroDelay01; tipd_A12 : VitalDelayType01 := VitalZeroDelay01; tipd_A13 : VitalDelayType01 := VitalZeroDelay01; tipd_A14 : VitalDelayType01 := VitalZeroDelay01; tipd_A15 : VitalDelayType01 := VitalZeroDelay01; tipd_A16 : VitalDelayType01 := VitalZeroDelay01; tipd_A17 : VitalDelayType01 := VitalZeroDelay01; tipd_A18 : VitalDelayType01 := VitalZeroDelay01; tipd_A19 : VitalDelayType01 := VitalZeroDelay01; tipd_A20 : VitalDelayType01 := VitalZeroDelay01; tipd_A21 : VitalDelayType01 := VitalZeroDelay01; tipd_A22 : VitalDelayType01 := VitalZeroDelay01; tipd_A23 : VitalDelayType01 := VitalZeroDelay01; tipd_A24 : VitalDelayType01 := VitalZeroDelay01; tipd_D0 : VitalDelayType01 := VitalZeroDelay01; tipd_D1 : VitalDelayType01 := VitalZeroDelay01; tipd_D2 : VitalDelayType01 := VitalZeroDelay01; tipd_D3 : VitalDelayType01 := VitalZeroDelay01; tipd_D4 : VitalDelayType01 := VitalZeroDelay01; tipd_D5 : VitalDelayType01 := VitalZeroDelay01; tipd_D6 : VitalDelayType01 := VitalZeroDelay01; tipd_D7 : VitalDelayType01 := VitalZeroDelay01; tipd_D8 : VitalDelayType01 := VitalZeroDelay01; tipd_D9 : VitalDelayType01 := VitalZeroDelay01; tipd_D10 : VitalDelayType01 := VitalZeroDelay01; tipd_D11 : VitalDelayType01 := VitalZeroDelay01; tipd_D12 : VitalDelayType01 := VitalZeroDelay01; tipd_D13 : VitalDelayType01 := VitalZeroDelay01; tipd_D14 : VitalDelayType01 := VitalZeroDelay01; tipd_D15 : VitalDelayType01 := VitalZeroDelay01; tipd_CE0Neg : VitalDelayType01 := VitalZeroDelay01; tipd_CE1Neg : VitalDelayType01 := VitalZeroDelay01; tipd_CE2Neg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RPNeg : VitalDelayType01 := VitalZeroDelay01; tipd_VPEN : VitalDelayType01 := VitalZeroDelay01; tipd_BYTE : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_A0_D0_InitialPageAccess : VitalDelayType01 := UnitDelay01; tpd_A0_D0_SubsequentPageAccess : VitalDelayType01 := UnitDelay01; tpd_CE0Neg_D0 : VitalDelayType01Z := UnitDelay01Z; tpd_CE1Neg_D0 : VitalDelayType01Z := UnitDelay01Z; tpd_CE2Neg_D0 : VitalDelayType01Z := UnitDelay01Z; tpd_OENeg_D0_Array : VitalDelayType01Z := UnitDelay01Z; tpd_OENeg_D0_NonArray : VitalDelayType01Z := UnitDelay01Z; tpd_RPNeg_D0 : VitalDelayType01 := UnitDelay01; tpd_WENeg_STS : VitalDelayType01 := UnitDelay01; -- tpw values: pulse widths tpw_WENeg_negedge : VitalDelayType := UnitDelay; tpw_WENeg_posedge : VitalDelayType := UnitDelay; tpw_CE0Neg_posedge : VitalDelayType := UnitDelay; tpw_RPNeg_negedge : VitalDelayType := UnitDelay; -- tsetup values tsetup_CE0Neg_WENeg : VitalDelayType := UnitDelay; --low tsetup_D0_WENeg : VitalDelayType := UnitDelay; --high tsetup_A0_WENeg : VitalDelayType := UnitDelay; --high tsetup_VPEN_WENeg : VitalDelayType := UnitDelay; --high -- thold values thold_CE0Neg_WENeg : VitalDelayType := UnitDelay; --high thold_D0_WENeg : VitalDelayType := UnitDelay; --high thold_A0_WENeg : VitalDelayType := UnitDelay; --high -- trecovery values WRITE trecovery_RPNeg_WENeg : VitalDelayType := UnitDelay; trecovery_WENeg_OENeg : VitalDelayType := UnitDelay; -- tdevice values tdevice_ByteProgram : VitalDelayType := UnitDelay; tdevice_BufProgram : VitalDelayType := UnitDelay; tdevice_BlockErase : VitalDelayType := UnitDelay; tdevice_SetLock : VitalDelayType := UnitDelay; tdevice_ClearLock : VitalDelayType := UnitDelay; tdevice_ProgramSuspend : VitalDelayType := UnitDelay; tdevice_EraseSuspend : VitalDelayType := UnitDelay; tdevice_ResetLow : VitalDelayType := UnitDelay; tdevice_ResetRecovery : VitalDelayType := UnitDelay; -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- memory file to be loaded mem_file_name : STRING := "i28f256j3.mem"; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( A24 : IN std_logic := 'L'; A23 : IN std_logic := 'L'; A22 : IN std_logic := 'L'; A21 : IN std_logic := 'L'; A20 : IN std_logic := 'L'; A19 : IN std_logic := 'L'; A18 : IN std_logic := 'L'; A17 : IN std_logic := 'L'; A16 : IN std_logic := 'L'; A15 : IN std_logic := 'L'; A14 : IN std_logic := 'L'; A13 : IN std_logic := 'L'; A12 : IN std_logic := 'L'; A11 : IN std_logic := 'L'; A10 : IN std_logic := 'L'; A9 : IN std_logic := 'L'; A8 : IN std_logic := 'L'; A7 : IN std_logic := 'L'; A6 : IN std_logic := 'L'; A5 : IN std_logic := 'L'; A4 : IN std_logic := 'L'; A3 : IN std_logic := 'L'; A2 : IN std_logic := 'L'; A1 : IN std_logic := 'L'; A0 : IN std_logic := 'L'; D15 : INOUT std_logic := 'L'; D14 : INOUT std_logic := 'L'; D13 : INOUT std_logic := 'L'; D12 : INOUT std_logic := 'L'; D11 : INOUT std_logic := 'L'; D10 : INOUT std_logic := 'L'; D9 : INOUT std_logic := 'L'; D8 : INOUT std_logic := 'L'; D7 : INOUT std_logic := 'L'; D6 : INOUT std_logic := 'L'; D5 : INOUT std_logic := 'L'; D4 : INOUT std_logic := 'L'; D3 : INOUT std_logic := 'L'; D2 : INOUT std_logic := 'L'; D1 : INOUT std_logic := 'L'; D0 : INOUT std_logic := 'L'; CE0Neg : IN std_logic := 'U'; CE1Neg : IN std_logic := 'U'; CE2Neg : IN std_logic := 'U'; OENeg : IN std_logic := 'U'; WENeg : IN std_logic := 'U'; RPNeg : IN std_logic := 'U'; VPEN : IN std_logic := 'U'; BYTE : IN std_logic := 'U'; STS : OUT std_logic := 'Z' ); ATTRIBUTE VITAL_LEVEL0 of i28f256j3 : ENTITY IS TRUE; END i28f256j3; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of i28f256j3 IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "i28f256j3"; CONSTANT MaxData : NATURAL := 16#FFFF#; --65536; CONSTANT MaxDataByte : NATURAL := 16#FF#; --256 CONSTANT MemSize : NATURAL := 16#1FFFFFF#; -- ipd SIGNAL A24_ipd : std_ulogic := 'U'; SIGNAL A23_ipd : std_ulogic := 'U'; SIGNAL A22_ipd : std_ulogic := 'U'; SIGNAL A21_ipd : std_ulogic := 'U'; SIGNAL A20_ipd : std_ulogic := 'U'; SIGNAL A19_ipd : std_ulogic := 'U'; SIGNAL A18_ipd : std_ulogic := 'U'; SIGNAL A17_ipd : std_ulogic := 'U'; SIGNAL A16_ipd : std_ulogic := 'U'; SIGNAL A15_ipd : std_ulogic := 'U'; SIGNAL A14_ipd : std_ulogic := 'U'; SIGNAL A13_ipd : std_ulogic := 'U'; SIGNAL A12_ipd : std_ulogic := 'U'; SIGNAL A11_ipd : std_ulogic := 'U'; SIGNAL A10_ipd : std_ulogic := 'U'; SIGNAL A9_ipd : std_ulogic := 'U'; SIGNAL A8_ipd : std_ulogic := 'U'; SIGNAL A7_ipd : std_ulogic := 'U'; SIGNAL A6_ipd : std_ulogic := 'U'; SIGNAL A5_ipd : std_ulogic := 'U'; SIGNAL A4_ipd : std_ulogic := 'U'; SIGNAL A3_ipd : std_ulogic := 'U'; SIGNAL A2_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL D15_ipd : std_ulogic := 'U'; SIGNAL D14_ipd : std_ulogic := 'U'; SIGNAL D13_ipd : std_ulogic := 'U'; SIGNAL D12_ipd : std_ulogic := 'U'; SIGNAL D11_ipd : std_ulogic := 'U'; SIGNAL D10_ipd : std_ulogic := 'U'; SIGNAL D9_ipd : std_ulogic := 'U'; SIGNAL D8_ipd : std_ulogic := 'U'; SIGNAL D7_ipd : std_ulogic := 'U'; SIGNAL D6_ipd : std_ulogic := 'U'; SIGNAL D5_ipd : std_ulogic := 'U'; SIGNAL D4_ipd : std_ulogic := 'U'; SIGNAL D3_ipd : std_ulogic := 'U'; SIGNAL D2_ipd : std_ulogic := 'U'; SIGNAL D1_ipd : std_ulogic := 'U'; SIGNAL D0_ipd : std_ulogic := 'U'; SIGNAL CE0Neg_ipd : std_ulogic := 'U'; SIGNAL CE1Neg_ipd : std_ulogic := 'U'; SIGNAL CE2Neg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL RPNeg_ipd : std_ulogic := 'U'; SIGNAL VPEN_ipd : std_ulogic := 'U'; SIGNAL BYTE_ipd : std_ulogic := 'U'; -- nwv SIGNAL A24_nwv : UX01 := 'U'; SIGNAL A23_nwv : UX01 := 'U'; SIGNAL A22_nwv : UX01 := 'U'; SIGNAL A21_nwv : UX01 := 'U'; SIGNAL A20_nwv : UX01 := 'U'; SIGNAL A19_nwv : UX01 := 'U'; SIGNAL A18_nwv : UX01 := 'U'; SIGNAL A17_nwv : UX01 := 'U'; SIGNAL A16_nwv : UX01 := 'U'; SIGNAL A15_nwv : UX01 := 'U'; SIGNAL A14_nwv : UX01 := 'U'; SIGNAL A13_nwv : UX01 := 'U'; SIGNAL A12_nwv : UX01 := 'U'; SIGNAL A11_nwv : UX01 := 'U'; SIGNAL A10_nwv : UX01 := 'U'; SIGNAL A9_nwv : UX01 := 'U'; SIGNAL A8_nwv : UX01 := 'U'; SIGNAL A7_nwv : UX01 := 'U'; SIGNAL A6_nwv : UX01 := 'U'; SIGNAL A5_nwv : UX01 := 'U'; SIGNAL A4_nwv : UX01 := 'U'; SIGNAL A3_nwv : UX01 := 'U'; SIGNAL A2_nwv : UX01 := 'U'; SIGNAL A1_nwv : UX01 := 'U'; SIGNAL A0_nwv : UX01 := 'U'; SIGNAL D15_nwv : UX01 := 'U'; SIGNAL D14_nwv : UX01 := 'U'; SIGNAL D13_nwv : UX01 := 'U'; SIGNAL D12_nwv : UX01 := 'U'; SIGNAL D11_nwv : UX01 := 'U'; SIGNAL D10_nwv : UX01 := 'U'; SIGNAL D9_nwv : UX01 := 'U'; SIGNAL D8_nwv : UX01 := 'U'; SIGNAL D7_nwv : UX01 := 'U'; SIGNAL D6_nwv : UX01 := 'U'; SIGNAL D5_nwv : UX01 := 'U'; SIGNAL D4_nwv : UX01 := 'U'; SIGNAL D3_nwv : UX01 := 'U'; SIGNAL D2_nwv : UX01 := 'U'; SIGNAL D1_nwv : UX01 := 'U'; SIGNAL D0_nwv : UX01 := 'U'; SIGNAL CE0Neg_nwv : UX01 := 'U'; SIGNAL CE1Neg_nwv : UX01 := 'U'; SIGNAL CE2Neg_nwv : UX01 := 'U'; SIGNAL OENeg_nwv : UX01 := 'U'; SIGNAL WENeg_nwv : UX01 := 'U'; SIGNAL RPNeg_nwv : UX01 := 'U'; SIGNAL VPEN_nwv : UX01 := 'U'; SIGNAL BYTE_nwv : UX01 := 'U'; --internal delays SIGNAL WriteBuf_in : std_ulogic := '0'; SIGNAL WriteBuf_out : std_ulogic := '0'; SIGNAL ByteProgram_in : std_ulogic := '0'; SIGNAL ByteProgram_out : std_ulogic := '0'; SIGNAL WordProgram_in : std_ulogic := '0'; SIGNAL WordProgram_out : std_ulogic := '0'; SIGNAL BufProgram_in : std_ulogic := '0'; SIGNAL BufProgram_out : std_ulogic := '0'; SIGNAL BlockErase_in : std_ulogic := '0'; SIGNAL BlockErase_out : std_ulogic := '0'; SIGNAL SetLock_in : std_ulogic := '0'; SIGNAL SetLock_out : std_ulogic := '0'; SIGNAL ClearLock_in : std_ulogic := '0'; SIGNAL ClearLock_out : std_ulogic := '0'; SIGNAL ProgramSuspend_in : std_ulogic := '0'; SIGNAL ProgramSuspend_out : std_ulogic := '0'; SIGNAL EraseSuspend_in : std_ulogic := '0'; SIGNAL EraseSuspend_out : std_ulogic := '0'; SIGNAL ResetRecovery_in : std_ulogic := '0'; SIGNAL ResetRecovery_out : std_ulogic := '0'; SIGNAL ResetLow_in : std_ulogic := '0'; SIGNAL ResetLow_out : std_ulogic := '0'; FUNCTION ALLIGN_TYPES( Input_nwv : UX01 ) RETURN std_ulogic IS VARIABLE Output : std_ulogic; BEGIN Output := 'U'; CASE Input_nwv IS WHEN 'U' => Output := 'U'; WHEN 'X' => Output := 'X'; WHEN '0' => Output := '0'; WHEN '1' => Output := '1'; END CASE; RETURN Output; END ALLIGN_TYPES; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays ByteProgram :VitalBuf(ByteProgram_out, ByteProgram_in, (tdevice_ByteProgram ,UnitDelay)); BufProgram :VitalBuf(BufProgram_out, BufProgram_in, (tdevice_BufProgram ,UnitDelay)); BlockErase :VitalBuf(BlockErase_out, BlockErase_in, (tdevice_BlockErase ,UnitDelay)); SetLock :VitalBuf(SetLock_out, SetLock_in, (tdevice_SetLock ,UnitDelay)); ClearLock :VitalBuf(ClearLock_out, ClearLock_in, (tdevice_ClearLock ,UnitDelay)); ProgramSuspend :VitalBuf(ProgramSuspend_out, ProgramSuspend_in, (tdevice_ProgramSuspend,UnitDelay)); EraseSuspend :VitalBuf(EraseSuspend_out, EraseSuspend_in, (tdevice_EraseSuspend ,UnitDelay)); ResetLow :VitalBuf(ResetLow_out, ResetLow_in, (tdevice_ResetLow ,UnitDelay)); ResetRecovery :VitalBuf(ResetRecovery_out, ResetRecovery_in, (tdevice_ResetRecovery ,UnitDelay)); ---------------------------------------------------------------------------- -- Wire Delays ---------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (A24_ipd, A24, tipd_A24); w_2 : VitalWireDelay (A23_ipd, A23, tipd_A23); w_3 : VitalWireDelay (A22_ipd, A22, tipd_A22); w_4 : VitalWireDelay (A21_ipd, A21, tipd_A21); w_5 : VitalWireDelay (A20_ipd, A20, tipd_A20); w_6 : VitalWireDelay (A19_ipd, A19, tipd_A19); w_7 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_8 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_9 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_10 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_11 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_12 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_13 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_14 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_15 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_16 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_17 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_18 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_19 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_20 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_21 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_22 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_23 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_24 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_25 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_33 : VitalWireDelay (D15_ipd, D15, tipd_D15); w_34 : VitalWireDelay (D14_ipd, D14, tipd_D14); w_35 : VitalWireDelay (D13_ipd, D13, tipd_D13); w_36 : VitalWireDelay (D12_ipd, D12, tipd_D12); w_37 : VitalWireDelay (D11_ipd, D11, tipd_D11); w_38 : VitalWireDelay (D10_ipd, D10, tipd_D10); w_39 : VitalWireDelay (D9_ipd, D9, tipd_D9); w_40 : VitalWireDelay (D8_ipd, D8, tipd_D8); w_41 : VitalWireDelay (D7_ipd, D7, tipd_D7); w_42 : VitalWireDelay (D6_ipd, D6, tipd_D6); w_43 : VitalWireDelay (D5_ipd, D5, tipd_D5); w_44 : VitalWireDelay (D4_ipd, D4, tipd_D4); w_45 : VitalWireDelay (D3_ipd, D3, tipd_D3); w_46 : VitalWireDelay (D2_ipd, D2, tipd_D2); w_47 : VitalWireDelay (D1_ipd, D1, tipd_D1); w_48 : VitalWireDelay (D0_ipd, D0, tipd_D0); w_50 : VitalWireDelay (CE0Neg_ipd, CE0Neg, tipd_CE0Neg); w_51 : VitalWireDelay (CE1Neg_ipd, CE1Neg, tipd_CE1Neg); w_52 : VitalWireDelay (CE2Neg_ipd, CE2Neg, tipd_CE2Neg); w_53 : VitalWireDelay (OENeg_ipd, OENeg, tipd_OENeg); w_54 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_55 : VitalWireDelay (RPNeg_ipd, RPNeg, tipd_RPNeg); w_56 : VitalWireDelay (VPEN_ipd, VPEN, tipd_VPEN); w_57 : VitalWireDelay (BYTE_ipd, BYTE, tipd_BYTE); END BLOCK; -- sig_nwv <= To_UX01(sig_ipd); A24_nwv <= To_UX01(A24_ipd); A23_nwv <= To_UX01(A23_ipd); A22_nwv <= To_UX01(A22_ipd); A21_nwv <= To_UX01(A21_ipd); A20_nwv <= To_UX01(A20_ipd); A19_nwv <= To_UX01(A19_ipd); A18_nwv <= To_UX01(A18_ipd); A17_nwv <= To_UX01(A17_ipd); A16_nwv <= To_UX01(A16_ipd); A15_nwv <= To_UX01(A15_ipd); A14_nwv <= To_UX01(A14_ipd); A13_nwv <= To_UX01(A13_ipd); A12_nwv <= To_UX01(A12_ipd); A11_nwv <= To_UX01(A11_ipd); A10_nwv <= To_UX01(A10_ipd); A9_nwv <= To_UX01(A9_ipd); A8_nwv <= To_UX01(A8_ipd); A7_nwv <= To_UX01(A7_ipd); A6_nwv <= To_UX01(A6_ipd); A5_nwv <= To_UX01(A5_ipd); A4_nwv <= To_UX01(A4_ipd); A3_nwv <= To_UX01(A3_ipd); A2_nwv <= To_UX01(A2_ipd); A1_nwv <= To_UX01(A1_ipd); A0_nwv <= To_UX01(A0_ipd); D15_nwv <= To_UX01(D15_ipd); D14_nwv <= To_UX01(D14_ipd); D13_nwv <= To_UX01(D13_ipd); D12_nwv <= To_UX01(D12_ipd); D11_nwv <= To_UX01(D11_ipd); D10_nwv <= To_UX01(D10_ipd); D9_nwv <= To_UX01(D9_ipd); D8_nwv <= To_UX01(D8_ipd); D7_nwv <= To_UX01(D7_ipd); D6_nwv <= To_UX01(D6_ipd); D5_nwv <= To_UX01(D5_ipd); D4_nwv <= To_UX01(D4_ipd); D3_nwv <= To_UX01(D3_ipd); D2_nwv <= To_UX01(D2_ipd); D1_nwv <= To_UX01(D1_ipd); D0_nwv <= To_UX01(D0_ipd); CE0Neg_nwv <= To_UX01(CE0Neg_ipd); CE1Neg_nwv <= To_UX01(CE1Neg_ipd); CE2Neg_nwv <= To_UX01(CE2Neg_ipd); OENeg_nwv <= To_UX01(OENeg_ipd); WENeg_nwv <= To_UX01(WENeg_ipd); RPNeg_nwv <= To_UX01(RPNeg_ipd); VPEN_nwv <= To_UX01(VPEN_ipd); BYTE_nwv <= To_UX01(BYTE_ipd); ---------------------------------------------------------------------------- -- Main Behavior Block ---------------------------------------------------------------------------- Behavior: BLOCK PORT ( A : IN std_logic_vector(24 downto 0) := (OTHERS => 'U'); DIn : IN std_logic_vector(15 downto 0) := (OTHERS => 'U'); DOut : OUT std_logic_vector(15 downto 0) := (OTHERS => 'Z'); CE0Neg : IN std_ulogic := 'U'; CE1Neg : IN std_ulogic := 'U'; CE2Neg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RPNeg : IN std_ulogic := 'U'; VPEN : IN std_ulogic := 'U'; BYTE : IN std_ulogic := 'U'; STS : OUT std_ulogic := 'Z' ); PORT MAP ( A(24) => A24_nwv, A(23) => A23_nwv, A(22) => A22_nwv, A(21) => A21_nwv, A(20) => A20_nwv, A(19) => A19_nwv, A(18) => A18_nwv, A(17) => A17_nwv, A(16) => A16_nwv, A(15) => A15_nwv, A(14) => A14_nwv, A(13) => A13_nwv, A(12) => A12_nwv, A(11) => A11_nwv, A(10) => A10_nwv, A(9) => A9_nwv, A(8) => A8_nwv, A(7) => A7_nwv, A(6) => A6_nwv, A(5) => A5_nwv, A(4) => A4_nwv, A(3) => A3_nwv, A(2) => A2_nwv, A(1) => A1_nwv, A(0) => A0_nwv, DIn(15) => D15_nwv, DIn(14) => D14_nwv, DIn(13) => D13_nwv, DIn(12) => D12_nwv, DIn(11) => D11_nwv, DIn(10) => D10_nwv, DIn(9) => D9_nwv, DIn(8) => D8_nwv, DIn(7) => D7_nwv, DIn(6) => D6_nwv, DIn(5) => D5_nwv, DIn(4) => D4_nwv, DIn(3) => D3_nwv, DIn(2) => D2_nwv, DIn(1) => D1_nwv, DIn(0) => D0_nwv, DOut(15) => D15, DOut(14) => D14, DOut(13) => D13, DOut(12) => D12, DOut(11) => D11, DOut(10) => D10, DOut(9) => D9, DOut(8) => D8, DOut(7) => D7, DOut(6) => D6, DOut(5) => D5, DOut(4) => D4, DOut(3) => D3, DOut(2) => D2, DOut(1) => D1, DOut(0) => D0, CE0Neg => ALLIGN_TYPES(CE0Neg_nwv), CE1Neg => ALLIGN_TYPES(CE1Neg_nwv), CE2Neg => ALLIGN_TYPES(CE2Neg_nwv), OENeg => ALLIGN_TYPES(OENeg_nwv), WENeg => ALLIGN_TYPES(WENeg_nwv), RPNeg => ALLIGN_TYPES(RPNeg_nwv), VPEN => ALLIGN_TYPES(VPEN_nwv), BYTE => ALLIGN_TYPES(BYTE_nwv), STS => STS ); -- State Machine : State_Type TYPE state_type IS ( READ_ARRAY,-- RESET_POWER_DOWN,-- READ_STATUS,-- READ_ID_CODES,-- READ_QUERY,-- LOCK_SETUP,-- BOTCH,-- BOTCH_ERS_SUSP,-- LOCK_SETUP_ERS_SUSP,-- PROT_PROG_SETUP,-- PROT_PROG_BUSY,-- PROT_PROG_DONE,-- PROG_SETUP,-- PROG_SETUP_ERS_SUSP,-- PROG_BUSY,-- PROG_BUSY_ERS_SUSP,-- READ_STATUS_PROG_SUSP,-- READ_STATUS_BOTH_SUSP,-- READ_ARRAY_PROG_SUSP,-- READ_ARRAY_BOTH_SUSP,-- READ_ID_CODES_PROG_SUSP,-- READ_ID_CODES_BOTH_SUSP,-- READ_QUERY_PROG_SUSP,-- READ_QUERY_BOTH_SUSP,-- PROG_DONE,-- PROG_DONE_ERS_SUSP,-- ERASE_SETUP,-- ERASE_BUSY,-- READ_STATUS_ERS_SUSP,-- READ_ARRAY_ERS_SUSP,-- READ_ID_CODES_ERS_SUSP,-- READ_QUERY_ERS_SUSP,-- ERASE_DONE,-- WRITE_TO_BUF_SETUP,-- DATA_LOAD,-- COUNT_LOAD,-- WRITE_TO_BUF_CONFIRM,-- WRITE_TO_BUF_SETUP_ERS_SUSP,-- DATA_LOAD_ERS_SUSP,-- COUNT_LOAD_ERS_SUSP,-- WRITE_TO_BUF_CONFIRM_ERS_SUSP,-- CONFIGURE_STS_SETUP-- ); --states SIGNAL current_state : state_type; -- SIGNAL next_state : state_type; -- --zero delay signals SIGNAL DOut_zd : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); SIGNAL STS_zd : std_logic := 'Z'; --Status Register SIGNAL S_Reg : std_logic_vector(7 downto 0) := "10000000";-- 0x80 SIGNAL XS_Reg : std_logic_vector(7 downto 0) := "00000000"; --Block Lock Status SIGNAL Block_Lock : std_logic_vector (255 downto 0) := (OTHERS => '1'); SIGNAL WDone : boolean := FALSE; SIGNAL WBDone : boolean := FALSE; SIGNAL EDone : boolean := FALSE; SIGNAL ECount : integer RANGE 0 TO 1023 :=0; SIGNAL CEXNeg : std_logic := 'H'; SIGNAL RSTNeg : std_logic := '1'; SIGNAL Write : std_logic := '0'; SIGNAL Read : std_logic := '0'; SIGNAL N : integer RANGE 0 TO 32 := 0; SIGNAL WBAddr_change : boolean := FALSE; SIGNAL WCount : integer RANGE 0 TO 32 := 0; -- timing check violation SIGNAL Viol : X01 := '0'; SIGNAL SubsequentPageAccess : boolean := FALSE; SIGNAL InitialPageAccess : boolean := TRUE; SIGNAL ReadArray : boolean := TRUE; SIGNAL ReadNonArray : boolean := FALSE; SIGNAL Entrance : boolean := TRUE; SIGNAL OPENLATCH : boolean := FALSE; SIGNAL FROMOE : boolean := FALSE; SIGNAL FROMCE : boolean := FALSE; BEGIN -- process used to assert the signal CEXNeq; this signal -- is used during all of the timing checks PROCESS(CE0Neg, CE1Neg, CE2Neg) VARIABLE TEMP : std_logic_vector(2 downto 0); BEGIN TEMP := CE2Neg & CE1Neg & CE0Neg; IF (TEMP = "001" OR TEMP = "010" OR TEMP = "011" OR TEMP = "111") THEN CEXNeg <= '1'; -- disabled ELSIF (TEMP = "000" OR TEMP = "100" OR TEMP = "101" OR TEMP = "110") THEN CEXNeg <= '0'; -- enabled ELSE CEXNeg <= '1'; END IF; END PROCESS; -- clocked process for FSM state transition PROCESS(next_state) BEGIN current_state <= next_state; END PROCESS; -- signal RSTNeg is asserted low only if RPNeg is asserted low and stays asserted -- at least for tPLPH (valid system reset/power-down); when a valid system -- reset/power-down occurs and the device is in a read mode, the device should -- be deselected, the outputs driven in high-impedance and the power consupmtion -- should be significantly decreased -- RSTNeg <= RPNeg AFTER tdevice_ResetLow; RESETGlitchControl : PROCESS(RPNeg) BEGIN IF RPNeg = '0' THEN RSTNeg <= RPNeg AFTER tdevice_ResetLow; ELSIF RPNeg = '1' THEN RSTNeg <= RPNeg; END IF; END PROCESS RESETGlitchControl; -- process for setting the signal write SetWrite : PROCESS(CEXNeg, WENeg) BEGIN IF(CEXNeg = '0' AND rising_edge(WENeg)) OR (WENeg = '0' AND rising_edge(CEXNeg)) THEN Write <= '1', '0' after 1 ns; END IF; END PROCESS SetWrite; -- process for setting the signal read SetRead : PROCESS(OENeg, CEXNeg, A) BEGIN IF(CEXNeg = '0' AND falling_edge(OENeg)) OR (OENeg = '0' AND falling_edge(CEXNeg)) OR (A'EVENT AND CEXNeg = '0' AND OENeg = '0') THEN Read <= '1', '0' after 1 ns; END IF; END PROCESS SetRead; TriggerDetect : PROCESS(DOut_zd) VARIABLE CEDQ_t : time; VARIABLE OEDQ_t : time; BEGIN IF DOut_zd(0) /= 'Z' THEN OPENLATCH <= TRUE; CEDQ_t := -CEXNeg'LAST_EVENT + tpd_CE0Neg_D0(trz0); IF ReadArray THEN OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_D0_Array(trz0); ELSE OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_D0_NonArray(trz0); END IF; FROMOE <= (OEDQ_t >= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE <= (CEDQ_t > OEDQ_t) AND (CEDQ_t > 0 ns); ELSE OPENLATCH <= FALSE; END IF; END PROCESS TriggerDetect; ---------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation ---------------------------------------------------------------------------- VITALBehaviour: PROCESS(A, DIn, Write, Read, RSTNeg, VPEN, WDone, WCount, S_Reg, XS_Reg, EDone, ECount, WBDone, N, WBAddr_change, RPNeg) -- Timing Check Variables VARIABLE Tviol_CE0Neg_WENeg : X01 := '0'; VARIABLE TD_CE0Neg_WENeg : VitalTimingDataType; VARIABLE Tviol_D0_WENeg : X01 := '0'; VARIABLE TD_D0_WENeg : VitalTimingDataType; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_VPEN_WENeg : X01 := '0'; VARIABLE TD_VPEN_WENeg : VitalTimingDataType; VARIABLE Tviol_WENeg_CE0Neg : X01 := '0'; VARIABLE TD_WENeg_CE0Neg : VitalTimingDataType; VARIABLE Tviol_D0_CE0Neg : X01 := '0'; VARIABLE TD_D0_CE0Neg : VitalTimingDataType; VARIABLE Tviol_A0_CE0Neg : X01 := '0'; VARIABLE TD_A0_CE0Neg : VitalTimingDataType; VARIABLE Tviol_VPEN_CE0Neg : X01 := '0'; VARIABLE TD_VPEN_CE0Neg : VitalTimingDataType; VARIABLE Tviol_WPNeg_CE0Neg : X01 := '0'; VARIABLE TD_WPNeg_CE0Neg : VitalTimingDataType; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CE0Neg : X01 := '0'; VARIABLE PD_CE0Neg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_RPNeg : X01 := '0'; VARIABLE PD_RPNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; VARIABLE data : integer RANGE -1 TO MaxData; BEGIN ---------------------------------------------------------------------------- -- Timing Check Section ---------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between A0 and WENeg/CENeg VitalSetupHoldCheck ( TestSignal => A0, TestSignalName => "A0", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, CheckEnabled => CEXNeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); VitalSetupHoldCheck ( TestSignal => A0, TestSignalName => "A0", RefSignal => CEXNeg, RefSignalName => "CEXNeg", SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, CheckEnabled => WENEg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CE0Neg, Violation => Tviol_A0_CE0Neg ); -- Setup/Hold Check between D0 and WENeg/CENeg VitalSetupHoldCheck ( TestSignal => D0, TestSignalName => "D0", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_D0_WENeg, HoldHigh => thold_D0_WENeg, CheckEnabled => CEXNeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_D0_WENeg, Violation => Tviol_D0_WENeg ); VitalSetupHoldCheck ( TestSignal => D0, TestSignalName => "D0", RefSignal => CEXNeg, RefSignalName => "CEXNeg", SetupLow => tsetup_D0_WENeg, HoldHigh => thold_D0_WENeg, CheckEnabled => WENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_D0_CE0Neg, Violation => Tviol_D0_CE0Neg ); -- Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CEXNeg, TestSignalName => "CEXNeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_CE0Neg_WENeg, HoldHigh => thold_CE0Neg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CE0Neg_WENeg, Violation => Tviol_CE0Neg_WENeg ); VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CEXNeg, RefSignalName => "CEXNeg", SetupLow => tsetup_CE0Neg_WENeg, HoldHigh => thold_CE0Neg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CE0Neg, Violation => Tviol_WENeg_CE0Neg ); -- Setup Check between VPN and WENeg VitalSetupHoldCheck ( TestSignal => VPEN, TestSignalName => "VPEN", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_VPEN_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_VPEN_WENeg, Violation => Tviol_VPEN_WENeg ); VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WENeg", PulseWidthHigh => tpw_WENeg_posedge, PulseWidthLow => tpw_WENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); VitalPeriodPulseCheck ( TestSignal => CEXNeg, TestSignalName => "CEXNeg", PulseWidthHigh => tpw_CE0Neg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CE0Neg, Violation => Pviol_CE0Neg ); VitalPeriodPulseCheck ( TestSignal => RPNeg, TestSignalName => "RPNeg", PulseWidthLow => tpw_RPNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RPNeg, Violation => Pviol_RPNeg ); Violation := Tviol_CE0Neg_WENeg OR Tviol_D0_WENeg OR Tviol_A0_WENeg OR Tviol_VPEN_WENeg OR Tviol_WENeg_CE0Neg OR Tviol_D0_CE0Neg OR Tviol_A0_CE0Neg OR Tviol_VPEN_CE0Neg OR Pviol_WENeg OR Pviol_CE0Neg OR Pviol_RPNeg; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; ---------------------------------------------------------------------------- -- Functionality Section ---------------------------------------------------------------------------- -- FSM IF rising_edge(Write) THEN IF (BYTE = '1') THEN data := to_nat(DIn); ELSE data := to_nat(DIn(7 downto 0)); END IF; END IF; IF falling_edge(RSTNeg) THEN next_state <= RESET_POWER_DOWN; ELSE CASE current_state IS WHEN READ_ARRAY | READ_STATUS | READ_ID_CODES | READ_QUERY | PROG_DONE | PROT_PROG_DONE | ERASE_DONE => IF rising_edge(Write) THEN CASE data IS WHEN 16#10# | 16#40# => next_state <= PROG_SETUP; WHEN 16#20# => next_state <= ERASE_SETUP; WHEN 16#70# => next_state <= READ_STATUS; WHEN 16#90# => next_state <= READ_ID_CODES; WHEN 16#98# => next_state <= READ_QUERY; WHEN 16#60# => next_state <= LOCK_SETUP; WHEN 16#C0# => next_state <= PROT_PROG_SETUP; WHEN 16#E8# => next_state <= WRITE_TO_BUF_SETUP; WHEN 16#B8# => next_state <= CONFIGURE_STS_SETUP; WHEN OTHERS => next_state <= READ_ARRAY; END CASE; END IF; WHEN RESET_POWER_DOWN => --reset/power-down mode: the device can enter the reset/power-down mode from --any of the read modes; while in this mode, the device is de-selected, output --drivers are in a high-impedance state and internal circuits are turned off; --the default mode after reset/power-down is read array IF rising_edge(RPNeg) THEN next_state <= READ_ARRAY; END IF; WHEN BOTCH => IF rising_edge(Write) THEN CASE data IS WHEN 16#10# | 16#40# => next_state <= PROG_SETUP; WHEN 16#20# => next_state <= ERASE_SETUP; WHEN 16#70# => next_state <= READ_STATUS; WHEN 16#90# => next_state <= READ_ID_CODES; WHEN 16#B8# => next_state <= CONFIGURE_STS_SETUP; WHEN 16#98# => next_state <= READ_QUERY; WHEN 16#60# => next_state <= LOCK_SETUP; WHEN 16#C0# => next_state <= PROT_PROG_SETUP; WHEN OTHERS => next_state <= READ_ARRAY; END CASE; END IF; WHEN BOTCH_ERS_SUSP => IF rising_edge(Write) THEN CASE data IS WHEN 16#10# | 16#40# => next_state <= PROG_SETUP_ERS_SUSP; WHEN 16#D0# => next_state <= ERASE_BUSY; WHEN 16#70# => next_state <= READ_STATUS_ERS_SUSP; WHEN 16#90# => next_state <= READ_ID_CODES_ERS_SUSP; WHEN 16#98# => next_state <= READ_QUERY_ERS_SUSP; WHEN 16#60# => next_state <= LOCK_SETUP_ERS_SUSP; WHEN 16#E8# => next_state <= WRITE_TO_BUF_SETUP_ERS_SUSP; WHEN OTHERS => next_state <= READ_ARRAY_ERS_SUSP; END CASE; END IF; WHEN LOCK_SETUP => IF rising_edge(Write) THEN -- SECOND CYCLE CHECK IF data=16#D0# OR data=16#01# THEN next_state <= READ_ARRAY; ELSE next_state <= BOTCH; END IF; END IF; WHEN LOCK_SETUP_ERS_SUSP => IF rising_edge(Write) THEN IF data=16#D0# OR data=16#01# THEN next_state <= READ_ARRAY_ERS_SUSP; ELSE next_state <= BOTCH_ERS_SUSP; END IF; END IF; WHEN PROT_PROG_SETUP => IF rising_edge(Write) THEN next_state <= PROT_PROG_BUSY; END IF; WHEN PROT_PROG_BUSY => IF S_Reg(7)='1' THEN next_state <= PROT_PROG_DONE; ELSE next_state <= PROT_PROG_BUSY; END IF; WHEN PROG_SETUP => IF rising_edge(Write) THEN next_state <= PROG_BUSY; END IF; WHEN PROG_SETUP_ERS_SUSP => IF rising_edge(Write) THEN next_state <= PROG_BUSY_ERS_SUSP; END IF; WHEN PROG_BUSY => IF WDone OR (WBDone AND WCount>N ) THEN next_state<=PROG_DONE; ELSIF rising_edge(Write) THEN IF data= 16#B0# THEN next_state <= READ_STATUS_PROG_SUSP; ELSE next_state <= PROG_BUSY; END IF; END IF; WHEN PROG_BUSY_ERS_SUSP => IF WDone OR WBDone THEN next_state<=PROG_DONE_ERS_SUSP; ELSIF rising_edge(Write) THEN IF data= 16#B0# THEN next_state <= READ_STATUS_BOTH_SUSP; ELSE next_state <= PROG_BUSY_ERS_SUSP; END IF; END IF; WHEN READ_STATUS_PROG_SUSP | READ_ARRAY_PROG_SUSP | READ_ID_CODES_PROG_SUSP | READ_QUERY_PROG_SUSP => IF rising_edge(Write) THEN CASE data IS WHEN 16#D0# => next_state <= PROG_BUSY; WHEN 16#B0# | 16#70# => next_state <= READ_STATUS_PROG_SUSP; WHEN 16#90# => next_state <= READ_ID_CODES_PROG_SUSP; WHEN 16#98# => next_state <= READ_QUERY_PROG_SUSP; WHEN OTHERS => next_state <= READ_ARRAY_PROG_SUSP; END CASE; END IF; WHEN READ_STATUS_BOTH_SUSP | READ_ARRAY_BOTH_SUSP | READ_ID_CODES_BOTH_SUSP | READ_QUERY_BOTH_SUSP => IF rising_edge(Write) THEN CASE data IS WHEN 16#D0# => next_state <= PROG_BUSY_ERS_SUSP; WHEN 16#B0# | 16#70# => next_state <= READ_STATUS_BOTH_SUSP; WHEN 16#90# => next_state <= READ_ID_CODES_BOTH_SUSP; WHEN 16#98# => next_state <= READ_QUERY_BOTH_SUSP; WHEN OTHERS => next_state <= READ_ARRAY_BOTH_SUSP; END CASE; END IF; WHEN ERASE_SETUP => IF rising_edge(Write) THEN IF data=16#D0# THEN next_state<= ERASE_BUSY; ELSE next_state<=BOTCH; END IF; END IF; WHEN ERASE_BUSY => IF rising_edge(Write) AND data= 16#B0# THEN next_state <= READ_STATUS_ERS_SUSP; ELSIF EDone AND ECount=1023 THEN next_state<=ERASE_DONE; END IF; WHEN READ_STATUS_ERS_SUSP | READ_ARRAY_ERS_SUSP | READ_ID_CODES_ERS_SUSP | READ_QUERY_ERS_SUSP | PROG_DONE_ERS_SUSP => IF rising_edge(Write) THEN CASE data IS WHEN 16#10# | 16#40# => next_state <=PROG_SETUP_ERS_SUSP; WHEN 16#B0# | 16#70# => next_state<= READ_STATUS_ERS_SUSP; WHEN 16#D0# => next_state <= ERASE_BUSY; WHEN 16#90# => next_state <= READ_ID_CODES_ERS_SUSP; WHEN 16#98# => next_state <= READ_QUERY_ERS_SUSP; WHEN 16#60# => next_state <= LOCK_SETUP_ERS_SUSP; WHEN 16#E8# => next_state <= WRITE_TO_BUF_SETUP_ERS_SUSP; WHEN OTHERS => next_state <= READ_ARRAY_ERS_SUSP; END CASE; END IF; WHEN WRITE_TO_BUF_SETUP => IF S_Reg(7)='0' THEN next_state<=READ_ARRAY; ELSIF rising_edge(Write) THEN next_state<=COUNT_LOAD; END IF; WHEN COUNT_LOAD => IF rising_edge(Write) THEN IF WBAddr_change THEN next_state<=BOTCH; ELSE next_state<= DATA_LOAD; END IF; END IF; WHEN DATA_LOAD => IF rising_edge(Write) THEN IF WBAddr_change THEN next_state<=BOTCH; ELSIF WCount= 0 OR WCount= N THEN next_state <= WRITE_TO_BUF_CONFIRM; ELSIF WCount IF rising_edge(Write) THEN IF data=16#D0# THEN next_state<= PROG_BUSY; ELSE next_state<=BOTCH; END IF; END IF; WHEN WRITE_TO_BUF_SETUP_ERS_SUSP => IF rising_edge(Write) THEN next_state<= COUNT_LOAD_ERS_SUSP; END IF; WHEN COUNT_LOAD_ERS_SUSP => IF rising_edge(Write) THEN next_state<= DATA_LOAD_ERS_SUSP; END IF; WHEN DATA_LOAD_ERS_SUSP => IF rising_edge(Write) THEN IF WCount= 0 OR WCount= N THEN next_state <= WRITE_TO_BUF_CONFIRM_ERS_SUSP; ELSIF WCount IF rising_edge(Write) THEN IF data=16#D0# THEN next_state<= PROG_BUSY_ERS_SUSP; ELSE next_state<=BOTCH_ERS_SUSP; END IF; END IF; WHEN CONFIGURE_STS_SETUP => --If second cycle is 00h or 01h or 02h or 03h then reconfigure the STS --functionality and goto Read Status; If not Botch; IF rising_edge(Write) THEN IF Data>=0 AND Data<=3 THEN next_state<=READ_STATUS; ELSE next_state<=BOTCH; END IF; END IF; WHEN OTHERS => END CASE; END IF; END PROCESS; --------------------------------------------------------------------------- -- combinatorial output generation (Mealy machine) --------------------------------------------------------------------------- output: PROCESS( current_state, A, DIn, Read, Write, RSTNeg, RPNeg, VPEN, WDone, WBDone, WCount, S_Reg, XS_Reg, EDone, CEXNeg, OENeg, ECount) -- Functionality Results Variables VARIABLE Data : INTEGER RANGE -1 TO MaxData:=0; VARIABLE WData : INTEGER RANGE -1 TO MaxData:=0; VARIABLE ActBlock : integer RANGE 0 to 255 :=0; VARIABLE CurrBlock : integer RANGE 0 to 255 :=0; VARIABLE PrevBlock : integer RANGE 0 to 255 :=0; VARIABLE EBlock : integer RANGE 0 to 255 :=0; VARIABLE Ecnt : integer RANGE 0 to 16#1FFFF# :=0; VARIABLE Addr : integer RANGE 0 to MemSize :=0; VARIABLE WAddr : integer RANGE 0 to MemSize :=0; VARIABLE EBlockLock : boolean := FALSE; VARIABLE EBlock_Addr : integer RANGE 0 to MemSize :=0; --Protection registers TYPE PR_type IS ARRAY(16#100# TO 16#111#) OF INTEGER RANGE 0 TO MaxDataByte; VARIABLE PR : PR_type := (OTHERS =>16#FF#); -- Common Flash Interface TYPE CFI_type IS ARRAY(16#10# TO 16#46#) OF INTEGER RANGE 0 TO 16#FF#; TYPE BUF_type IS ARRAY(0 TO 31) OF integer RANGE -1 TO 16#FFFF#; VARIABLE CFI : CFI_type := (OTHERS => 0); VARIABLE BUF : BUF_type := (OTHERS => 16#FFFF#); VARIABLE WBlock : integer RANGE 0 to 63 :=0; TYPE WBAddr_type IS ARRAY(0 TO 31) OF INTEGER RANGE 0 TO 16#FF#; VARIABLE WBAddr : WBAddr_type:=(OTHERS=>0); -- Memory array declaration TYPE MemStore IS ARRAY (0 to MemSize) OF INTEGER RANGE -1 TO 16#FF#; VARIABLE MemData : MemStore := (OTHERS =>16#FF#); VARIABLE STS_Code : std_logic_vector(1 downto 0) := "00"; -- text file input variables FILE mem_file : text is mem_file_name; VARIABLE ind : NATURAL := 0; VARIABLE buff : line; BEGIN IF rising_edge(Write) OR falling_edge(Read) THEN Addr := to_nat(A); ActBlock := to_nat(A(24 downto 17)); --Active Block END IF; IF falling_edge(Read) THEN PrevBlock := CurrBlock; CurrBlock := to_nat(A(24 downto 17)); IF PrevBlock=CurrBlock THEN SubsequentPageAccess <= TRUE; InitialPageAccess <= FALSE; END IF; END IF; IF rising_edge(Write) THEN IF BYTE = '1' THEN Data := to_nat(DIn); ELSE Data := to_nat(DIn(7 downto 0)); END IF; END IF; CASE current_state IS WHEN READ_ARRAY => IF falling_edge(Read) THEN IF BYTE = '1' THEN Dout_zd(15 downto 8) <= to_slv(MemData(Addr+1),8); Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); ELSE Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); Dout_zd(15 downto 8) <= (OTHERS => 'Z'); END IF; END IF; IF rising_edge(Write) AND Data=16#50# THEN S_Reg<="10000000"; END IF; ReadArray <= TRUE; ReadNonArray <= FALSE; WHEN RESET_POWER_DOWN => DOut_zd <= (OTHERS => 'Z'); IF S_Reg(7)='0' AND Entrance THEN S_Reg(7)<='0', '1' AFTER tdevice_ResetRecovery; Entrance<=FALSE, TRUE AFTER tdevice_ResetRecovery; END IF; WHEN READ_STATUS => IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND Data=16#50# THEN S_Reg<="10000000"; END IF; ReadArray <= FALSE; ReadNonArray <= TRUE; WHEN READ_ID_CODES | READ_ID_CODES_PROG_SUSP | READ_ID_CODES_ERS_SUSP | READ_ID_CODES_BOTH_SUSP => IF falling_edge(Read) THEN IF Addr= 0 THEN DOut_zd(7 downto 0) <=to_slv(16#89#,8); ELSIF Addr=1 THEN DOut_zd(7 downto 0) <=to_slv(16#1D#,8); ELSIF Addr>=16#80# AND Addr<=16#88# THEN DOut_zd(7 downto 0)<=to_slv(PR(Addr),8); ELSIF A(16 DOWNTO 1)= to_slv(16#0002#, 16) THEN DOut_zd(0)<=Block_Lock(ActBlock); DOut_zd(15 DOWNTO 1)<= (OTHERS=>'0'); END IF; END IF; IF rising_edge(Write) THEN --ERS SUSP IF Data=16#50# THEN CASE current_state IS WHEN READ_ID_CODES => S_Reg<="10000000"; WHEN READ_ID_CODES_PROG_SUSP => S_Reg<="10000100"; WHEN READ_ID_CODES_ERS_SUSP => S_Reg<="11000000"; WHEN OTHERS => S_Reg<="11000100"; END CASE; ELSIF Data=16#D0# THEN IF current_state = READ_ID_CODES_ERS_SUSP THEN S_Reg(6)<='0'; ELSE S_Reg(2)<='0'; END IF; END IF; END IF; ReadArray <= FALSE; ReadNonArray <= TRUE; WHEN READ_QUERY | READ_QUERY_PROG_SUSP | READ_QUERY_ERS_SUSP | READ_QUERY_BOTH_SUSP => IF falling_edge(Read) THEN DOut_zd<=(OTHERS=>'0'); IF Addr= 0 THEN DOut_zd(7 downto 0) <= to_slv(16#89#,8); ELSIF Addr=1 THEN DOut_zd(7 downto 0) <= to_slv(16#1D#,8); ELSIF A(16 DOWNTO 1)= to_slv(16#0002#, 16) THEN DOut_zd(0)<=Block_Lock(ActBlock); DOut_zd(15 DOWNTO 1)<= (OTHERS=>'0'); ELSIF Addr>=16#10# AND Addr<=16#47# THEN DOut_zd(7 downto 0)<=to_slv(CFI(Addr),8); ELSE -- RESERVED OR Address out of range DOut_zd<=(OTHERS=>'0'); END IF; END IF; IF rising_edge(Write) THEN IF Data=16#50# THEN CASE current_state IS WHEN READ_QUERY => S_Reg<="10000000"; WHEN READ_QUERY_PROG_SUSP => S_Reg<="10000100"; WHEN READ_QUERY_ERS_SUSP => S_Reg<="11000000"; WHEN OTHERS => S_Reg<="11000100"; END CASE; ELSIF Data=16#D0# THEN IF current_state = READ_QUERY_ERS_SUSP THEN S_Reg(6)<='0'; ELSE S_Reg(2)<='0'; END IF; END IF; END IF; ReadArray <= FALSE; ReadNonArray <= TRUE; WHEN BOTCH | BOTCH_ERS_SUSP => S_Reg(7)<='1'; S_Reg(5)<='1';--command sequence error S_Reg(4)<='1'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND Data=16#50# THEN S_Reg <="10000000"; END IF; WHEN LOCK_SETUP | LOCK_SETUP_ERS_SUSP => S_Reg(7)<='0'; IF rising_edge(Write) THEN -- SECOND CYCLE CHECK IF Data=16#01# THEN -- Lock Block Block_Lock(ActBlock) <='0', '1' AFTER tdevice_SetLock; S_Reg(7) <='0', '1' AFTER tdevice_SetLock; IF current_state = LOCK_SETUP_ERS_SUSP AND ActBlock=EBlock THEN EBlockLock:=FALSE; END IF; ELSIF Data=16#D0# THEN -- UnLock Block Block_Lock(ActBlock) <='1', '0' AFTER tdevice_ClearLock; S_Reg(7) <='0', '1' AFTER tdevice_ClearLock; END IF; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN PROT_PROG_SETUP => IF rising_edge(Write) THEN IF Addr=16#100# THEN IF BYTE = '1' THEN -- word programming IF Data=16#FFFD# THEN PR(Addr) :=16#FD#; PR(Addr+1):=16#FF#; S_Reg(7)<='0', '1' AFTER tdevice_ByteProgram*2; ELSE S_Reg(7)<='1'; END IF; ELSE -- byte programming IF Data=16#FD# THEN PR(Addr):=Data; S_Reg(7)<='0', '1' AFTER tdevice_ByteProgram; ELSE S_Reg(7)<='1'; END IF; END IF; ELSIF Addr=16#101# THEN IF BYTE = '0' THEN IF Data=16#FF# THEN PR(Addr):=Data; S_Reg(7)<='0', '1' AFTER tdevice_ByteProgram; ELSE S_Reg(7)<='1'; END IF; ELSE S_Reg(7)<='1'; S_Reg(4)<='1'; S_Reg(1)<='1'; END IF; ELSIF Addr>=16#102# AND Addr<=16#109# THEN --Intel Factory Programmed -- S_Reg(7)<='1'; S_Reg(4)<='1'; S_Reg(1)<='1'; ELSIF Addr>=16#10A# AND Addr<=16#111# THEN IF PR(16#100#)=16#FD# AND PR(16#101#)=16#FF# AND PR(Addr) =16#FF# AND PR(Addr+1) =16#FF# THEN --PR0 user segment NOT locked -- and NOT programmed IF BYTE = '1' THEN PR(Addr) :=Data / 16#100#; PR(Addr+1):=Data MOD 16#100#; S_Reg(7)<='0', '1' AFTER tdevice_ByteProgram*2; ELSE PR(Addr):=Data; S_Reg(7)<='0', '1' AFTER tdevice_ByteProgram; END IF; ELSE --PR0 user segment NOT available S_Reg(7)<='1'; S_Reg(4)<='1'; S_Reg(1)<='1'; END IF; ELSE S_Reg(7)<='1'; END IF; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN PROT_PROG_BUSY => IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN PROT_PROG_DONE => S_Reg(7)<='1'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND Data=16#50# THEN S_Reg<="10000000"; END IF; WHEN PROG_SETUP | PROG_SETUP_ERS_SUSP => S_Reg(7)<='0'; IF rising_edge(Write) THEN IF Block_Lock(ActBlock) = '0' THEN IF VPEN = '1' THEN WAddr := Addr; WData := Data; ELSE S_Reg(3) <= '1'; S_Reg(4) <= '1'; END IF; ELSE S_Reg(1) <= '1'; -- Block is Locked S_Reg(4) <= '1'; -- Programming Failure END IF; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN PROG_BUSY | PROG_BUSY_ERS_SUSP => IF WBDone AND WCount<=N THEN XS_Reg(7) <= '1'; IF Viol='0' AND S_Reg(4) /= '1' THEN IF BYTE = '0' THEN MemData(WBAddr(WCount)) :=BUF(WCount); WBDone <= FALSE, TRUE AFTER tdevice_BufProgram; ELSE MemData(WBAddr(WCount)+1) :=BUF(WCount) / 16#100#; MemData(WBAddr(WCount)) :=BUF(WCount) MOD 16#100#; WBDone <= FALSE, TRUE AFTER tdevice_BufProgram*2; END IF; ELSIF Viol /= '0' THEN S_Reg(4)<='1'; IF BYTE = '0' THEN MemData(WBAddr(WCount)):=-1; ELSE MemData(WBAddr(WCount)+1) :=-1; MemData(WBAddr(WCount)):=-1; END IF; END IF; WCount <= WCount + 1; ELSE XS_Reg(7) <= '1'; IF Viol = '0' AND S_Reg(4) /= '1' THEN IF BYTE = '0' THEN MemData(WAddr) := WData; --OK IF WDone = FALSE AND S_Reg(7) = '0' THEN WDone <= FALSE, TRUE AFTER tdevice_ByteProgram; END IF; ELSE MemData(WAddr) := WData MOD 16#100#; MemData(WAddr+1) := WData / 16#100#; IF WDone = FALSE AND S_Reg(7) = '0' THEN WDone <= FALSE, TRUE AFTER tdevice_ByteProgram*2; END IF; END IF; ELSIF Viol /= '0' THEN S_Reg(4)<='1'; IF BYTE = '0' THEN MemData(WBAddr(WCount)):=-1; ELSE MemData(WBAddr(WCount)) :=-1; MemData(WBAddr(WCount)+1):=-1; END IF; WDone <= TRUE; ELSIF S_Reg(4) = '1' THEN WDone <= TRUE; END IF; END IF; IF WDone OR (WBDone AND WCount>N )THEN S_Reg(7)<='1'; END IF; IF rising_edge(Write)AND Data= 16#B0# THEN S_Reg(2)<='0', '1' AFTER tdevice_ProgramSuspend; --program suspend END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN READ_STATUS_PROG_SUSP => IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) THEN IF Data=16#50# THEN S_Reg<="10000100"; ELSIF Data=16#D0# THEN S_Reg(2)<='0'; -- Program NOT suspended END IF; END IF; WHEN READ_ARRAY_PROG_SUSP => IF falling_edge(Read) THEN IF NOT(Addr>=WAddr AND Addr<=WAddr+N )THEN IF BYTE = '1' THEN Dout_zd(15 downto 8) <= to_slv(MemData(Addr+1),8); Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); ELSE Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); Dout_zd(15 downto 8) <= (OTHERS => 'Z'); END IF; ELSE ASSERT FALSE REPORT "accessed memory is suspended" SEVERITY WARNING; END IF; END IF; IF rising_edge(Write) THEN IF Data=16#50# THEN S_Reg<="10000100"; ELSIF Data=16#D0# THEN S_Reg(2)<='0'; -- Program NOT suspended END IF; END IF; WHEN PROG_DONE | PROG_DONE_ERS_SUSP => WDone <= FALSE; WBDone <= FALSE; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) THEN IF Data=16#50# THEN IF current_state = PROG_DONE THEN S_Reg<="10000000"; ELSE S_Reg<="11000000"; END IF; ELSIF Data=16#D0# AND current_state = PROG_DONE_ERS_SUSP THEN S_Reg(6)<='0'; END IF; END IF; WHEN ERASE_SETUP => IF rising_edge(Write) THEN IF Data=16#D0# THEN S_Reg(7)<='0'; IF Block_Lock(ActBlock) = '0' THEN IF VPEN = '1' THEN EBlock_Addr:=Addr-to_nat(A(16 DOWNTO 0)); --Block should be unlocked after erase EBlock:=ActBlock; EBlockLock:=TRUE; ECount<=0; Ecnt:=0; EDone <= FALSE, TRUE AFTER tdevice_BlockErase; ELSE S_Reg(3) <= '1'; S_Reg(5) <= '1'; END IF; ELSE S_Reg(1) <= '1'; -- Block is Locked S_Reg(5) <= '1'; -- Erase Failure END IF; END IF; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN ERASE_BUSY => IF EDone AND ECount<=1023 THEN FOR i IN 0 TO 127 LOOP Memdata(EBlock_Addr+ECnt):=16#FF#; EXIT WHEN Ecnt=16#1FFFF#; Ecnt:=Ecnt+1; END LOOP; IF Ecnt=16#1FFFF# THEN ASSERT Ecount=1023 REPORT "ECount should be 1023" SEVERITY ERROR; END IF; IF ECount=1023 THEN S_Reg(7)<='1'; ELSE EDone <= FALSE, TRUE AFTER tdevice_BlockErase; ECount<=ECount+1; END IF; END IF; IF rising_edge(Write)AND Data=16#B0# THEN S_Reg(6)<='1'; --erase suspend ELSE S_Reg(6)<='0'; -- erase NOT suspend END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN READ_STATUS_ERS_SUSP => IF S_Reg(6)/='1' THEN S_Reg(6)<='0', '1' AFTER tdevice_EraseSuspend; --erase suspend END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) THEN IF Data=16#50# THEN S_Reg<="11000000"; ELSIF Data=16#D0# THEN S_Reg(6)<='0'; -- ERASE NOT suspended END IF; END IF; WHEN READ_ARRAY_ERS_SUSP => IF falling_edge(Read) THEN IF ActBlock/=EBlock THEN IF BYTE = '1' THEN Dout_zd(15 downto 8) <= to_slv(MemData(Addr+1),8); Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); ELSE Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); Dout_zd(15 downto 8) <= (OTHERS => 'Z'); END IF; ELSE ASSERT FALSE REPORT "accessed memory is suspended" SEVERITY WARNING; END IF; END IF; IF rising_edge(Write) THEN IF Data=16#50# THEN S_Reg<="11000000"; ELSIF Data=16#D0# THEN S_Reg(6)<='0'; -- ERASE NOT suspended END IF; END IF; WHEN READ_ARRAY_BOTH_SUSP => IF falling_edge(Read) THEN IF NOT(Addr>=WAddr AND Addr<=WAddr+N )THEN IF BYTE = '1' THEN Dout_zd(15 downto 8) <= to_slv(MemData(Addr+1),8); Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); ELSE Dout_zd(7 downto 0) <= to_slv(MemData(Addr),8); Dout_zd(15 downto 8) <= (OTHERS => 'Z'); END IF; ELSE ASSERT FALSE REPORT "accessed memory is suspended" SEVERITY WARNING; END IF; END IF; IF rising_edge(Write) THEN IF data=16#50# THEN S_Reg<="11000100"; ELSIF data=16#D0# THEN S_Reg(2)<='0'; -- Program NOT suspended END IF; END IF; WHEN READ_STATUS_BOTH_SUSP => IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) THEN IF data=16#50# THEN S_Reg<="11000100"; ELSIF data=16#D0# THEN S_Reg(2)<='0'; -- Program NOT suspended END IF; END IF; WHEN ERASE_DONE => EDone<=FALSE; IF EBlockLock THEN Block_Lock(EBlock)<='0'; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND Data=16#50# THEN S_Reg<="10000000"; END IF; WHEN WRITE_TO_BUF_SETUP | WRITE_TO_BUF_SETUP_ERS_SUSP => --Count load (Supplied count = N-1. Part assumes that N words will be loaded. --For any command/illegal data in this write cycle, lowest 5 bits of the --command assumed as the count) IF rising_edge(Write) THEN N<=to_nat(DIn(4 DOWNTO 0));--count load WBlock:=ActBlock; WBAddr_change<=FALSE; WAddr:=Addr; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= XS_Reg; END IF; WHEN COUNT_LOAD | COUNT_LOAD_ERS_SUSP => --Data load; Initialize data counter to 0; To quit/abort change the block --address during a write cycle. The UI botches on a block address change. IF N>0 THEN WCount<=1; ELSE WCount<=0; END IF; IF rising_edge(Write) THEN IF WBlock /=ActBlock THEN WBAddr_change<=TRUE; ELSE WBAddr(0):=Addr; BUF(0) :=Data; END IF; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN DATA_LOAD | DATA_LOAD_ERS_SUSP => --If count = 0, goto Write to buffer confirm; If count < N, stay in Data load --and increment data counter; If count = N, goto Write to buffer confirm; --To quit/abort change the block address during a write cycle. The UI botches on --a block address change. IF rising_edge(Write) THEN IF WCount<=N THEN IF WBlock /=ActBlock THEN WBAddr_change<=TRUE; ELSE WBAddr(WCount):=Addr; BUF(WCount):=Data; END IF; IF N>0 AND WCount 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN WRITE_TO_BUF_CONFIRM | WRITE_TO_BUF_CONFIRM_ERS_SUSP => IF rising_edge(Write) THEN WBDone<=FALSE; IF Data=16#D0# THEN S_Reg(7)<='0'; WBDone<=TRUE; IF Block_Lock(ActBlock) = '0' THEN IF VPEN = '1' THEN WCount <= 0; IF BYTE='1' THEN WBDone <= FALSE, TRUE AFTER tdevice_BufProgram*2; ELSE WBDone <= FALSE, TRUE AFTER tdevice_BufProgram; END IF; ELSE S_Reg(3) <= '1'; S_Reg(4) <= '1'; END IF; ELSE S_Reg(1) <= '1'; -- Block is Locked S_Reg(4) <= '1'; -- Programming Failure END IF; END IF; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN CONFIGURE_STS_SETUP => --If second cycle is 00h or 01h or 02h or 03h then reconfigure the STS --functionality and goto Read Status; If not Botch; IF rising_edge(Write) THEN IF Data>=0 AND Data<=3 THEN STS_Code:=DIn(1 downto 0); S_Reg <= "10000000"; ELSE S_Reg(4)<='1'; S_Reg(5)<='1'; END IF; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => 'Z'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN OTHERS => END CASE; --this section is common to all command states IF rising_edge(OENeg) OR rising_edge(CEXNeg) OR falling_edge(RSTNeg) THEN -- data lines should be HiZ when bus cycle is Output Disable, Standby -- or reset whatever the command state is DOut_zd<= (OTHERS => 'Z'); END IF; -- Register data to default value IF falling_edge(RSTNeg) THEN S_Reg <="10000000"; XS_Reg(7) <='0'; Block_Lock <=(OTHERS=>'1'); WDone <= FALSE; EDone <= FALSE; Entrance <= TRUE; ECount <=0; PR(16#100#) :=16#FE#; PR(16#101#) :=16#FF#;-- PR0 Lock Register -- CFI Indentification CFI(16#10#):=16#51#; CFI(16#11#):=16#52#; CFI(16#12#):=16#59#; CFI(16#13#):=16#01#; CFI(16#14#):=16#00#; CFI(16#15#):=16#31#; CFI(16#16#):=16#00#; CFI(16#17#):=16#00#; CFI(16#18#):=16#00#; CFI(16#19#):=16#00#; CFI(16#1A#):=16#00#; -- System Interface Information CFI(16#1B#):=16#27#; CFI(16#1C#):=16#36#; CFI(16#1D#):=16#00#; CFI(16#1E#):=16#00#; CFI(16#1F#):=16#08#; CFI(16#20#):=16#08#; CFI(16#21#):=16#0A#; CFI(16#22#):=16#00#; CFI(16#23#):=16#04#; CFI(16#24#):=16#04#; CFI(16#25#):=16#04#; CFI(16#26#):=16#00#; -- Device Geometry definition CFI(16#27#):=16#16#; CFI(16#28#):=16#02#; CFI(16#29#):=16#00#; CFI(16#2A#):=16#05#; CFI(16#2B#):=16#00#; CFI(16#2C#):=16#01#; CFI(16#2D#):=16#1F#; CFI(16#2E#):=16#00#; CFI(16#2F#):=16#00#; CFI(16#30#):=16#02#; --primary-vendor specific extended query CFI(16#31#):=16#50#; CFI(16#32#):=16#52#; CFI(16#33#):=16#49#; CFI(16#34#):=16#31#; CFI(16#35#):=16#31#; CFI(16#36#):=16#0A#; CFI(16#37#):=16#00#; CFI(16#38#):=16#00#; CFI(16#39#):=16#00#; CFI(16#3A#):=16#01#; CFI(16#3B#):=16#01#; CFI(16#3C#):=16#00#; CFI(16#3D#):=16#33#; CFI(16#3E#):=16#00#; --protection register information CFI(16#3F#):=16#01#; CFI(16#40#):=16#80#; CFI(16#41#):=16#00#; CFI(16#42#):=16#03#; CFI(16#43#):=16#03#; --burst read information CFI(16#44#):=16#03#; CFI(16#45#):=16#00#; CFI(16#46#):=16#00#; -------------------------------------------------------------------- -- File Read Section -------------------------------------------------------------------- IF (mem_file_name /= "none") THEN ind := 0; WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buff); IF buff(1) = '#' THEN NEXT; ELSIF buff(1) = '@' THEN ind := h(buff(2 to 2)); ELSE MemData(ind) := h(buff(1 to 2)); ind := ind + 1; END IF; END LOOP; END IF; END IF; IF (WDone OR(WBDone AND WCount>N)) AND S_Reg(2)/='1' AND (STS_Code="10" OR STS_Code="11") THEN STS_zd<='0','1' AFTER 250 ns; ELSIF (EDone AND ECount=1023) AND S_Reg(6)/='1' AND (STS_Code="01" OR STS_Code="11") THEN STS_zd<='0','1' AFTER 250 ns; ELSIF STS_Code="00" THEN IF S_Reg(7)='1' THEN STS_zd <= '1'; ELSE STS_zd<= '0'; END IF; END IF; END PROCESS; ---------------------------------------------------------------------------- -- Path Delay Section ---------------------------------------------------------------------------- D_Out_PathDelay_Gen : FOR i IN Dout_zd'RANGE GENERATE PROCESS(DOut_zd(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_zd(i), GlitchData => D0_GlitchData, Paths => ( 0 => (InputChangeTime => CEXNeg'LAST_EVENT, PathDelay => tpd_CE0Neg_D0, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMCE)), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_D0_Array, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMOE AND ReadArray = TRUE)), 2 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_D0_NonArray, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMOE AND ReadNonArray = TRUE)), 3 => (InputChangeTime => RPNeg'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_RPNeg_D0), PathCondition => RPNeg = '0'), 4 => (InputChangeTime => A0'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_D0_InitialPageAccess), PathCondition => InitialPageAccess = TRUE), 5 => (InputChangeTime => A0'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_D0_SubsequentPageAccess), PathCondition => SubsequentPageAccess = TRUE) ) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; PROCESS(STS_zd) VARIABLE STS_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01( OutSignal => STS, OutSignalName => "STS", OutTemp => STS_zd, GlitchData => STS_GlitchData, Paths => ( 0 => (InputChangeTime => WENeg'LAST_EVENT, PathDelay => tpd_WENeg_STS, PathCondition => WENeg='1' AND WENeg'EVENT) ) ); END PROCESS; END BLOCK behavior; END vhdl_behavioral;