------------------------------------------------------------------------------- -- File name : s29ws256p.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2004-2008, Spansion, LCC. -- -- MODIFICATION HISTORY : -- -- version: | author: | mod date: | changes made: -- V1.0 T.Popovic 04 Dec 13 Initial -- V1.1 T.Popovic 05 Feb 25 Latest datasheet aligned -- Added Page Read -- V1.2 I.Milutinovic 06 Apr 04 Corrected address latching in -- Async. and Sync. mode -- V1.3 I.Milutinovic 06 Apr 10 Implemented LongTiming option -- V1.4 M.Milanovic 06 Jun 22 Corrected Autoselect codes -- V1.5 D.Lukovic 06 Aug 01 Latest datasheet aligned: Removed -- DDR burst mode, pin DQS1 removed -- and RDYDQS0 renamed to RDY, reset -- command is not needed after setting -- configuration registers, CFI codes -- changed, modified StateTransition -- process because of larger width of -- RESETNeg pulse ... -- V1.6 M.Milanovic 06 Aug 16 Software reset command must follow -- configuration registers setting -- V1.7 S.Petrovic 06 Nov 22 Latest datasheet aligned: Corrected -- timing parameters tCE,tOE..;address -- latch for asyn read; condition for -- program suspend command. -- V1.8 K.Kojdic 07 Feb 19 Fixed bug for data latch -- V1.9 K.Kojdic 07 Mar 08 Address latch bug fixed -- V1.10 M.Vlahovic 07 Jun 14 Consecutive reads bug fixed -- V1.11 S.Janevski 07 Sep 12 Assertion of AVDNeg doesn't affect -- to RDY -- V1.12 S.Petrovic 07 Oct 17 Corrected Erase Suspend during -- Erase Timeout -- V1.13 D.Stanojkovic 08 Jan 28 Fixed bug for polling toggles -- during sector erase -- V1.14 S.Petrovic 08 Apr 16 Allowed memory read during -- valid command sequences before -- start of embedded algorithm -- V1.15 S.Petrovic 08 May 27 Corrected setting of RDY when burst -- terminated with AVDNeg set low ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH -- Technology: Flash Memory -- Part: s29ws256p -- -- Description: 256 Mb (16 M x 16 bit) -- 1.8 V Burst Simultaneous Read/Write MirrorBit Flash Memory ------------------------------------------------------------------------------- -- Comments : -- For correct simulation, simulator resolution should be set to 1 ps -- ------------------------------------------------------------------------------- -- Known Bugs: -- ------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.VITAL_timing.ALL; USE IEEE.VITAL_primitives.ALL; USE STD.textio.ALL; LIBRARY FMF; USE FMF.gen_utils.all; USE FMF.conversions.all; ------------------------------------------------------------------------------- -- ENTITY DECLARATION ------------------------------------------------------------------------------- ENTITY s29ws256p IS GENERIC( --tipd delays: interconnect path delays tipd_A0 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A1 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A2 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A3 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A4 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A5 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A6 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A7 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A8 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A9 :VitalDelayType01 := VitalZeroDelay01; --address tipd_A10 :VitalDelayType01 := VitalZeroDelay01; --lines tipd_A11 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A12 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A13 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A14 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A15 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A16 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A17 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A18 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A19 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A20 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A21 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A22 :VitalDelayType01 := VitalZeroDelay01; -- tipd_A23 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ0 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ1 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ2 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ3 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ4 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ5 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ6 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ7 :VitalDelayType01 := VitalZeroDelay01; --data tipd_DQ8 :VitalDelayType01 := VitalZeroDelay01; --lines tipd_DQ9 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ10 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ11 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ12 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ13 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ14 :VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ15 :VitalDelayType01 := VitalZeroDelay01; -- tipd_CLK :VitalDelayType01 := VitalZeroDelay01; -- tipd_CENeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_OENeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_WENeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_RESETNeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_AVDNeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_WPNeg :VitalDelayType01 := VitalZeroDelay01; -- tipd_ACC :VitalDelayType01 := VitalZeroDelay01; -- --tpd delays tpd_RESETNeg_DQ0 :VitalDelayType01Z := UnitDelay01Z; tpd_A0_DQ0_InitialPageAccess :VitalDelayType01 := UnitDelay01; -- tacc tpd_A0_DQ0_SubsequentPageAccess:VitalDelayType01 := UnitDelay01; -- tpacc tpd_CENeg_DQ0_SYN_EQ_0 :VitalDelayType01Z := UnitDelay01Z; -- tce, tcez tpd_CENeg_DQ0_SYN_EQ_1 :VitalDelayType01Z := UnitDelay01Z; -- tce, tcez tpd_OENeg_DQ0_SYN_EQ_0 :VitalDelayType01Z := UnitDelay01Z; -- toe, toeZ tpd_OENeg_DQ0_SYN_EQ_1 :VitalDelayType01Z := UnitDelay01Z; -- toe, toeZ tpd_CLK_DQ0 :VitalDelayType01 := UnitDelay01; -- tbacc tpd_CENeg_RDY :VitalDelayType01Z := UnitDelay01Z; -- trdy, tcez tpd_OENeg_RDY :VitalDelayType01 := UnitDelay01; -- toe tpd_CLK_RDY :VitalDelayType01 := UnitDelay01; -- tracc --tsetup values tsetup_CENeg_CLK :VitalDelayType := UnitDelay; -- tces edge / tsetup_A0_CLK :VitalDelayType := UnitDelay; -- tacs edge / tsetup_A0_AVDNeg :VitalDelayType := UnitDelay; -- taavds edge / tsetup_AVDNeg_CLK :VitalDelayType := UnitDelay; -- tavc edge / tsetup_A0_WENeg_SYN_EQ_0_noedge_posedge :VitalDelayType := UnitDelay; -- tas edge / tsetup_A0_WENeg_SYN_EQ_1_noedge_posedge :VitalDelayType := UnitDelay; -- tas edge / tsetup_A0_CENeg_SYN_EQ_0_noedge_posedge :VitalDelayType := UnitDelay; -- tas edge / tsetup_A0_CENeg_SYN_EQ_1_noedge_posedge :VitalDelayType := UnitDelay; -- tas edge / tsetup_AVDNeg_WENeg :VitalDelayType := UnitDelay; -- tavsw edge \ tsetup_AVDNeg_CENeg :VitalDelayType := UnitDelay; -- tavsw edge \ tsetup_DQ0_WENeg :VitalDelayType := UnitDelay; -- tds edge / tsetup_DQ0_CENeg :VitalDelayType := UnitDelay; -- tds edge / tsetup_CENeg_AVDNeg :VitalDelayType := UnitDelay; -- tcas edge \ tsetup_CENeg_WENeg :VitalDelayType := UnitDelay; -- tcs edge \ tsetup_WENeg_CENeg :VitalDelayType := UnitDelay; -- tcs edge \ --thold values thold_CENeg_RESETNeg :VitalDelayType := UnitDelay; -- trh edge / thold_OENeg_RESETNeg :VitalDelayType := UnitDelay; -- trh edge / thold_A0_CLK :VitalDelayType := UnitDelay; -- tach edge / thold_A0_AVDNeg :VitalDelayType :=UnitDelay; -- taavdh edge / thold_AVDNeg_CLK :VitalDelayType := UnitDelay; -- tavhc edge / thold_A0_WENeg_SYN_EQ_0_noedge_posedge :VitalDelayType := UnitDelay; -- tah edge / thold_A0_WENeg_SYN_EQ_1_noedge_posedge :VitalDelayType := UnitDelay; -- tah edge / thold_A0_CENeg_SYN_EQ_0_noedge_posedge :VitalDelayType := UnitDelay; -- tah edge / thold_A0_CENeg_SYN_EQ_1_noedge_posedge :VitalDelayType := UnitDelay; -- tah edge / thold_AVDNeg_WENeg :VitalDelayType := UnitDelay; -- tavhw edge \ thold_AVDNeg_CENeg :VitalDelayType := UnitDelay; -- tavhw edge \ thold_OENeg_WENeg_P_E_EQ_0_noedge_posedge :VitalDelayType:=UnitDelay; -- toeh edge / thold_OENeg_WENeg_P_E_EQ_1_noedge_posedge:VitalDelayType:=UnitDelay; -- toeh edge / thold_CENeg_WENeg :VitalDelayType := UnitDelay; -- tch edge / thold_WENeg_CENeg :VitalDelayType := UnitDelay; -- tch edge / thold_DQ0_WENeg :VitalDelayType := UnitDelay; -- tdh edge / thold_DQ0_CENeg :VitalDelayType := UnitDelay; -- tdh edge / --tpw values: pulse width tpw_RESETNeg_negedge :VitalDelayType := UnitDelay; -- trp tpw_AVDNeg_SYN_EQ_0_negedge :VitalDelayType := UnitDelay; -- tavdp tpw_AVDNeg_SYN_EQ_1_negedge :VitalDelayType := UnitDelay; -- tavd tpw_WENeg_negedge :VitalDelayType := UnitDelay; -- twp tpw_WENeg_posedge :VitalDelayType := UnitDelay; -- twph tpw_CENeg_negedge :VitalDelayType := UnitDelay; -- twp tpw_CENeg_posedge :VitalDelayType := UnitDelay; -- twph tpw_CLK_negedge :VitalDelayType := UnitDelay; -- tcl tpw_CLK_posedge :VitalDelayType := UnitDelay; -- tch --tperiod values tperiod_WENeg :VitalDelayType := UnitDelay; --twc tperiod_CENeg :VitalDelayType := UnitDelay; --twc tperiod_CLK :VitalDelayType := UnitDelay; --tclk --tdevice values: values for internal delays -- Program Operation tdevice_PWO :VitalDelayType := 40 us; --Write Buffer Program tdevice_WRBO :VitalDelayType := 9.4 us; -- Sector Erase Operation -- 64 Kword sector tdevice_SEO64 :VitalDelayType := 600 ms; -- 16 Kword sector tdevice_SEO16 :VitalDelayType := 350 ms; -- Initial access delay tdevice_IACC :VitalDelayType := 80 ns; -- PPB program timeout tdevice_PPBP :VitalDelayType := 150 us; -- PPB erase all timeout tdevice_PPBE :VitalDelayType := 15 ms; -- Password Unlock Timeout tdevice_PUT :VitalDelayType := 1 us; -- Program/Erase Suspend Timeout tdevice_START :VitalDelayType := 20 us; --Sector Erase Timeout tdevice_SET :VitalDelayType := 50 us; --Device ready after Hardware reset tdevice_READY :VitalDelayType := 30 us; --Timing Limit Exceeded tdevice_HANG :VitalDelayType := 4000 ms; --Resume to Suspend tdevice_RSTMOUT :VitalDelayType := 20 us; -- generic control parameters InstancePath :STRING := DefaultInstancePath; TimingChecksOn :BOOLEAN := DefaultTimingChecks; MsgOn :BOOLEAN := DefaultMsgOn; XOn :BOOLEAN := DefaultXOn; -- memory file to be loaded mem_file_name : STRING := "none";--"s29ws256p.mem"; secsi_file_name : STRING := "none";--"s29ws256p_secsi.mem"; prot_file_name : STRING := "none";--"s29ws256p_prot.mem"; UserPreload : BOOLEAN := FALSE; LongTiming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( A23 :IN std_ulogic := 'U'; -- A22 :IN std_ulogic := 'U'; -- A21 :IN std_ulogic := 'U'; -- A20 :IN std_ulogic := 'U'; --address A19 :IN std_ulogic := 'U'; --lines A18 :IN std_ulogic := 'U'; -- A17 :IN std_ulogic := 'U'; -- A16 :IN std_ulogic := 'U'; -- A15 :IN std_ulogic := 'U'; -- A14 :IN std_ulogic := 'U'; -- A13 :IN std_ulogic := 'U'; -- A12 :IN std_ulogic := 'U'; -- A11 :IN std_ulogic := 'U'; -- A10 :IN std_ulogic := 'U'; -- A9 :IN std_ulogic := 'U'; -- A8 :IN std_ulogic := 'U'; -- A7 :IN std_ulogic := 'U'; -- A6 :IN std_ulogic := 'U'; -- A5 :IN std_ulogic := 'U'; -- A4 :IN std_ulogic := 'U'; -- A3 :IN std_ulogic := 'U'; -- A2 :IN std_ulogic := 'U'; -- A1 :IN std_ulogic := 'U'; -- A0 :IN std_ulogic := 'U'; -- DQ15 : INOUT std_ulogic := 'U'; -- DQ14 : INOUT std_ulogic := 'U'; -- DQ13 : INOUT std_ulogic := 'U'; -- DQ12 : INOUT std_ulogic := 'U'; -- DQ11 : INOUT std_ulogic := 'U'; -- DQ10 : INOUT std_ulogic := 'U'; -- DQ9 : INOUT std_ulogic := 'U'; -- data DQ8 : INOUT std_ulogic := 'U'; -- lines DQ7 : INOUT std_ulogic := 'U'; -- DQ6 : INOUT std_ulogic := 'U'; -- DQ5 : INOUT std_ulogic := 'U'; -- DQ4 : INOUT std_ulogic := 'U'; -- DQ3 : INOUT std_ulogic := 'U'; -- DQ2 : INOUT std_ulogic := 'U'; -- DQ1 : INOUT std_ulogic := 'U'; -- DQ0 : INOUT std_ulogic := 'U'; -- CLK :IN std_ulogic := 'U'; -- RESETNeg :IN std_ulogic := 'U'; -- CENeg :IN std_ulogic := 'U'; -- OENeg :IN std_ulogic := 'U'; -- WENeg :IN std_ulogic := 'U'; -- AVDNeg :IN std_ulogic := 'U'; -- WPNeg :IN std_ulogic := 'U'; -- ACC :IN std_ulogic := 'U'; -- RDY :OUT std_ulogic := 'U' -- ); ATTRIBUTE VITAL_LEVEL0 of s29ws256p : ENTITY IS TRUE; END s29ws256p; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of s29ws256p IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID :STRING := "s29ws256p"; CONSTANT MaxData :NATURAL := 16#FFFF#; CONSTANT MemSize :NATURAL := 16#FFFFFF#; CONSTANT SecNum :NATURAL := 261; CONSTANT BankNum :NATURAL := 15; CONSTANT SecGroupNum :NATURAL := 2; CONSTANT SecSize64 :NATURAL := 16#FFFF#; CONSTANT SecSize16 :NATURAL := 16#3FFF#; CONSTANT BankSize :NATURAL := 16#FFFFF#; CONSTANT HiAddrBit :NATURAL := 23; CONSTANT PWLength :NATURAL := 3; CONSTANT WrBuffLength :NATURAL := 31; CONSTANT WrBuffPgNum :NATURAL := 16#7FFFF#; -- interconnect path delay signals SIGNAL A23_ipd :std_ulogic := 'U'; SIGNAL A22_ipd :std_ulogic := 'U'; SIGNAL A21_ipd :std_ulogic := 'U'; SIGNAL A20_ipd :std_ulogic := 'U'; SIGNAL A19_ipd :std_ulogic := 'U'; SIGNAL A18_ipd :std_ulogic := 'U'; SIGNAL A17_ipd :std_ulogic := 'U'; SIGNAL A16_ipd :std_ulogic := 'U'; SIGNAL A15_ipd :std_ulogic := 'U'; SIGNAL A14_ipd :std_ulogic := 'U'; SIGNAL A13_ipd :std_ulogic := 'U'; SIGNAL A12_ipd :std_ulogic := 'U'; SIGNAL A11_ipd :std_ulogic := 'U'; SIGNAL A10_ipd :std_ulogic := 'U'; SIGNAL A9_ipd :std_ulogic := 'U'; SIGNAL A8_ipd :std_ulogic := 'U'; SIGNAL A7_ipd :std_ulogic := 'U'; SIGNAL A6_ipd :std_ulogic := 'U'; SIGNAL A5_ipd :std_ulogic := 'U'; SIGNAL A4_ipd :std_ulogic := 'U'; SIGNAL A3_ipd :std_ulogic := 'U'; SIGNAL A2_ipd :std_ulogic := 'U'; SIGNAL A1_ipd :std_ulogic := 'U'; SIGNAL A0_ipd :std_ulogic := 'U'; SIGNAL DQ15_ipd :std_ulogic := 'U'; SIGNAL DQ14_ipd :std_ulogic := 'U'; SIGNAL DQ13_ipd :std_ulogic := 'U'; SIGNAL DQ12_ipd :std_ulogic := 'U'; SIGNAL DQ11_ipd :std_ulogic := 'U'; SIGNAL DQ10_ipd :std_ulogic := 'U'; SIGNAL DQ9_ipd :std_ulogic := 'U'; SIGNAL DQ8_ipd :std_ulogic := 'U'; SIGNAL DQ7_ipd :std_ulogic := 'U'; SIGNAL DQ6_ipd :std_ulogic := 'U'; SIGNAL DQ5_ipd :std_ulogic := 'U'; SIGNAL DQ4_ipd :std_ulogic := 'U'; SIGNAL DQ3_ipd :std_ulogic := 'U'; SIGNAL DQ2_ipd :std_ulogic := 'U'; SIGNAL DQ1_ipd :std_ulogic := 'U'; SIGNAL DQ0_ipd :std_ulogic := 'U'; SIGNAL CLK_ipd :std_ulogic := 'U'; SIGNAL RESETNeg_ipd :std_ulogic := 'U'; SIGNAL CENeg_ipd :std_ulogic := 'U'; SIGNAL OENeg_ipd :std_ulogic := 'U'; SIGNAL WENeg_ipd :std_ulogic := 'U'; SIGNAL AVDNeg_ipd :std_ulogic := 'U'; SIGNAL WPNeg_ipd :std_ulogic := 'U'; SIGNAL ACC_ipd :std_ulogic := 'U'; -- internal delays SIGNAL IACC_in :std_ulogic := '0';-- Initial access delay SIGNAL IACC_out :std_ulogic := '0';-- SIGNAL PPBP_in :std_ulogic := '0';-- PPB Program Timeout SIGNAL PPBP_out :std_ulogic := '0';-- SIGNAL PPBE_in :std_ulogic := '0';-- PPB Erase All Timeout SIGNAL PPBE_out :std_ulogic := '0';-- SIGNAL PUT_in :std_ulogic := '0';-- Password Unlock Timeout SIGNAL PUT_out :std_ulogic := '0';-- SIGNAL START_in :std_ulogic := '0';-- Program/Erase Suspend SIGNAL START_out :std_ulogic := '0';-- Timeout SIGNAL SET_in :std_ulogic := '0';-- Sector Erase Timeout SIGNAL SET_out :std_ulogic := '0';-- SIGNAL READY_in :std_ulogic := '0';-- Device Ready after Hardware SIGNAL READY_out :std_ulogic := '0';-- Reset SIGNAL HANG_in :std_ulogic := '0';-- Operation Timing Limit SIGNAL HANG_out :std_ulogic := '0';-- SIGNAL RSTMOUT_in :std_ulogic := '1';-- Resume to Suspend Timeout SIGNAL RSTMOUT_out :std_ulogic := '1';-- -- Annotate SIGNAL P1_in : std_ulogic := '0'; SIGNAL P1_out : std_ulogic := '0'; SIGNAL P2_in : std_ulogic := '0'; SIGNAL P2_out : std_ulogic := '0'; SIGNAL P3_in : std_ulogic := '0'; SIGNAL P3_out : std_ulogic := '0'; SIGNAL P4_in : std_ulogic := '0'; SIGNAL P4_out : std_ulogic := '0'; SIGNAL P5_in : std_ulogic := '0'; SIGNAL P5_out : std_ulogic := '0'; SIGNAL P6_in : std_ulogic := '0'; SIGNAL P6_out : std_ulogic := '0'; SIGNAL P7_in : std_ulogic := '0'; SIGNAL P7_out : std_ulogic := '0'; SIGNAL P8_in : std_ulogic := '0'; SIGNAL P8_out : std_ulogic := '0'; SIGNAL P9_in : std_ulogic := '0'; SIGNAL P9_out : std_ulogic := '0'; SIGNAL START_int :std_ulogic := '0';-- Program/Erase Suspend SIGNAL START_outt :std_ulogic := '0';-- Timeout SIGNAL SET_int :std_ulogic := '0';-- Sector Erase Timeout SIGNAL SET_outt :std_ulogic := '0';-- SIGNAL READY_int :std_ulogic := '0';-- Device Ready after Hardware SIGNAL READY_outt :std_ulogic := '0';-- Reset SIGNAL RSTMOUT_int :std_ulogic := '1'; SIGNAL RSTMOUT_outt :std_ulogic := '1'; SIGNAL P1_int : std_ulogic := '0'; SIGNAL P1_outt : std_ulogic := '0'; SIGNAL P2_int : std_ulogic := '0'; SIGNAL P2_outt : std_ulogic := '0'; SIGNAL P3_int : std_ulogic := '0'; SIGNAL P3_outt : std_ulogic := '0'; SIGNAL P4_int : std_ulogic := '0'; SIGNAL P4_outt : std_ulogic := '0'; SIGNAL P7_int : std_ulogic := '0'; SIGNAL P7_outt : std_ulogic := '0'; SIGNAL P8_int : std_ulogic := '0'; SIGNAL P8_outt : std_ulogic := '0'; BEGIN ---------------------------------------------------------------------------- -- INTERNAL DELAYS ---------------------------------------------------------------------------- -- VITAL primitives which incorporate internal delays START:VitalBUF(START_outt,START_int,tpd_a_q=>(tdevice_START,UnitDelay)); READY:VitalBUF(READY_outt,READY_int,tpd_a_q=>(tdevice_READY,UnitDelay)); SET: VitalBUF(SET_outt ,SET_int ,tpd_a_q=>(tdevice_SET-1 ns,UnitDelay)); HANG: VitalBUF(HANG_out ,HANG_in ,tpd_a_q=>(tdevice_HANG,UnitDelay)); RSTMOUT: VitalBUF(RSTMOUT_outt, RSTMOUT_int, tpd_a_q=>(tdevice_RSTMOUT, UnitDelay) ); ------------------------------------------------------------------------- -- Annotate ------------------------------------------------------------------------- PWO :VitalBUF(P1_outt, P1_int,tpd_a_q=>(tdevice_PWO,UnitDelay)); WRBO :VitalBUF(P2_outt, P2_int,tpd_a_q=>(tdevice_WRBO,UnitDelay)); SEO16 :VitalBUF(P3_outt, P3_int,tpd_a_q=>(tdevice_SEO16,UnitDelay)); SEO64 :VitalBUF(P4_outt, P4_int,tpd_a_q=>(tdevice_SEO64,UnitDelay)); IACC :VitalBuf(P5_out , P5_in ,tpd_a_q=>(tdevice_IACC,UnitDelay)); PPBP :VitalBuf(P7_outt, P7_int,tpd_a_q=>(tdevice_PPBP,UnitDelay)); PPBE :VitalBuf(P8_outt, P8_int,tpd_a_q=>(tdevice_PPBE,UnitDelay)); PUT :VitalBuf(P9_out , P9_in ,tpd_a_q=>(tdevice_PUT,UnitDelay)); ---------------------------------------------------------------------------- -- WIRE DELAYS ---------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_0 : VitalWireDelay( A23_ipd,A23,tipd_A23 ); w_1 : VitalWireDelay( A22_ipd,A22,tipd_A22 ); w_2 : VitalWireDelay( A21_ipd,A21,tipd_A21 ); w_3 : VitalWireDelay( A20_ipd,A20,tipd_A20 ); w_4 : VitalWireDelay( A19_ipd,A19,tipd_A19 ); w_5 : VitalWireDelay( A18_ipd,A18,tipd_A18 ); w_6 : VitalWireDelay( A17_ipd,A17,tipd_A17 ); w_7 : VitalWireDelay( A16_ipd,A16,tipd_A16 ); w_8 : VitalWireDelay( A15_ipd,A15,tipd_A15 ); w_9 : VitalWireDelay( A14_ipd,A14,tipd_A14 ); w_10: VitalWireDelay( A13_ipd,A13,tipd_A13 ); w_11: VitalWireDelay( A12_ipd,A12,tipd_A12 ); w_12: VitalWireDelay( A11_ipd,A11,tipd_A11 ); w_13: VitalWireDelay( A10_ipd,A10,tipd_A10 ); w_14: VitalWireDelay( A9_ipd,A9,tipd_A9 ); w_15: VitalWireDelay( A8_ipd,A8,tipd_A8 ); w_16: VitalWireDelay( A7_ipd,A7,tipd_A7 ); w_17: VitalWireDelay( A6_ipd,A6,tipd_A6 ); w_18: VitalWireDelay( A5_ipd,A5,tipd_A5 ); w_19: VitalWireDelay( A4_ipd,A4,tipd_A4 ); w_20: VitalWireDelay( A3_ipd,A3,tipd_A3 ); w_21: VitalWireDelay( A2_ipd,A2,tipd_A2 ); w_22: VitalWireDelay( A1_ipd,A1,tipd_A1 ); w_23: VitalWireDelay( A0_ipd,A0,tipd_A0 ); w_24: VitalWireDelay( DQ15_ipd,DQ15,tipd_DQ15 ); w_25: VitalWireDelay( DQ14_ipd,DQ14,tipd_DQ14 ); w_26: VitalWireDelay( DQ13_ipd,DQ13,tipd_DQ13 ); w_27: VitalWireDelay( DQ12_ipd,DQ12,tipd_DQ12 ); w_28: VitalWireDelay( DQ11_ipd,DQ11,tipd_DQ11 ); w_29: VitalWireDelay( DQ10_ipd,DQ10,tipd_DQ10 ); w_30: VitalWireDelay( DQ9_ipd,DQ9,tipd_DQ9 ); w_31: VitalWireDelay( DQ8_ipd,DQ8,tipd_DQ8 ); w_32: VitalWireDelay( DQ7_ipd,DQ7,tipd_DQ7 ); w_33: VitalWireDelay( DQ6_ipd,DQ6,tipd_DQ6 ); w_34: VitalWireDelay( DQ5_ipd,DQ5,tipd_DQ5 ); w_35: VitalWireDelay( DQ4_ipd,DQ4,tipd_DQ4 ); w_36: VitalWireDelay( DQ3_ipd,DQ3,tipd_DQ3 ); w_37: VitalWireDelay( DQ2_ipd,DQ2,tipd_DQ2 ); w_38: VitalWireDelay( DQ1_ipd,DQ1,tipd_DQ1 ); w_39: VitalWireDelay( DQ0_ipd,DQ0,tipd_DQ0 ); w_40: VitalWireDelay( CLK_ipd,CLK,tipd_CLK ); w_41: VitalWireDelay( RESETNeg_ipd,RESETNeg,tipd_RESETNeg ); w_42: VitalWireDelay( CENeg_ipd,CENeg,tipd_CENeg ); w_43: VitalWireDelay( OENeg_ipd,OENeg,tipd_OENeg ); w_44: VitalWireDelay( WENeg_ipd,WENeg,tipd_WENeg ); w_45: VitalWireDelay( AVDNeg_ipd,AVDNeg,tipd_AVDNeg ); w_46: VitalWireDelay( WPNeg_ipd,WPNeg,tipd_WPNeg ); w_47: VitalWireDelay( ACC_ipd,ACC,tipd_ACC ); END BLOCK WireDelay; ---------------------------------------------------------------------------- -- Main Behavior Block ---------------------------------------------------------------------------- Behavior : BLOCK PORT ( A :IN std_logic_vector (HiAddrBit downto 0) := (others => 'U'); DIn :IN std_logic_vector ( 15 downto 0 ) := (others => 'U'); DOut :OUT std_ulogic_vector( 15 downto 0 ) := (others => 'Z'); CLK :IN std_ulogic := 'U'; -- RESETNeg :IN std_ulogic := 'U'; -- CENeg :IN std_ulogic := 'U'; -- OENeg :IN std_ulogic := 'U'; -- WENeg :IN std_ulogic := 'U'; -- AVDNeg :IN std_ulogic := 'U'; -- WPNeg :IN std_ulogic := 'U'; -- ACC :IN std_ulogic := 'U'; -- RDY :OUT std_ulogic := 'U' -- ); PORT MAP ( A(23) => A23_ipd, A(22) => A22_ipd, A(21) => A21_ipd, A(20) => A20_ipd, A(19) => A19_ipd, A(18) => A18_ipd, A(17) => A17_ipd, A(16) => A16_ipd, A(15) => A15_ipd, A(14) => A14_ipd, A(13) => A13_ipd, A(12) => A12_ipd, A(11) => A11_ipd, A(10) => A10_ipd, A(9) => A9_ipd, A(8) => A8_ipd, A(7) => A7_ipd, A(6) => A6_ipd, A(5) => A5_ipd, A(4) => A4_ipd, A(3) => A3_ipd, A(2) => A2_ipd, A(1) => A1_ipd, A(0) => A0_ipd, DIn(15) => DQ15_ipd, DIn(14) => DQ14_ipd, DIn(13) => DQ13_ipd, DIn(12) => DQ12_ipd, DIn(11) => DQ11_ipd, DIn(10) => DQ10_ipd, DIn(9) => DQ9_ipd, DIn(8) => DQ8_ipd, DIn(7) => DQ7_ipd, DIn(6) => DQ6_ipd, DIn(5) => DQ5_ipd, DIn(4) => DQ4_ipd, DIn(3) => DQ3_ipd, DIn(2) => DQ2_ipd, DIn(1) => DQ1_ipd, DIn(0) => DQ0_ipd, DOut(15) => DQ15, DOut(14) => DQ14, DOut(13) => DQ13, DOut(12) => DQ12, DOut(11) => DQ11, DOut(10) => DQ10, DOut(9) => DQ9, DOut(8) => DQ8, DOut(7) => DQ7, DOut(6) => DQ6, DOut(5) => DQ5, DOut(4) => DQ4, DOut(3) => DQ3, DOut(2) => DQ2, DOut(1) => DQ1, DOut(0) => DQ0, CLK => CLK_ipd, RESETNeg => RESETNeg_ipd, CENeg => CENeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, AVDNeg => AVDNeg_ipd, WPNeg => WPNeg_ipd, ACC => ACC_ipd, RDY => RDY ); -- State Machine : State_Type TYPE state_type IS ( RESET, Z001, CFI, PREL_SETBWB, PREL_ULBYPASS, PREL_ULBYPASS_RESET, A0SEEN, C8, C8_Z001, C8_PREL, ERS, SERS, ESPS, SERS_EXEC, ESP, ESP_Z001, ESP_PREL, PREL_WR2BUFF, WR2BUFF_0, WR2BUFF_CNT, PREL_PRFLASH, PGMS, PGSPS, PGS, PGS_Z001, PGS_PREL, WR2BUFF_AB, WR2BUFF_AB_Z001, WR2BUFF_AB_PREL, AS, SECSI_EX, SET_CONF, SET_CONF1, SET_CONF_EXIT, RD_CONF, PREL_PASS, PASS_A0SEEN, PASS_EX, PASS_UN_Z001, PASS_UN_PREL, PASS_UN1, PASS_UN2, PASS_UN3, PASS_UN4, PASS_UN_W, PREL_LR, LR_A0SEEN, LR_PREL_EX, PREL_PPB, PPB_PREL_PR, PPB_PGMS, PPB_PREL_ER, PPB_ERS, PPB_PREL_EX, PREL_PPBLCK, PPBLCK_PREL_ST, PPBLCK_PREL_EX, PREL_DYB, DYB_PREL_ST, DYB_PREL_EX, HW_RESET_UNKNOWN, HW_RESET_INIT ); TYPE RD_MODE_type IS( SYNCR, NOSYNC, LINEAR, LINEAR_NO_WRAP, CONTINUOUS ); --Flash Memory Array TYPE SecGroupAddr IS ARRAY (0 TO SecGroupNum) OF NATURAL; TYPE MemArr IS ARRAY (0 TO MemSize) OF INTEGER RANGE -1 TO MaxData; --SecSi Memory Array TYPE SecSiArr IS ARRAY (0 TO 16#FF# ) OF INTEGER RANGE -1 TO MaxData; --CFI Array TYPE CFIArr IS ARRAY (16#10# TO 16#67#) OF INTEGER RANGE -1 TO MaxData; --Password Array TYPE PWArr IS ARRAY (0 TO PWLength) OF INTEGER RANGE -1 TO MaxData; --Write Buffer Array TYPE WrBuffDataArr IS ARRAY (0 TO WrBuffLength) OF INTEGER RANGE -1 TO MaxData; TYPE WrBuffAddrArr IS ARRAY (0 TO WrBuffLength) OF INTEGER RANGE -1 TO MemSize; TYPE WrBuffAddrArrTemp IS ARRAY (0 TO WrBuffLength + 1) OF INTEGER RANGE -1 TO MemSize; -- states SIGNAL current_state : state_type; SIGNAL next_state : state_type; SIGNAL CFIExit : state_type; SIGNAL RD_MODE : RD_MODE_type; -- powerup SIGNAL PoweredUp : std_logic := '0'; SHARED VARIABLE SYN : std_logic := '0'; --Synchronous mode SIGNAL SYNC_DIS : std_logic := '0'; --FSM control signals SIGNAL ULBYPASS : std_logic := '0'; --Unlock Bypass Active SIGNAL ESP_ACT : std_logic := '0'; --Erase Suspend Active SIGNAL PSP_ACT : std_logic := '0'; --Program Suspend Active SIGNAL PASS_ACT : std_logic := '0'; SIGNAL LOCK_ACT : std_logic := '0'; SIGNAL WRBUFF_ACT : std_logic := '0'; SIGNAL SecSi : std_logic := '0'; --SecSi Sector mapped in Sec 0 SIGNAL PDONE : std_logic := '1'; --Programming Done SIGNAL PSTART : std_logic := '0'; --Start Programming SIGNAL PSUSP : std_logic := '0'; --Suspend Programming SIGNAL PRES : std_logic := '0'; --Resume Programming --All sectors selected for programming are protected SIGNAL PERR : std_logic := '0'; SIGNAL EDONE : std_logic := '1'; --Erase Done SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL ESUSP : std_logic := '0'; --Suspend Erase SIGNAL ERES : std_logic := '0'; --Resume Erase --All sectors selected for erasure are protected SIGNAL EERR : std_logic := '0'; --Sectors selected for erasure SIGNAL ERS_QUEUE : std_logic_vector(SecNum downto 0) := (OTHERS => '0'); --Banks selected for erasure SIGNAL ERS_QUEUE_B : std_logic_vector(BankNum downto 0) := (OTHERS => '0'); --Active program/erase operation SIGNAL P_E : std_logic := '1'; SIGNAL WRITE : std_logic := '1'; SIGNAL READ : std_logic := '1'; SIGNAL BURST : std_logic := '1'; SIGNAL ReadINIT : std_logic := '1'; SIGNAL DOut_zd : std_logic_vector(15 downto 0) := (OTHERS=>'Z'); SIGNAL DOut_Pass : std_logic_vector(15 downto 0) := (OTHERS=>'Z'); SIGNAL RDY_zd : std_logic := 'Z'; SHARED VARIABLE OutputD : std_logic_vector(15 downto 0); -- Access time variables SHARED VARIABLE FROMCE : BOOLEAN:=FALSE; SHARED VARIABLE FROMOE : BOOLEAN:=FALSE; SHARED VARIABLE FROMADDR : BOOLEAN:=FALSE; --Address SIGNAL Addr : INTEGER RANGE -1 TO MemSize := -1; SIGNAL AddrPass : INTEGER RANGE 0 TO 3; --Sector Address SIGNAL SecAddr : INTEGER RANGE -1 TO SecNum := -1; --Bank Address SIGNAL BankID : INTEGER RANGE -1 TO BankNum := -1; -- Write page buffer address SIGNAL BuffPageAddr : INTEGER RANGE -1 TO WrBuffPgNum; SHARED VARIABLE sgsa : SecGroupAddr := (16#000000#,16#010000#,16#FF0000#); --Data SIGNAL D_tmp : INTEGER RANGE -1 TO MaxData; SIGNAL BankASAddr : INTEGER RANGE -1 TO BankNum; SIGNAL BankCFIAddr : INTEGER RANGE -1 TO BankNum; SIGNAL PrgBank : INTEGER RANGE -1 TO BankNum; SIGNAL BankDYBAddr : INTEGER RANGE -1 TO BankNum; SIGNAL BankPPBAddr : INTEGER RANGE -1 TO BankNum; SIGNAL SecPPBAddr : INTEGER RANGE -1 TO SecNum; SHARED VARIABLE CurrentReadPage : NATURAL; SHARED VARIABLE PreviousReadPage : INTEGER; SHARED VARIABLE InitialPageAccess : BOOLEAN; SHARED VARIABLE SubsequentPageAccess: BOOLEAN; SIGNAL HANG : std_logic := '0'; --glitch protection SIGNAL gWE_n : std_logic := '1'; SIGNAL gCE_n : std_logic := '1'; SIGNAL gOE_n : std_logic := '1'; SIGNAL gAVD_n : std_logic := '1'; SIGNAL tAVD_p : std_logic := '0'; SIGNAL AddrREF : std_logic := '0'; SIGNAL CLKMerge : std_logic := '0'; SIGNAL WP_l : std_logic; SHARED VARIABLE IN_W_ELAPSED: BOOLEAN; SHARED VARIABLE DATA_DELAY : BOOLEAN; --reset timing SIGNAL RST : std_logic := '0'; SIGNAL reseted : std_logic := '0'; -- Mem(Address) SHARED VARIABLE Mem : MemArr := (OTHERS => MaxData); -- SecSi Sector SHARED VARIABLE SecSiMem: SecSiArr := (OTHERS => MaxData); -- CFI Sector SHARED VARIABLE CFIMem : CFIArr; -- PPB(Sec) SHARED VARIABLE PPB : std_logic_vector(SecNum downto 0) := (OTHERS => '1'); -- DYB(Sec) SHARED VARIABLE DYB : std_logic_vector(SecNum downto 0) := (OTHERS => '1'); SHARED VARIABLE Password: PWArr := ( OTHERS => MaxData); SHARED VARIABLE ConfReg0 : std_logic_vector(15 downto 0) := "1110111111001000"; SHARED VARIABLE ConfReg1 : std_logic_vector(15 downto 0) := "1111111111101111"; SHARED VARIABLE LOCK_REG : std_logic_vector(15 downto 0) := "1111111111111111"; SHARED VARIABLE PPB_LOCK : std_logic := '1'; -- Write Buffer Signals SIGNAL WrBuffData : WrBuffDataArr := ( OTHERS => -1); SIGNAL WrBuffAddr : WrBuffAddrArr := ( OTHERS => -1); SIGNAL PrevBuffAd : INTEGER RANGE -1 TO MemSize; SIGNAL WrBuffSec : INTEGER RANGE -1 TO SecNum := -1; SIGNAL WrBuffPage : NATURAL RANGE 0 TO WrBuffPgNum; SIGNAL WrBuffCnt : NATURAL RANGE 0 TO WrBuffLength; SIGNAL WrCnt : NATURAL RANGE 0 TO WrBuffLength; SIGNAL RDY_temp : std_logic; SIGNAL PASS_UNLCK : boolean := FALSE; SIGNAL PASS_TEMP : PWArr; SIGNAL Boot_Sec : std_logic_vector(SecNum downto 0) := (OTHERS => '1'); -- 1 for boot sec -- HW RESET# shorter than tRP detection SIGNAL HWResetGlitch : std_ulogic := '0'; SIGNAL HWResetStart : std_ulogic := '0'; SHARED VARIABLE BurstDelay : NATURAL; SHARED VARIABLE WS_Initial : NATURAL ; SHARED VARIABLE ResumeFlag : boolean; SHARED VARIABLE Check_freq : boolean; -- timing check violation SIGNAL Viol : X01 := '0'; FUNCTION ReturnSectorID(ADDR : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; VARIABLE conv : NATURAL; BEGIN conv := ADDR / 16#10000#; IF ( conv = 0 ) THEN result := ADDR / 16#4000#; ELSIF ( conv >= 1 ) AND ( conv <= 254 ) THEN result := 3 + conv; ELSE result := 258 + (ADDR - 16#FF0000#)/16#4000#; END IF; RETURN result; END ReturnSectorID; FUNCTION ReturnBuffPage(ADDR : NATURAL) RETURN NATURAL IS VARIABLE result : NATURAL; BEGIN result := ADDR / 16#20#; RETURN result; END ReturnBuffPage; FUNCTION ReturnBank(ADDR : NATURAL) RETURN NATURAL IS VARIABLE BankResult : NATURAL; BEGIN BankResult := ADDR/16#100000#; RETURN BankResult; END ReturnBank; BEGIN ---------------------------------------------------------------------------- --Power Up time 30 us ---------------------------------------------------------------------------- PoweredUp <= '1' AFTER 30 us; RSTtiming: PROCESS(RESETNeg) BEGIN IF falling_edge(RESETNeg) THEN IF LongTiming = TRUE THEN RST <= '0' AFTER tdevice_READY; ELSE RST <= '0' AFTER tdevice_READY/10; END IF; ELSIF rising_edge(RESETNeg) THEN RST <= '1'; END IF; END PROCESS; -- This process may be timing model specific Set_Lock : PROCESS(PoweredUp) BEGIN LOCK_REG (15 DOWNTO 5) := (OTHERS => '1'); LOCK_REG(4) := '1'; LOCK_REG(3) := '1'; LOCK_REG(2 DOWNTO 0) := "111"; PPB_LOCK := '1'; PreviousReadPage := -1; END PROCESS Set_Lock; -- This process may be timing model specific Set_Boot: PROCESS(PoweredUp) BEGIN IF PoweredUp = '1' THEN Boot_Sec <= (OTHERS => '0'); Boot_Sec(3 DOWNTO 0) <=(OTHERS =>'1'); Boot_Sec(SecNum DOWNTO SecNum - 3 ) <=(OTHERS =>'1'); END IF; END PROCESS Set_Boot; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A, Din, CENeg, OENeg, WENeg, RESETNeg, CLK, AVDNeg) -- Timing Check Variables VARIABLE Tviol_CENeg_CLK : X01 := '0'; VARIABLE TD_CENeg_CLK : VitalTimingDataType; VARIABLE Tviol_A_CLK : X01 := '0'; VARIABLE TD_A_CLK : VitalTimingDataType; VARIABLE Tviol_AVDNeg_CLK : X01 := '0'; VARIABLE TD_AVDNeg_CLK : VitalTimingDataType; VARIABLE Tviol_A_AVDNeg : X01 := '0'; VARIABLE TD_A_AVDNeg : VitalTimingDataType; VARIABLE Tviol_A0_WENeg_1 : X01 := '0'; VARIABLE TD_A0_WENeg_1 : VitalTimingDataType; VARIABLE Tviol_A0_WENeg_2 : X01 := '0'; VARIABLE TD_A0_WENeg_2 : VitalTimingDataType; VARIABLE Tviol_A0_CENeg_1 : X01 := '0'; VARIABLE TD_A0_CENeg_1 : VitalTimingDataType; VARIABLE Tviol_A0_CENeg_2 : X01 := '0'; VARIABLE TD_A0_CENeg_2 : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg_T : X01 := '0'; VARIABLE TD_OENeg_WENeg_T : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg_R : X01 := '0'; VARIABLE TD_OENeg_WENeg_R : VitalTimingDataType; VARIABLE Tviol_AVDNeg_WENeg : X01 := '0'; VARIABLE TD_AVDNeg_WENeg : VitalTimingDataType; VARIABLE Tviol_AVDNeg_CENeg : X01 := '0'; VARIABLE TD_AVDNeg_CENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_AVDNeg : X01 := '0'; VARIABLE TD_CENeg_AVDNeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_F : X01 := '0'; VARIABLE TD_CENeg_WENeg_F : VitalTimingDataType; VARIABLE Tviol_CENeg_AVDNeg_A : X01 := '0'; VARIABLE TD_CENeg_AVDNeg_A : VitalTimingDataType; VARIABLE Tviol_WENeg_CENeg_F : X01 := '0'; VARIABLE TD_WENeg_CENeg_F : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_R : X01 := '0'; VARIABLE TD_CENeg_WENeg_R : VitalTimingDataType; VARIABLE Tviol_WENeg_CENeg_R : X01 := '0'; VARIABLE TD_WENeg_CENeg_R : VitalTimingDataType; VARIABLE Tviol_OENeg_RESETNeg : X01 := '0'; VARIABLE TD_OENeg_RESETNeg : VitalTimingDataType; VARIABLE Tviol_CENeg_RESETNeg : X01 := '0'; VARIABLE TD_CENeg_RESETNeg : VitalTimingDataType; VARIABLE Pviol_AVDNeg_AS : X01 := '0'; VARIABLE PD_AVDNeg_AS : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_AVDNeg_S : X01 := '0'; VARIABLE PD_AVDNeg_S : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE PViol_CLK : X01 := '0'; VARIABLE PD_CLK : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup Check between CENeg and CLK active edge -- tces VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_CENeg_CLK, CheckEnabled => ConfReg0(15) = '0' AND AVDNeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLK, Violation => Tviol_CENeg_CLK ); -- Setup/Hold Check between A and CLK active edge -- tas,tah VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_A0_CLK, SetupHigh => tsetup_A0_CLK, HoldHigh => thold_A0_CLK, HoldLow => thold_A0_CLK, CheckEnabled => ConfReg0(15) = '0' AND AVDNeg = '0' AND CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A_CLK, Violation => Tviol_A_CLK ); --- AVD# setup/hold time to CLK -- tAVC,tAVHC VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => CLK, RefSignalName => "CLK", SetupLow => tsetup_AVDNeg_CLK, HoldLow => thold_AVDNeg_CLK, CheckEnabled => ConfReg0(15) = '0' AND CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_CLK, Violation => Tviol_AVDNeg_CLK ); -- Setup/Hold Check between A and AVDNeg -- tas,tah VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => AVDNeg, RefSignalName => "AVD#", SetupLow => tsetup_A0_AVDNeg, SetupHigh => tsetup_A0_AVDNeg, HoldHigh => thold_A0_AVDNeg, HoldLow => thold_A0_AVDNeg, CheckEnabled => CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A_AVDNeg, Violation => Tviol_A_AVDNeg ); -- Setup/Hold Check between A and WENeg falling edge -- tAS,tAH VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_A0_WENeg_SYN_EQ_0_noedge_posedge, SetupLow => tsetup_A0_WENeg_SYN_EQ_0_noedge_posedge, HoldHigh => thold_A0_WENeg_SYN_EQ_0_noedge_posedge, HoldLow => thold_A0_WENeg_SYN_EQ_0_noedge_posedge, CheckEnabled => CENeg = '0' AND OENeg = '1' AND AVDNeg = '0' AND ConfReg0(15)= '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg_1, Violation => Tviol_A0_WENeg_1 ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_A0_WENeg_SYN_EQ_1_noedge_posedge, SetupLow => tsetup_A0_WENeg_SYN_EQ_1_noedge_posedge, HoldHigh => thold_A0_WENeg_SYN_EQ_1_noedge_posedge, HoldLow => thold_A0_WENeg_SYN_EQ_1_noedge_posedge, CheckEnabled => CENeg = '0' AND OENeg = '1' AND AVDNeg = '0' AND ConfReg0(15)= '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg_2, Violation => Tviol_A0_WENeg_2 ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_A0_CENeg_SYN_EQ_0_noedge_posedge, SetupLow => tsetup_A0_CENeg_SYN_EQ_0_noedge_posedge, HoldHigh => thold_A0_CENeg_SYN_EQ_0_noedge_posedge, HoldLow => thold_A0_CENeg_SYN_EQ_0_noedge_posedge, CheckEnabled => WENeg = '0' AND OENeg = '1' AND AVDNeg = '0' AND ConfReg0(15)= '1', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CENeg_1, Violation => Tviol_A0_CENeg_1 ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_A0_CENeg_SYN_EQ_1_noedge_posedge, SetupLow => tsetup_A0_CENeg_SYN_EQ_1_noedge_posedge, HoldHigh => thold_A0_CENeg_SYN_EQ_1_noedge_posedge, HoldLow => thold_A0_CENeg_SYN_EQ_1_noedge_posedge, CheckEnabled => WENeg = '0' AND OENeg = '1' AND AVDNeg = '0' AND ConfReg0(15)= '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CENeg_2, Violation => Tviol_A0_CENeg_2 ); -- Setup/Hold Check between DATA and WENeg/CEneg rising edge -- tDS, tDH VitalSetupHoldCheck ( TestSignal => DIn, TestSignalName => "DIn", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_WENeg, HoldLow => thold_DQ0_WENeg, CheckEnabled => CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_WENeg, Violation => Tviol_DQ0_WENeg ); VitalSetupHoldCheck ( TestSignal => DIn, TestSignalName => "DIn", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_DQ0_CENeg, SetupLow => tsetup_DQ0_CENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => WENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_DQ0_CENeg, Violation => Tviol_DQ0_CENeg ); -- AVD# setup/hold LOW time around WE# falling edge -- tAVSW, tAVHW VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_AVDNeg_WENeg, HoldLow => thold_AVDNeg_WENeg, CheckEnabled => CENeg='0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_WENeg, Violation => Tviol_AVDNeg_WENeg ); VitalSetupHoldCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", RefSignal => CENeg, RefSignalName => "CENeg", SetupLow => tsetup_AVDNeg_CENeg, HoldLow => thold_AVDNeg_CENeg, CheckEnabled => WENeg='0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_AVDNeg_CENeg, Violation => Tviol_AVDNeg_CENeg ); -- CENeg setup LOW time around AVD# falling edge -- tCAS VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupLow => tsetup_CENeg_AVDNeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_AVDNeg, Violation => Tviol_CENeg_AVDNeg ); -- CENeg setup LOW time to WENeg -- tCS VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_F, Violation => Tviol_CENeg_WENeg_F ); -- CENeg setup LOW time around AVD# rising edge -- tAVDP VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => AVDNeg, RefSignalName => "AVDNeg", SetupLow => tpw_AVDNeg_SYN_EQ_0_negedge, CheckEnabled => SYN = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_AVDNeg_A, Violation => Tviol_CENeg_AVDNeg_A ); -- WENeg setup LOW time to CENeg -- tCS VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CENeg, RefSignalName => "CENeg", SetupLow => tsetup_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_F, Violation => Tviol_WENeg_CENeg_F ); -- Hold Check between OENeg and WENeg -- tOEH VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_OENeg_WENeg_P_E_EQ_0_noedge_posedge , CheckEnabled => P_E = '0', -- toggle RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg_R, Violation => TViol_OENeg_WENeg_R ); -- Hold Check between OENeg and WENeg -- tOEH VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OE#", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_OENeg_WENeg_P_E_EQ_1_noedge_posedge , CheckEnabled => P_E = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg_T, Violation => TViol_OENeg_WENeg_T ); -- OE# hold HIGH time after RESET rising edge -- tRH VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_OENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_RESETNeg, Violation => Tviol_OENeg_RESETNeg ); -- CE# hold HIGH time after RESET rising edge -- tRH VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => RESETNeg, RefSignalName => "RESETNeg", HoldHigh => thold_CENeg_RESETNeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RESETNeg, Violation => Tviol_CENeg_RESETNeg ); -- CENeg hold LOW time from WENeg -- tCS VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_R, Violation => Tviol_CENeg_WENeg_R ); -- WENeg hold LOW time from CENeg -- tCS VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CENeg, RefSignalName => "CENeg", SetupLow => thold_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_R, Violation => Tviol_WENeg_CENeg_R ); -- PulseWidth Check for AVDNeg VitalPeriodPulseCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", PulseWidthLow => tpw_AVDNeg_SYN_EQ_0_negedge, CheckEnabled => SYN = '0', HeaderMsg => InstancePath & PartID, PeriodData => PD_AVDNeg_AS, Violation => Pviol_AVDNeg_AS ); -- PulseWidth Check for AVDNeg VitalPeriodPulseCheck ( TestSignal => AVDNeg, TestSignalName => "AVDNeg", PulseWidthLow => tpw_AVDNeg_SYN_EQ_1_negedge, CheckEnabled => SYN = '1', HeaderMsg => InstancePath & PartID, PeriodData => PD_AVDNeg_S, Violation => Pviol_AVDNeg_S ); -- PulseWidth Check for RESETNeg VitalPeriodPulseCheck ( TestSignal => RESETNeg, TestSignalName => "RESETNeg", PulseWidthLow => tpw_RESETNeg_negedge, CheckEnabled => LongTiming, HeaderMsg => InstancePath & PartID, PeriodData => PD_RESETNeg, Violation => Pviol_RESETNeg ); -- PulseWidth, Period Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WENeg", PulseWidthLow => tpw_WENeg_negedge, PulseWidthHigh => tpw_WENeg_posedge, Period => tperiod_WENeg, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); -- PulseWidth, Period Check for CENeg VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CENeg", PulseWidthLow => tpw_CENeg_negedge, PulseWidthHigh => tpw_CENeg_posedge, Period => tperiod_CENeg, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CENeg, Violation => Pviol_CENeg ); -- Period Check for CLK VitalPeriodPulseCheck ( TestSignal => CLK, TestSignalName => "CLK", PulseWidthLow => tpw_CLK_negedge, PulseWidthHigh => tpw_CLK_posedge, Period => tperiod_CLK, CheckEnabled => ConfReg0(15) = '0', HeaderMsg => InstancePath & PartID, PeriodData => PD_CLK, Violation => PViol_CLK ); Violation := Tviol_CENeg_CLK OR Tviol_A_CLK OR Tviol_AVDNeg_CLK OR Tviol_A_AVDNeg OR Tviol_A0_WENeg_1 OR Tviol_A0_WENeg_2 OR Tviol_A0_CENeg_1 OR Tviol_A0_CENeg_2 OR Tviol_DQ0_WENeg OR Tviol_DQ0_CENeg OR Tviol_OENeg_WENeg_T OR Tviol_OENeg_WENeg_R OR Tviol_AVDNeg_WENeg OR Tviol_AVDNeg_CENeg OR Tviol_CENeg_AVDNeg OR Tviol_CENeg_WENeg_F OR Tviol_CENeg_AVDNeg_A OR Tviol_WENeg_CENeg_F OR Tviol_CENeg_WENeg_R OR Tviol_WENeg_CENeg_R OR Tviol_OENeg_RESETNeg OR Tviol_CENeg_RESETNeg OR Pviol_AVDNeg_AS OR Pviol_AVDNeg_S OR Pviol_RESETNeg OR Pviol_WENeg OR Pviol_CENeg OR PViol_CLK; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; ---------------------------------------------------------------------------- -- sequential process for reset control and FSM state transition ---------------------------------------------------------------------------- StateTransition : PROCESS(next_state, RESETNeg, RST, PoweredUp) BEGIN IF PoweredUp = '1' THEN --Hardware reset timing control IF falling_edge(RESETNeg) THEN HWResetStart <= '1', '0' AFTER 1 ns; current_state <= HW_RESET_INIT; ELSIF rising_edge(RESETNeg) AND RST = '1' THEN --RESET# pulse < tRP HWResetGlitch <= '1', '0' AFTER 1 ns; END IF; IF RESETNeg = '1' THEN current_state <= next_state; reseted <= '1'; ELSIF (RESETNeg='0' AND RST='0') THEN --no state transition while RESET# low current_state <= RESET; --reset start reseted <= '0'; END IF; ELSE current_state <= RESET; --reset reseted <= '0'; END IF; END PROCESS StateTransition; ---------------------------------------------------------------------------- --Glitch Protection: Inertial Delay does not Propagate Pulses < 3 ns ---------------------------------------------------------------------------- gWE_n <= WENeg AFTER 3 ns WHEN WENeg = '0' ELSE WENeg; gCE_n <= CENeg AFTER 3 ns WHEN CENeg = '0' ELSE CENeg; gOE_n <= OENeg AFTER 3 ns WHEN OENeg = '0' ELSE OENeg; gAVD_n<= AVDNeg AFTER 3 ns WHEN AVDNeg = '0' ELSE AVDNeg; -- AVD delay for address latching tAVD_p<= AVDNeg AFTER 3 ns WHEN AVDNeg = '1' ELSE AVDNeg; --------------------------------------------------------------------------- -- Clock active edge --> CLKMerge rising edge, needed for burst sequences --------------------------------------------------------------------------- CLKGen : PROCESS(CLK) BEGIN IF rising_edge(CLK) THEN CLKMerge <= '1', '0' AFTER 1 ns; END IF; END PROCESS CLKGen; ---------------------------------------------------------------------------- -- Device internal operation control ---------------------------------------------------------------------------- -- Protection Bit Program ProtPROG : PROCESS(PPBP_in) BEGIN IF rising_edge(PPBP_in) THEN IF LongTiming THEN PPBP_out <= '0', '1' AFTER (tdevice_PPBP - 1 ns); ELSE PPBP_out <= '0', '1' AFTER (tdevice_PPBP - 1 ns)/100; END IF; ELSE PPBP_out <= '0'; END IF; END PROCESS ProtPROG; -- Protection Bit Erase ProtERS : PROCESS(PPBE_in) BEGIN IF rising_edge(PPBE_in) THEN IF LongTiming THEN PPBE_out <= '0', '1' AFTER (tdevice_PPBE - 1 ns); ELSE PPBE_out <= '0', '1' AFTER (tdevice_PPBE - 1 ns)/100; END IF; ELSE PPBE_out <= '0'; END IF; END PROCESS ProtERS; -- Password Unlock UNL : PROCESS(PUT_in) BEGIN IF PUT_in = '0' THEN PUT_out <= '0'; ELSE PUT_out <= '1' AFTER tdevice_PUT; END IF; END PROCESS UNL; TIACCB : PROCESS(IACC_in) BEGIN IF IACC_in = '0' THEN IACC_out <= '0'; ELSE IACC_out <= '1' AFTER (tdevice_IACC - 1 ns); END IF; END PROCESS TIACCB; --------------------------------------------------------------------------- -- Address Latch and Bus Cycle Decode ---------------------------------------------------------------------------- BusCycleDecode : PROCESS(A, gWE_n, gCE_n, gOE_n, gAVD_n, WENeg, CENeg, OENeg, reseted, AVDNeg, CLK) VARIABLE AddressLatched : NATURAL RANGE 0 TO MemSize; VARIABLE WrAddressLatched : NATURAL RANGE 0 TO MemSize; VARIABLE READCYCLE : BOOLEAN; VARIABLE WRITECYCLE : BOOLEAN; VARIABLE LATCHED : BOOLEAN; VARIABLE AVDLATCHED : BOOLEAN; VARIABLE ASYN_LATCH_ADDRESS : BOOLEAN; BEGIN IF reseted='1' AND (ConfReg0(15) = '1' OR SYNC_DIS = '1') THEN -- Asynchronous Mode address latch IF RESETNeg /= '0' AND (falling_edge(gWE_n) OR falling_edge(gCE_n)) AND gCE_n = '0' AND gWE_n = '0' AND gOE_n = '1' AND tAVD_p = '0' AND NOT (ASYN_LATCH_ADDRESS) THEN WrAddressLatched := to_nat(A); AddressLatched := to_nat(A); ASYN_LATCH_ADDRESS := TRUE; END IF; IF ((falling_edge(AVDNeg) OR (A'EVENT AND AVDNeg = '0')) AND WENeg = '1') THEN -- tACC count AddrREF <= NOT AddrREF; ASYN_LATCH_ADDRESS := FALSE; END IF; IF ((rising_edge(AVDNeg) AND gCE_n = '0' AND gWE_n = '1') OR (A'EVENT AND AVDNeg = '0' AND gCE_n = '0' AND gWE_n = '1' )) AND NOT (ASYN_LATCH_ADDRESS) THEN WrAddressLatched := to_nat(A); AddressLatched := to_nat(A); ASYN_LATCH_ADDRESS := TRUE; END IF; IF ((falling_edge(OENeg) OR falling_edge(CENeg) OR (A'EVENT AND AVDNeg = '0') OR falling_edge(AVDNeg)) AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN IF AVDNeg = '0' THEN AddressLatched := to_nat(A); ASYN_LATCH_ADDRESS := TRUE; END IF; -- Initiate READ SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr <= ReturnBuffPage(AddressLatched); AddrPass <= AddressLatched mod 4; Addr <= AddressLatched ; CurrentReadPage := AddressLatched / 8; SubsequentPageAccess := (PreviousReadPage = CurrentReadPage); InitialPageAccess := NOT SubsequentPageAccess; READ <= '0', '1' AFTER 1 ns; ASYN_LATCH_ADDRESS := FALSE; END IF; IF RESETNeg /= '0' AND ((rising_edge(gWE_n) AND gCE_n = '0') OR (rising_edge(gCE_n) AND gWE_n = '0') OR (rising_edge(gWE_n) AND rising_edge(gCE_n))) AND OENeg = '1' THEN -- WRITE operation SecAddr <= ReturnSectorID(WrAddressLatched); BankID <= ReturnBank(WrAddressLatched); Addr <= WrAddressLatched; BuffPageAddr <= ReturnBuffPage(WrAddressLatched); AddrPass <= WrAddressLatched mod 4; D_tmp <= to_nat(Din(15 downto 0)); WRITE <= '0', '1' AFTER 1 ns; ASYN_LATCH_ADDRESS := FALSE; END IF; ELSIF reseted = '1' AND ConfReg0(15) = '0' AND SYNC_DIS='0' THEN IF falling_edge(AVDNeg) THEN LATCHED := FALSE; AVDLATCHED := FALSE; READCYCLE := FALSE; WRITECYCLE := FALSE; END IF; --Initiate READ (Burst mode) IF rising_edge(CLK) AND READCYCLE THEN READCYCLE := FALSE; IACC_in <= '1' AFTER 1 ns; BURST <= '0', '1' AFTER 2 ns; IF AVDLATCHED THEN AddrREF <= NOT AddrREF; END IF; Check_freq := TRUE; END IF; -- Synchronous CLK active edge address latch IF rising_edge(CLK) AND gWE_n = '1' AND gCE_n = '0' AND AVDNeg = '0' AND NOT LATCHED THEN READCYCLE := TRUE; LATCHED := TRUE; AddressLatched := to_nat(A); SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr<= ReturnBuffPage(AddressLatched); AddrPass <= AddressLatched mod 4; Addr <= AddressLatched; BurstDelay := 0; IACC_in <= '0', '1' AFTER 1 ns; AddrREF <= NOT AddrREF; IF OENeg = '0' THEN CurrentReadPage := AddressLatched / 8; SubsequentPageAccess := (PreviousReadPage=CurrentReadPage); InitialPageAccess := NOT SubsequentPageAccess; READ <= '0', '1' AFTER 1 ns; END IF; END IF; -- Synchronous AVD# rising edge address latch IF rising_edge(AVDNeg) AND WENeg = '1' AND CENeg = '0' AND NOT LATCHED THEN READCYCLE := TRUE; LATCHED := TRUE; AVDLATCHED := TRUE; AddressLatched := to_nat(A); SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr<= ReturnBuffPage(AddressLatched); AddrPass <= AddressLatched mod 4; Addr <= AddressLatched; BurstDelay := 1; IACC_in <= '0'; IF OENeg = '0' THEN CurrentReadPage := AddressLatched / 8; SubsequentPageAccess := (PreviousReadPage=CurrentReadPage); InitialPageAccess := NOT SubsequentPageAccess; READ <= '0', '1' AFTER 1 ns; END IF; END IF; -- Synchronous WRITE cycle IF (falling_edge(gWE_n) OR falling_edge(gCE_n)) AND gCE_n = '0' AND gWE_n = '0' AND gOE_n = '1' THEN READCYCLE := FALSE; WRITECYCLE := TRUE; END IF; -- Synchronous WRITE operation data latch IF ((rising_edge(gWE_n) AND gCE_n = '0') OR (rising_edge(gCE_n) AND gWE_n = '0')) AND WRITECYCLE AND gOE_n = '1' AND RESETNeg /= '0' THEN WRITECYCLE := FALSE; SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr<= ReturnBuffPage(AddressLatched); AddrPass <= AddressLatched mod 4; Addr <= AddressLatched; D_tmp <= to_nat(Din(15 downto 0)); WRITE <= '0', '1' AFTER 1 ns; END IF; -- Asynchronous WRITE cycle Address Latch -- Supported in synchronous mode IF (falling_edge(gWE_n) OR falling_edge(gCE_n)) AND gCE_n = '0' AND gOE_n = '1' AND tAVD_p = '0' AND gWE_n = '0' AND NOT LATCHED AND CLK = '0' THEN READCYCLE := FALSE; WRITECYCLE := TRUE; LATCHED := TRUE; AddressLatched := to_nat(A); SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr <= ReturnBuffPage(AddressLatched); AddrPass <= AddressLatched mod 4; Addr <= AddressLatched; END IF; -- Inititate READ, Synchronous mode IF (falling_edge(OENeg) AND WENeg = '1' AND CENeg = '0') THEN -- Initiate READ SecAddr <= ReturnSectorID(AddressLatched); BankID <= ReturnBank(AddressLatched); BuffPageAddr<= ReturnBuffPage(AddressLatched); AddrPass <= AddressLatched mod 4; Addr <= AddressLatched; CurrentReadPage := AddressLatched / 8; SubsequentPageAccess := (PreviousReadPage = CurrentReadPage); InitialPageAccess := NOT SubsequentPageAccess; READ <= '0', '1' AFTER 1 ns; END IF; END IF; -- Terminate Page Access IF ( rising_edge(CENeg)) THEN PreviousReadPage := -1; END IF; END PROCESS BusCycleDecode; ---------------------------------------------------------------------------- -- Page Access Control Process ---------------------------------------------------------------------------- PageMode : PROCESS(READ) BEGIN IF rising_edge(READ) THEN PreviousReadPage := CurrentReadPage; END IF; END PROCESS PageMode; ---------------------------------------------------------------------------- -- Timing control for the Program/ Write Buffer Program Operations -- start/ suspend/ resume ---------------------------------------------------------------------------- ProgTime :PROCESS(PSTART, PSUSP, PRES, ESP_ACT, reseted) VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE i : INTEGER RANGE 0 TO SecNum; VARIABLE pwo : time; VARIABLE wrbo : time; BEGIN IF LongTiming THEN pwo := tdevice_PWO; wrbo := tdevice_WRBO; ELSE pwo := tdevice_PWO / 3; wrbo := tdevice_WRBO / 1.2; END IF; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programing terminated ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE='1' THEN i := WrBuffSec; start := NOW; elapsed := 0 ns; IF(((PPB(i)='0' OR DYB(i)='0' OR (WP_l ='0' AND Boot_Sec(i) ='1') OR ACC = '0') OR (ESP_ACT='1' AND ERS_QUEUE(i)='1')) AND PASS_ACT='0' AND LOCK_ACT='0' AND (SecSi='0' OR WrBuffAddr(0)>BankSize)) OR (SecSi='1' AND (((WrBuffAddr(0)< 16#80# OR LOCK_REG(0)='0' OR WrBuffAddr(0)>16#FF# OR WP_l ='0' OR ACC = '0') AND i=0) OR (WrBuffAddr(0)<=BankSize AND i>0))) OR (PASS_ACT='1' AND LOCK_REG(2)='0') THEN PERR <= '1', '0' AFTER 1 us; ELSE IF WRBUFF_ACT = '1' THEN duration := (WrBuffCnt+1)* wrbo; ELSE duration := pwo; END IF; PDONE <= '0', '1' AFTER duration; END IF; ELSIF rising_edge(PSUSP) AND PDONE = '0' THEN elapsed := NOW - start; duration := duration - elapsed; PDONE <= '0'; ELSIF rising_edge(PRES) AND PDONE = '0' THEN start := NOW; PDONE <= '0', '1' AFTER duration; END IF; END IF; END PROCESS ProgTime; ---------------------------------------------------------------------------- -- Timing control for the Erase Operations ---------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, ESUSP, ERES, ERS_QUEUE,reseted) VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE seo16 : time; VARIABLE seo64 : time; BEGIN IF LongTiming THEN seo16 := tdevice_SEO16; seo64 := tdevice_SEO64; ELSE seo16 := tdevice_SEO16 / 1000; seo64 := tdevice_SEO64 / 1000; END IF; IF rising_edge( reseted ) THEN EDONE <= '1'; -- reset done, ERASE terminated ELSIF reseted = '1' THEN IF rising_edge( ESTART ) AND EDONE = '1' THEN start := NOW; elapsed := 0 ns; duration := 0 ns; FOR i IN ERS_QUEUE'RANGE LOOP IF ERS_QUEUE(i) = '1' AND PPB(i)='1' AND DYB(i)='1' AND ( WP_l /= '0' OR Boot_Sec(i)/='1')AND ACC /= '0' THEN IF i <= 3 OR i >= SecNum-3 THEN duration:=duration + seo16; ELSE duration:=duration + seo64; END IF; END IF; END LOOP; IF duration > 0 ns THEN elapsed := 0 ns; EDONE <= '0', '1' AFTER duration; start := NOW; ELSE EERR <= '1', '0' AFTER 100 us; END IF; ELSIF rising_edge(ESUSP) AND EDONE = '0' THEN elapsed := NOW - start; duration := duration - elapsed; EDONE <= '0'; ELSIF rising_edge(ERES) AND EDONE = '0' THEN start := NOW; EDONE <= '0', '1' AFTER duration; END IF; END IF; END PROCESS ErsTime; ---------------------------------------------------------------------------- -- Process that determines clock frequency ---------------------------------------------------------------------------- CLK_FREQ :PROCESS(CLK) VARIABLE CLK_PER : time := 0 ns; VARIABLE LAST_CLK : time := 0 ns; BEGIN IF rising_edge(CLK) THEN CLK_PER := NOW - LAST_CLK; LAST_CLK := NOW; IF ConfReg0(15) = '0' AND Check_freq THEN IF (CLK_PER < 71.429 ns AND WS_Initial < 3) OR (CLK_PER < 37.037 ns AND WS_Initial < 4) OR (CLK_PER < 25 ns AND WS_Initial < 5) OR (CLK_PER < 18.519 ns AND WS_Initial < 6) OR (CLK_PER < 14.925 ns AND WS_Initial < 7) OR (CLK_PER < 12.5 ns AND WS_Initial < 8) OR (CLK_PER < 10.526 ns AND WS_Initial < 9) THEN ASSERT FALSE REPORT "More wait states are required for " & "this clock frequency value" SEVERITY warning; END IF; END IF; Check_freq := FALSE; END IF; END PROCESS CLK_FREQ; ---------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation ---------------------------------------------------------------------------- StateGen :PROCESS(WRITE, Addr, BankID, SecAddr,D_tmp, ULBYPASS, PDONE, EDONE,SecSi, SET_out,ESP_ACT,PSP_ACT, START_out, reseted, PERR, EERR, current_state, PPBP_out, PPBE_out, PASS_ACT,LOCK_ACT,PUT_out, HWResetGlitch,HWResetStart) VARIABLE PATTERN_1 : boolean := FALSE; VARIABLE PATTERN_2 : boolean := FALSE; VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE DataLo : NATURAL RANGE 0 TO 16#FF# := 0; VARIABLE AddrCom : NATURAL RANGE 0 TO 16#FFF# := 0; BEGIN ------------------------------------------------------------------------ -- Functionality Section ------------------------------------------------------------------------ IF falling_edge(WRITE) THEN Data := D_tmp; DataLo := D_tmp mod 16#100#; AddrCom := Addr mod 16#1000#; PATTERN_1 := (AddrCom = 16#555#) AND (DataLo = 16#AA#) ; PATTERN_2 := (AddrCom = 16#2AA#) AND (DataLo = 16#55#) ; END IF; IF rising_edge(HWResetGlitch) THEN next_state <= HW_RESET_UNKNOWN; ELSIF rising_edge(HWResetStart) THEN next_state <= HW_RESET_INIT; ELSIF reseted /= '1' THEN next_state <= current_state; ELSE CASE current_state IS WHEN RESET => IF falling_edge(WRITE) THEN IF (PATTERN_1)THEN next_state <= Z001; ELSIF (AddrCom mod 16#100# = 16#55#) AND DataLo = 16#98# AND SecSi = '0' THEN next_state <= CFI; END IF; END IF; WHEN Z001 => IF falling_edge(WRITE) THEN IF (PATTERN_2) THEN next_state <= PREL_SETBWB; ELSE next_state <= RESET; END IF; END IF; WHEN CFI => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= CFIExit; END IF; END IF; WHEN PREL_SETBWB => IF falling_edge(WRITE) THEN IF AddrCom=16#555# AND DataLo=16#E0# AND SecSi='0' THEN next_state <= PREL_DYB; ELSIF AddrCom=16#555# AND DataLo=16#50# AND SecSi='0' THEN next_state <= PREL_PPBLCK; ELSIF AddrCom=16#555# AND DataLo=16#C0# AND SecSi='0' THEN next_state <= PREL_PPB; ELSIF AddrCom=16#555# AND DataLo=16#40# AND SecSi='0' THEN next_state <= PREL_LR; ELSIF AddrCom=16#555# AND DataLo=16#20# AND SecSi='0' THEN next_state <= PREL_ULBYPASS; ELSIF AddrCom=16#555# AND DataLo=16#90# AND SecSi='0' THEN next_state <= AS; ELSIF AddrCom=16#555# AND DataLo=16#90# AND SecSi='1' THEN next_state <= SECSI_EX; ELSIF AddrCom=16#555# AND DataLo=16#60# AND SecSi='0' THEN next_state <= PREL_PASS; -- Password entry ELSIF AddrCom=16#555# AND DataLo=16#A0# THEN next_state <= A0SEEN; ELSIF DataLo=16#25# AND (SecSi='0' OR BankID>0) THEN next_state <= PREL_WR2BUFF; ELSIF AddrCom=16#555# AND DataLo=16#D0# AND SecSi='0' THEN next_state <= SET_CONF; ELSIF AddrCom=16#555# AND DataLo=16#C6# AND SecSi='0' THEN next_state <= RD_CONF; ELSIF AddrCom=16#555# AND DataLo=16#80# THEN next_state <= C8; ELSIF AddrCom=16#555# AND DataLo=16#88# THEN next_state <= RESET; -- SecSi Entry ELSE next_state <= RESET; END IF; END IF; WHEN PREL_ULBYPASS => IF falling_edge(WRITE) THEN IF DataLo = 16#A0# THEN next_state <= A0SEEN; ELSIF DataLo=16#25# THEN next_state <= PREL_WR2BUFF; ELSIF DataLo = 16#98# THEN next_state <= CFI; ELSIF DataLo = 16#80# THEN next_state <= C8_PREL; ELSIF DataLo = 16#90# THEN next_state <= PREL_ULBYPASS_RESET; END IF; END IF; WHEN PREL_ULBYPASS_RESET => IF falling_edge(WRITE) THEN IF DataLo = 16#00# THEN next_state <= RESET; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; WHEN A0SEEN => IF falling_edge(WRITE) THEN next_state <= PGMS; END IF; WHEN C8 => IF falling_edge(WRITE) THEN IF PATTERN_1 THEN next_state <= C8_Z001; ELSE next_state <= RESET; END IF; END IF; WHEN C8_Z001 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= C8_PREL; ELSE next_state <= RESET; END IF; END IF; WHEN C8_PREL => IF falling_edge(WRITE) THEN IF DataLo=16#10# AND ( (AddrCom=16#555# AND SecSi='0') OR ULBYPASS = '1')THEN next_state <= ERS; ELSIF DataLo=16#30# AND (BankID/=0 OR SecSi='0') THEN next_state <= SERS; ELSIF ULBYPASS /='1' THEN next_state <= RESET; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; WHEN ERS => IF rising_edge(EDONE) OR falling_edge(EERR) THEN IF ULBYPASS /= '1' THEN next_state <= RESET; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; WHEN SERS => IF SET_out'EVENT AND SET_out = '1' THEN next_state <= SERS_EXEC; ELSIF falling_edge(WRITE) THEN IF DataLo = 16#B0# AND ERS_QUEUE_B(BankID)='1' THEN next_state <= ESP; ELSIF DataLo = 16#30# AND (BankID/=0 OR SecSi='0') THEN next_state <= SERS; ELSE IF ULBYPASS /= '1' THEN next_state <= RESET; ELSE next_state <= PREL_ULBYPASS; END IF; END IF; END IF; WHEN ESPS => IF START_out = '1' THEN next_state <= ESP; END IF; WHEN SERS_EXEC => IF rising_edge(EDONE) OR falling_edge(EERR) THEN IF ULBYPASS /= '1' THEN next_state <= RESET; ELSE next_state <= PREL_ULBYPASS; END IF; ELSIF EERR /= '1' THEN IF falling_edge(WRITE) THEN IF DataLo = 16#B0# AND ERS_QUEUE_B(BankID)='1' AND (RSTMOUT_out = '1' OR NOT ResumeFlag) THEN next_state <= ESPS; END IF; END IF; END IF; WHEN ESP => IF falling_edge(WRITE) THEN IF DataLo = 16#30# AND ERS_QUEUE_B(BankID)= '1' THEN next_state <= SERS_EXEC; ELSIF PATTERN_1 THEN next_state <= ESP_Z001; ELSIF (AddrCom mod 16#100# = 16#55#) AND DataLo= 16#98# AND SecSi='0' THEN next_state <= CFI; END IF; END IF; WHEN ESP_Z001 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= ESP_PREL; ELSE next_state <= ESP; END IF; END IF; WHEN ESP_PREL => IF falling_edge(WRITE) THEN IF DataLo = 16#25# AND (SecSi='0' OR BankID>0) THEN next_state <= PREL_WR2BUFF; ELSIF AddrCom=16#555# AND DataLo=16#A0# THEN next_state <= A0SEEN; ELSIF AddrCom=16#555# AND DataLo=16#E0# AND SecSi='0' THEN next_state <= PREL_DYB; ELSIF AddrCom=16#555# AND DataLo=16#C0# AND SecSi='0' THEN next_state <= PREL_PPB; ELSIF AddrCom=16#555# AND DataLo = 16#90# AND SecSi='0' THEN next_state <= AS; ELSIF AddrCom=16#555# AND DataLo = 16#90# AND SecSi='1' THEN next_state <= SECSI_EX; ELSIF AddrCom=16#555# AND DataLo = 16#88# AND ERS_QUEUE(0) /='1' THEN next_state <= ESP; --SecSi Entry ELSE next_state <= ESP; END IF; END IF; WHEN PREL_WR2BUFF => IF falling_edge(WRITE) THEN IF SecAddr=WrBuffSec AND DataLo < 32 THEN next_state <= WR2BUFF_0; ELSE next_state <= WR2BUFF_AB; END IF; END IF; WHEN WR2BUFF_0 => IF falling_edge(WRITE) THEN IF SecAddr=WrBuffSec AND WRCNT >0 THEN next_state <= WR2BUFF_CNT; ELSIF SecAddr=WrBuffSec AND WRCNT =0 THEN next_state <= PREL_PRFLASH; ELSE next_state <= WR2BUFF_AB; END IF; END IF; WHEN WR2BUFF_CNT => IF falling_edge(WRITE) THEN IF BuffPageAddr=WrBuffPage AND Addr >= PrevBuffAd AND WRCNT >0 THEN next_state <= WR2BUFF_CNT; ELSIF BuffPageAddr=WrBuffPage AND Addr >= PrevBuffAd AND WRCNT =0 THEN next_state <= PREL_PRFLASH; ELSE next_state <= WR2BUFF_AB; END IF; END IF; WHEN PREL_PRFLASH => IF falling_edge(WRITE) THEN IF SecAddr=WrBuffSec AND DataLo=16#29# THEN next_state <= PGMS; ELSE next_state <= WR2BUFF_AB; END IF; END IF; WHEN PGMS => IF rising_edge(PDONE) OR falling_edge(PERR) THEN IF ESP_ACT = '1' THEN next_state <= ESP; ELSIF ULBYPASS ='1' THEN next_state <= PREL_ULBYPASS; ELSIF PASS_ACT ='1' THEN next_state <= PREL_PASS; ELSIF LOCK_ACT ='1' THEN next_state <= PREL_LR; ELSE next_state <= RESET; END IF; ELSIF PERR /= '1' THEN IF falling_edge(WRITE) THEN IF DataLo = 16#B0# AND PASS_ACT='0' AND LOCK_ACT='0' AND BankID=PrgBank AND (RSTMOUT_out = '1' OR NOT ResumeFlag) THEN next_state <= PGSPS; END IF; END IF; END IF; WHEN PGSPS => IF START_out = '1' THEN next_state <= PGS; END IF; WHEN PGS => IF falling_edge(WRITE) THEN IF DataLo = 16#30# THEN next_state <= PGMS; ELSIF PATTERN_1 THEN next_state <= PGS_Z001; ELSIF (AddrCom mod 16#100# = 16#55#) AND DataLo= 16#98# AND SecSi='0' THEN next_state <= CFI; END IF; END IF; WHEN PGS_Z001 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= PGS_PREL; ELSE next_state <= PGS; END IF; END IF; WHEN PGS_PREL => IF falling_edge(WRITE) THEN IF AddrCom=16#555# AND DataLo=16#E0# AND SecSi='0' THEN next_state <= PREL_DYB; ELSIF AddrCom=16#555# AND DataLo=16#C0# AND SecSi='0' THEN next_state <= PREL_PPB; ELSIF AddrCom=16#555# AND DataLo= 16#90# AND SecSi='0' THEN next_state <= AS; ELSIF AddrCom=16#555# AND DataLo = 16#90# AND SecSi='1' AND WrBuffSec/=0 THEN next_state <= SECSI_EX; ELSIF AddrCom=16#555# AND DataLo = 16#88# AND WrBuffSec/=0 AND (ESP_ACT='0' OR ERS_QUEUE(0)='0') THEN next_state <= PGS; --SecSi Entry ELSE next_state <= PGS; END IF; END IF; WHEN WR2BUFF_AB => IF falling_edge(WRITE) THEN IF PATTERN_1 THEN next_state <= WR2BUFF_AB_Z001; END IF; END IF; WHEN WR2BUFF_AB_Z001 => IF falling_edge(WRITE) THEN IF PATTERN_2 THEN next_state <= WR2BUFF_AB_PREL; ELSE next_state <= WR2BUFF_AB; END IF; END IF; WHEN WR2BUFF_AB_PREL => IF falling_edge(WRITE) THEN IF AddrCom = 16#555# AND DataLo = 16#F0# THEN IF ESP_ACT ='1' THEN next_state <= ESP; ELSIF ULBYPASS = '1' THEN next_state <= PREL_ULBYPASS; ELSE next_state <= RESET; END IF; ELSE next_state <= WR2BUFF_AB; END IF; END IF; WHEN SET_CONF => IF falling_edge(WRITE) THEN IF AddrCom mod 16#100# = 16#00# THEN next_state <= SET_CONF1; -- set conf reg ELSE next_state <= RESET; END IF; END IF; WHEN SET_CONF1 => IF falling_edge(WRITE) THEN IF AddrCom mod 16#100# = 16#01# THEN next_state <= SET_CONF_EXIT; -- set conf reg ELSE next_state <= RESET; END IF; END IF; WHEN SET_CONF_EXIT => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= RESET; END IF; END IF; WHEN RD_CONF => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN next_state <= RESET; END IF; END IF; WHEN PREL_PASS => IF falling_edge(WRITE) THEN IF DataLo = 16#A0# THEN next_state <= PASS_A0SEEN; ELSIF DataLo = 16#90# THEN next_state <= PASS_EX; ELSIF AddrCom mod 16#100# = 16#00# AND DataLo= 16#25# THEN next_state <= PASS_UN_Z001; END IF; END IF; WHEN PASS_A0SEEN => IF falling_edge(WRITE) THEN next_state <= PGMS; END IF; WHEN PASS_EX => IF falling_edge(WRITE) THEN IF DataLo = 16#00# THEN next_state <= RESET; -- exit password ELSE next_state <= PREL_PASS; END IF; END IF; WHEN PASS_UN_Z001 => IF falling_edge(WRITE) THEN IF DataLo = 16#03# AND AddrCom mod 16#100# = 16#00# THEN next_state <= PASS_UN_PREL; ELSE next_state <= PREL_PASS; END IF; END IF; WHEN PASS_UN_PREL => IF falling_edge(WRITE) THEN next_state <= PASS_UN1; END IF; WHEN PASS_UN1 => IF falling_edge(WRITE) THEN next_state <= PASS_UN2; END IF; WHEN PASS_UN2 => IF falling_edge(WRITE) THEN next_state <= PASS_UN3; END IF; WHEN PASS_UN3 => IF falling_edge(WRITE) THEN next_state <= PASS_UN4; END IF; WHEN PASS_UN4 => IF falling_edge(WRITE) THEN IF AddrCom mod 16#100# = 16#00# AND DataLo = 16#29# THEN next_state <=PASS_UN_W; ELSE next_state <= PREL_PASS; END IF; END IF; WHEN PASS_UN_W => IF PUT_out = '1' THEN next_state <= PREL_PASS; END IF; WHEN PREL_LR => IF falling_edge(WRITE) THEN IF DataLo = 16#A0# THEN next_state <= LR_A0SEEN; ELSIF DataLo = 16#90# THEN next_state <= LR_PREL_EX; END IF; END IF; WHEN LR_A0SEEN => IF falling_edge(WRITE) THEN IF AddrCom = 16#00# THEN next_state <= PGMS; -- write to LR ELSE next_state <= PREL_LR; END IF; END IF; WHEN LR_PREL_EX => IF falling_edge(WRITE) THEN IF DataLo = 16#00# THEN next_state <= RESET; ELSE next_state <= PREL_LR; END IF; END IF; WHEN PREL_PPB => IF falling_edge(WRITE) THEN IF DataLo = 16#A0# THEN next_state <= PPB_PREL_PR; ELSIF DataLo = 16#80# THEN next_state <= PPB_PREL_ER; ELSIF DataLo = 16#90# THEN next_state <= PPB_PREL_EX; END IF; END IF; WHEN PPB_PREL_PR => IF falling_edge(WRITE) THEN IF DataLo = 16#00# AND (BankID = BankPPBAddr) THEN next_state <= PPB_PGMS; ELSE next_state <= PREL_PPB; END IF; END IF; WHEN PPB_PGMS => IF PPBP_out = '1' THEN next_state <= PREL_PPB; END IF; WHEN PPB_PREL_ER => IF falling_edge(WRITE) THEN IF DataLo = 16#30# THEN next_state <= PPB_ERS; ELSE next_state <= PREL_PPB; END IF; END IF; WHEN PPB_ERS => IF PPBE_out = '1' THEN next_state <= PREL_PPB; END IF; WHEN PPB_PREL_EX => IF falling_edge(WRITE) THEN IF DataLo = 16#00# THEN IF PSP_ACT='1' THEN next_state <= PGS; ELSIF ESP_ACT='1' THEN next_state <= ESP; ELSE next_state <= RESET; END IF; ELSE next_state <= PREL_PPB; END IF; END IF; WHEN PREL_PPBLCK => IF falling_edge(WRITE) THEN IF DataLo = 16#A0# THEN next_state <= PPBLCK_PREL_ST; ELSIF DataLo = 16#90# THEN next_state <= PPBLCK_PREL_EX; END IF; END IF; WHEN PPBLCK_PREL_ST => IF falling_edge(WRITE) THEN IF DataLo = 16#00# THEN next_state <= PREL_PPBLCK; -- set PPB Lock Bit ELSE next_state <= PREL_PPBLCK; END IF; END IF; WHEN PPBLCK_PREL_EX => IF falling_edge(WRITE) THEN IF DataLo = 16#00# THEN next_state <= RESET; ELSE next_state <= PREL_PPBLCK; END IF; END IF; WHEN PREL_DYB => IF falling_edge(WRITE) THEN IF DataLo = 16#A0# THEN next_state <= DYB_PREL_ST; ELSIF DataLo = 16#90# THEN next_state <= DYB_PREL_EX; END IF; END IF; WHEN DYB_PREL_ST => IF falling_edge(WRITE) THEN next_state <= PREL_DYB; -- set/reset DYB END IF; WHEN DYB_PREL_EX => IF falling_edge(WRITE) THEN IF DataLo = 16#00# THEN IF PSP_ACT='1' THEN next_state <= PGS; ELSIF ESP_ACT='1' THEN next_state <= ESP; ELSE next_state <= RESET; END IF; ELSE next_state <= PREL_DYB; END IF; END IF; WHEN AS => IF falling_edge(WRITE) THEN IF DataLo = 16#F0# THEN IF PSP_ACT='1' THEN next_state <= PGS; ELSIF ESP_ACT='1' THEN next_state <= ESP; ELSE next_state <= RESET; END IF; ELSIF DataLo = 16#98# AND (Addr mod 16#100# = 16#55#) THEN next_state <= CFI; END IF; END IF; WHEN SECSI_EX => IF falling_edge(WRITE) THEN IF PSP_ACT='1' THEN next_state <= PGS; ELSIF ESP_ACT='1' THEN next_state <= ESP; ELSE next_state <= RESET; END IF; END IF; WHEN HW_RESET_UNKNOWN | HW_RESET_INIT => NULL; --Proper HW RESET# cycle needed --Until then, unknown device state / behavior END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for Read Mode Generation --------------------------------------------------------------------------- ReadModeGen :PROCESS(current_state,gWE_n ,BURST,reseted,gCE_n,AVDNeg,RST ) VARIABLE BURST_TR : BOOLEAN; VARIABLE SYNCREAD : BOOLEAN; BEGIN BURST_TR := FALSE; SYNCREAD := FALSE; SYNC_DIS <= '0'; IF falling_edge(RST) AND RESETNeg = '0' THEN RD_MODE <= NOSYNC; END IF; IF reseted = '1' THEN CASE current_state IS WHEN RESET => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN Z001 => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN CFI => IF falling_edge(BURST) THEN IF BankID = BankCFIAddr THEN SYNCREAD := TRUE; ELSIF CFIExit = AS AND BankID = BankASAddr THEN SYNCREAD := TRUE; ELSIF ESP_ACT='1' AND ERS_QUEUE(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSIF PSP_ACT = '0' OR SecAddr /= WrBuffSec THEN BURST_TR := TRUE; END IF; END IF; WHEN PREL_SETBWB => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN PREL_ULBYPASS => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN PREL_ULBYPASS_RESET => NULL; WHEN A0SEEN => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN C8 => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN C8_Z001 => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN C8_PREL => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN ERS => IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN SERS => IF falling_edge(BURST) THEN IF ERS_QUEUE_B(BankID)='1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ESPS => IF falling_edge(BURST) THEN IF ERS_QUEUE_B(BankID)='1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN SERS_EXEC => IF falling_edge(BURST) THEN IF ERS_QUEUE_B(BankID)='1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ESP => IF falling_edge(BURST) THEN IF ERS_QUEUE(SecAddr)='1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN ESP_Z001 => NULL; WHEN ESP_PREL => NULL; WHEN PREL_WR2BUFF => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN WR2BUFF_0 => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN WR2BUFF_CNT => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN PREL_PRFLASH => IF falling_edge(BURST) THEN BURST_TR := TRUE; END IF; WHEN PGMS => IF falling_edge(BURST) THEN IF BankID = PrgBank THEN SYNCREAD := TRUE; ELSIF ESP_ACT = '1' AND ERS_QUEUE(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSIF LOCK_ACT = '1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PGSPS => IF falling_edge(BURST) THEN IF SecAddr = WrBuffSec THEN SYNCREAD := TRUE; ELSIF ESP_ACT = '1' AND ERS_QUEUE(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PGS => IF falling_edge(BURST) THEN IF SecAddr = WrBuffSec THEN SYNCREAD := TRUE; ELSIF ESP_ACT = '1' AND ERS_QUEUE(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PGS_Z001 => NULL; WHEN PGS_PREL => NULL; WHEN WR2BUFF_AB => IF falling_edge(BURST) THEN IF BankID = PrgBank THEN SYNCREAD := TRUE; ELSIF ESP_ACT = '1' AND ERS_QUEUE(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN WR2BUFF_AB_Z001 => NULL; WHEN WR2BUFF_AB_PREL => NULL; WHEN SET_CONF => NULL; WHEN SET_CONF1 => NULL; WHEN SET_CONF_EXIT => NULL; WHEN RD_CONF => IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PREL_PASS => IF falling_edge(BURST) THEN IF BankID = 0 THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN PASS_A0SEEN => NULL; WHEN PASS_EX => NULL; WHEN PASS_UN_Z001 => NULL; WHEN PASS_UN_PREL => NULL; WHEN PASS_UN1 => NULL; WHEN PASS_UN2 => NULL; WHEN PASS_UN3 => NULL; WHEN PASS_UN4 => NULL; WHEN PASS_UN_W => NULL; WHEN PREL_LR => IF falling_edge(BURST) THEN IF BankID = 0 THEN SYNCREAD := TRUE; ELSE BURST_TR := TRUE; END IF; END IF; WHEN LR_A0SEEN => NULL; WHEN LR_PREL_EX => NULL; WHEN PREL_PPB => SYNC_DIS <= '1'; WHEN PPB_PREL_PR => NULL; WHEN PPB_PREL_ER => NULL; WHEN PPB_PGMS | PPB_ERS => IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PPB_PREL_EX => NULL; WHEN PREL_PPBLCK => IF falling_edge(BURST) THEN SYNCREAD := TRUE; END IF; WHEN PPBLCK_PREL_ST => NULL; WHEN PPBLCK_PREL_EX => NULL; WHEN PREL_DYB => IF falling_edge(BURST) THEN IF BankID = BankDYBAddr THEN SYNCREAD := TRUE; ELSIF ESP_ACT='1' AND ERS_QUEUE(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSIF PSP_ACT = '0' OR SecAddr /= WrBuffSec THEN BURST_TR := TRUE; END IF; END IF; WHEN DYB_PREL_ST => NULL; WHEN DYB_PREL_EX => NULL; WHEN AS => IF falling_edge(BURST) THEN IF BankID = BankASAddr THEN SYNCREAD := TRUE; ELSIF ESP_ACT='1' AND ERS_QUEUE(SecAddr) = '1' THEN SYNCREAD := TRUE; ELSIF PSP_ACT = '0' OR SecAddr /= WrBuffSec THEN BURST_TR := TRUE; END IF; END IF; WHEN SECSI_EX => NULL; WHEN HW_RESET_UNKNOWN | HW_RESET_INIT => NULL; --Proper HW RESET# cycle needed --Until then, unknown device state / behavior END CASE; IF(rising_edge(gCE_n) OR falling_edge(AVDNeg) OR falling_edge(gWE_n))AND (RD_MODE /= NOSYNC) THEN RD_MODE <= NOSYNC; END IF; IF BURST_TR THEN IF NOT ( SecSi ='1' AND SecAddr=0 AND Addr> 16#FF# ) THEN IF ConfReg0(2 downto 0) = "000" THEN RD_MODE <= CONTINUOUS; ELSIF ConfReg0(3) = '0' THEN RD_MODE <= LINEAR_NO_WRAP; ELSE RD_MODE <= LINEAR; END IF; ReadINIT <= '0', '1' AFTER 2 ns; END IF; ELSIF SYNCREAD THEN RD_MODE <= SYNCR; ReadINIT <= '0', '1' AFTER 2 ns; END IF; END IF; END PROCESS ReadModeGen; ---------------------------------------------------------------------------- --FSM Output generation and general funcionality ---------------------------------------------------------------------------- Functional : PROCESS(WRITE, READ, BURST,Addr, SecAddr, BankID, SecSi, SET_out, AVDNeg,ReadINIT, PDONE, EDONE, HANG, START_out , RST, reseted, gOE_n, OENeg, CENeg, WENeg, current_state , PERR, PPBP_out, PPBE_out, PUT_out, CLK,CLKMerge, EERR,IACC_out ) VARIABLE PATTERN_1: BOOLEAN:=FALSE; VARIABLE PATTERN_2: BOOLEAN:=FALSE; VARIABLE Status : std_logic_vector( 7 downto 0):=(OTHERS => '0'); VARIABLE temp : std_logic_vector( 7 downto 0); VARIABLE x : INTEGER RANGE 0 to SecNum; VARIABLE Data : NATURAL RANGE 0 TO MaxData := 0; VARIABLE DataLo : NATURAL RANGE 0 TO 16#FF# := 0; VARIABLE AddrCom : NATURAL RANGE 0 TO 16#FFF# := 0; VARIABLE oe : BOOLEAN:=FALSE; VARIABLE SecProt : std_logic; VARIABLE old_bit : std_logic_vector(15 downto 0); VARIABLE new_bit : std_logic_vector(15 downto 0); VARIABLE old_int : INTEGER RANGE -1 to MaxData; VARIABLE new_int : INTEGER RANGE -1 to MaxData; -- Burst variables VARIABLE BurstAddr : INTEGER RANGE -1 TO MemSize := -1; VARIABLE BurstSec : INTEGER RANGE -1 TO SecNum := -1; VARIABLE LatencyAddr : INTEGER RANGE -1 TO MemSize := -1; VARIABLE BurstLength : NATURAL RANGE 0 TO 32; VARIABLE RdCnt : NATURAL RANGE 0 TO 32; VARIABLE DOut_burst : std_logic_vector(15 downto 0) := (OTHERS=>'Z'); VARIABLE WS_Latency : NATURAL RANGE 0 TO 7; VARIABLE WS_Boundary : NATURAL RANGE 0 TO 4; VARIABLE DelayCyc_CNT : INTEGER; VARIABLE DelayCycSwitch: NATURAL RANGE 0 TO 5; VARIABLE BoundarySwitch: NATURAL RANGE 0 TO 3; VARIABLE BusyBound : boolean; VARIABLE WrBuffData_temp : WrBuffDataArr := ( OTHERS => -1); VARIABLE WrBuffAddr_temp : WrBuffAddrArrTemp := ( OTHERS => -1); VARIABLE WrBuffCnt_temp : NATURAL RANGE 0 TO WrBuffLength; VARIABLE WrCnt_temp : NATURAL RANGE 0 TO WrBuffLength; -- Burst mode control VARIABLE INITIAL : boolean; VARIABLE BOUNDARY_CROSS : boolean; VARIABLE NO_PROGRESS : boolean; VARIABLE BURST_END : boolean; VARIABLE PR_FLAG : BOOLEAN := FALSE; VARIABLE ER_FLAG : BOOLEAN := FALSE; VARIABLE SyncData : std_logic_vector(15 downto 0); VARIABLE CrossData: std_logic_vector(15 downto 0); VARIABLE ConfReg0temp : std_logic_vector(15 downto 0) := "1110111111001000"; VARIABLE ConfReg1temp : std_logic_vector(15 downto 0) := "1111111111101111"; PROCEDURE READMEM(Address :IN INTEGER; Bank :IN INTEGER; Sec :IN INTEGER; SS :IN std_logic)IS VARIABLE ReadData : STD_LOGIC_VECTOR(15 downto 0); BEGIN IF (SS/='1' OR Sec/=0) THEN IF Mem(Address)/=-1 THEN ReadData := to_slv(Mem(Address),16); ELSE ReadData := ( OTHERS =>'X'); END IF; ELSIF Address>=16#00# AND Address<=16#FF# THEN IF SecSiMem(Address) /= -1 THEN ReadData := to_slv(SecSiMem(Address),16); ELSE ReadData := ( OTHERS =>'X'); END IF; ELSE ReadData := (OTHERS => 'Z'); -- SecSi Address out of range ASSERT FALSE REPORT "Address out of SecSi range." SEVERITY WARNING; END IF; OutputD := ReadData; END READMEM; PROCEDURE READ_BURST_DATA( BAddr:IN INTEGER; BSec :IN INTEGER; SS :IN STD_LOGIC) IS BEGIN IF( SS='0' OR BSec>0) THEN DOut_burst := ( OTHERS =>'X'); IF Mem(BAddr)/=-1 THEN DOut_burst := to_slv(Mem(BAddr),16); END IF; ELSE DOut_burst := ( OTHERS =>'X'); IF SecSiMem(BAddr)/=-1 THEN DOut_burst := to_slv(SecSiMem(BAddr),16); END IF; END IF; END READ_BURST_DATA; PROCEDURE NEXT_ADDR_LIN( BAddr :INOUT INTEGER; Length :IN INTEGER RANGE 0 TO 32 ) IS BEGIN BAddr := BAddr + 1; IF BAddr MOD Length = 0 THEN BAddr:= BAddr - Length; END IF; END NEXT_ADDR_LIN; PROCEDURE CHECK_END( CNT :INOUT INTEGER; Enable :IN BOOLEAN; BEnd :OUT BOOLEAN ) IS BEGIN IF Enable THEN CNT:=CNT-1; IF CNT= 0 THEN BEnd := TRUE; ELSE BEnd := FALSE; END IF; ELSE BEnd := FALSE; END IF; END CHECK_END; PROCEDURE NEXT_ADDR( BAddr:INOUT INTEGER; BSec :INOUT INTEGER; SS :IN STD_LOGIC ) IS BEGIN IF SecSi ='0' OR BSec>0 THEN IF BAddr = MemSize THEN BAddr := 0; BSec := 0; ELSE BAddr:=BAddr+1; IF BSec < (SecNum -3) AND BSec > 3 THEN IF(BAddr MOD (SecSize64+1) = 0)THEN BSec:= BSec + 1; END IF; ELSE IF (BAddr MOD (SecSize16+1) = 0) THEN BSec := BSec+1; END IF; END IF; END IF; ELSE IF BAddr = 16#FF# THEN BAddr := 0; ELSE BAddr := BAddr+1; END IF; END IF; END NEXT_ADDR; PROCEDURE CheckBoundary(BusyBound : INOUT BOOLEAN; CrossData : INOUT STD_LOGIC_VECTOR(15 downto 0); BurstAddr : INOUT NATURAL; BurstSect : INOUT NATURAL) IS VARIABLE BankCHECK : NATURAL; VARIABLE SectorCHECK : NATURAL; BEGIN BankCHECK := ReturnBank((BurstAddr+1) mod (MemSize+1)); SectorCHECK := ReturnSectorID((BurstAddr+1) mod (MemSize+1)); BusyBOUND := FALSE; IF (BankCheck = BankCFIAddr AND current_state=CFI) THEN CrossData := ( OTHERS => 'Z'); BusyBOUND := TRUE; ELSIF((BankCheck /= BankCFIAddr AND current_state=CFI) OR (BankCheck/=PrgBank AND current_state=PGMS) OR (BankCheck/=PrgBank AND current_state=PGSPS) OR (SectorCHECK/=WrBuffSec AND current_state=PGS) OR (BankCheck/=PrgBank AND current_state=WR2BUFF_AB) OR (BankCheck/=BankDYBAddr AND current_state=PREL_DYB)) AND (ESP_ACT='1' AND ERS_QUEUE(SectorCHECK)='1') THEN CrossData := ( OTHERS => '0'); CrossData(7 downto 0) := Status; CrossData(7) := '1'; BusyBOUND := TRUE; ELSIF ( ERS_QUEUE(SectorCHECK)='1' AND current_state=ESP) THEN Status(7) := '1'; CrossData := ( OTHERS => '0'); CrossData(7 downto 0) := Status; BusyBOUND := TRUE; ELSIF (ERS_QUEUE_B(BankCheck)='1' AND (current_state=SERS OR current_state=SERS_EXEC OR current_state=ESPS)) THEN IF (Ers_Queue(SectorCHECK) = '1' ) THEN Status(7) := '0'; ELSE Status(7) := '1'; END IF; CrossData := ( OTHERS => '0'); CrossData(7 downto 0) := Status; BusyBOUND := TRUE; ELSIF (BankCHECK=PrgBank AND (current_state=PGMS OR current_state=PGSPS OR current_state=WR2BUFF_AB)) THEN CrossData := ( OTHERS => '0'); CrossData(7 downto 0) := Status; IF (BurstAddr+1) mod (MemSize+1)=WrBuffAddr(0) OR LOCK_ACT='1' THEN CrossData(7) := Status(7); ELSE CrossData(7) := NOT Status(7); END IF; BusyBOUND := TRUE; ELSIF (SectorCHECK=WrBuffSec AND current_state=PGS) THEN CrossData := ( OTHERS => 'Z'); BusyBOUND := TRUE; ELSIF (BankCHECK=0 AND current_state=PREL_PASS) THEN IF LOCK_REG(2) = '1' THEN CrossData := to_slv(Password(0),16); ELSE CrossData := (OTHERS => '1'); END IF; BusyBOUND := TRUE; ELSIF (BankCHECK=0 AND current_state=PREL_LR) THEN CrossData := LOCK_REG; BusyBOUND := TRUE; ELSIF (CFIExit = AS AND BankCHECK = BankASAddr AND current_state=CFI) OR (BankCHECK = BankASAddr AND current_state=AS) THEN CrossData := to_slv(16#0001#,16); BusyBOUND := TRUE; ELSIF (SectorCHECK=0 AND SecSi='1') THEN CrossData := (OTHERS => 'Z'); BusyBOUND := TRUE; ELSIF (BankCHECK = BankDYBAddr AND current_state=PREL_DYB) THEN CrossData := (OTHERS => '0'); CrossData(0) := DYB(SecAddr); BusyBOUND := TRUE; END IF; BusyBOUND := BusyBOUND AND ( ReturnBank(BurstAddr)/= BankCHECK OR ReturnSectorID(BurstAddr)/= SectorCHECK ); END PROCEDURE CheckBoundary; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(WRITE) THEN Data := D_tmp; DataLo := D_tmp mod 16#100#; AddrCom := Addr mod 16#1000#; PATTERN_1 := (AddrCom = 16#555#) AND (DataLo = 16#AA#) ; PATTERN_2 := (AddrCom = 16#2AA#) AND (DataLo = 16#55#) ; END IF; oe := falling_edge(READ); IF falling_edge(RST) AND RESETNeg='0' THEN PASS_ACT <= '0'; LOCK_ACT <= '0'; SecSi <= '0'; ULBYPASS <= '0'; ESP_ACT <= '0'; PSP_ACT <= '0'; WRBUFF_ACT <='0'; ConfReg0 := "1110111111001000"; ConfReg1 := "1111111111101111"; SYN := '0'; ERS_QUEUE <= (OTHERS => '0'); ERS_QUEUE_B <= (OTHERS => '0'); IF LOCK_REG(2) = '0' THEN PPB_LOCK := '0'; ELSE PPB_LOCK := '1'; END IF; IF LOCK_REG(4) = '1' THEN DYB := (OTHERS => '1'); ELSE DYB := (OTHERS => '0'); END IF; PPBP_in <= '0'; PPBE_in <= '0'; PUT_in <= '0'; START_in <= '0'; SET_in <= '0'; END IF; IF falling_edge(BURST) THEN INITIAL := TRUE; DelayCycSwitch := 0; BurstAddr := Addr; BurstSec := SecAddr; IF (to_nat(ConfReg0(2 DOWNTO 0)) = 2 ) THEN BurstLength := 8; ELSIF (to_nat(ConfReg0(2 DOWNTO 0)) = 3 )THEN