-------------------------------------------------------------------------------- -- File Name: isf28f256k3.vhd -------------------------------------------------------------------------------- -- Copyright (C) 2002-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.Marinkovic 02 DEC 13 Initial release based on possibly -- incomplete datasheet -- V1.1 R. Munden 03 FEB 15 Changed type of some _nwv signals to -- satisfy ncvhdl -- V1.2 A.Savic 04 APR 13 Burst Read functionality update : -- buffer load modifed -- latency count initialization -- V1.3 A.Savic 04 APR 19 Latency count 1CLK reduced -- Modified for ncvhdl -- V1.4 M.Stojsavljevic 04 MAY 25 Removed CENeg from FSM change -- state control; -- Added processes for generating -- signals Write and Read, which are -- now used to trigger appropriate -- device operations -- Added missing path delays, setup -- puls width and tdevice; corrected -- some of the VitalSetupHoldCheck -- procedures; -- Added boolean signals for handling -- initial and subsequent page access -- timing, corrected appropriate -- procedures; -- Added suspend latency control -- Added process TrigerDetect to -- allow detecting which signal -- triggered the read operation -------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH MEMORY -- Technology: CMOS -- Part: ISF28F256K3 -- -- Description: 256Mbit synchronous Intel StrataFlash 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 ISF28F256K3 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_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_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RSTNeg : VitalDelayType01 := VitalZeroDelay01; tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; tipd_ADVNeg : VitalDelayType01 := VitalZeroDelay01; tipd_VPEN : VitalDelayType01 := VitalZeroDelay01; tipd_CLK : VitalDelayType01 := VitalZeroDelay01; -- tpd delays READ tpd_CLK_D0 : VitalDelayType01 := UnitDelay01; tpd_A0_D0_InitialPageAccess : VitalDelayType01 := UnitDelay01; tpd_A0_D0_SubsequentPageAccess : VitalDelayType01 := UnitDelay01; tpd_CENeg_D0 : VitalDelayType01Z := UnitDelay01Z; tpd_OENeg_D0 : VitalDelayType01Z := UnitDelay01Z; tpd_RSTNeg_D0 : VitalDelayType01Z := UnitDelay01Z; tpd_CENeg_WAITS : VitalDelayType01Z := UnitDelay01Z; tpd_CLK_WAITS : VitalDelayType01 := UnitDelay01; tpd_ADVNeg_D0 : VitalDelayType01 := UnitDelay01; -- tpd delays WRITE tpd_VPEN_STS : VitalDelayType01Z := UnitDelay01Z; --high tpd_WENeg_D0 : VitalDelayType01Z := UnitDelay01Z; --high -- tpw values: pulse widths READ tpw_ADVNeg : VitalDelayType := UnitDelay; tpw_CLK : VitalDelayType := UnitDelay; tpw_WENeg_negedge : VitalDelayType := UnitDelay; tpw_WENeg_posedge : VitalDelayType := UnitDelay; tpw_CENeg_posedge : VitalDelayType := UnitDelay; tpw_RSTNeg_negedge : VitalDelayType := UnitDelay; -- tperiod_min: minimum clock period = 1/max freq READ tperiod_CLK : VitalDelayType := UnitDelay; -- tsetup values: setup times READ tsetup_A0_ADVNeg : VitalDelayType := UnitDelay; tsetup_A0_CLK : VitalDelayType := UnitDelay; tsetup_ADVNeg_CLK : VitalDelayType := UnitDelay; tsetup_CENeg_CLK : VitalDelayType := UnitDelay; -- tsetup values WRITE tsetup_D0_WENeg : VitalDelayType := UnitDelay; --high tsetup_A0_WENeg : VitalDelayType := UnitDelay; --high tsetup_WPNeg_WENeg : VitalDelayType := UnitDelay; --high tsetup_CENeg_ADVNeg : VitalDelayType := UnitDelay; tsetup_CLK_ADVNeg : VitalDelayType := UnitDelay; -- thold values: hold times READ thold_A0_ADVNeg : VitalDelayType := UnitDelay; thold_A0_CLK : VitalDelayType := UnitDelay; -- thold values WRITE thold_D0_WENeg : VitalDelayType := UnitDelay; -- high thold_A0_WENeg : VitalDelayType := UnitDelay; -- high thold_D0_CLK : VitalDelayType := UnitDelay; -- trecovery values WRITE trecovery_RSTNeg_WENeg : VitalDelayType := UnitDelay; trecovery_WENeg_OENeg : VitalDelayType := UnitDelay; -- tdevice delays tdevice_WriteBuf : VitalDelayType := UnitDelay; tdevice_WordProgram : VitalDelayType := UnitDelay; tdevice_BEFPProgram : VitalDelayType := UnitDelay; tdevice_BEFPSetup : VitalDelayType := UnitDelay; tdevice_EraseWordGroup : VitalDelayType := UnitDelay; tdevice_ProgSuspend : VitalDelayType := UnitDelay; tdevice_ErsSuspend : VitalDelayType := UnitDelay; tdevice_STSPulse : 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 := "isf28f256k3.mem"; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( 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'; CENeg : IN std_logic := 'H'; OENeg : IN std_logic := 'H'; WENeg : IN std_logic := 'H'; RSTNeg : IN std_logic := 'H'; WPNeg : IN std_logic := 'H'; ADVNeg : IN std_logic := 'H'; VPEN : IN std_logic := 'H'; CLK : IN std_logic := 'L'; STS : OUT std_logic := 'Z'; WAITS : OUT std_logic := 'Z' ); ATTRIBUTE VITAL_LEVEL0 of ISF28F256K3 : ENTITY IS TRUE; END ISF28F256K3; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of ISF28F256K3 IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "ISF28F256K3"; CONSTANT MaxData : NATURAL := 16#FFFF#; --65536; CONSTANT MemSize : NATURAL := 16#FFFFFF#; -- ipd 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 CENeg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL RSTNeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; SIGNAL ADVNeg_ipd : std_ulogic := 'U'; SIGNAL VPEN_ipd : std_ulogic := 'U'; SIGNAL CLK_ipd : std_ulogic := 'U'; -- nwv 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 CENeg_nwv : std_ulogic := 'U'; SIGNAL OENeg_nwv : std_ulogic := 'U'; SIGNAL WENeg_nwv : std_ulogic := 'U'; SIGNAL RSTNeg_nwv : std_ulogic := 'U'; SIGNAL WPNeg_nwv : std_ulogic := 'U'; SIGNAL ADVNeg_nwv : std_ulogic := 'U'; SIGNAL VPEN_nwv : std_ulogic := 'U'; SIGNAL CLK_nwv : std_ulogic := 'U'; SIGNAL WriteBuf_in : std_ulogic := '0'; SIGNAL WriteBuf_out : std_ulogic := '0'; SIGNAL WordProgram_in : std_ulogic := '0'; SIGNAL WordProgram_out : std_ulogic := '0'; SIGNAL BEFPProgram_in : std_ulogic := '0'; SIGNAL BEFPProgram_out : std_ulogic := '0'; SIGNAL BEFPSetup_in : std_ulogic := '0'; SIGNAL BEFPSetup_out : std_ulogic := '0'; SIGNAL EraseWordGroup_in : std_ulogic := '0'; SIGNAL EraseWordGroup_out : std_ulogic := '0'; SIGNAL ProgSuspend_in : std_ulogic := '0'; SIGNAL ProgSuspend_out : std_ulogic := '0'; SIGNAL ErsSuspend_in : std_ulogic := '0'; SIGNAL ErsSuspend_out : std_ulogic := '0'; SIGNAL STSPulse_in : std_ulogic := '0'; SIGNAL STSPulse_out : std_ulogic := '0'; FUNCTION Allign_Types( Input_nwv : UX01 ) RETURN std_ulogic IS VARIABLE Output : std_ulogic; BEGIN 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 WriteBuf : VitalBuf(WriteBuf_out, WriteBuf_in, (tdevice_WriteBuf, UnitDelay)); WordProgram : VitalBuf(WordProgram_out, WordProgram_in, (tdevice_WordProgram, UnitDelay)); BEFPProgram : VitalBuf(BEFPProgram_out, BEFPProgram_in, (tdevice_BEFPProgram, UnitDelay)); BEFPSetup : VitalBuf(BEFPSetup_out, BEFPSetup_in, (tdevice_BEFPSetup, UnitDelay)); EraseWordGroup : VitalBuf(EraseWordGroup_out, EraseWordGroup_in, (tdevice_EraseWordGroup, UnitDelay)); ProgSuspend : VitalBuf(ProgSuspend_out, ProgSuspend_in, (tdevice_ProgSuspend, UnitDelay)); ErsSuspend : VitalBuf(ErsSuspend_out, ErsSuspend_in, (tdevice_ErsSuspend, UnitDelay)); STSPulse : VitalBuf(STSPulse_out, STSPulse_in, (tdevice_STSPulse, UnitDelay)); ---------------------------------------------------------------------------- -- Wire Delays ---------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (A21_ipd, A21, tipd_A21); w_2 : VitalWireDelay (A20_ipd, A20, tipd_A20); w_3 : VitalWireDelay (A19_ipd, A19, tipd_A19); w_4 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_5 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_6 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_7 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_8 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_9 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_10 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_11 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_12 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_13 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_14 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_15 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_16 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_17 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_18 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_19 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_20 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_21 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_22 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_23 : VitalWireDelay (A23_ipd, A23, tipd_A0); w_24 : VitalWireDelay (A22_ipd, A22, 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 (OENeg_ipd, OENeg, tipd_OENeg); w_51 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_52 : VitalWireDelay (RSTNeg_ipd, RSTNeg, tipd_RSTNeg); w_53 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); w_54 : VitalWireDelay (ADVNeg_ipd, ADVNeg, tipd_ADVNeg); w_55 : VitalWireDelay (VPEN_ipd, VPEN, tipd_VPEN); w_56 : VitalWireDelay (CLK_ipd, CLK, tipd_CLK); w_57 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); END BLOCK; -- sig_nwv <= To_UX01(sig_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); CENeg_nwv <= To_UX01(CENeg_ipd); OENeg_nwv <= To_UX01(OENeg_ipd); WENeg_nwv <= To_UX01(WENeg_ipd); RSTNeg_nwv <= To_UX01(RSTNeg_ipd); WPNeg_nwv <= To_UX01(WPNeg_ipd); ADVNeg_nwv <= To_UX01(ADVNeg_ipd); VPEN_nwv <= To_UX01(VPEN_ipd); CLK_nwv <= To_UX01(CLK_ipd); ---------------------------------------------------------------------------- -- Main Behavior Block ---------------------------------------------------------------------------- Behavior: BLOCK PORT ( A : IN std_logic_vector(23 downto 0) := (OTHERS => 'U'); DIn : IN std_logic_vector(15 downto 0) := (OTHERS => 'U'); DOut : OUT std_logic_vector(15 downto 0) := (OTHERS => 'Z'); CENeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RSTNeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U'; ADVNeg : IN std_ulogic := 'U'; VPEN : IN std_ulogic := 'U'; CLK : IN std_ulogic := 'U'; STS : OUT std_logic := 'U'; WAITS : OUT std_logic := 'U' ); PORT MAP ( 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, CENeg => Allign_Types(CENeg_nwv), OENeg => Allign_Types(OENeg_nwv), WENeg => Allign_Types(WENeg_nwv), RSTNeg => Allign_Types(RSTNeg_nwv), WPNeg => Allign_Types(WPNeg_nwv), ADVNeg => Allign_Types(ADVNeg_nwv), VPEN => Allign_Types(VPEN_nwv), CLK => Allign_Types(CLK_nwv), STS => STS, WAITS => WAITS ); -- State Machine : State_Type TYPE state_type IS ( READ_ARRAY, READ_STATUS, READ_CONFIG, READ_QUERY, LOCK_SETUP, LOCK_SETUP_ERS_SUSP, BOTCH, --COMMAND SEQUENCE ERROR BOTCH_ERS_SUSP, --COMMAND SEQUENCE ERROR OTP_PROT_PROG_SETUP, OTP_PROT_PROG_BUSY, OTP_PROT_PROG_DONE, PROG_SETUP, PROG_SETUP_ERS_SUSP, PROG_BUSY, PROG_BUSY_ERS_SUSP, READ_STATUS_PROG_SUSP, READ_ARRAY_PROG_SUSP, READ_CONFIG_PROG_SUSP, READ_QUERY_PROG_SUSP, PROGRAM_DONE, PROGRAM_DONE_ERS_SUSP, READ_STATUS_BOTH_SUSP, READ_ARRAY_BOTH_SUSP, READ_CONFIG_BOTH_SUSP, READ_QUERY_BOTH_SUSP, BUFFERED_EFP_SETUP, BUFFERED_EFP_SETUP_TIME, BUFFERED_EFP_LOAD, BEFP_BUSY, BEFP_EXIT_BUSY, BEFP_EXIT, WRITE_TO_BUFFER_SETUP, COUNT_LOAD, DATA_LOAD, WRITE_TO_BUFFER_CONFIRM, WRITE_TO_BUFFER_SETUP_ERS_SUSP, COUNT_LOAD_ERS_SUSP, DATA_LOAD_ERS_SUSP, WRITE_TO_BUFFER_CONFIRM_ERS_SUSP, ERASE_SETUP, ERASE_BUSY, READ_STATUS_ERS_SUSP, READ_ARRAY_ERS_SUSP, READ_CONFIG_ERS_SUSP, READ_QUERY_ERS_SUSP, ERASE_DONE, STS_RECONFIG_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'; SIGNAL WAIT_zd : std_logic := 'Z'; -- Status Register SIGNAL S_Reg : std_logic_vector(7 downto 0) := "10000000";-- 0x80 -- Read Configuration Register SIGNAL RC_Reg : std_logic_vector(15 downto 0) := (OTHERS => '1'); --Block Lock Status SIGNAL Lock_Down : std_logic_vector (255 downto 0) := (OTHERS => '0'); SIGNAL Block_Lock : std_logic_vector (255 downto 0) := (OTHERS => '1'); -- Write to Buffer count & Buffer size SIGNAL WCount : integer RANGE 0 TO 32 := 0; SIGNAL N : integer RANGE 0 TO 32 := 0; SIGNAL WDone : boolean := FALSE; SIGNAL WBDone : boolean := FALSE; SIGNAL EFP_Block : integer RANGE 0 TO 255 := 0; SIGNAL EDone : boolean := FALSE; SIGNAL WBAddr_change : boolean := FALSE; SIGNAL ECount : integer RANGE 0 TO 511 :=0; -- timing check violation SIGNAL Viol : X01 := '0'; SIGNAL Write : std_logic := '0'; SIGNAL Read : std_logic := '0'; SIGNAL SuspendLatency : std_logic := '0'; SIGNAL InitialPageAccess : boolean := TRUE; SIGNAL SubsequentPageAccess : boolean := FALSE; SIGNAL OPENLATCH : boolean := FALSE; SIGNAL FROMOE : boolean := FALSE; SIGNAL FROMCE : boolean := FALSE; BEGIN -- clocked process for reset and FSM state transition -- on RSTNeg='0' device is in reset -- on CENeg='1' device is in standby mode PROCESS(CLK, RSTNeg) BEGIN IF rising_edge(CLK) THEN IF RSTNeg='0' THEN current_state<=READ_ARRAY; -- reset ELSE current_state <= next_state; END IF; END IF; END PROCESS; -- process for setting the signal write SetWrite : PROCESS(CENeg, WENeg) BEGIN IF(CENeg = '0' AND rising_edge(WENeg)) OR (WENeg = '0' AND rising_edge(CENeg)) THEN Write <= '1', '0' after 1 ns; END IF; END PROCESS SetWrite; -- process for setting the signal read SetRead : PROCESS(OENeg, CENeg, A) BEGIN IF(CENeg = '0' AND falling_edge(OENeg)) OR (OENeg = '0' AND falling_edge(CENeg)) OR (A'EVENT AND CENeg = '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 := -CENeg'LAST_EVENT + tpd_CENeg_D0(trz0); OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_D0(trz0); 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, Read, Write, RSTNeg, WPNeg, ADVNeg, VPEN, WCount, N, WDone, WBDone, EFP_Block, EDone, ECount, CLK, SuspendLatency, OENeg, CENeg, WENeg, S_Reg) -- Timing Check Variables VARIABLE Tviol_A0_ADVNeg : X01 := '0'; VARIABLE TD_A0_ADVNeg : VitalTimingDataType; VARIABLE Tviol_D0_CLK : X01 := '0'; VARIABLE TD_D0_CLK : VitalTimingDataType; VARIABLE Tviol_A0_CLK : X01 := '0'; VARIABLE TD_A0_CLK : VitalTimingDataType; VARIABLE Tviol_ADVNeg_CLK : X01 := '0'; VARIABLE TD_ADVNeg_CLK : VitalTimingDataType; VARIABLE Tviol_CENeg_CLK : X01 := '0'; VARIABLE TD_CENeg_CLK : 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_WPNeg_WENeg : X01 := '0'; VARIABLE TD_WPNeg_WENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_ADVNeg: X01 := '0'; VARIABLE TD_CENeg_ADVNeg : VitalTimingDataType; VARIABLE Tviol_CLK_ADVNeg : X01 := '0'; VARIABLE TD_CLK_ADVNeg : VitalTimingDataType; VARIABLE Rviol_RSTNeg_WENeg: X01 := '0'; VARIABLE TD_RSTNeg_WENeg : VitalTimingDataType; VARIABLE Rviol_WENeg_OENeg : X01 := '0'; VARIABLE TD_WENeg_OENeg : VitalTimingDataType; VARIABLE Pviol_ADVNeg : X01 := '0'; VARIABLE PD_ADVNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CLK : X01 := '0'; VARIABLE PD_CLK : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_RSTNeg : X01 := '0'; VARIABLE PD_RSTNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; VARIABLE data : integer RANGE -1 TO MaxData; VARIABLE OTP_Addr : boolean := FALSE; VARIABLE ActBlock : integer RANGE 0 TO 255; BEGIN ---------------------------------------------------------------------------- -- Timing Check Section ---------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between A and ADVNeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => ADVNeg, RefSignalName => "ADVNeg", SetupHigh => tsetup_A0_ADVNeg, HoldHigh => thold_A0_ADVNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_ADVNeg, Violation => Tviol_A0_ADVNeg ); -- Setup/Hold Check between A and CLK VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLK", SetupHigh => tsetup_A0_CLK, SetupLow => tsetup_A0_CLK, HoldHigh => thold_A0_CLK, HoldLow => thold_A0_CLK, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CLK, Violation => Tviol_A0_CLK ); -- Setup/Hold Check between A and WENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_A0_WENeg, HoldLow => thold_A0_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); -- Setup/Hold Check between D and WENeg VitalSetupHoldCheck ( TestSignal => Din, TestSignalName => "Din", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_D0_WENeg, HoldHigh => thold_D0_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_D0_WENeg, Violation => Tviol_D0_WENeg ); -- Setup Check between ADVNeg and CLK VitalSetupHoldCheck ( TestSignal => ADVNeg, TestSignalName => "ADVNeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_ADVNeg_CLK, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_ADVNeg_CLK, Violation => Tviol_ADVNeg_CLK ); -- Setup Check between CENeg and CLK VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_CENeg_CLK, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLK, Violation => Tviol_CENeg_CLK ); -- Setup Check between WPNeg and WENeg VitalSetupHoldCheck ( TestSignal => WPNeg, TestSignalName => "WPNeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_WPNeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_WENeg, Violation => Tviol_WPNeg_WENeg ); -- Setup Check between CENeg and ADVNeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => ADVNeg, RefSignalName => "ADVNeg", SetupLow => tsetup_CENeg_ADVNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_WENeg, Violation => Tviol_WPNeg_WENeg ); -- Setup Check between CLK and ADVNeg VitalSetupHoldCheck ( TestSignal => CLK, TestSignalName => "CLK", RefSignal => ADVNeg, RefSignalName => "ADVNeg", SetupLow => tsetup_WPNeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_WENeg, Violation => Tviol_WPNeg_WENeg ); -- Recovery Check between RSTNeg and WENeg VitalRecoveryRemovalCheck ( TestSignal => RSTNeg, TestSignalName => "RSTNeg", RefSignal => WENeg, RefSignalName => "WENeg", Recovery => trecovery_RSTNeg_WENeg, ActiveLow => TRUE, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_RSTNeg_WENeg, XOn => XOn, MsgOn => MsgOn, Violation => Rviol_RSTNeg_WENeg ); -- Recovery Check between WENeg and OENeg VitalRecoveryRemovalCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => OENeg, RefSignalName => "OENeg", Recovery => trecovery_WENeg_OENeg, ActiveLow => TRUE, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_WENeg_OENeg, XOn => XOn, MsgOn => MsgOn, Violation => Rviol_WENeg_OENeg ); -- PulseWidth Check for ADVNeg VitalPeriodPulseCheck ( TestSignal => ADVNeg, TestSignalName => "ADVNeg", PulseWidthHigh => tpw_ADVNeg, PulseWidthLow => tpw_ADVNeg, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_ADVNeg, Violation => Pviol_ADVNeg ); -- PulseWidth and Period Check for CLK VitalPeriodPulseCheck ( TestSignal => CLK, TestSignalName => "CLK", Period => tperiod_CLK, PulseWidthHigh => tpw_CLK, PulseWidthLow => tpw_CLK, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CLK, Violation => Pviol_CLK ); -- PulseWidth Check for 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 ); -- PulseWidth Check for RSTNeg VitalPeriodPulseCheck ( TestSignal => RSTNeg, TestSignalName => "RSTNeg", PulseWidthLow => tpw_RSTNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RSTNeg, Violation => Pviol_RSTNeg ); -- PulseWidth Check for WENeg VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CENeg", PulseWidthHigh => tpw_CENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CENeg, Violation => Pviol_CENeg ); Violation := Tviol_A0_ADVNeg OR Tviol_A0_CLK OR Tviol_D0_CLK OR Tviol_ADVNeg_CLK OR Tviol_CENeg_CLK OR Pviol_ADVNeg OR Pviol_WENeg OR Pviol_RSTNeg OR Pviol_CENeg OR Tviol_A0_WENeg OR Tviol_D0_WENeg OR Tviol_WPNeg_WENeg OR Tviol_CENeg_ADVNeg OR Tviol_CLK_ADVNeg OR Rviol_RSTNeg_WENeg OR Rviol_WENeg_OENeg OR Pviol_CLK ; 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 data:=to_nat(DIn); OTP_Addr:= (to_nat(A)>=16#80# AND to_nat(A)<=16#109#) ; ActBlock:=to_nat(A(23 DOWNTO 16)); END IF; CASE current_state IS WHEN READ_ARRAY | READ_STATUS | READ_CONFIG | READ_QUERY | BOTCH | OTP_PROT_PROG_DONE | PROGRAM_DONE | ERASE_DONE | BEFP_EXIT => IF rising_edge(Write) THEN CASE data IS WHEN 16#10# | 16#40# => next_state <= PROG_SETUP; WHEN 16#E8# => IF current_state = BOTCH THEN next_state <= BOTCH; ELSE next_state <= WRITE_TO_BUFFER_SETUP; END IF; WHEN 16#80# => next_state <= BUFFERED_EFP_SETUP; WHEN 16#20# => next_state <= ERASE_SETUP; WHEN 16#B0# | 16#70# => next_state <= READ_STATUS; WHEN 16#90# => next_state <= READ_CONFIG; WHEN 16#B8# => next_state <= STS_RECONFIG_SETUP; WHEN 16#98# => next_state <= READ_QUERY; WHEN 16#60# => next_state <= LOCK_SETUP; WHEN 16#C0# => IF OTP_Addr THEN next_state <= OTP_PROT_PROG_SETUP; END IF; WHEN OTHERS => next_state <= READ_ARRAY; END CASE; END IF; WHEN LOCK_SETUP => --Botch (command sequence error) if second cycle is anything other than --D0h(Unlock), 01h(Lock), 2Fh(Lock down), 03(Write to Read configuration --register(RCR data on A[16:1])); IF rising_edge(Write) THEN -- SECOND CYCLE CHECK IF data=16#D0# OR data=16#01# OR data=16#2F# OR data=16#03# THEN next_state<=READ_ARRAY; ELSE next_state <= BOTCH; END IF; END IF; WHEN LOCK_SETUP_ERS_SUSP => --Botch (command sequence error) Ers Susp if second cycle is anything other --than D0h(Unlock), 01h(Lock), 2Fh(Lock down), 03(Write to Read configuration --register(RCR data on A[16:1])) IF rising_edge(Write) THEN IF data=16#D0# OR data=16#01# OR data=16#2F# OR data=16#03# THEN next_state<=READ_ARRAY_ERS_SUSP; ELSE next_state <= BOTCH_ERS_SUSP; END IF; END IF; WHEN OTP_PROT_PROG_SETUP => IF rising_edge(Write) THEN IF OTP_Addr THEN next_state <= OTP_PROT_PROG_BUSY; ELSE next_state <= BOTCH; END IF; END IF; WHEN OTP_PROT_PROG_BUSY => IF S_Reg(7)='1' THEN next_state <= OTP_PROT_PROG_DONE; ELSE next_state <= OTP_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<=PROGRAM_DONE; ELSIF rising_edge(SuspendLatency) THEN next_state <= READ_STATUS_PROG_SUSP; END IF; WHEN PROG_BUSY_ERS_SUSP => IF WDone OR WBDone THEN next_state<=PROGRAM_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_CONFIG_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_CONFIG_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_CONFIG_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_CONFIG_BOTH_SUSP; WHEN 16#98# => next_state <= READ_QUERY_BOTH_SUSP; WHEN OTHERS => next_state <= READ_ARRAY_BOTH_SUSP; END CASE; END IF; WHEN BUFFERED_EFP_SETUP => IF rising_edge(Write) THEN IF data=16#D0# THEN next_state <= BUFFERED_EFP_SETUP_TIME; ELSE next_state <= BOTCH; END IF; END IF; WHEN BUFFERED_EFP_SETUP_TIME => --If Time-out > 5us, goto Buffered EFP Load; If time-out < 5us, stay in --Buffered EFP set-up time IF S_Reg(4)='1' THEN next_state<=BEFP_EXIT; --error ELSIF S_Reg(0)='0' THEN next_state<=BUFFERED_EFP_LOAD; ELSE next_state<=BUFFERED_EFP_SETUP_TIME; END IF; WHEN BUFFERED_EFP_LOAD => --******************************************************************** --Initialize buffer load count to 31; If buffer count = 0, then goto BEFP(Busy) --If Buffer load count > 0 and if the block address is the same, stay in --Buffered EFP Load; If the block address is changed goto BEFP exit --***************************************************************************** IF rising_edge(Write) THEN IF EFP_Block/=ActBlock THEN next_state<=BEFP_EXIT; ELSIF WCount= 0 THEN next_state <= BEFP_BUSY; ELSIF WCount>0 THEN next_state <= BUFFERED_EFP_LOAD; END IF; END IF; WHEN BEFP_BUSY => --To exit, change block address*; To cotinue, proceed to BEFP after SR.0 = '0'. IF EFP_Block/=ActBlock THEN next_state<=BEFP_EXIT; ELSIF S_Reg(0)='0' THEN --all buffer data has been transfered next_state<=BEFP_EXIT_BUSY; END IF; WHEN BEFP_EXIT_BUSY => --Internally timed; Goto BEFP Exit after internal timeout; Transition indicated --by SR.0 tansitioning from a 1 to a 0. IF EFP_Block/=ActBlock THEN next_state<=BEFP_EXIT; ELSE next_state<=BUFFERED_EFP_LOAD; END IF; WHEN WRITE_TO_BUFFER_SETUP => --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 S_Reg(7)='0' THEN next_state<=READ_ARRAY; ELSIF rising_edge(Write) THEN --- ??!!!!!!! next_state<=COUNT_LOAD; END IF; WHEN COUNT_LOAD => --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 rising_edge(Write) THEN IF WBAddr_change THEN next_state<=BOTCH; ELSE next_state<= DATA_LOAD; END IF; END IF; WHEN DATA_LOAD => --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 WBAddr_change THEN next_state<=BOTCH; ELSIF WCount= 0 OR WCount= N THEN next_state <= WRITE_TO_BUFFER_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_BUFFER_SETUP_ERS_SUSP => --Count load Erase suspend(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 S_Reg(7) = '0' THEN next_state <= READ_ARRAY_ERS_SUSP; ELSIF rising_edge(Write) THEN next_state<= COUNT_LOAD_ERS_SUSP; END IF; WHEN COUNT_LOAD_ERS_SUSP => --Data load Erase suspend; Initialize data counter to 0; To quit/abort changethe --block address during a write cycle. The UI botches on a block address change. IF rising_edge(Write) THEN next_state<= DATA_LOAD_ERS_SUSP; END IF; WHEN DATA_LOAD_ERS_SUSP => --If count = 0, goto Write to buffer confirm Erase suspend; If count < N, stay --in Data load Erase suspend and increment data counter; If count = N, goto --Write to buffer confirm Erase suspend; 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= 0 OR WCount= N THEN next_state <= WRITE_TO_BUFFER_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 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(SuspendLatency) THEN next_state <= READ_STATUS_ERS_SUSP; ELSIF EDone AND ECount=511 THEN next_state<=ERASE_DONE; END IF; WHEN READ_STATUS_ERS_SUSP | READ_ARRAY_ERS_SUSP | READ_CONFIG_ERS_SUSP | READ_QUERY_ERS_SUSP | BOTCH_ERS_SUSP | PROGRAM_DONE_ERS_SUSP => IF rising_edge(Write) THEN CASE data IS WHEN 16#10# | 16#40# => next_state <=PROG_SETUP_ERS_SUSP; WHEN 16#E8# => IF current_state = BOTCH_ERS_SUSP THEN next_state <= BOTCH_ERS_SUSP; ELSE next_state <= WRITE_TO_BUFFER_SETUP_ERS_SUSP; END IF; WHEN 16#B0# | 16#70# | 16#80# => next_state<= READ_STATUS_ERS_SUSP; WHEN 16#D0# => next_state <= ERASE_BUSY; WHEN 16#90# => next_state <= READ_CONFIG_ERS_SUSP; WHEN 16#98# => next_state <= READ_QUERY_ERS_SUSP; WHEN 16#60# => next_state <= LOCK_SETUP_ERS_SUSP; WHEN OTHERS => next_state <= READ_ARRAY_ERS_SUSP; END CASE; END IF; WHEN STS_RECONFIG_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; END CASE; END PROCESS; --------------------------------------------------------------------------- -- combinatorial output generation (Mealy machine) --------------------------------------------------------------------------- output: PROCESS(current_state, A, Din, Read, Write, RSTNeg, WPNeg, ADVNeg, VPEN, WCount, N, WDone, WBDone, WBAddr_change, RC_Reg, EDone, ECount, CLK, OENeg, CENeg, WENeg, S_Reg) -- Output Glitch Detection Variables VARIABLE STS_GlitchData : VitalGlitchDataType; VARIABLE WAIT_GlitchData : VitalGlitchDataType; -- Functionality Results Variables VARIABLE Data : INTEGER RANGE -1 TO MaxData:=0; VARIABLE WData : INTEGER RANGE -1 TO MaxData:=0; VARIABLE Addr_temp : integer RANGE 0 TO MemSize :=0; VARIABLE ActBlock : integer RANGE 0 to 255 :=0; VARIABLE ActB_tmp : integer RANGE 0 to 255 :=0; VARIABLE EBlock : integer RANGE 0 to 255 :=0; VARIABLE Ecnt : integer RANGE 0 TO 65536 :=0; VARIABLE Addr : integer RANGE 0 to MemSize :=0; VARIABLE WAddr : integer RANGE 0 to MemSize :=0; VARIABLE EBlockLock : boolean := FALSE; VARIABLE WBlock_Addr : integer RANGE 0 to MemSize :=0; VARIABLE EBlock_Addr : integer RANGE 0 to MemSize :=0; VARIABLE loop_cnt : integer RANGE 0 TO 32 :=0; VARIABLE latency : integer RANGE 0 TO 15 :=0; VARIABLE burst_ln : integer RANGE 0 TO 15 :=0; VARIABLE burst_tmp : integer RANGE 0 TO 15 :=0; VARIABLE clk_tmp : integer RANGE 0 TO 1 :=0; VARIABLE burst_CLK : boolean:=FALSE; VARIABLE page_load : boolean := FALSE; TYPE WBuffer_type IS ARRAY(0 TO 31) OF INTEGER RANGE -1 TO MaxData; VARIABLE WBuffer : WBuffer_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 MemSize; VARIABLE WBAddr : WBAddr_type:=(OTHERS=>0); VARIABLE Page : WBAddr_type:=(OTHERS=>0); --Protection registers TYPE PR_type IS ARRAY(16#80# TO 16#109#) OF INTEGER RANGE 0 TO MaxData; VARIABLE PR : PR_type := (OTHERS =>16#FFFF#); VARIABLE PR_Addr : std_logic_vector(15 DOWNTO 0) :=(OTHERS=>'0'); VARIABLE PR_tmp : integer RANGE 0 TO MaxData:=0; VARIABLE Ident_Addr : integer RANGE 0 TO 16#109#:=0; -- Common Flash Interface TYPE CFI_type IS ARRAY(16#10# TO 16#51#) OF INTEGER RANGE 0 TO 16#FF#; VARIABLE CFI : CFI_type := (OTHERS => 0); -- Read Identifier VARIABLE cycle : integer RANGE 0 TO 1 :=0; -- STS signal configuration VARIABLE sts_conf : std_logic_vector(1 DOWNTO 0) := "00"; -- Memory array declaration TYPE MemStore IS ARRAY (0 to MemSize) OF INTEGER RANGE -1 TO MaxData; VARIABLE MemData : MemStore := (OTHERS =>16#FFFF#); -- text file input variables FILE mem_file : text is mem_file_name; VARIABLE ind : NATURAL := 0; VARIABLE buf : line; BEGIN IF rising_edge(Write) OR falling_edge(Read) THEN Addr := to_nat(A); ActBlock := to_nat(A(23 downto 16)); -- active Block END IF; IF rising_edge(ADVNeg) THEN Addr_temp:= to_nat(A); END IF; IF rising_edge(Write) THEN Data := to_nat(DIn); END IF; -- Reset buffer load / address latch flag IF falling_edge(ADVNeg) THEN page_load := FALSE; END IF; CASE current_state IS WHEN READ_ARRAY | READ_ARRAY_ERS_SUSP | READ_ARRAY_PROG_SUSP | READ_ARRAY_BOTH_SUSP=> S_Reg(7) <= '1'; --any other value would prevent write buffer command IF RC_Reg(15)='1' THEN IF falling_edge(Read) THEN IF (((current_state = READ_ARRAY_PROG_SUSP OR current_state = READ_ARRAY_BOTH_SUSP) AND NOT(Addr>=WAddr AND Addr<=WAddr+N )) OR ((current_state = READ_ARRAY_ERS_SUSP OR current_state = READ_ARRAY_BOTH_SUSP) AND ActBlock/=EBlock) OR current_state = READ_ARRAY) THEN Dout_zd <= to_slv(MemData(Addr),16); ELSE ASSERT FALSE REPORT "accessed memory is suspended" SEVERITY WARNING; END IF; END IF; ELSE -- Synch Array Read - Burst Mode Read -- clock edge IF (rising_edge(CLK) AND RC_Reg(6)='1') OR (falling_edge(CLK) AND RC_Reg(6)='0')THEN burst_clk := TRUE; ELSE burst_clk := FALSE; END IF; IF (NOT page_load)AND((burst_clk AND ADVNeg ='0')OR rising_edge(ADVNeg))THEN page_load:=TRUE; --burst length IF RC_Reg(2 downto 0) = "011" THEN burst_ln := 15; Addr_Temp := to_nat(A(23 downto 4)&"0000"); burst_tmp := to_nat(A(3 DOWNTO 0)); ELSIF RC_Reg(2 downto 0) = "010" THEN burst_ln := 7; Addr_Temp := to_nat(A(23 downto 3)&"000"); burst_tmp := to_nat(A(2 DOWNTO 0)); ELSE ASSERT FALSE REPORT "Burst Length has RFU value " & to_bin_str(RC_Reg(2 downto 0)) SEVERITY ERROR; END IF; -- Latency initialization, ADV# latch IF rising_edge(ADVNeg) THEN latency := to_nat(RC_Reg(14 downto 11)) - 1; END IF; -- Latency initialization, CLK active edge latch -- See Specification Update IF burst_clk THEN latency := to_nat(RC_Reg(14 downto 11)); END IF; ASSERT (latency>1 AND latency<11) REPORT "Latency Count has RFU value " & to_bin_str(RC_Reg(14 downto 11)) SEVERITY ERROR; FOR i IN 0 TO burst_ln LOOP Page(i):=MemData(Addr_Temp+burst_tmp); IF (burst_tmp0 THEN latency := latency -1; --wait delay IF (RC_Reg(8)= '1' AND latency= 0) THEN WAIT_zd <= not(RC_Reg(10)); END IF; ELSIF latency=0 AND loop_cnt <= burst_ln AND Read = '0' THEN WAIT_zd <= not(RC_Reg(10)); --hold data for one OR two clocks IF clk_tmp=0 THEN DOut_zd <= to_slv(Page(loop_cnt),16); loop_cnt := loop_cnt +1; clk_tmp:=to_nat(RC_Reg(9)); ELSE clk_tmp:=0; END IF; END IF; END IF; END IF; IF rising_edge(Write) THEN IF data=16#50# THEN CASE current_state IS WHEN READ_ARRAY => S_Reg<="10000000"; WHEN READ_ARRAY_PROG_SUSP => S_Reg<="10000100"; WHEN READ_ARRAY_ERS_SUSP => S_Reg<="11000000"; WHEN OTHERS => S_Reg<="11000100"; END CASE; ELSIF data=16#D0# THEN IF current_state = READ_ARRAY_ERS_SUSP THEN S_Reg(6)<='0'; -- Program NOT suspended ELSIF current_state = READ_ARRAY_PROG_SUSP OR current_state = READ_ARRAY_BOTH_SUSP THEN S_Reg(2)<='0'; END IF; END IF; END IF; WHEN READ_STATUS => IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND data=16#50# THEN S_Reg<="10000000"; END IF; WHEN READ_CONFIG | READ_CONFIG_PROG_SUSP | READ_CONFIG_ERS_SUSP | READ_CONFIG_BOTH_SUSP => -- if identifier data has more than 1 byte then -- low byte is read first IF falling_edge(Read) THEN IF Addr= 0 THEN cycle:=0; DOut_zd(7 DOWNTO 0) <=to_slv(16#89#,8); ELSIF Addr=1 THEN IF cycle=0 OR Ident_Addr/=Addr THEN -- first read cycle Ident_Addr:=Addr; cycle:=1; DOut_zd(7 DOWNTO 0) <=to_slv(16#01#,8); ELSIF cycle=1 AND Ident_Addr=Addr THEN --second cycle cycle:=0; DOut_zd(7 DOWNTO 0) <=to_slv(16#88#,8); END IF; ELSIF Addr=5 THEN IF cycle=0 OR Ident_Addr/=Addr THEN -- first read cycle Ident_Addr:=Addr; cycle:=1; DOut_zd(7 DOWNTO 0) <=RC_Reg(7 DOWNTO 0); ELSIF cycle=1 AND Ident_Addr=Addr THEN --second cycle cycle:=0; DOut_zd(7 DOWNTO 0) <=RC_Reg(15 DOWNTO 8); END IF; ELSIF Addr>=16#80# AND Addr<=16#109# THEN IF cycle=0 OR Ident_Addr/=Addr THEN -- first read cycle cycle:=1; Ident_Addr:=Addr; PR_Addr:=to_slv(PR(Addr),16); DOut_zd(7 DOWNTO 0)<=PR_Addr(7 DOWNTO 0); ELSIF cycle=1 AND Ident_Addr=Addr THEN --second cycle cycle:=0; PR_Addr:=to_slv(PR(Addr),16); DOut_zd(7 DOWNTO 0)<=PR_Addr(15 DOWNTO 8); END IF; ELSIF A(15 DOWNTO 0)= "0000000000000010" THEN cycle:=0; DOut_zd(0)<=Block_Lock(ActBlock); DOut_zd(1)<=Lock_Down(ActBlock); DOut_zd(7 DOWNTO 2)<= "000000"; END IF; DOut_zd(15 DOWNTO 8)<=(OTHERS=>'0'); END IF; IF rising_edge(Write) THEN IF data=16#50# THEN CASE current_state IS WHEN READ_CONFIG => S_Reg<="10000000"; WHEN READ_CONFIG_PROG_SUSP => S_Reg<="10000100"; WHEN READ_CONFIG_ERS_SUSP => S_Reg<="11000000"; WHEN OTHERS => S_Reg<="11000100"; END CASE; ELSIF data=16#D0# THEN IF current_state = READ_CONFIG_ERS_SUSP THEN S_Reg(6)<='0'; -- Program NOT suspended ELSIF current_state = READ_CONFIG_PROG_SUSP OR current_state = READ_CONFIG_BOTH_SUSP THEN S_Reg(2)<='0'; END IF; END IF; END IF; WHEN READ_QUERY | READ_QUERY_PROG_SUSP | READ_QUERY_ERS_SUSP | READ_QUERY_BOTH_SUSP => IF falling_edge(Read) THEN IF Addr= 0 THEN DOut_zd <=to_slv(16#89#,16); ELSIF Addr=1 THEN DOut_zd <=to_slv(16#8801#,16); ELSIF A(15 DOWNTO 0)= "0000000000000010" THEN DOut_zd(0)<=Block_Lock(ActBlock); DOut_zd(1)<=Lock_Down(ActBlock); DOut_zd(15 DOWNTO 2)<= (OTHERS=>'0'); ELSIF Addr>=16#10# AND Addr<=16#51# THEN DOut_zd<=to_slv(CFI(Addr),16); 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'; -- Program NOT suspended ELSIF current_state = READ_QUERY_PROG_SUSP OR current_state = READ_QUERY_BOTH_SUSP THEN S_Reg(2)<='0'; END IF; END IF; END IF; WHEN LOCK_SETUP => --Botch (command sequence error) if second cycle is anything other than --D0h(Unlock), 01h(Lock), 2Fh(Lock down), 03(Write to Read configuration --register(RCR data on A[16:1])); IF rising_edge(Write) THEN -- SECOND CYCLE CHECK IF Data=16#03# THEN -- Configuration Register Data Update RC_Reg <= A(15 DOWNTO 0); ELSIF Data=16#01# THEN -- Lock Block Block_Lock(ActBlock) <='1'; ELSIF Data=16#D0# THEN -- UnLock Block IF NOT(WPNeg='0' AND Lock_Down(ActBlock)='1') THEN Block_Lock(ActBlock) <='0'; END IF; ELSIF Data=16#2F# THEN -- Lock Down Block Lock_Down(ActBlock) <='1'; Block_Lock(ActBlock) <='1'; 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 LOCK_SETUP_ERS_SUSP => --Botch (command sequence error) Ers Susp if second cycle is anything other --than D0h(Unlock), 01h(Lock), 2Fh(Lock down), 03(Write to Read configuration --register(RCR data on A[16:1])) IF rising_edge(Write) THEN -- SECOND CYCLE CHECK IF Data=16#03# THEN -- Configuration Register Data Update RC_Reg <= A(15 downto 0); ELSIF Data=16#01# THEN -- Lock Block Block_Lock(ActBlock) <='1'; IF ActBlock=EBlock THEN EBlockLock:=FALSE; END IF; ELSIF Data=16#D0# THEN -- UnLock Block IF NOT(WPNeg='0' AND Lock_Down(ActBlock)='1') THEN Block_Lock(ActBlock) <='0'; END IF; ELSIF Data=16#2F# THEN -- Lock Down Block Lock_Down(ActBlock) <='1'; Block_Lock(ActBlock) <='1'; 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 BOTCH => IF (S_Reg /= "1011000" AND next_state = BOTCH) THEN S_Reg(7)<='1'; S_Reg(5)<='1';--command sequence error S_Reg(4)<='1'; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND data=16#50# THEN S_Reg<="10000000"; END IF; WHEN BOTCH_ERS_SUSP => IF (S_Reg /= "1111000" AND next_state = BOTCH_ERS_SUSP) THEN S_Reg(7)<='1'; S_Reg(6)<='1'; S_Reg(5)<='1';--command sequence error S_Reg(4)<='1'; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND data=16#50# THEN S_Reg<="11000000"; END IF; WHEN OTP_PROT_PROG_SETUP => --S_Reg(7)<='0'; IF rising_edge(Write) THEN IF Addr=16#80# THEN -- PR Lock Register 0 IF Data=16#FFFD# THEN PR(Addr):=Data; --program time should be 450 us maximal S_Reg(7)<='0', '1' AFTER tdevice_WordProgram; ELSE S_Reg(7)<='1'; END IF; ELSIF Addr>=16#81# AND Addr<=16#84# THEN --PR0 --Intel Factory Programmed -- S_Reg(7)<='1'; S_Reg(5 DOWNTO 4)<="11"; ELSIF Addr>=16#85# AND Addr<=16#88# THEN IF PR(16#80#)=16#FFFE# AND PR(Addr)=16#FFFF# THEN --PR0 user segment NOT locked -- and NOT programmed PR(Addr):=Data; --program time should be 450 us maximal S_Reg(7)<='0', '1' AFTER tdevice_WordProgram; ELSE --PR0 user segment NOT available S_Reg(7)<='1'; S_Reg(5 DOWNTO 4)<="11"; END IF; ELSIF Addr=16#89# THEN -- PR Lock Register 1 IF Data/=16#FFFF# THEN -- valid values are between 0xFFFE and 0x0000 PR(Addr):=Data; --program time should be 450 us maximal S_Reg(7)<='0', '1' AFTER tdevice_WordProgram; ELSE S_Reg(7)<='1'; S_Reg(5 DOWNTO 4)<="11"; END IF; ELSIF Addr>=16#8A# AND Addr<=16#109# THEN --word addres in 2K OTP PR_Addr:=(OTHERS=>'0'); PR_Addr(6 DOWNTO 0):=to_slv((Addr-16#8A#),7); --Prot Reg num PR_tmp:=to_nat(PR_Addr(6 DOWNTO 3)); -- PR Lock register 1 PR_Addr:= to_slv(PR(16#89#),16); IF PR_Addr(PR_tmp)='1' AND PR(Addr)=16#FFFF# THEN --PR0 user segment NOT locked -- and NOT programmed PR(Addr):=Data; --program time should be 450 us maximal S_Reg(7)<='0', '1' AFTER tdevice_WordProgram; ELSE --PR0 user segment NOT available S_Reg(7)<='1'; S_Reg(5 DOWNTO 4)<="11"; END IF; ELSE S_Reg(7)<='1'; 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 OTP_PROT_PROG_BUSY | BEFP_BUSY => IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN OTP_PROT_PROG_DONE => S_Reg(7)<='1'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); 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 WDone<=TRUE; IF Block_Lock(ActBlock) = '0' THEN IF VPEN = '1' THEN WAddr := Addr; WData := Data; N<=0; --program time should be 450 us maximal WDone <= FALSE, TRUE AFTER tdevice_WordProgram; 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 => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN PROG_BUSY | PROG_BUSY_ERS_SUSP => IF WBDone AND WCount<=N THEN IF VIOL='0' AND S_Reg(4) /= '1' THEN MemData(WBAddr(WCount)):=WBuffer(WCount); ELSIF VIOL /= '0' THEN S_Reg(4)<='1'; MemData(WBAddr(WCount)):=-1; END IF; WCount<=WCount+1; --write buffer program time should be 10us per word --960us maximal for 32words at worst case WBDone <= FALSE, TRUE AFTER tdevice_WriteBuf; ELSIF WDone THEN IF Viol = '0' AND S_Reg(4) /= '1' THEN MemData(WAddr) := WData; --OK ELSIF VIOL /= '0' THEN MemData(WAddr) := -1; -- invalid entry ! S_Reg(4) <= '1'; -- Programming Failure 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 --program suspend S_Reg(2) <= '1'; SuspendLatency <= '0', '1' AFTER tdevice_ProgSuspend; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN READ_STATUS_PROG_SUSP => SuspendLatency <= '0'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); 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 PROGRAM_DONE => WBDone <=FALSE; WDone <=FALSE; S_Reg(7)<='1'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND data=16#50# THEN S_Reg<="10000000"; END IF; WHEN PROGRAM_DONE_ERS_SUSP => WBDone <=FALSE; WDone <=FALSE; S_Reg(7)<='1'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); 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_STATUS_BOTH_SUSP => SuspendLatency <= '0'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); 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 BUFFERED_EFP_SETUP => IF rising_edge(Write) THEN IF data=16#D0# THEN S_Reg(0)<='1'; IF Block_Lock(ActBlock) = '0' THEN IF VPEN = '1' THEN --address within the block WAddr := to_nat(A(15 DOWNTO 0)); WBlock_Addr:=Addr-WAddr; EFP_Block <= ActBlock; S_Reg(7)<='0'; -- BEFP setup time out is 5 us S_Reg(0)<='1','0' AFTER tdevice_BEFPSetup; 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 => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN BUFFERED_EFP_SETUP_TIME => --If Time-out > 5us, goto Buffered EFP Load; If time-out < 5us, stay in --Buffered EFP set-up time IF S_Reg(0)='0' THEN WCount<=31; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN BUFFERED_EFP_LOAD => --******************************************************************** --Initialize buffer load count to 31; If buffer count = 0, then goto BEFP(Busy) --If Buffer load count > 0 and if the block address is the same, stay in --Buffered EFP Load; If the block address is changed goto BEFP exit --***************************************************************************** S_Reg(7)<='0'; IF EFP_Block=ActBlock AND rising_edge(Write)AND WCount>=0 THEN WBuffer(WCount):=Data; IF WCount=0 THEN -- BEFP write time is 288 us S_Reg(0)<='1','0' AFTER tdevice_BEFPProgram; ELSE WCount<=WCount-1; 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 BEFP_EXIT_BUSY => --Internally timed; Goto BEFP Exit after internal timeout; Transition indicated --by SR.0 tansitioning from a 1 to a 0. IF S_Reg(7)='0' THEN S_Reg(7)<='1'; FOR i IN 31 DOWNTO 0 LOOP MemData(WBlock_Addr+WAddr):=WBuffer(i); IF WAddr=16#FFFF# THEN WAddr:=0; ELSE WAddr:=WAddr+1; END IF; END LOOP; END IF; IF EFP_Block=ActBlock THEN WCount<=31; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN BEFP_EXIT => S_Reg(7)<='1'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN WRITE_TO_BUFFER_SETUP | WRITE_TO_BUFFER_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 => '0'); DOut_zd(7 downto 0) <= S_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; WBuffer(0):=Data; 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 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; WBuffer(WCount):=Data; IF N>0 AND WCount '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN WRITE_TO_BUFFER_CONFIRM | WRITE_TO_BUFFER_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 --write buffer program time should be 10us per word --320us typical for 32words WCount<=0; WBDone <= FALSE, TRUE AFTER tdevice_WriteBuf; 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 => '0'); DOut_zd(7 downto 0) <= S_Reg; 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(15 DOWNTO 0)); --Block should be unlocked after erase EBlock:=ActBlock; EBlockLock:=TRUE; ECount<=0; Ecnt:=0; --Block Erase time should be 1 s --16 us per word --2 ms per 128 word group EDone <= FALSE, TRUE AFTER tdevice_EraseWordGroup; 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<=511 THEN FOR i IN 0 TO 127 LOOP Memdata(EBlock_Addr+ECnt):=16#FFFF#; EXIT WHEN Ecnt=16#FFFF#; Ecnt:=Ecnt+1; END LOOP; IF Ecnt=16#FFFF# THEN ASSERT Ecount=511 REPORT "ECount should be 511" SEVERITY ERROR; END IF; IF ECount=511 THEN S_Reg(7)<='1'; ELSE EDone <= FALSE, TRUE AFTER tdevice_EraseWordGroup; ECount<=ECount+1; END IF; END IF; IF rising_edge(Write)AND Data=16#B0# THEN S_Reg(6) <= '1'; --erase suspend SuspendLatency <= '0', '1' after tdevice_ProgSuspend; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; WHEN READ_STATUS_ERS_SUSP => S_Reg(6) <='1'; --erase suspend SuspendLatency <='0'; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); 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 ERASE_DONE => EDone<=FALSE; IF EBlockLock THEN Block_Lock(EBlock)<='0'; END IF; IF falling_edge(Read) THEN DOut_zd(15 downto 8) <= (OTHERS => '0'); DOut_zd(7 downto 0) <= S_Reg; END IF; IF rising_edge(Write) AND data=16#50# THEN S_Reg<="10000000"; END IF; WHEN STS_RECONFIG_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_conf:=DIn(1 DOWNTO 0); 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; END CASE; --this section is common to all command states --** IF rising_edge(OENeg) OR rising_edge(CENeg) 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; IF (Addr = Addr_temp) THEN SubsequentPageAccess <= TRUE; InitialPageAccess <= FALSE; ELSE InitialPageAccess <= TRUE; SubsequentPageAccess <= FALSE; END IF; -- Register data to default value IF rising_edge(RSTNeg) THEN S_Reg <="10000000"; Block_Lock <=(OTHERS=>'1'); RC_Reg <=(OTHERS=>'1'); Lock_Down <=(OTHERS=>'0'); WCount <= 0; N <= 0; WDone <= FALSE; WBDone <= FALSE; WBAddr_change<= FALSE; EDone <= FALSE; ECount <=0; PR(16#80#) :=16#FFFE#; -- PR0 Lock Register sts_conf :="00"; -- CFI Indentification CFI(16#10#):=16#51#; CFI(16#11#):=16#52#; CFI(16#12#):=16#59#; CFI(16#13#):=16#1#; CFI(16#14#):=16#0#; CFI(16#15#):=16#31#; CFI(16#16#):=16#0#; CFI(16#17#):=16#0#; CFI(16#18#):=16#0#; CFI(16#19#):=16#0#; CFI(16#1A#):=16#0#; -- System Interface Information CFI(16#1B#):=16#27#; CFI(16#1C#):=16#36#; CFI(16#1D#):=16#0#; CFI(16#1E#):=16#0#; CFI(16#1F#):=16#8#; CFI(16#20#):=16#9#; CFI(16#21#):=16#A#; CFI(16#22#):=16#0#; CFI(16#23#):=16#1#; CFI(16#24#):=16#1#; CFI(16#25#):=16#2#; CFI(16#26#):=16#0#; -- Device Geometry definition CFI(16#27#):=16#19#; CFI(16#28#):=16#1#; CFI(16#29#):=16#0#; CFI(16#2A#):=16#6#; CFI(16#2B#):=16#0#; CFI(16#2C#):=16#1#; CFI(16#2D#):=16#FF#; CFI(16#2E#):=16#0#; CFI(16#2F#):=16#0#; CFI(16#30#):=16#2#; -- Primary Vendor Specific Ectended Table 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#E6#; CFI(16#37#):=16#1#; CFI(16#38#):=16#0#; CFI(16#39#):=16#0#; CFI(16#3A#):=16#1#; CFI(16#3B#):=16#7#; CFI(16#3C#):=16#0#; CFI(16#3D#):=16#33#; CFI(16#3E#):=16#0#; -- Protection Register Information CFI(16#3F#):=16#2#; CFI(16#40#):=16#80#; CFI(16#41#):=16#0#; CFI(16#42#):=16#3#; CFI(16#43#):=16#3#; CFI(16#44#):=16#89#; CFI(16#45#):=16#0#; CFI(16#46#):=16#0#; CFI(16#47#):=16#0#; CFI(16#48#):=16#0#; CFI(16#49#):=16#0#; CFI(16#4A#):=16#0#; CFI(16#4B#):=16#10#; CFI(16#4C#):=16#0#; CFI(16#4D#):=16#4#; -- Burst/Page Read Information CFI(16#4E#):=16#4#; CFI(16#4F#):=16#2#; CFI(16#50#):=16#2#; CFI(16#51#):=16#3#; -------------------------------------------------------------------- -- File Read Section -------------------------------------------------------------------- IF (mem_file_name /= "none") THEN ind := 0; WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '#' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 to 2)); ELSE MemData(ind) := h(buf(1 to 4)); ind := ind + 1; END IF; END LOOP; END IF; END IF; IF rising_edge(Read) THEN WAIT_zd<='Z'; END IF; IF (WDone OR(WBDone AND WCount>N)) AND S_Reg(2)/='1' AND (sts_conf="10" OR sts_conf="11") THEN STS_zd<='0','1' AFTER tdevice_STSPulse; ELSIF (EDone AND ECount=511) AND S_Reg(6)/='1' AND (sts_conf="01" OR sts_conf="11") THEN STS_zd<='0','1' AFTER tdevice_STSPulse; ELSIF sts_conf="00" THEN IF S_Reg(7)='1' THEN STS_zd <= '1'; ELSE STS_zd<= '0'; END IF; END IF; END PROCESS; ---------------------------------------------------------------------------- -- Path Delay Section ---------------------------------------------------------------------------- PROCESS(STS_zd) VARIABLE STS_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => STS, OutSignalName => "STS", OutTemp => STS_zd, Mode => VitalTransport, GlitchData => STS_GlitchData, Paths => ( 0 => (InputChangeTime => VPEN'LAST_EVENT, PathDelay => tpd_VPEN_STS, PathCondition => FALSE) -- NOT IMPLEMENTED !!! ) ); END PROCESS; PROCESS(WAIT_zd) VARIABLE WAIT_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => WAITS, OutSignalName => "WAIT", OutTemp => WAIT_zd, Mode => VitalTransport, GlitchData => WAIT_GlitchData, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_WAITS, PathCondition => CENeg='1'), 1 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_WAITS), PathCondition => FALSE), -- NOT IMPLEMENTED !!! 2 => (InputChangeTime => RSTNeg'LAST_EVENT, PathDelay => UnitDelay01Z, PathCondition => RSTNeg='0') ) ); END PROCESS; ---------------------------------------------------------------------------- -- Path Delay Section for DOut signal ---------------------------------------------------------------------------- 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 => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_D0, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMCE)), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_D0, PathCondition => NOT OPENLATCH OR (OPENLATCH AND FROMOE)), 2 => (InputChangeTime => RSTNeg'LAST_EVENT, PathDelay => tpd_RSTNeg_D0, PathCondition => TRUE), 3 => (InputChangeTime => WENeg'LAST_EVENT, PathDelay => tpd_WENeg_D0, PathCondition => TRUE), 4 => (InputChangeTime => CLK'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_D0), PathCondition => OENeg = '0' AND RC_Reg(15) = '0'), 5 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_D0_SubsequentPageAccess), PathCondition => SubsequentPageAccess), 6 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_D0_InitialPageAccess), PathCondition => InitialPageAccess) ) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral;