------------------------------------------------------------------------------- -- File name : mt28f800b5.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2004 Free Model Foundry; http://www.FreeModelFoundry.com -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2 as -- published by the Free Software Foundation. -- -- MODIFICATION HISTORY : -- -- version: | author: | mod date: | changes made: -- V1.0 D. Komaromi 04 Sep 27 Initial -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: Micron -- Technology: Flash Memory -- Part: mt28f800b5 -- -- Description: 8Mbit(1M x 8-Bit/512K x 16-Bit) 5 Boot Block Flash Memory -- ------------------------------------------------------------------------------- -- Note: -- Protection against over-erasure and optimization of the write margin to each -- cell is not implemented, since the maximum number of erase and write cycles -- executed by the ISM without a successful verification is not given in the -- datasheet. Also, the method of verification is not explained ------------------------------------------------------------------------------- -- 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 mt28f800b5 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_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; -- data tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RPNeg : VitalDelayType01 := VitalZeroDelay01; tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; tipd_VPP : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_RPNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z;--tRWH tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tAA tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z;-- --(tACE,tACE,tOD,-,tOD,-) tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(tAOE,tAOE,tOD,-,tOD,-) --tsetup values tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge / tsetup_A0_WENeg : VitalDelayType := UnitDelay; --tAS edge / tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / tsetup_DQ0_WENeg : VitalDelayType := UnitDelay; --tDS edge / tsetup_CENeg_WENeg : VitalDelayType := UnitDelay; --0 ns tsetup_WENeg_CENeg : VitalDelayType := UnitDelay; --0 ns tsetup_Vpp_WENeg : VitalDelayType := UnitDelay; --tVPS1 edge/ tsetup_Vpp_CENeg : VitalDelayType := UnitDelay; --tVPS1 edge/ tsetup_WPNeg_WENeg : VitalDelayType := UnitDelay; --tRHS edge/ tsetup_WPNeg_CENeg : VitalDelayType := UnitDelay; --tRHS edge/ --thold values thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge / thold_A0_WENeg : VitalDelayType := UnitDelay; --tAH edge / thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / thold_DQ0_WENeg : VitalDelayType := UnitDelay; --tDH edge / thold_CENeg_WENeg : VitalDelayType := UnitDelay; --0 ns edge / thold_WENeg_CENeg : VitalDelayType := UnitDelay; --0 ns edge / --tpw values: pulse width tpw_RPNeg_negedge : VitalDelayType := UnitDelay; --tRP tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCPH -- tdevice values: values for internal delays --Write Operation --byte / word write tdevice_POW : VitalDelayType := 4.5 us; --Block Erase Operation --Boot Block tdevice_BBEO : VitalDelayType := 100 ms; --Parameter Block tdevice_PBEO : VitalDelayType := 100 ms; --Main Block tdevice_MBEO : VitalDelayType := 500 ms; --WE#(CE#) to valid status tWB tdevice_BUSY : VitalDelayType := 200 ns; --Boot Block Relock Delay Time tREL tdevice_REL : VitalDelayType := 100 ns; tdevice_READY : VitalDelayType := 1000 ns; -- 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";--"mt28f800b5.mem"; UserPreload : BOOLEAN := FALSE;--TRUE; LongTimming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel --"mt28f800b5" ); PORT ( 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'; --address A12 : IN std_ulogic := 'U'; --lines 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'; -- DQ15/A-1 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'; -- CENeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RPNeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U'; BYTENeg : IN std_ulogic := 'U'; VPP : IN std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of mt28f800b5 : ENTITY IS TRUE; END mt28f800b5; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of mt28f800b5 IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "mt28f800b5"; CONSTANT MaxData : NATURAL := 16#FF#; CONSTANT SecSize : NATURAL := 16#1FFFF#; CONSTANT MemSize : NATURAL := 16#FFFFF#; CONSTANT SecNum : NATURAL := 8; CONSTANT SubSecNum : NATURAL := 4; CONSTANT HiAddrBit : NATURAL := 18; -- interconnect path delay signals 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 CENeg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL RPNeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; SIGNAL BYTENeg_ipd : std_ulogic := 'U'; SIGNAL VPP_ipd : std_ulogic := 'U'; --- internal delays SIGNAL POW_in : std_ulogic := '0'; SIGNAL POW_out : std_ulogic := '0'; SIGNAL BBEO_in : std_ulogic := '0'; SIGNAL BBEO_out : std_ulogic := '0'; SIGNAL PBEO_in : std_ulogic := '0'; SIGNAL PBEO_out : std_ulogic := '0'; SIGNAL MBEO_in : std_ulogic := '0'; SIGNAL MBEO_out : std_ulogic := '0'; SIGNAL READY_out : std_ulogic := '0'; --tRS SIGNAL READY_in : std_ulogic := '0'; SIGNAL BUSY_out : std_ulogic := '0';--WE#(CE#)to valid status tWB SIGNAL BUSY_in : std_ulogic := '0'; SIGNAL REL_out : std_ulogic := '0';--Boot Block Relock Delay tREL SIGNAL REL_in : std_ulogic := '0'; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays POW :VitalBuf(POW_out , POW_in , (tdevice_POW ,UnitDelay)); BBEO :VitalBuf(BBEO_out , BBEO_in , (tdevice_BBEO ,UnitDelay)); PBEO :VitalBuf(PBEO_out , PBEO_in , (tdevice_PBEO ,UnitDelay)); MBEO :VitalBuf(MBEO_out , MBEO_in , (tdevice_MBEO ,UnitDelay)); BUSY :VitalBuf(BUSY_out , BUSY_in , (tdevice_BUSY ,UnitDelay)); READY :VitalBuf(READY_out, READY_in, (tdevice_READY ,UnitDelay)); REL :VitalBuf(REL_out , REL_in , (tdevice_REL ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_0 : VitalWireDelay (A18_ipd, A18, tipd_A18); w_1 : VitalWireDelay (A17_ipd, A17, tipd_A17); w_2 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_3 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_4 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_5 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_6 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_7 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_8 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_9 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_10 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_11 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_12 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_13 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_14 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_15 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_16 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_17 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_18 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_19 : VitalWireDelay (DQ15_ipd, DQ15, tipd_DQ15); w_20 : VitalWireDelay (DQ14_ipd, DQ14, tipd_DQ14); w_21 : VitalWireDelay (DQ13_ipd, DQ13, tipd_DQ13); w_22 : VitalWireDelay (DQ12_ipd, DQ12, tipd_DQ12); w_23 : VitalWireDelay (DQ11_ipd, DQ11, tipd_DQ11); w_24 : VitalWireDelay (DQ10_ipd, DQ10, tipd_DQ10); w_25 : VitalWireDelay (DQ9_ipd, DQ9, tipd_DQ9); w_26 : VitalWireDelay (DQ8_ipd, DQ8, tipd_DQ8); w_27 : VitalWireDelay (DQ7_ipd, DQ7, tipd_DQ7); w_28 : VitalWireDelay (DQ6_ipd, DQ6, tipd_DQ6); w_29 : VitalWireDelay (DQ5_ipd, DQ5, tipd_DQ5); w_30 : VitalWireDelay (DQ4_ipd, DQ4, tipd_DQ4); w_31 : VitalWireDelay (DQ3_ipd, DQ3, tipd_DQ3); w_32 : VitalWireDelay (DQ2_ipd, DQ2, tipd_DQ2); w_33 : VitalWireDelay (DQ1_ipd, DQ1, tipd_DQ1); w_34 : VitalWireDelay (DQ0_ipd, DQ0, tipd_DQ0); w_35 : VitalWireDelay (OENeg_ipd, OENeg, tipd_OENeg); w_36 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_37 : VitalWireDelay (RPNeg_ipd, RPNeg, tipd_RPNeg); w_38 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); w_39 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); w_40 : VitalWireDelay (BYTENeg_ipd, BYTENeg, tipd_BYTENeg); w_41 : VitalWireDelay (VPP_ipd, VPP, tipd_VPP); END BLOCK; --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior: BLOCK PORT ( A : IN std_logic_vector(HiAddrBit downto 0) := (OTHERS => 'U'); DIn : IN std_logic_vector(15 downto 0) := (OTHERS => 'U'); DOut : OUT std_ulogic_vector(15 downto 0) := (OTHERS => 'Z'); CENeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; RPNeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U'; BYTENeg : IN std_ulogic := 'U'; VPP : IN std_logic := 'U' ); PORT MAP ( 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, CENeg => CENeg_ipd, OENeg => OENeg_ipd, WENeg => WENeg_ipd, RPNeg => RPNeg_ipd, WPNeg => WPNeg_ipd, VPP => VPP_ipd, BYTENeg => BYTENeg_ipd ); -- State Machine : State_Type TYPE state_type IS ( READ_ARRAY, READ_IDENT, READ_STATUS, CLR_STATUS, W_SETUP, WRITE_T, WRITE_EX, E_SETUP, ERS_T, ERS_EX, SERS_T, SERS, SERS_RA, SERS_RS, RES_T ); --Array of Sub sector start-end address within sector TYPE SubSecSEAddr IS ARRAY (0 TO SubSecNum-1) OF NATURAL; --Addresses of all Sectors devided to sub sectors TYPE SubSecAddr IS ARRAY (0 TO 1) OF SubSecSEAddr; --Flash Memory Array TYPE SecType IS ARRAY (0 TO SecSize) OF INTEGER RANGE -1 TO MaxData; TYPE MemArray IS ARRAY (0 TO SecNum-1) OF SecType; TYPE WDataType IS ARRAY ( 0 TO 1) OF INTEGER RANGE -1 TO MaxData; TYPE WAddrType IS ARRAY ( 0 TO 1) OF INTEGER RANGE -1 TO SecSize; -- states SIGNAL current_state : state_type; SIGNAL next_state : state_type; -- powerup SIGNAL PoweredUp : std_logic := '0'; --zero delay signals SIGNAL DOut_zd : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); SIGNAL DOut_Pass : std_logic_vector(15 downto 0):=(OTHERS=>'Z'); SIGNAL PDONE : std_logic := '1'; --Prog. Done SIGNAL PSTART : std_logic := '0'; --Start Programming --Program error occured SIGNAL PERR : std_logic := '0'; SIGNAL EDONE : std_logic := '1'; --Ers. Done SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL ESUSP : std_logic := '0'; --Suspend Erase SIGNAL ERES : std_logic := '0'; --Resume Erase --Erase error occured SIGNAL EERR : std_logic := '0'; --Command Register SIGNAL write : std_logic := '0'; SIGNAL read : std_logic := '0'; --Sector Address SIGNAL SA : INTEGER RANGE -1 TO SecNum-1 := -1; SIGNAL SubSect : INTEGER RANGE -1 TO SubSecNum-1 := -1; SIGNAL ErsSec : NATURAL RANGE 0 TO SecNum-1 := 0; SIGNAL ErsSubSec : NATURAL RANGE 0 TO SubSecNum-1 := 0; --Address within sector SIGNAL Address : NATURAL RANGE 0 TO SecSize := 0; SIGNAL IDAddr : std_logic; SIGNAL D_tmp0 : NATURAL RANGE 0 TO MaxData; SIGNAL D_tmp1 : NATURAL RANGE 0 TO MaxData; SHARED VARIABLE WData : WDataType:=(OTHERS=>0); SHARED VARIABLE WAddr : WAddrType:=(OTHERS=>-1); SHARED VARIABLE WSec : NATURAL RANGE 0 TO SecNum-1 := 0; SHARED VARIABLE WSubSec : NATURAL RANGE 0 TO SubSecNum-1 := 0; SIGNAL RST : std_logic := '1'; SIGNAL reseted : std_logic := '0'; SIGNAL OK_to_l : std_logic := '1'; -- Mem(SecAddr)(Address).... SHARED VARIABLE Mem : MemArray := (OTHERS =>(OTHERS=> MaxData)); --starting addresses of subsectors SHARED VARIABLE sssa : SubSecAddr := ((16#00000#,16#04000#,16#06000#,16#08000#),--B ( 16#00000#,16#18000#,16#1A000#,16#1C000#));--T SHARED VARIABLE ssea : SubSecAddr:= ((16#03FFF#,16#05FFF#,16#07FFF#,16#1FFFF#),--B ( 16#17FFF#,16#19FFF#,16#1BFFF#,16#1FFFF#));--T SHARED VARIABLE StatusReg : std_logic_vector (7 DOWNTO 0):= "10000000"; SHARED VARIABLE Boot_Prot : std_logic := '1'; -- timing check violation SIGNAL Viol : X01 := '0'; --Address of variable size sector (bottom or top boot sector) SIGNAL VarSect : INTEGER := -1; SIGNAL vs : INTEGER;--0 if VarSect = 0 else 1 -- Access time variables SHARED VARIABLE FROMCE : BOOLEAN; SHARED VARIABLE FROMOE : BOOLEAN; PROCEDURE RestoreSectAddr ( VARIABLE A : IN NATURAL RANGE 0 TO MemSize; VARIABLE SecAddr : INOUT NATURAL RANGE 0 TO SecNum; VARIABLE A_tmp : INOUT NATURAL RANGE 0 TO SecSize ) IS BEGIN FOR i IN 0 TO SecNum-1 LOOP IF A >= i*(SecSize+1) AND A <= i*(SecSize+1) + SecSize THEN SecAddr := i; A_tmp := A - i*(SecSize + 1); END IF; END LOOP; END RestoreSectAddr; BEGIN --------------------------------------------------------------------------- --VarSect --------------------------------------------------------------------------- VarSect <= SecNum-1 WHEN TimingModel(15) = 'T' ELSE 0; vs <= 1 WHEN TimingModel(15)='T' ELSE 0; ---------------------------------------------------------------------------- --Power Up time 100 ns; --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 100 ns; RST <= RPNeg AFTER 60 ns; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A, Din, CENeg, OENeg, WENeg, RPNeg, WPNeg, VPP) -- Timing Check Variables VARIABLE Tviol_A0_CENeg : X01 := '0'; VARIABLE TD_A0_CENeg : VitalTimingDataType; VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_CENeg : X01 := '0'; VARIABLE TD_DQ0_CENeg : VitalTimingDataType; VARIABLE Tviol_DQ0_WENeg : X01 := '0'; VARIABLE TD_DQ0_WENeg : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_F : X01 := '0'; VARIABLE TD_CENeg_WENeg_F : 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_VPP_CENeg : X01 := '0'; VARIABLE TD_VPP_CENeg : VitalTimingDataType; VARIABLE Tviol_VPP_WENeg : X01 := '0'; VARIABLE TD_VPP_WENeg : VitalTimingDataType; VARIABLE Tviol_WPNeg_CENeg : X01 := '0'; VARIABLE TD_WPNeg_CENeg : VitalTimingDataType; VARIABLE Tviol_WPNeg_WENeg : X01 := '0'; VARIABLE TD_WPNeg_WENeg : VitalTimingDataType; VARIABLE Pviol_RPNeg : X01 := '0'; VARIABLE PD_RPNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between A and CENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_A0_CENeg, SetupLow => tsetup_A0_CENeg, HoldHigh => thold_A0_CENeg, HoldLow => thold_A0_CENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_CENeg, Violation => Tviol_A0_CENeg ); -- Setup/Hold Check between A and WENeg VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_A0_WENeg, SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, HoldLow => thold_A0_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_A0_WENeg, Violation => Tviol_A0_WENeg ); -- Setup/Hold Check between DQ and CENeg VitalSetupHoldCheck ( TestSignal => DQ0, TestSignalName => "DQ", RefSignal => CENeg, RefSignalName => "CE#", 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 ); -- Setup/Hold Check between DQ and WENeg VitalSetupHoldCheck ( TestSignal => DQ0, TestSignalName => "DQ", RefSignal => WENeg, RefSignalName => "WE#", 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 ); -- Setup/Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => CENeg, RefSignalName => "CE#", SetupLow => tsetup_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_F, Violation => Tviol_WENeg_CENeg_F ); -- Setup/Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => CENeg, RefSignalName => "CE#", HoldLow => thold_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_R, Violation => Tviol_WENeg_CENeg_R ); -- Setup/Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_F, Violation => Tviol_CENeg_WENeg_F ); -- Setup/Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_R, Violation => Tviol_CENeg_WENeg_R ); -- Setup/Hold Check between VPP and WENeg VitalSetupHoldCheck ( TestSignal => VPP, TestSignalName => "VPP", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_VPP_WENeg, CheckEnabled => CENeg ='0' AND (current_state=E_SETUP OR current_state=W_SETUP), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_VPP_WENeg, Violation => Tviol_VPP_WENeg ); -- Setup/Hold Check between VPP and CENeg VitalSetupHoldCheck ( TestSignal => VPP, TestSignalName => "VPP", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_VPP_CENeg, CheckEnabled => WENeg ='0' AND (current_state=E_SETUP OR current_state=W_SETUP), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_VPP_CENeg, Violation => Tviol_VPP_CENeg ); -- Setup/Hold Check between WPNeg and WENeg VitalSetupHoldCheck ( TestSignal => WPNeg, TestSignalName => "WPNeg", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_WPNeg_WENeg, CheckEnabled => CENeg ='0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_WENeg, Violation => Tviol_WPNeg_WENeg ); -- Setup/Hold Check between WPNeg and CENeg VitalSetupHoldCheck ( TestSignal => WPNeg, TestSignalName => "WPNeg", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_WPNeg_CENeg, CheckEnabled => WENeg ='0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_CENeg, Violation => Tviol_WPNeg_CENeg ); -- PulseWidth Check for RPNeg VitalPeriodPulseCheck ( TestSignal => RPNeg, TestSignalName => "RP#", PulseWidthLow => tpw_RPNeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RPNeg, Violation => Pviol_RPNeg ); -- PulseWidth Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WE#", PulseWidthHigh => tpw_WENeg_posedge, PulseWidthLow => tpw_WENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => Pviol_WENeg ); -- PulseWidth Check for CENeg VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CE#", PulseWidthHigh => tpw_CENeg_posedge, PulseWidthLow => tpw_CENeg_negedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_CENeg, Violation => Pviol_CENeg ); Violation := Tviol_A0_CENeg OR Tviol_A0_WENeg OR Tviol_DQ0_CENeg OR Tviol_DQ0_WENeg OR Tviol_WENeg_CENeg_F OR Tviol_WENeg_CENeg_R OR Tviol_CENeg_WENeg_F OR Tviol_CENeg_WENeg_R OR Tviol_VPP_CENeg OR Tviol_VPP_WENeg OR Tviol_WPNeg_CENeg OR Tviol_WPNeg_WENeg OR Pviol_RPNeg OR Pviol_WENeg OR Pviol_CENeg ; 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, RPNeg, RST, READY_out,PoweredUp) VARIABLE R : std_logic; BEGIN IF PoweredUp='1' THEN --Hardware reset timing control IF rising_edge(RPNeg) THEN IF RST='1' THEN --RP# pulse < tRP READY_in <= '0'; R:='0'; ELSE READY_in <= '1'; reseted <= '0'; R:='1'; END IF; ELSIF rising_edge (READY_out) THEN R:='0'; END IF; IF RPNeg='1' AND (R='0' OR READY_out='1') THEN current_state <= next_state; READY_in <= '0'; reseted <= '1'; ELSIF ( RPNeg='0' AND RST='0')OR ( RPNeg='0' AND RST='0' AND READY_out='0')OR ( RPNeg='1' AND RST='0' AND READY_out='0')OR ( RPNeg='1' AND RST='1' AND READY_out='0') THEN --no state transition while RP# low current_state <= READ_ARRAY; --reset start reseted <= '0'; END IF; ELSE current_state <= READ_ARRAY; -- reset reseted <= '0'; END IF; END PROCESS StateTransition; --process that generates write or read signals depending on cycle write_dc: PROCESS (WENeg,CENeg,OENeg, RPNeg, reseted) BEGIN IF RPNeg /= '0' AND reseted = '1' THEN IF (WENeg = '0') AND (CENeg = '0') AND (OENeg = '1') THEN write <= '1'; ELSIF (WENeg = '1' OR CENeg = '1') AND OENeg = '1' THEN write <= '0'; ELSE write <= 'X'; END IF; END IF; IF ((WENeg = '1') AND (CENeg = '0') AND (OENeg = '0') )THEN read <= '1'; ELSE read <= '0'; END IF; END PROCESS write_dc; --------------------------------------------------------------------------- --Latch address and data on rising edge of WE# or CE# what ever comes first -- also Write cycle decode --------------------------------------------------------------------------- BusCycleDecode : PROCESS(A, Din, write, WENeg, CENeg, OENeg, BYTENeg, reseted) VARIABLE SA_tmp : NATURAL RANGE 0 TO SecNum-1; VARIABLE A_tmp1 : NATURAL RANGE 0 TO SecSize; VARIABLE i : NATURAL; BEGIN IF reseted='1' THEN IF (rising_edge(WENeg) AND CENeg='0' AND OENeg = '1' ) OR (rising_edge(CENeg) AND WENeg= '0' AND OENeg = '1') OR (falling_edge(OENeg) AND WENeg='1' AND CENeg = '0' ) OR (falling_edge(CENeg) AND WENeg='1' AND OENeg = '0' ) OR ((A'EVENT OR (Din(15)'EVENT AND BYTENeg='0' AND Din(15) /= Dout_zd(15)) )AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN SA_tmp:= to_nat( A(HiAddrBit DOWNTO 16)); IF (BYTENeg = '0') THEN A_tmp1 := to_nat( A(15 downto 0) & Din(15) ); ELSE A_tmp1 := to_nat( A(15 downto 0) & '0' ); END IF; IDAddr <= A(0); END IF; IF (rising_edge(WENeg) OR rising_edge(CENeg)) AND write = '1' THEN D_tmp0 <= to_nat(Din(7 DOWNTO 0)); IF BYTENeg = '1' THEN D_tmp1 <= to_nat(Din(15 DOWNTO 8)); END IF; SA <= SA_tmp; Address <= A_tmp1; FOR i IN 0 TO SubSecNum-1 LOOP IF A_tmp1 >= sssa(vs)(i) AND A_tmp1 <= ssea(vs)(i) THEN SubSect <= i; END IF; END LOOP; END IF; IF falling_edge(CENeg) OR falling_edge(OENeg) OR ((A'EVENT OR (Din(15)'EVENT AND BYTENeg = '0')) AND WENeg = '1' AND CENeg = '0' AND OENeg = '0') THEN SA <= SA_tmp; Address <= A_tmp1; FOR i IN 0 TO SubSecNum-1 LOOP IF A_tmp1 >= sssa(vs)(i) AND A_tmp1 <= ssea(vs)(i) THEN SubSect <= i; END IF; END LOOP; END IF; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Write Operations --------------------------------------------------------------------------- ProgTime :PROCESS(PSTART, reseted) VARIABLE duration : time; BEGIN IF LongTimming THEN duration := tdevice_POW; ELSE duration := tdevice_POW / 2; END IF; IF rising_edge(reseted) THEN PDONE <= '1'; -- reset done, programing terminated StatusReg(7):='1'; ELSIF reseted = '1' THEN IF rising_edge(PSTART) AND PDONE='1' THEN IF (WSec /= VarSect OR (WSec = VarSect AND ((vs=1 AND (WSubSec/=3 OR (WSubSec=3 AND Boot_Prot='0'))) OR(vs=0 AND(WSubSec/=0 OR(WSubSec=0 AND Boot_Prot='0')))))) AND StatusReg(3)='0' THEN PDONE <= '0', '1' AFTER (duration); --increment wrcnt --set StatusReg(4) if wrcnt is greater then ? END IF; END IF; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Erase Operations --------------------------------------------------------------------------- ErsTime :PROCESS(ESTART, ESUSP, ERES, reseted) VARIABLE elapsed : time; VARIABLE duration : time; VARIABLE start : time; VARIABLE seo : time; BEGIN IF rising_edge(reseted) THEN EDONE <= '1'; StatusReg(7):='1'; ELSIF reseted = '1' THEN IF rising_edge(ESTART) AND EDONE = '1' THEN IF (ErsSec /= VarSect OR (ErsSec = VarSect AND ((vs=1 AND (ErsSubSec/=3 OR (ErsSubSec=3 AND Boot_Prot='0'))) OR(vs=0 AND(ErsSubSec/=0 OR(ErsSubSec=0 AND Boot_Prot='0'))))))AND StatusReg(3)='0' THEN IF ErsSec = VarSect THEN CASE (ErsSubSec)IS WHEN 0 => IF vs= 0 THEN seo:= tdevice_BBEO; ELSE seo:= tdevice_MBEO; END IF; WHEN 1|2 => seo := tdevice_PBEO; WHEN 3 => IF vs= 1 THEN seo:= tdevice_BBEO; ELSE seo:= tdevice_MBEO; END IF; END CASE; ELSE seo:= tdevice_MBEO; END IF; IF LongTimming THEN duration := seo; ELSE duration := seo/1000; END IF; elapsed := 0 ns; EDONE <= '0', '1' AFTER duration; start := NOW; --increment erscnt --set StatusReg(5) if erscnt is greater then ? 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 IF current_state = SERS_T THEN EDONE <= '0', '1' AFTER duration; start := NOW; ELSE duration := duration + tdevice_BUSY; EDONE <= '0', '1' AFTER duration; start := NOW ; END IF; END IF; END IF; END PROCESS; REL_CTRL: PROCESS(PDONE,EDONE,REL_out) BEGIN IF (rising_edge(PDONE) AND WSec=VarSect AND ((vs=0 AND WSubSec=0) OR (vs=1 AND WSubSec=3))) OR (rising_edge(EDONE) AND ErsSec=VarSect AND ((vs=0 AND ErsSubSec=0) OR (vs=1 AND ErsSubSec=3))) THEN REL_in <= '1'; OK_to_l<='0'; ELSIF rising_edge(REL_out)THEN REL_in <= '0'; OK_to_l<='1'; END IF; END PROCESS REL_CTRL; WP_CTRL: PROCESS(WPNeg) BEGIN --Hardware Write Protection IF rising_edge(WPNeg)THEN Boot_Prot := '0'; ELSIF falling_edge(WPNeg) THEN IF OK_to_l='1' THEN Boot_Prot := '1'; ELSE ASSERT FALSE REPORT " Boot block relock delay time has not elapsed" & ", simulation may be inaccurate due to timing violations" SEVERITY WARNING; END IF; END IF; END PROCESS WP_CTRL; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(write, Address,D_tmp0,PDONE, EDONE, BUSY_out, reseted, PERR, EERR, VPP) --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO MaxData := 0; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(write) THEN DataLo := D_tmp0; END IF; IF reseted /= '1' THEN next_state <= current_state; ELSE CASE current_state IS WHEN READ_ARRAY => IF falling_edge(write) THEN IF (DataLo= 16#90#)THEN next_state <= READ_IDENT; ELSIF (DataLo= 16#70#)THEN next_state <= READ_STATUS; ELSIF (DataLo= 16#50#)THEN next_state <= CLR_STATUS; ELSIF DataLo= 16#20# THEN next_state <= E_SETUP; ELSIF (DataLo=16#10# OR DataLo=16#40#)THEN next_state <= W_SETUP; END IF; END IF; WHEN READ_IDENT => IF falling_edge(write) THEN IF (DataLo= 16#FF#)THEN next_state <= READ_ARRAY; ELSIF (DataLo= 16#70#)THEN next_state <= READ_STATUS; ELSIF (DataLo= 16#50#)THEN next_state <= CLR_STATUS; ELSIF (DataLo= 16#20#) THEN next_state <= E_SETUP; ELSIF (DataLo=16#10# OR DataLo=16#40#)THEN next_state <= W_SETUP; END IF; END IF; WHEN READ_STATUS => IF falling_edge(write) THEN IF (DataLo= 16#FF#)THEN next_state <= READ_ARRAY; ELSIF (DataLo= 16#90#)THEN next_state <= READ_IDENT; ELSIF (DataLo= 16#50#)THEN next_state <= CLR_STATUS; ELSIF (DataLo= 16#20#) THEN next_state <= E_SETUP; ELSIF (DataLo= 16#10# OR DataLo= 16#40#)THEN next_state <= W_SETUP; END IF; END IF; WHEN CLR_STATUS => IF falling_edge(write) THEN IF (DataLo= 16#FF#)THEN next_state <= READ_ARRAY; ELSIF (DataLo= 16#90#)THEN next_state <= READ_IDENT; ELSIF (DataLo= 16#70#)THEN next_state <= READ_STATUS; ELSIF (DataLo= 16#20#)THEN next_state <= E_SETUP; ELSIF (DataLo= 16#10# OR DataLo= 16#40#)THEN next_state <= W_SETUP; END IF; END IF; WHEN W_SETUP => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF falling_edge(write) THEN IF VPP='1' AND StatusReg(3)='0' AND(SA /= VarSect OR(SA =VarSect AND ((vs=1 AND (SubSect/=3 OR ( SubSect=3 AND Boot_Prot='0'))) OR (vs=0 AND (SubSect/=0 OR ( SubSect=0 AND Boot_Prot='0'))))))THEN next_state <= WRITE_T; ELSE next_state <= READ_STATUS; END IF; END IF; WHEN WRITE_T => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN next_state <= WRITE_EX; END IF; WHEN WRITE_EX => IF falling_edge(VPP) OR rising_edge(PDONE) THEN next_state <= READ_STATUS; END IF; WHEN E_SETUP => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF falling_edge(write) THEN IF VPP='1' AND (DataLo= 16#D0#) AND StatusReg(3)='0' AND (SA /= VarSect OR(SA =VarSect AND ((vs=1 AND (SubSect/=3 OR ( SubSect=3 AND Boot_Prot='0'))) OR (vs=0 AND (SubSect/=0 OR ( SubSect=0 AND Boot_Prot='0'))))))THEN next_state <= ERS_T; ELSE next_state <= READ_STATUS; END IF; END IF; WHEN ERS_T => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN next_state <= ERS_EX; END IF; WHEN ERS_EX => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF rising_edge(EDONE) OR falling_edge(EERR) THEN next_state <= READ_STATUS; ELSIF EERR /= '1' THEN IF falling_edge(write) THEN IF DataLo = 16#B0# AND VPP='1' THEN next_state <= SERS_T; END IF; END IF; END IF; WHEN SERS_T => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN next_state <= SERS; ELSIF falling_edge(write) THEN IF DataLo = 16#D0# THEN next_state <= ERS_EX; END IF; END IF; WHEN SERS => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF falling_edge(write) THEN IF (DataLo= 16#FF#)THEN next_state <= SERS_RA; ELSIF (DataLo= 16#70#)THEN next_state <= SERS_RS; ELSIF (DataLo= 16#D0#)THEN next_state <= RES_T; END IF; END IF; WHEN SERS_RA => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF falling_edge(write) THEN IF (DataLo= 16#D0#)THEN next_state <= RES_T; ELSIF (DataLo= 16#70#)THEN next_state <= SERS_RS; END IF; END IF; WHEN SERS_RS => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF falling_edge(write) THEN IF (DataLo= 16#D0#)THEN next_state <= RES_T; ELSIF (DataLo= 16#FF#)THEN next_state <= SERS_RA; END IF; END IF; WHEN RES_T => IF falling_edge(VPP) THEN next_state <= READ_STATUS; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN next_state <= ERS_EX; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS(write, read, Address, D_tmp0, D_tmp1, SA, PDONE, EDONE, BUSY_out, RST, reseted,OENeg, current_state, BYTENeg, READY_out,VPP) --Program VARIABLE cnt : NATURAL RANGE 0 TO 31 := 0; VARIABLE oe : boolean := FALSE; VARIABLE old_bit : std_logic_vector(7 downto 0); VARIABLE new_bit : std_logic_vector(7 downto 0); VARIABLE old_int : INTEGER RANGE -1 to MaxData; VARIABLE new_int : INTEGER RANGE -1 to MaxData; VARIABLE wr_cnt : NATURAL RANGE 0 TO 31; --DATA High Byte VARIABLE DataHi : NATURAL RANGE 0 TO MaxData := 0; --DATA Low Byte VARIABLE DataLo : NATURAL RANGE 0 TO MaxData := 0; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF falling_edge(write) THEN DataLo := D_tmp0; DataHi := D_tmp1; END IF; oe := rising_edge(read) OR (read = '1' AND (Address'EVENT OR SA'EVENT OR BYTENEg'EVENT)); IF reseted = '1' THEN CASE current_state IS WHEN READ_ARRAY => IF oe THEN IF Mem(SA)(Address) = -1 THEN DOut_zd(7 downto 0) <= (OTHERS=>'X'); ELSE DOut_zd(7 downto 0) <= to_slv(Mem(SA)(Address),8); END IF; IF BYTENeg = '1' THEN IF Mem(SA)(Address+1) = -1 THEN DOut_zd(15 downto 8)<= (OTHERS=>'X'); ELSE DOut_zd(15 downto 8)<=to_slv(Mem(SA)(Address+1),8); END IF; END IF; END IF; PERR <='0'; EERR <='0'; WHEN READ_IDENT => IF oe THEN IF IDAddr='0' THEN DOut_zd(7 downto 0) <= to_slv(16#89#,8); ELSE IF vs=1 THEN DOut_zd(7 downto 0) <= to_slv(16#9C#,8); ELSE DOut_zd(7 downto 0) <= to_slv(16#9D#,8); END IF; END IF; IF BYTENeg = '1' THEN IF IDAddr='0' THEN DOut_zd(15 downto 8) <= to_slv(16#00#,8); ELSE DOut_zd(15 downto 8) <= to_slv(16#88#,8); END IF; END IF; END IF; WHEN READ_STATUS => IF oe THEN DOut_zd(7 downto 0) <= StatusReg; IF BYTENeg = '1' THEN DOut_zd(15 downto 8) <= (OTHERS=> '0'); ELSE DOut_zd(15 downto 8) <= (OTHERS=> 'Z'); END IF; END IF; WHEN CLR_STATUS => StatusReg(5 DOWNTO 3) := (OTHERS=> '0'); WHEN W_SETUP => IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; PERR <='1'; ELSIF falling_edge(write) THEN IF (VPP='1') AND StatusReg(3)='0' AND (SA /= VarSect OR(SA =VarSect AND ((vs=1 AND (SubSect/=3 OR(SubSect=3 AND Boot_Prot='0'))) OR(vs=0 AND (SubSect/=0 OR (SubSect=0 AND Boot_Prot='0'))))))THEN BUSY_in <= '1'; PSTART <= '1', '0' AFTER 1 ns; WData(0) := -1; WData(1) := -1; IF Viol = '0' THEN WData(0) := DataLo; WData(1) := DataHi; END IF; WAddr(0) := Address; WSec := SA; WSubSec := SubSect; IF BYTENeg = '1' THEN WAddr(1) := WAddr(0) + 1; ELSE WAddr(1) := -1; END IF; ELSE StatusReg(7):='1'; PERR <='1'; StatusReg(4):='1'; END IF; END IF; WHEN WRITE_T => IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; PERR <='1'; BUSY_in<='0'; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN BUSY_in<='0'; StatusReg(7):='0'; END IF; WHEN WRITE_EX => IF oe THEN DOut_zd(7 downto 0) <= StatusReg; IF BYTENeg = '1' THEN DOut_zd(15 downto 8) <= (OTHERS=> '0'); ELSE DOut_zd(15 downto 8) <= (OTHERS=> 'Z'); END IF; END IF; IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; PERR <='1'; ELSIF rising_edge(PDONE) THEN StatusReg(7):='1'; END IF; IF PERR/='1' THEN IF WAddr(1) < 0 THEN wr_cnt := 0; ELSE wr_cnt := 1; END IF; FOR i IN wr_cnt downto 0 LOOP new_int:= WData(i); old_int:=Mem(WSec)(WAddr(i)); WData(i):= -1; IF new_int>-1 THEN new_bit:=to_slv(new_int,8); IF old_int>-1 THEN old_bit:=to_slv(old_int,8); FOR j IN 0 TO 7 LOOP IF old_bit(j) = '0' THEN new_bit(j):='0'; END IF; END LOOP; new_int:=to_nat(new_bit); END IF; WData(i):= new_int; END IF; Mem(WSec)(WAddr(i)) := -1; END LOOP; IF PDONE = '1' AND (NOT PERR'EVENT) THEN FOR i IN wr_cnt downto 0 LOOP Mem(WSec)(WAddr(i)) := WData(i); WData(i):= -1; END LOOP; END IF; END IF; WHEN E_SETUP => IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; EERR <='1'; ELSIF falling_edge(write) THEN IF VPP='1' AND (DataLo= 16#D0#) AND StatusReg(3)='0' AND (SA /= VarSect OR(SA =VarSect AND ((vs=1 AND (SubSect/=3 OR ( SubSect=3 AND Boot_Prot='0'))) OR (vs=0 AND (SubSect/=0 OR ( SubSect=0 AND Boot_Prot='0'))))))THEN ErsSec <= SA; ErsSubSec <= SubSect; BUSY_in <= '1'; ESTART <= '1', '0' AFTER 1 ns; ESUSP <= '0'; ERES <= '0'; ELSE StatusReg(4):='1'; StatusReg(5):='1'; END IF; END IF; WHEN ERS_T => IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; EERR <='1'; BUSY_in<='0'; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN BUSY_in<='0'; StatusReg(7):='0'; END IF; WHEN ERS_EX => IF oe THEN DOut_zd(7 downto 0) <= StatusReg; IF BYTENeg = '1' THEN DOut_zd(15 downto 8) <= (OTHERS=> '0'); ELSE DOut_zd(15 downto 8) <= (OTHERS=> 'Z'); END IF; END IF; IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; EERR <='1'; ELSIF rising_edge(EDONE) THEN StatusReg(7):='1'; END IF; IF EERR /= '1' THEN IF ErsSec = VarSect THEN IF(vs=1 AND((ErsSubSec=3 AND Boot_Prot='0') OR ErsSubSec/=3)) OR (vs=0 AND((ErsSubSec=0 AND Boot_Prot='0')OR ErsSubSec/=0))THEN Mem(ErsSec)(sssa(vs)(ErsSubSec) TO ssea(vs)(ErsSubSec)):=(OTHERS => -1); END IF; ELSE Mem(ErsSec) := (OTHERS => -1); END IF; IF EDONE = '1' THEN IF ErsSec = VarSect THEN Mem(ErsSec)(sssa(vs)(ErsSubSec) TO ssea(vs)(ErsSubSec)):=(OTHERS=> MaxData); ELSE Mem(ErsSec) := (OTHERS => MaxData); END IF; ELSIF falling_edge(write) THEN IF DataLo = 16#B0# AND VPP='1' THEN BUSY_in <= '1'; ESUSP<='1', '0' AFTER 1 ns; END IF; END IF; END IF; WHEN SERS_T => IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; EERR <='1'; BUSY_in<='0'; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN BUSY_in <= '0'; StatusReg(7):='1'; StatusReg(6):='1'; END IF; IF falling_edge(write) THEN IF DataLo = 16#D0# THEN BUSY_in <= '0'; ERES <= '1', '0' AFTER 1 ns; StatusReg(7):='0'; StatusReg(6):='0'; END IF; END IF; WHEN SERS => IF oe THEN DOut_zd(7 downto 0) <= StatusReg; IF BYTENeg = '1' THEN DOut_zd(15 downto 8) <= (OTHERS=> '0'); ELSE DOut_zd(15 downto 8) <= (OTHERS=> 'Z'); END IF; END IF; IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; EERR <='1'; ELSIF falling_edge(write) THEN IF (DataLo= 16#D0#)THEN ERES <= '1', '0' AFTER 1 ns; BUSY_in <= '1'; END IF; END IF; WHEN SERS_RA => IF oe THEN IF (SA=ErsSec OR (SubSect=ErsSubSec AND SA= VarSect)) THEN DOut_zd(7 downto 0) <= StatusReg; IF BYTENeg = '1' THEN DOut_zd(15 downto 8) <= (OTHERS=> '0'); ELSE DOut_zd(15 downto 8) <= (OTHERS=> 'Z'); END IF; ELSE IF Mem(SA)(Address) = -1 THEN DOut_zd(7 downto 0) <= (OTHERS=>'X'); ELSE DOut_zd(7 downto 0) <= to_slv(Mem(SA)(Address),8); END IF; IF BYTENeg = '1' THEN IF Mem(SA)(Address+1) = -1 THEN DOut_zd(15 downto 8)<= (OTHERS=>'X'); ELSE DOut_zd(15 downto 8)<= to_slv(Mem(SA)(Address+1),8); END IF; END IF; END IF; END IF; IF falling_edge(VPP) THEN StatusReg(3):='1'; StatusReg(7):='1'; EERR <='1'; ELSIF falling_edge(write) THEN IF (DataLo= 16#D0#)THEN ERES <= '1', '0' AFTER 1 ns; BUSY_in <= '1'; END IF; END IF; WHEN SERS_RS => IF oe THEN DOut_zd(7 downto 0) <= StatusReg; IF BYTENeg = '1' THEN DOut_zd(15 downto 8) <= (OTHERS=> '0'); ELSE DOut_zd(15 downto 8) <= (OTHERS=> 'Z'); END IF; END IF; IF falling_edge(VPP) THEN StatusReg(7):='1'; StatusReg(3):='1'; EERR <='1'; ELSIF falling_edge(write) THEN IF (DataLo= 16#D0#)THEN ERES <= '1', '0' AFTER 1 ns; BUSY_in <= '1'; END IF; END IF; WHEN RES_T => IF falling_edge(VPP) THEN StatusReg(7):='1'; StatusReg(6) := '0'; StatusReg(3):='1'; EERR <='1'; BUSY_in<='0'; ELSIF BUSY_out = '1' AND BUSY_out'EVENT THEN BUSY_in <= '0'; StatusReg(7) := '0'; StatusReg(6) := '0'; END IF; END CASE; END IF; --Output Disable Control IF (OENeg = '1') OR (RPNeg = '0' AND RST = '0') THEN DOut_zd <= (OTHERS=>'Z'); ELSE IF (BYTENeg = '0') THEN DOut_zd(15 downto 8) <= (OTHERS =>'Z'); END IF; END IF; END PROCESS Functional; DQValueGen : PROCESS( DOut_zd ) VARIABLE ValidData : std_logic_vector(15 downto 0); VARIABLE CEDQ_t : TIME; VARIABLE OEDQ_t : TIME; VARIABLE ADDRDQ_t : TIME; BEGIN IF DOut_zd(0) /= 'Z' THEN CEDQ_t := -CENeg'LAST_EVENT + tpd_CENeg_DQ0(trz0); OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_DQ0(trz0); ADDRDQ_t := -A'LAST_EVENT + tpd_A0_DQ0(tr01);-- IF ( BYTENeg = '0' ) AND (DIn(15)'LAST_EVENT < A'LAST_EVENT )THEN ADDRDQ_t := -DIn(15)'LAST_EVENT + tpd_A0_DQ0(tr01);-- END IF; FROMOE := (OEDQ_t >= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t > OEDQ_t) AND (CEDQ_t > 0 ns); IF BYTENeg = '0' THEN ValidData := "ZZZZZZZZXXXXXXXX"; ELSE ValidData := "XXXXXXXXXXXXXXXX"; END IF; IF ((ADDRDQ_t > 0 ns) AND (((ADDRDQ_t > CEDQ_t) AND FROMCE) OR ((ADDRDQ_t > OEDQ_t) AND FROMOE))) THEN DOut_Pass <= ValidData, DOut_zd AFTER ADDRDQ_t; ELSE DOut_Pass <= DOut_zd; END IF; ELSE DOut_Pass <= DOut_zd; FROMOE := TRUE; FROMCE := TRUE; END IF; END PROCESS DQValueGen; --------------------------------------------------------------------------- ---- File Read Section - Preload Control --------------------------------------------------------------------------- MemPreload : PROCESS -- text file input variables FILE mem_file : text is mem_file_name; VARIABLE ind : NATURAL RANGE 0 TO MemSize:= 0; VARIABLE ind_sect : NATURAL RANGE 0 TO SecNum:= 0; VARIABLE ind_addr : NATURAL RANGE 0 TO SecSize:= 0; VARIABLE buf : line; BEGIN --------------------------------------------------------------------------- --mt28f800b5 memory preload file format ----------------------------------- --------------------------------------------------------------------------- -- / - comment -- @aaaaa - stands for address within Memory -- dd -
is byte to be written at Mem(aaaaa++) -- (aaaaaa is incremented at every load) -- NO empty lines !!!!!!!!!!!!!!!! --------------------------------------------------------------------------- WAIT ON VarSect; Boot_prot :='1'; StatusReg := "10000000"; IF (mem_file_name /= "none" AND UserPreload ) THEN ind := 0; Mem := (OTHERS => (OTHERS => MaxData)); WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN --address ind := h(buf(2 to 6)); ELSE IF ind <= MemSize THEN RestoreSectAddr(ind, ind_sect, ind_addr); Mem(ind_sect)(ind_addr) := h(buf(1 to 2)); END IF; IF ind < MemSize THEN ind := ind + 1; ELSE REPORT "ERROR preloaded location out of range"; END IF; END IF; END LOOP; END IF; END PROCESS MemPreload; --------------------------------------------------------------------------- -- Path Delay Section for DOut signal --------------------------------------------------------------------------- D_Out_PathDelay_Gen : FOR i IN 0 TO 7 GENERATE PROCESS(DOut_Pass(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_Pass(i), GlitchData => D0_GlitchData, IgnoreDefaultDelay => TRUE, Mode => VitalTransport, RejectFastPath => false, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => FROMCE), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => FROMOE), 2 => (InputChangeTime => RPNeg'LAST_EVENT, PathDelay => tpd_RPNeg_DQ0, PathCondition => RPNeg='1'), 3 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => TRUE), 4 => (InputChangeTime => Din(15)'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => BYTENeg='0' ) ) ); END PROCESS; END GENERATE D_Out_PathDelay_Gen; D_Out_15_7_PathDelay_Gen : FOR i IN 8 TO 15 GENERATE PROCESS(DOut_Pass(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_Pass(i), GlitchData => D0_GlitchData, IgnoreDefaultDelay => TRUE, Mode => VitalTransport, RejectFastPath => false, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_DQ0, PathCondition => FROMCE), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_DQ0, PathCondition => FROMOE), 2 => (InputChangeTime => RPNeg'LAST_EVENT, PathDelay => tpd_RPNeg_DQ0, PathCondition => RPNeg='1'), 3 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_DQ0), PathCondition => TRUE ) ) ); END PROCESS; END GENERATE D_Out_15_7_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral;