-------------------------------------------------------------------------------- -- File name : am29lv010b.vhd -------------------------------------------------------------------------------- -- Copyright (C) 2002 Free Model Foundry; http://www.FreeModelFoundry.com -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2 as -- published by the Free Software Foundation. -- -- MODIFICATION HISTORY : -- -- version: | author: | mod date: | changes made: -- V1.0 B. Bizic 02 FEB 28 Initial release -- V1.1 B. Bizic 02 MAY 18 Problem with sector protection fixed -------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: AMD -- Technology: Flash Memory -- Part: AM29LV010B -- -- Description: 1Megabit (128K x 8-Bit) Uniform Sector Flash Memory -- -------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.vital_primitives.all; USE IEEE.vital_timing.all; LIBRARY FMF; USE FMF.gen_utils.all; USE FMF.conversions.all; -------------------------------------------------------------------------------- -- ENTITY DECLARATION -------------------------------------------------------------------------------- ENTITY AM29LV010B IS GENERIC ( protection_mask : std_logic_vector(0 to 7) := "00000000"; tWHWH1 : time := 9 us; -- Byte Prog Oper Time tWHWH2 : time := 0.7 sec; -- Sector Erase Oper Time tREADY : time := 20 us; -- RESET Low to Read Mode tSUSPEND : time := 15 us; -- erase oper suspend time tSETO : time := 50 us; -- sector erase time out tOH : time := 0 ns; -- Output Hold Time thold_OENeg_WENeg_read : time := 0 ns; -- tOEH_READ thold_OENeg_WENeg_poll : time := 10 ns; --tOEH_POLLING tRH : time := 40 ns; -- tipd delays: interconnect path delays tipd_A0 : VitalDelayType01 := VitalZeroDelay01; tipd_A1 : VitalDelayType01 := VitalZeroDelay01; tipd_A2 : VitalDelayType01 := VitalZeroDelay01; tipd_A3 : VitalDelayType01 := VitalZeroDelay01; tipd_A4 : VitalDelayType01 := VitalZeroDelay01; tipd_A5 : VitalDelayType01 := VitalZeroDelay01; tipd_A6 : VitalDelayType01 := VitalZeroDelay01; tipd_A7 : VitalDelayType01 := VitalZeroDelay01; tipd_A8 : VitalDelayType01 := VitalZeroDelay01; tipd_A9 : VitalDelayType01 := VitalZeroDelay01; tipd_A10 : VitalDelayType01 := VitalZeroDelay01; tipd_A11 : VitalDelayType01 := VitalZeroDelay01; tipd_A12 : VitalDelayType01 := VitalZeroDelay01; tipd_A13 : VitalDelayType01 := VitalZeroDelay01; tipd_A14 : VitalDelayType01 := VitalZeroDelay01; tipd_A15 : VitalDelayType01 := VitalZeroDelay01; tipd_A16 : VitalDelayType01 := VitalZeroDelay01; tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; -- tpd delays: propagation delays tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01; -- tACC tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; -- tDF,tOE tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; -- tDF,tCE -- tsetup values: setup times tsetup_A0_WENeg : VitalDelayType := UnitDelay; -- tAS tsetup_A0_CENeg : VitalDelayType := UnitDelay; -- tAS tsetup_DQ0_WENeg : VitalDelayType := UnitDelay; -- tDS tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; -- tDS tsetup_OENeg_WENeg : VitalDelayType := UnitDelay; -- tOES tsetup_CENeg_WENeg : VitalDelayType := UnitDelay; -- tCS tsetup_WENeg_CENeg : VitalDelayType := UnitDelay; -- tWS -- thold values: hold times thold_A0_WENeg : VitalDelayType := UnitDelay; -- tAH thold_A0_CENeg : VitalDelayType := UnitDelay; -- tAH thold_DQ0_WENeg : VitalDelayType := UnitDelay; -- tDH thold_DQ0_CENeg : VitalDelayType := UnitDelay; -- tDH thold_CENeg_WENeg : VitalDelayType := UnitDelay; -- tCH thold_WENeg_CENeg : VitalDelayType := UnitDelay; -- tWH -- trecovery values: release times trecovery_OENeg_WENeg : VitalDelayType := UnitDelay; -- tGHWL trecovery_OENeg_CENeg : VitalDelayType := UnitDelay; -- tGHEL -- tpw values: pulse widths tpw_WENeg_negedge : VitalDelayType := UnitDelay; -- tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; -- tWPH tpw_CENeg_negedge : VitalDelayType := UnitDelay; -- tCP(CE ctrl) tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCPH(CE ctrl) -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXOn; TimingModel : STRING := DefaultTimingModel ); PORT ( A0 : IN std_logic; ----------------------------- A1 : IN std_logic; -- A2 : IN std_logic; -- A3 : IN std_logic; -- A4 : IN std_logic; -- A5 : IN std_logic; -- A6 : IN std_logic; -- A7 : IN std_logic; -- A8 : IN std_logic; -- A9 : IN std_logic; -- 17 pin address bus 17 A10 : IN std_logic; -- A11 : IN std_logic; -- A12 : IN std_logic; -- A13 : IN std_logic; -- A14 : IN std_logic; -- A15 : IN std_logic; -- A16 : IN std_logic; ----------------------------- DQ0 : INOUT std_logic; ----------------------------- DQ1 : INOUT std_logic; -- DQ2 : INOUT std_logic; -- DQ3 : INOUT std_logic; -- 8 pin data bus DQ4 : INOUT std_logic; -- DQ5 : INOUT std_logic; -- DQ6 : INOUT std_logic; -- DQ7 : INOUT std_logic; ----------------------------- CENeg : IN std_logic; -- Chip Enable OENeg : IN std_logic; -- Output Enable WENeg : IN std_logic -- Write Enable ); ATTRIBUTE vital_level0 OF AM29LV010B : ENTITY IS True; END AM29LV010B; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral OF AM29LV010B IS ATTRIBUTE vital_level1 OF vhdl_behavioral : ARCHITECTURE IS False; SIGNAL A0_ipd : std_logic := 'X'; SIGNAL A1_ipd : std_logic := 'X'; SIGNAL A2_ipd : std_logic := 'X'; SIGNAL A3_ipd : std_logic := 'X'; SIGNAL A4_ipd : std_logic := 'X'; SIGNAL A5_ipd : std_logic := 'X'; SIGNAL A6_ipd : std_logic := 'X'; SIGNAL A7_ipd : std_logic := 'X'; SIGNAL A8_ipd : std_logic := 'X'; SIGNAL A9_ipd : std_logic := 'X'; SIGNAL A10_ipd : std_logic := 'X'; SIGNAL A11_ipd : std_logic := 'X'; SIGNAL A12_ipd : std_logic := 'X'; SIGNAL A13_ipd : std_logic := 'X'; SIGNAL A14_ipd : std_logic := 'X'; SIGNAL A15_ipd : std_logic := 'X'; SIGNAL A16_ipd : std_logic := 'X'; SIGNAL CE_ipd : std_logic := 'X'; SIGNAL OE_ipd : std_logic := 'X'; SIGNAL WE_ipd : std_logic := 'X'; --<< sector bounds description >>-- TYPE sectorBounds IS RECORD LAddr : natural; -- sector lower address UAddr : natural; -- sector upper address END RECORD; --<< Sector Address Table, unused sectors must have 0 for LAddr and UAddr >>- TYPE sectorAddressTable IS ARRAY (0 to 31) OF sectorBounds; --<< Memory Data Table (except timing data that come in through generics) >>- TYPE MemoryData IS RECORD deviceID : natural; -- device ID SectNum : natural; -- number of sectors DBusW : natural; -- data bus width ABusW : natural; -- address bus width AddrW : natural; -- addr width in command sequence -- (see command definitions) sectors : sectorAddressTable; -- sector addresses END RECORD; CONSTANT MemoryDataTable : MemoryData := ( deviceID => 16#6E#, -- D5h is the device ID sectNum => 8, -- number of sectors DBusW => 8, -- data bus width ABusW => 17, -- address bus width AddrW => 16, -- addr width in command sequence -- (see command definitions) sectors => ( 0 => (16#00000#, 16#03FFF#), -- SA0 1 => (16#04000#, 16#07FFF#), -- SA1 2 => (16#08000#, 16#0BFFF#), -- SA2 3 => (16#0C000#, 16#09FFF#), -- SA3 4 => (16#10000#, 16#13FFF#), -- SA4 5 => (16#14000#, 16#17FFF#), -- SA5 6 => (16#18000#, 16#1BFFF#), -- SA6 7 => (16#1C000#, 16#1FFFF#), -- SA7 8 to 31 => (16#00000#, 16#00000#) --unexisting sectors ) -- sector table ); BEGIN ------------------------------------------------------------------------ -- Wire Delays -- ------------------------------------------------------------------------ WireDelay : BLOCK BEGIN w_1: VitalWireDelay (A0_ipd, A0, tipd_A0); w_2: VitalWireDelay (A1_ipd, A1, tipd_A1); w_3: VitalWireDelay (A2_ipd, A2, tipd_A2); w_4: VitalWireDelay (A3_ipd, A3, tipd_A3); w_5: VitalWireDelay (A4_ipd, A4, tipd_A4); w_6: VitalWireDelay (A5_ipd, A5, tipd_A5); w_7: VitalWireDelay (A6_ipd, A6, tipd_A6); w_8: VitalWireDelay (A7_ipd, A7, tipd_A7); w_9: VitalWireDelay (A8_ipd, A8, tipd_A8); w_10: VitalWireDelay (A9_ipd, A9, tipd_A9); w_11: VitalWireDelay (A10_ipd, A10, tipd_A10); w_12: VitalWireDelay (A11_ipd, A11, tipd_A11); w_13: VitalWireDelay (A12_ipd, A12, tipd_A12); w_14: VitalWireDelay (A13_ipd, A13, tipd_A13); w_15: VitalWireDelay (A14_ipd, A14, tipd_A14); w_16: VitalWireDelay (A15_ipd, A15, tipd_A15); w_17: VitalWireDelay (A16_ipd, A16, tipd_A16); w_20: VitalWireDelay (CE_ipd, CENeg, tipd_CENeg); w_21: VitalWireDelay (OE_ipd, OENeg, tipd_OENeg); w_22: VitalWireDelay (WE_ipd, WENeg, tipd_WENeg); END BLOCK; ---------------------------------------------------------------------------- -- Main Behavior Block -- ---------------------------------------------------------------------------- VITALBehavior: BLOCK PORT (A : in std_logic_vector (MemoryDataTable.ABusW-1 DOWNTO 0); DQ : inout std_logic_vector (MemoryDataTable.DBusW-1 DOWNTO 0); CENeg : in std_logic; OENeg : in std_logic; WENeg : in std_logic ); PORT MAP ( A(0) => A0_ipd, A(1) => A1_ipd, A(2) => A2_ipd, A(3) => A3_ipd, A(4) => A4_ipd, A(5) => A5_ipd, A(6) => A6_ipd, A(7) => A7_ipd, A(8) => A8_ipd, A(9) => A9_ipd, A(10) => A10_ipd, A(11) => A11_ipd, A(12) => A12_ipd, A(13) => A13_ipd, A(14) => A14_ipd, A(15) => A15_ipd, A(16) => A16_ipd, DQ(0) => DQ0, DQ(1) => DQ1, DQ(2) => DQ2, DQ(3) => DQ3, DQ(4) => DQ4, DQ(5) => DQ5, DQ(6) => DQ6, DQ(7) => DQ7, CENeg => CE_ipd, OENeg => OE_ipd, WENeg => WE_ipd ); --<< memory word definition >>-- SUBTYPE Flash_Array_Word is Bit_Vector(MemoryDataTable.DBusW-1 DOWNTO 0); --<< memory array definition >>-- TYPE Flash_Array is array ( 0 to 2**MemoryDataTable.ABusW-1) of FLASH_ARRAY_WORD; --<< array of sector addresses for erasing >>-- TYPE Erase_SAddrs is array( 0 to MemoryDataTable.sectNum-1) of natural; --<< manufacturer ID >>-- CONSTANT manufacID : std_logic_vector(7 downto 0) := "00000001"; -- 01h mnfct ID --<< address patterns used in command sequence >>-- CONSTANT h5555 : std_logic_vector(15 downto 0) := "0101010101010101"; CONSTANT h2AAA : std_logic_vector(15 downto 0) := "0010101010101010"; CONSTANT hXXXX : std_logic_vector(15 downto 0) := (others => '1'); CONSTANT MANUFAC_ADDR : std_logic_vector( 7 downto 0) := "00000000"; -- 00h CONSTANT DEVICE_ADDR : std_logic_vector( 7 downto 0) := "00000001"; -- 01h CONSTANT PROTECT_ADDR : std_logic_vector( 7 downto 0) := "00000010"; -- 02h --<< data patterns used in command sequence >>-- CONSTANT hAA : std_logic_vector(7 downto 0) := "10101010"; -- AAh CONSTANT h55 : std_logic_vector(7 downto 0) := "01010101"; -- 55h --<< Command set >>-- CONSTANT RESET_CMD : std_logic_vector(7 downto 0) := "11110000"; -- F0h CONSTANT ASEL_CMD : std_logic_vector(7 downto 0) := "10010000"; -- 90h CONSTANT PROGRAM_CMD : std_logic_vector(7 downto 0) := "10100000"; -- A0h CONSTANT ERS_SETUP_CMD : std_logic_vector(7 downto 0) := "10000000"; -- 80h CONSTANT SECTOR_ERS_CMD : std_logic_vector(7 downto 0) := "00110000"; -- 30h CONSTANT CHIP_ERS_CMD : std_logic_vector(7 downto 0) := "00010000"; -- 10h CONSTANT SUSPEND_CMD : std_logic_vector(7 downto 0) := "10110000"; -- B0h CONSTANT RESUME_CMD : std_logic_vector(7 downto 0) := "00110000"; -- 30h --<< memory states >>-- TYPE FLASH_STATE IS ( STANDBY1, STANDBY2, RESET_READ, PZ1, PREL, C8, C8_PZ1, C8_PREL, PGM_SETUP, PGMS, PGMS_END, PGMS_HANG, AUTO_SELECT, -- auto select AS_INVALID, CHIP_ERASE, -- chip erase CHERASE_END, -- chip erase end ERASE_HANG, SERASE_TIMEOUT, SERASE_START, SERASE, -- sector erase SERASE_END, ERASE_SUSPEND ); -- chip erase time including preprogramming CONSTANT ERS_TIME : time := tWHWH1 * 2**MemoryDataTable.ABusW + tWHWH2 * MemoryDataTable.SectNum; CONSTANT err_flg : std_logic := '0'; -- Error Flag(1: Error) SIGNAL FSTATE : FLASH_STATE := RESET_READ; -- latched address SIGNAL FADDR : std_logic_vector (MemoryDataTable.ABusW-1 DOWNTO 0); -- latched data SIGNAL FDATA : std_logic_vector (MemoryDataTable.DBusW-1 DOWNTO 0); -- erase-suspend mode flag SIGNAL ESP_mode : std_logic := '0'; -- an array of sect to be erased SIGNAL ESAddrs : Erase_SAddrs; -- write detected during sector erase time out SIGNAL SERS_ADD : std_logic := '0'; SIGNAL TIMER : time := 0 ns; -- erased sect counter SIGNAL ESA_NUM : integer range 0 TO MemoryDataTable.SectNum; -- latched sect number SIGNAL SectorAddr : natural; -- latched sect group number SIGNAL SGroupAddr : natural; SIGNAL TOGGLE : std_logic := '0'; SIGNAL CEorOE : std_logic := '1'; SIGNAL CEorWE : std_logic := '1'; SIGNAL SERS_TIMExESA_NUM : time := 0 us; SIGNAL AFTER_RESET : std_logic := '0'; SIGNAL AFTER_A : std_logic := '0'; SIGNAL AFTER_CE : std_logic := '0'; SIGNAL AFTER_OE : std_logic := '0'; SIGNAL AFTER_CEorOE_H : std_logic := '0'; SIGNAL INVALID : std_logic := '0'; -- data invalid (if 1) flag SIGNAL rfPGMS : time := 0 ns; SIGNAL rfERS : time := 0 ns; SIGNAL rfSERS : time := 0 ns; SIGNAL rfA : time := 0 ns; SIGNAL rfDQ : time := 0 ns; SIGNAL rCE : time := 0 ns; SIGNAL fCE : time := 0 ns; SIGNAL rOE : time := 0 ns; SIGNAL fOE : time := 0 ns; SIGNAL rWE : time := 0 ns; SIGNAL fWE : time := 0 ns; SIGNAL rRESET : time := 0 ns; SIGNAL fRESET : time := 0 ns; SIGNAL rCEorWE : time := 0 ns; SIGNAL fCEorWE : time := 0 ns; BEGIN ------------------------------------------------------------------------ -- Timing Check Section ------------------------------------------------------------------------ TimingChecks: PROCESS(WENeg, OENeg, CENeg, CEorWE, A, DQ) -- Pulse Width Check Variables VARIABLE Pviol_WE : X01 := '0'; VARIABLE PD_WE_ipd : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CE : X01 := '0'; VARIABLE PD_CE_ipd : VitalPeriodDataType := VitalPeriodDataInit; -- Setup/Hold Check Variables VARIABLE Tviol_A_WE : X01 := '0'; VARIABLE TD_A_WE : VitalTimingDataType; VARIABLE Tviol_A_CE : X01 := '0'; VARIABLE TD_A_CE : VitalTimingDataType; VARIABLE Tviol_DQ_WE : X01 := '0'; VARIABLE TD_DQ_WE : VitalTimingDataType; VARIABLE Tviol_DQ_CE : X01 := '0'; VARIABLE TD_DQ_CE : VitalTimingDataType; VARIABLE Tviol_OE_WE_read : X01 := '0'; VARIABLE TD_OE_WE_read : VitalTimingDataType; VARIABLE Tviol_OE_WE_poll : X01 := '0'; VARIABLE TD_OE_WE_poll : VitalTimingDataType; VARIABLE Tviol_OE_WE : X01 := '0'; VARIABLE TD_OE_WE : VitalTimingDataType; -- CE setup/hold checks -- use different edge of the ref signal WE -- so two different calls will be required VARIABLE Tviol_CE_WE_setup : X01 := '0'; VARIABLE TD_CE_WE_setup : VitalTimingDataType; VARIABLE Tviol_CE_WE_hold : X01 := '0'; VARIABLE TD_CE_WE_hold : VitalTimingDataType; -- WE setup/hold checks -- use different edge of the ref signal CE -- so two different calls will be required VARIABLE Tviol_WE_CE_setup : X01 := '0'; VARIABLE TD_WE_CE_setup : VitalTimingDataType; VARIABLE Tviol_WE_CE_hold : X01 := '0'; VARIABLE TD_WE_CE_hold : VitalTimingDataType; -- Recover Check Variables VARIABLE Rviol_OE_WE : X01 := '0'; VARIABLE RD_OE_WE : VitalTimingDataType; VARIABLE Rviol_OE_CE : X01 := '0'; VARIABLE RD_OE_CE : VitalTimingDataType; -- Common violation variable (used to OR all individual violation variables) VARIABLE Violation : X01 := '0'; BEGIN IF (TimingChecksOn) THEN -- WENeg pulse width (write cycle) VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WENeg", PulseWidthLow => tpw_WENeg_negedge, PulseWidthHigh => tpw_WENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & " WENeg Pulse Width was not suitable" & LF, PeriodData => PD_WE_ipd, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_WE ); -- CENeg pulse width (in CE controlled writes) VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CENeg", PulseWidthLow => tpw_CENeg_negedge, PulseWidthHigh => tpw_CENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & " CENeg Pulse Width was not suitable" & LF, PeriodData => PD_CE_ipd, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_WE ); -- Address setup/hold time check (write cycle) VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_A0_WENeg, SetupLow => tsetup_A0_WENeg, HoldHigh => thold_A0_WENeg, HoldLow => thold_A0_WENeg, CheckEnabled => True, RefTransition => '\', HeaderMsg => InstancePath & " address setup/hold time (tAS/tAH) was not suitable" & LF, TimingData => TD_A_WE, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_A_WE ); VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_A0_CENeg, SetupLow => tsetup_A0_CENeg, HoldHigh => thold_A0_CENeg, HoldLow => thold_A0_CENeg, CheckEnabled => True, RefTransition => '\', HeaderMsg => InstancePath & " address setup/hold time (tAS/tAH) was not suitable" & LF, TimingData => TD_A_CE, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_A_CE ); -- Data setup/hold time check (write cycle) VitalSetupHoldCheck ( TestSignal => DQ, TestSignalName => "DQ", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_DQ0_WENeg, SetupLow => tsetup_DQ0_WENeg, HoldHigh => thold_DQ0_WENeg, HoldLow => thold_DQ0_WENeg, CheckEnabled => True, RefTransition => '/', HeaderMsg => InstancePath & " data setup/hold time (tDS/tDH) was not suitable" & LF, TimingData => TD_DQ_WE, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_DQ_WE ); VitalSetupHoldCheck ( TestSignal => DQ, TestSignalName => "DQ", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_DQ0_CENeg, SetupLow => tsetup_DQ0_CENeg, HoldHigh => thold_DQ0_CENeg, HoldLow => thold_DQ0_CENeg, CheckEnabled => True, RefTransition => '/', HeaderMsg => InstancePath & " data setup/hold time (tDS/tDH) was not suitable" & LF, TimingData => TD_DQ_CE, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_DQ_CE ); -- Output enable hold time check (read cycle) IF FSTATE=RESET_READ or FSTATE=ERASE_SUSPEND THEN VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => WENeg, RefSignalName => "WENeg", HoldHigh => thold_OENeg_WENeg_read, HoldLow => thold_OENeg_WENeg_read, CheckEnabled => True, RefTransition => '/', HeaderMsg => InstancePath & "Output Enable Hold Time (tOEH_READ) was not suitable." & LF, TimingData => TD_OE_WE_read, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_OE_WE_read ); ELSIF FSTATE=PGMS or FSTATE=PGMS_END or FSTATE=PGMS_HANG or FSTATE=CHIP_ERASE or FSTATE=CHERASE_END or FSTATE=ERASE_HANG or FSTATE=SERASE_TIMEOUT or FSTATE=SERASE_START or FSTATE=SERASE or FSTATE=SERASE_END or FSTATE=ERASE_SUSPEND THEN VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => WENeg, RefSignalName => "WENeg", HoldHigh => thold_OENeg_WENeg_poll, HoldLow => thold_OENeg_WENeg_poll, CheckEnabled => True, RefTransition => '/', HeaderMsg => InstancePath & "Output Enable Hold Time (tOEH_POLLING) was not suitable." & LF, TimingData => TD_OE_WE_poll, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_OE_WE_poll ); END IF; -- Output enable setup time check (tOES) VitalSetupHoldCheck ( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_OENeg_WENeg, SetupLow => tsetup_OENeg_WENeg, CheckEnabled => True, RefTransition => '/', HeaderMsg => InstancePath & " Output Enable Setup Time (tOES) was not suitable" & LF, TimingData => TD_OE_WE, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_OE_WE ); -- CE setup time check (tCS) VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", SetupHigh => tsetup_CENeg_WENeg, SetupLow => tsetup_CENeg_WENeg, CheckEnabled => True, RefTransition => '\', HeaderMsg => InstancePath & " CS Setup Time (tCS) was not suitable" & LF, TimingData => TD_CE_WE_setup, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_CE_WE_setup ); -- WE setup time check tWS ( in CE controlled writes) VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CENeg, RefSignalName => "CENeg", SetupHigh => tsetup_WENeg_CENeg, SetupLow => tsetup_WENeg_CENeg, CheckEnabled => True, RefTransition => '\', HeaderMsg => InstancePath & " WE Setup Time (tWS) was not suitable" & LF, TimingData => TD_WE_CE_setup, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_WE_CE_setup ); -- CE hold time check (tCH) VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => WENeg, RefSignalName => "WENeg", HoldHigh => thold_CENeg_WENeg, HoldLow => thold_CENeg_WENeg, CheckEnabled => True, RefTransition => '/', HeaderMsg => InstancePath & " CS Hold Time (tCH) was not suitable" & LF, TimingData => TD_CE_WE_hold, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_CE_WE_hold ); -- WE hold time check tWH ( in CE controlled writes) VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WENeg", RefSignal => CENeg, RefSignalName => "CENeg", HoldHigh => thold_WENeg_CENeg, HoldLow => thold_WENeg_CENeg, CheckEnabled => True, RefTransition => '/', HeaderMsg => InstancePath & " WE HOLD Time (tWH) was not suitable" & LF, TimingData => TD_WE_CE_hold, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_WE_CE_hold ); -- WENeg Read Recover time (write cycle) tGHWL VitalRecoveryRemovalCheck( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => WENeg, RefSignalName => "WENeg", Recovery => trecovery_OENeg_WENeg, ActiveLow => False, CheckEnabled => True, RefTransition => '\', HeaderMsg => InstancePath & " WENeg Read Recover time (tGHWL) was not suitable" & LF, XOn => XOn, MsgOn => MsgOn, TimingData => RD_OE_WE, Violation => Rviol_OE_WE ); -- CENeg Read Recover time (write cycle) tGHEL VitalRecoveryRemovalCheck( TestSignal => OENeg, TestSignalName => "OENeg", RefSignal => CENeg, RefSignalName => "CENeg", Recovery => trecovery_OENeg_CENeg, ActiveLow => False, CheckEnabled => True, RefTransition => '\', HeaderMsg => InstancePath & " CENeg Read Recover time (tGHEL) was not suitable" & LF, XOn => XOn, MsgOn => MsgOn, TimingData => RD_OE_CE, Violation => Rviol_OE_CE ); END IF; Violation := Pviol_WE OR Pviol_CE OR Tviol_A_WE OR Tviol_A_CE OR Tviol_DQ_WE OR Tviol_DQ_CE OR Tviol_OE_WE_read OR Tviol_OE_WE_poll OR Tviol_OE_WE OR Tviol_CE_WE_setup OR Tviol_CE_WE_hold OR Tviol_WE_CE_setup OR Tviol_WE_CE_hold OR Rviol_OE_WE OR Rviol_OE_CE; END PROCESS TimingChecks; -------------------------------------------------------------------------------- -- Functionality section -- -------------------------------------------------------------------------------- --<< Toggle Bit Operation >>-- CEorOE <= CENeg or OENeg; PROCESS(FSTATE, CEorOE) BEGIN IF FSTATE=PGMS or FSTATE=PGMS_END or FSTATE=PGMS_HANG or FSTATE=CHIP_ERASE or FSTATE=CHERASE_END or FSTATE=ERASE_HANG or FSTATE=SERASE_TIMEOUT or FSTATE=SERASE_START or FSTATE=SERASE or FSTATE=SERASE_END or FSTATE=ERASE_SUSPEND or FSTATE=RESET_READ THEN IF CEorOE'event AND CEorOE = '1' THEN TOGGLE <= not TOGGLE; END IF; ELSE TOGGLE <= '0'; END IF; END PROCESS; --<< Address latch >>-- PROCESS(CENeg, WENeg) BEGIN CEorWE <= CENeg or WENeg; END PROCESS; PROCESS(CEorWE) BEGIN IF( CEorWE'event AND CEorWE = '0') THEN FADDR <= A; -- latch address bus contents SectorAddr <= to_nat(A(16 DOWNTO 14)); -- latch sector address SGroupAddr <= to_nat(A(16 DOWNTO 15)); -- latch sector group address END IF; END PROCESS; --<< Master process >>-- Master: PROCESS(A, CENeg, OENeg, WENeg, FSTATE, TIMER, CEorOE, CEorWE, AFTER_RESET, INVALID) VARIABLE FARRAY : FLASH_ARRAY := -- flash array (FLASH_ARRAY'range => FLASH_ARRAY_WORD'(others => '1')); VARIABLE HIT_ESA : std_logic := '0'; VARIABLE sectAddr : std_logic_vector(MemoryDataTable.ABusW-1 DOWNTO 0); VARIABLE protectedByte : std_logic; BEGIN --< Status transition Operation (WENeg or CENeg rising edge) >-- IF( CEorWE'event AND CEorWE = '1') THEN -- data writing time IF OENeg = '1' THEN CASE FSTATE is WHEN RESET_READ => -- first Bus Write cycle IF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h5555(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0) = hAA) THEN FSTATE <= PZ1; -- go to second write cycle ELSE FSTATE <= RESET_READ; -- Reset/Read command END IF; WHEN PZ1 => -- second Bus Write cycle IF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h2AAA(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0) = h55) THEN FSTATE <= PREL; -- go to 3-d write cycle ELSE IF ESP_mode = '1' -- erase suspend mode is on THEN -- Erase Suspend FSTATE <= ERASE_SUSPEND; ELSE FSTATE <= RESET_READ; END IF; END IF; WHEN PREL => -- 3-d Bus Write cycle IF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h5555(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0) = ERS_SETUP_CMD) AND -- DQ = 80H (ESP_mode = '0') THEN FSTATE <= C8; -- go to Chip or Sector Erase ELSIF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h5555(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0) = PROGRAM_CMD) -- DQ = A0H THEN FSTATE <= PGM_SETUP; -- get into Byte Program mode ELSIF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h5555(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ( 7 DOWNTO 0) = ASEL_CMD) -- DQ = 90H THEN FSTATE <= AUTO_SELECT; -- get into Autoselect mode ELSE IF ESP_mode = '1' -- in erase-suspend mode THEN FSTATE <= ERASE_SUSPEND; -- get into erase suspend mode ELSE FSTATE <= RESET_READ; -- F0H or others(illegal) END IF; END IF; WHEN C8 => -- 4-th Bus Write cycle (Chip/Sector Erase) IF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h5555(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0) = hAA) THEN FSTATE <= C8_PZ1; -- go to 5-th Bus Write cycle ELSE FSTATE <= RESET_READ; END IF; WHEN C8_PZ1 => -- 5-th Bus Write cycle (Chip/Sector Erase) IF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h2AAA(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0)=h55) THEN FSTATE <= C8_PREL; -- go to 6-th Bus Write cycle ELSE FSTATE <= RESET_READ; END IF; WHEN C8_PREL => -- 6-th Bus Write cycle (Chip/Sector Erase) IF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h5555(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0)= CHIP_ERS_CMD) -- Chip Erase 10H THEN FSTATE <= CHIP_ERASE; -- Chip erase state ELSIF DQ(7 DOWNTO 0) = SECTOR_ERS_CMD -- Sector Erase 30H THEN FSTATE <= SERASE_TIMEOUT; -- get into erase timeout SERS_ADD <= '1'; ELSE FSTATE <= RESET_READ; END IF; WHEN AUTO_SELECT => -- 4-th Bus Write cycle (Autoselect) IF DQ(7 DOWNTO 0) = RESET_CMD -- F0H THEN IF ESP_mode = '1' -- in erase-suspend mode THEN FSTATE <= ERASE_SUSPEND; -- get into erase suspend ELSE FSTATE <= RESET_READ; END IF; ELSE FSTATE <= AS_INVALID; END IF; WHEN AS_INVALID => IF DQ(7 DOWNTO 0)= RESET_CMD -- F0h THEN IF ESP_mode = '1' -- in erase-suspend mode THEN FSTATE <= ERASE_SUSPEND; ELSE FSTATE <= RESET_READ; END IF; END IF; WHEN PGM_SETUP => -- 4-th Bus Write Cycle (Byte Program) IF protection_mask(SGroupAddr) /= '1' THEN -- used sector group is not write-protected HIT_ESA := '0'; IF ESP_mode = '1' -- in erase-suspend mode THEN FOR i IN 0 TO ESA_NUM-1 LOOP -- check if prog sector is not an erase-suspended sector IF SectorAddr = ESAddrs(i) THEN HIT_ESA := '1'; -- yes it is exit; END IF; END LOOP; END IF; IF HIT_ESA = '0' -- no erase-suspended sectors THEN FSTATE <= PGMS; -- get into byte-programming mode FDATA <= DQ; ELSE FSTATE <= ERASE_SUSPEND; END IF; ELSE FSTATE <= RESET_READ; -- disable operation END IF; -- 'cause sector being used -- is write-protected WHEN PGMS => -- for transition see next case FSTATE NULL; WHEN PGMS_END => -- for transition see next case FSTATE NULL; WHEN PGMS_HANG => IF DQ(7 DOWNTO 0) = RESET_CMD -- exit byte programming by RESET cmd THEN FSTATE <= RESET_READ; ELSE FSTATE <= PGMS_HANG; END IF; WHEN CHIP_ERASE => -- for transition see next case FSTATE NULL; WHEN CHERASE_END => -- for transition see next case FSTATE NULL; WHEN ERASE_HANG => IF DQ(7 DOWNTO 0) = RESET_CMD THEN FSTATE <= RESET_READ; ELSE FSTATE <= ERASE_HANG; END IF; WHEN SERASE_TIMEOUT => -- sector erase timeout IF DQ(7 DOWNTO 0) = SECTOR_ERS_CMD THEN -- one more sector erase command detected FSTATE <= SERASE_TIMEOUT; SERS_ADD <= '1'; TIMER <= 0 ns; ELSIF DQ(7 DOWNTO 0) = SUSPEND_CMD THEN -- erase suspend during erase time out FSTATE <= ERASE_SUSPEND; -- get into erase-suspend mode ESP_mode <= '1'; ELSE FSTATE <= RESET_READ; END IF; WHEN SERASE_START => -- for transition see next case FSTATE NULL; WHEN SERASE => IF DQ(7 DOWNTO 0) = SUSPEND_CMD -- erase suspend during Sector Erase THEN -- get into erase-suspend mode FSTATE <= ERASE_SUSPEND AFTER tSUSPEND; ESP_mode <= '1'; END IF; WHEN SERASE_END => -- for transition see next case FSTATE NULL; WHEN ERASE_SUSPEND => IF DQ(7 DOWNTO 0) = RESUME_CMD THEN FSTATE <= SERASE_START; ESP_mode <= '0'; -- get out from erase-suspend ELSIF (FADDR(MemoryDataTable.AddrW-1 DOWNTO 0) = h5555(MemoryDataTable.AddrW-1 DOWNTO 0)) AND (DQ(7 DOWNTO 0) = hAA) THEN FSTATE <= PZ1; ELSE FSTATE <= ERASE_SUSPEND; END IF; WHEN OTHERS => NULL; END CASE; END IF; ELSE --< Status Transition Process >-- CASE FSTATE IS WHEN RESET_READ => IF( FSTATE'event) THEN SERS_ADD <= '0'; TIMER <= 0 ns; IF ESP_mode = '0' THEN ESA_NUM <= 0; FOR i IN 0 TO MemoryDataTable.SectNum-1 LOOP -- reset erased sectors list ESAddrs(i) <= (MemoryDataTable.SectNum); END LOOP; END IF; END IF; WHEN PGMS => IF FSTATE'event THEN IF (ERR_FLG = '1') or ((FARRAY(to_nat(FADDR)) AND To_bitvector(FDATA)) /= to_bitvector(FDATA)) -- 0 -> 1 programming is impossible THEN FSTATE <= PGMS_HANG AFTER tWHWH1; ELSE FARRAY(to_nat(FADDR)) := -- program byte into memory FARRAY(to_nat(FADDR)) AND to_bitvector( FDATA); FSTATE <= PGMS_END AFTER tWHWH1; END IF; END IF; WHEN PGMS_END => rfPGMS <= now; IF ESP_mode = '1' THEN FSTATE <= ERASE_SUSPEND; ELSE FSTATE <= RESET_READ; END IF; WHEN CHIP_ERASE => -- chip erasing IF FSTATE'event THEN IF ERR_FLG = '1' THEN FSTATE <= ERASE_HANG AFTER ERS_TIME; ELSE FOR ByteAddr IN 0 TO 2**MemoryDataTable.ABusW-1 LOOP sectAddr := to_slv(ByteAddr, MemoryDataTable.ABusW); protectedByte := protection_mask (to_nat(sectAddr(16 DOWNTO 14))); IF protectedByte = '0' THEN FARRAY(ByteAddr) := (OTHERS => '1'); END IF; END LOOP; FSTATE <= CHERASE_END AFTER ERS_TIME; END IF; END IF; WHEN CHERASE_END => rfERS <= now; FSTATE <= RESET_READ; WHEN SERASE_TIMEOUT => -- sector erase time out state IF TIMER >= tSETO -- time out period has expired THEN FSTATE <= SERASE_START; -- start sector erasing TIMER <= 0 ns; ELSIF (SERS_ADD = '1') AND (ESA_NUM < MemoryDataTable.sectNum) --one more write detected THEN IF protection_mask(SGroupAddr) /= '1' THEN -- used sector group is not write-protected ESAddrs(ESA_NUM) <= SectorAddr; -- save sector num ESA_NUM <= ESA_NUM + 1; -- adjust sector counter END IF; SERS_ADD <= '0'; -- reset extra_write_detected flag TIMER <= 0 ns; -- reset time out counter END IF; TIMER <= TIMER + 1 us AFTER 1 us; -- advance time out value WHEN SERASE_START => --SERS_TIMExESA_NUM <= (tWHWH1*2**(ABusW-SABusW)+ tWHWH2) * ESA_NUM; SERS_TIMExESA_NUM <= tWHWH2 * ESA_NUM; FSTATE <= SERASE; WHEN SERASE => -- erasing specified sectors IF FSTATE'event THEN IF ERR_FLG = '1' THEN FSTATE <= ERASE_HANG AFTER SERS_TIMExESA_NUM; ELSE FOR i IN 0 TO ESA_NUM - 1 -- erase specified sectors LOOP IF ESAddrs(i) /= MemoryDataTable.sectNum THEN -- if valid sector specified FOR j IN MemoryDataTable.sectors(ESAddrs(i)).LAddr TO MemoryDataTable.sectors(ESAddrs(i)).UAddr LOOP FARRAY(j) := (OTHERS => '1'); END loop; END IF; END LOOP; FSTATE <= SERASE_END AFTER SERS_TIMExESA_NUM; END IF; END IF; WHEN SERASE_END => rfSERS <= now; FOR i IN 0 TO ESA_NUM-1 -- reset erased sector list LOOP ESAddrs(i) <= (MemoryDataTable.sectNum); END LOOP; ESA_NUM <= 0; FSTATE <= RESET_READ; WHEN OTHERS => null; END CASE; END IF; --< DQ Output Setup >-------------------------------- --< Disable Process >-- IF CEorOE = '1' THEN IF CEorOE'event THEN DQ <= (OTHERS => 'X') AFTER tOH, (OTHERS => 'Z') AFTER tpd_OENeg_DQ0(tr0z); AFTER_CEorOE_H <= '1', '0' AFTER tOH + tpd_OENeg_DQ0(tr0z); ELSE IF AFTER_CEorOE_H = '0' THEN DQ <= ( OTHERS => 'Z'); END IF; END IF; --< Enable Process>-- ELSIF (CENeg = '0') AND (OENeg = '0') THEN IF (AFTER_RESET = '1') OR (INVALID = '1') THEN DQ <= (OTHERS => 'X'); --< Time Limit Over Output >-- ELSIF FSTATE = PGMS_HANG THEN IF ESP_mode = '0' THEN -- see table6. Byte Program exceeded time lim DQ(7) <= not FDATA(7); DQ(6) <= TOGGLE; DQ(5) <= '1'; DQ(4) <= 'X'; DQ(3) <= '0'; DQ(2) <= '1'; DQ(1) <= 'X'; DQ(0) <= 'X'; ELSIF ESP_mode = '1' THEN -- see table6. Erase Suspend Program exc. time lim DQ(7) <= not FDATA( 7); DQ(6) <= TOGGLE; DQ(5) <= '1'; DQ(4) <= 'X'; DQ(3) <= '1'; DQ(2) <= 'X'; DQ(1) <= 'X'; DQ(0) <= 'X'; END IF; ELSIF FSTATE = ERASE_HANG THEN -- see table6. Erase exceeded time lim DQ( 7) <= '0'; DQ( 6) <= TOGGLE; DQ( 5) <= '1'; DQ( 4) <= 'X'; DQ( 3) <= '1'; DQ( 2) <= 'X'; DQ( 1) <= 'X'; DQ( 0) <= 'X'; ---- ELSIF ESP_mode = '0' THEN IF FSTATE = RESET_READ THEN DQ <= To_StdLogicVector(FARRAY(to_nat(A( MemoryDataTable.ABusW-1 DOWNTO 0)))); ELSIF (FSTATE = AUTO_SELECT) AND (A(7 DOWNTO 0) = MANUFAC_ADDR) THEN -- read Manufacturer Code -AMD DQ <= manufacID(MemoryDataTable.DBusW-1 DOWNTO 0); ELSIF (FSTATE = AUTO_SELECT) AND (A(7 DOWNTO 0) = DEVICE_ADDR) THEN -- read Am29F040 Device ID DQ <= to_slv(MemoryDataTable.deviceID, MemoryDataTable.DBusW); ELSIF (FSTATE = AUTO_SELECT) AND (A(7 DOWNTO 0) = PROTECT_ADDR) THEN -- read Sector Group Protect Status DQ <= "0000000" & protection_mask( to_nat(FADDR(16 downto 15))); ELSIF (FSTATE = PGMS) OR (FSTATE = PGMS_END) THEN -- see table6. Byte Program in progress DQ(7) <= not FDATA( 7); DQ(6) <= TOGGLE; DQ(5) <= '0'; DQ(4) <= 'X'; DQ(3) <= '0'; DQ(2) <= '1'; DQ(1) <= 'X'; DQ(0) <= 'X'; ELSIF FSTATE = SERASE_TIMEOUT THEN -- sector erase timeout DQ(7) <= '0'; DQ(6) <= TOGGLE; DQ(5) <= '0'; DQ(4) <= 'X'; DQ(3) <= '0'; DQ(2) <= TOGGLE; DQ(1) <= 'X'; DQ(0) <= 'X'; ELSIF (FSTATE = CHIP_ERASE) OR (FSTATE = CHERASE_END) OR (FSTATE = SERASE_START) OR (FSTATE = SERASE) OR (FSTATE = SERASE_END) THEN -- see table6 Erase in Progress DQ(7) <= '0'; DQ(6) <= TOGGLE; DQ(5) <= '0'; DQ(4) <= 'X'; DQ(3) <= '1'; DQ(2) <= TOGGLE; DQ(1) <= 'X'; DQ(0) <= 'X'; ELSIF FSTATE=PZ1 or FSTATE=PREL or FSTATE=C8 or FSTATE=C8_PZ1 or FSTATE=C8_PREL THEN DQ <= To_StdLogicVector(FARRAY( to_nat(A(MemoryDataTable.ABusW-1 DOWNTO 0)))); ELSE DQ <= ( others => 'X'); END IF; ELSIF ESP_mode = '1' -- Erase SuspEND Read Output, THEN -- address to read from is on A bus HIT_ESA := '0'; FOR i IN 0 TO ESA_NUM-1 LOOP IF to_nat(A(MemoryDataTable.ABusW-1 DOWNTO 14)) = ESAddrs(i) THEN -- erase-suspended sector HIT_ESA := '1'; exit; END IF; END LOOP; IF FSTATE = ERASE_SUSPEND THEN IF HIT_ESA = '0' -- non-erase sector is read THEN DQ <= To_StdLogicVector( FARRAY(to_nat(A( MemoryDataTable.ABusW-1 DOWNTO 0)))); ELSIF HIT_ESA = '1' THEN -- see table6. Erase Suspend Read(erase suspended sector) DQ( 7) <= '1'; DQ( 6) <= '1'; DQ( 5) <= '0'; DQ( 4) <= 'X'; DQ( 3) <= '0'; DQ( 2) <= TOGGLE; DQ( 1) <= 'X'; DQ( 0) <= 'X'; ELSE DQ <= (OTHERS => 'X'); END IF; ELSIF( FSTATE = AUTO_SELECT AND A(7 DOWNTO 0) = MANUFAC_ADDR) THEN -- read Manufacturer Code -AMD DQ <= manufacID(MemoryDataTable.DBusW-1 DOWNTO 0); ELSIF( FSTATE=AUTO_SELECT AND A(7 DOWNTO 0) = DEVICE_ADDR) THEN -- read Am29lv010b Device ID DQ <= to_slv(MemoryDataTable.deviceID, MemoryDataTable.DBusW-1); ELSIF( FSTATE=AUTO_SELECT AND A(7 DOWNTO 0) = PROTECT_ADDR) THEN -- read Sector Group Protect Status DQ <= "0000000" & protection_mask(to_nat(FADDR( 16 downto 15))); ELSIF (FSTATE = PGMS) OR (FSTATE = PGMS_END) THEN IF HIT_ESA = '1' THEN -- see table6. Erase Suspend Program(erase susp sect) DQ(7) <= not FDATA( 7); DQ(6) <= TOGGLE; DQ(5) <= '0'; DQ(4) <= 'X'; DQ(3) <= '0'; DQ(2) <= TOGGLE; DQ(1) <= 'X'; DQ(0) <= 'X'; ELSIF HIT_ESA = '0' THEN -- see table6. Erase Suspend Program(non-erase susp sect) DQ( 7) <= not FDATA( 7); DQ( 6) <= TOGGLE; DQ( 5) <= '0'; DQ( 4) <= 'X'; DQ( 3) <= '0'; DQ( 2) <= '1'; DQ( 1) <= 'X'; DQ( 0) <= 'X'; ELSE DQ <= (OTHERS => 'X'); END IF; ELSIF (FSTATE = PZ1) OR (FSTATE = PREL) THEN DQ <= To_StdLogicVector( FARRAY(to_nat(A( MemoryDataTable.ABusW-1 DOWNTO 0)))); ELSE DQ <= (OTHERS => 'X'); END IF; ELSE DQ <= (OTHERS => 'Z'); END IF; ELSE DQ <= (OTHERS => 'Z'); END IF; -- END IF; END PROCESS Master; ---------------------------------------------------------- --<< DQ Output delay >>-- PROCESS( A, CENeg, OENeg) BEGIN IF A'event THEN -- AFTER_A <= '1', '0' AFTER tACC; AFTER_A <= '1', '0' AFTER tpd_A0_DQ0(tr01); END IF; IF (CENeg'event) AND (CENeg = '0') THEN -- AFTER_CE <= '1', '0' AFTER tCE; AFTER_CE <= '1', '0' AFTER tpd_CENeg_DQ0(trz1); END IF; IF (OENeg'event) AND (OENeg = '0') THEN -- AFTER_OE <= '1', '0' AFTER tOE; AFTER_OE <= '1', '0' AFTER tpd_OENEg_DQ0(trz1); END IF; END PROCESS; PROCESS (AFTER_A, AFTER_CE, AFTER_OE) BEGIN IF (AFTER_A or AFTER_CE or AFTER_OE) = '1' THEN INVALID <= '1'; ELSE INVALID <= '0'; END IF; END PROCESS; END BLOCK VITALBehavior; END vhdl_behavioral;