------------------------------------------------------------------------------- -- File Name: at28c010.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2007 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.Beatovic 07 Aug 21 Inital Release -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: RAM -- Technology: EEPROM -- Part: at28c010 -- -- Description: 1M (128k x 8) Paged Paralel EEPROM ------------------------------------------------------------------------------- -- Known Bugs: -- ------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE STD.textio.ALL; USE IEEE.VITAL_timing.ALL; USE IEEE.VITAL_primitives.ALL; LIBRARY FMF; USE FMF.gen_utils.ALL; USE FMF.conversions.ALL; ------------------------------------------------------------------------------- -- ENTITY DECLARATION ------------------------------------------------------------------------------- ENTITY at28c010 IS GENERIC ( -- tipd delays: interconnect path delays tipd_A0 : VitalDelayType01 := VitalZeroDelay01; tipd_A1 : VitalDelayType01 := VitalZeroDelay01; tipd_A2 : VitalDelayType01 := VitalZeroDelay01; tipd_A3 : VitalDelayType01 := VitalZeroDelay01; tipd_A4 : VitalDelayType01 := VitalZeroDelay01; tipd_A5 : VitalDelayType01 := VitalZeroDelay01; tipd_A6 : VitalDelayType01 := VitalZeroDelay01; tipd_A7 : VitalDelayType01 := VitalZeroDelay01; tipd_A8 : VitalDelayType01 := VitalZeroDelay01; tipd_A9 : VitalDelayType01 := VitalZeroDelay01; tipd_A10 : VitalDelayType01 := VitalZeroDelay01; tipd_A11 : VitalDelayType01 := VitalZeroDelay01; tipd_A12 : VitalDelayType01 := VitalZeroDelay01; tipd_A13 : VitalDelayType01 := VitalZeroDelay01; tipd_A14 : VitalDelayType01 := VitalZeroDelay01; tipd_A15 : VitalDelayType01 := VitalZeroDelay01; tipd_A16 : VitalDelayType01 := VitalZeroDelay01; tipd_IO0 : VitalDelayType01 := VitalZeroDelay01; tipd_IO1 : VitalDelayType01 := VitalZeroDelay01; tipd_IO2 : VitalDelayType01 := VitalZeroDelay01; tipd_IO3 : VitalDelayType01 := VitalZeroDelay01; tipd_IO4 : VitalDelayType01 := VitalZeroDelay01; tipd_IO5 : VitalDelayType01 := VitalZeroDelay01; tipd_IO6 : VitalDelayType01 := VitalZeroDelay01; tipd_IO7 : VitalDelayType01 := VitalZeroDelay01; tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_A0_IO0 : VitalDelayType01 := UnitDelay01;--tACC tpd_CENeg_IO0 : VitalDelayType01Z := UnitDelay01Z;--tCE,tDF tpd_OENeg_IO0 : VitalDelayType01Z := UnitDelay01Z;--tOE, tDF --tsetup values tsetup_A0_WENeg : VitalDelayType := UnitDelay; --tAS tsetup_OENeg_WENeg : VitalDelayType := UnitDelay; --tOES tsetup_CENeg_WENeg : VitalDelayType := UnitDelay; --tCS tsetup_WENeg_CENeg : VitalDelayType := UnitDelay; --tCS tsetup_IO0_WENeg : VitalDelayType := UnitDelay; --tDS tsetup_IO0_CENeg : VitalDelayType := UnitDelay; --tDS --thold values thold_A0_WENeg : VitalDelayType := UnitDelay; --tAH thold_CENeg_WENeg : VitalDelayType := UnitDelay; --tCH thold_WENeg_CENeg : VitalDelayType := UnitDelay; --tCH thold_IO0_WENeg_Write_noedge_posedge : VitalDelayType := UnitDelay; --tDH thold_OENeg_WENeg_Write_noedge_posedge : VitalDelayType := UnitDelay; --tOEH thold_IO0_WENeg_DataPolling_noedge_posedge : VitalDelayType := UnitDelay; --tDH thold_OENeg_WENeg_DataPolling_noedge_posedge : VitalDelayType := UnitDelay; --tOEH thold_OENeg_CENeg : VitalDelayType := UnitDelay; --tDH thold_IO0_WENeg : VitalDelayType := UnitDelay; --tDH thold_IO0_CENeg : VitalDelayType := UnitDelay; --tDH --tpw values: pulse width tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH tpw_OENeg_DataPolling_posedge : VitalDelayType := UnitDelay; --tOEHP -- tdevice values: values for internal delays -- Write cycle time tdevice_WR : VitalDelayType := 10 ms; --tWC -- Byte Load cycle time tdevice_BLC : VitalDelayType := 150 us; --tBLC -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- memory file to be loaded mem_file_name : STRING := "at28c010.mem"; UserPreload : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING ); PORT ( A0 : IN std_ulogic := 'U'; A1 : IN std_ulogic := 'U'; A2 : IN std_ulogic := 'U'; A3 : IN std_ulogic := 'U'; A4 : IN std_ulogic := 'U'; A5 : IN std_ulogic := 'U'; A6 : IN std_ulogic := 'U'; A7 : IN std_ulogic := 'U'; A8 : IN std_ulogic := 'U'; A9 : IN std_ulogic := 'U'; A10 : IN std_ulogic := 'U'; A11 : IN std_ulogic := 'U'; A12 : IN std_ulogic := 'U'; A13 : IN std_ulogic := 'U'; A14 : IN std_ulogic := 'U'; A15 : IN std_ulogic := 'U'; A16 : IN std_ulogic := 'U'; CENeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; IO0 : INOUT std_ulogic := 'U'; IO1 : INOUT std_ulogic := 'U'; IO2 : INOUT std_ulogic := 'U'; IO3 : INOUT std_ulogic := 'U'; IO4 : INOUT std_ulogic := 'U'; IO5 : INOUT std_ulogic := 'U'; IO6 : INOUT std_ulogic := 'U'; IO7 : INOUT std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of at28c010 : ENTITY IS TRUE; END at28c010; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of at28c010 IS ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "at28c010"; CONSTANT MaxData : NATURAL := 16#FF#; --255 CONSTANT HiAddrBit : NATURAL := 16; CONSTANT AddrRANGE : NATURAL := 16#1FFFF#; -- interconnect path delay signals SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL A2_ipd : std_ulogic := 'U'; SIGNAL A3_ipd : std_ulogic := 'U'; SIGNAL A4_ipd : std_ulogic := 'U'; SIGNAL A5_ipd : std_ulogic := 'U'; SIGNAL A6_ipd : std_ulogic := 'U'; SIGNAL A7_ipd : std_ulogic := 'U'; SIGNAL A8_ipd : std_ulogic := 'U'; SIGNAL A9_ipd : std_ulogic := 'U'; SIGNAL A10_ipd : std_ulogic := 'U'; SIGNAL A11_ipd : std_ulogic := 'U'; SIGNAL A12_ipd : std_ulogic := 'U'; SIGNAL A13_ipd : std_ulogic := 'U'; SIGNAL A14_ipd : std_ulogic := 'U'; SIGNAL A15_ipd : std_ulogic := 'U'; SIGNAL A16_ipd : std_ulogic := 'U'; SIGNAL IO0_ipd : std_ulogic := 'U'; SIGNAL IO1_ipd : std_ulogic := 'U'; SIGNAL IO2_ipd : std_ulogic := 'U'; SIGNAL IO3_ipd : std_ulogic := 'U'; SIGNAL IO4_ipd : std_ulogic := 'U'; SIGNAL IO5_ipd : std_ulogic := 'U'; SIGNAL IO6_ipd : std_ulogic := 'U'; SIGNAL IO7_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL OENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL A0_nwv : std_ulogic := 'U'; SIGNAL A1_nwv : std_ulogic := 'U'; SIGNAL A2_nwv : std_ulogic := 'U'; SIGNAL A3_nwv : std_ulogic := 'U'; SIGNAL A4_nwv : std_ulogic := 'U'; SIGNAL A5_nwv : std_ulogic := 'U'; SIGNAL A6_nwv : std_ulogic := 'U'; SIGNAL A7_nwv : std_ulogic := 'U'; SIGNAL A8_nwv : std_ulogic := 'U'; SIGNAL A9_nwv : std_ulogic := 'U'; SIGNAL A10_nwv : std_ulogic := 'U'; SIGNAL A11_nwv : std_ulogic := 'U'; SIGNAL A12_nwv : std_ulogic := 'U'; SIGNAL A13_nwv : std_ulogic := 'U'; SIGNAL A14_nwv : std_ulogic := 'U'; SIGNAL A15_nwv : std_ulogic := 'U'; SIGNAL A16_nwv : std_ulogic := 'U'; SIGNAL IO0_nwv : std_ulogic := 'U'; SIGNAL IO1_nwv : std_ulogic := 'U'; SIGNAL IO2_nwv : std_ulogic := 'U'; SIGNAL IO3_nwv : std_ulogic := 'U'; SIGNAL IO4_nwv : std_ulogic := 'U'; SIGNAL IO5_nwv : std_ulogic := 'U'; SIGNAL IO6_nwv : std_ulogic := 'U'; SIGNAL IO7_nwv : std_ulogic := 'U'; SIGNAL CENeg_nwv : std_ulogic := 'U'; SIGNAL OENeg_nwv : std_ulogic := 'U'; SIGNAL WENeg_nwv : std_ulogic := 'U'; --- internal delays SIGNAL WR_in : std_ulogic := '0'; SIGNAL WR_out : std_ulogic := '0'; SIGNAL BLC_in : std_ulogic := '0'; SIGNAL BLC_out : std_ulogic := '0'; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays WR :VitalBuf(WR_out, WR_in, (tdevice_WR ,UnitDelay)); BLC :VitalBuf(BLC_out, BLC_in, (tdevice_BLC ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); w_2 : VitalWireDelay (OENeg_ipd, OENeg, tipd_OENeg); w_3 : VitalWireDelay (WENeg_ipd, WENeg, tipd_WENeg); w_4 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_5 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_6 : VitalWireDelay (A2_ipd, A2, tipd_A2); w_7 : VitalWireDelay (A3_ipd, A3, tipd_A3); w_8 : VitalWireDelay (A4_ipd, A4, tipd_A4); w_9 : VitalWireDelay (A5_ipd, A5, tipd_A5); w_10 : VitalWireDelay (A6_ipd, A6, tipd_A6); w_11 : VitalWireDelay (A7_ipd, A7, tipd_A7); w_12 : VitalWireDelay (A8_ipd, A8, tipd_A8); w_13 : VitalWireDelay (A9_ipd, A9, tipd_A9); w_14 : VitalWireDelay (A10_ipd, A10, tipd_A10); w_15 : VitalWireDelay (A11_ipd, A11, tipd_A11); w_16 : VitalWireDelay (A12_ipd, A12, tipd_A12); w_17 : VitalWireDelay (A13_ipd, A13, tipd_A13); w_18 : VitalWireDelay (A14_ipd, A14, tipd_A14); w_19 : VitalWireDelay (A15_ipd, A15, tipd_A15); w_20 : VitalWireDelay (A16_ipd, A16, tipd_A16); w_21 : VitalWireDelay (IO0_ipd, IO0, tipd_IO0); w_22 : VitalWireDelay (IO1_ipd, IO1, tipd_IO1); w_23 : VitalWireDelay (IO2_ipd, IO2, tipd_IO2); w_24 : VitalWireDelay (IO3_ipd, IO3, tipd_IO3); w_25 : VitalWireDelay (IO4_ipd, IO4, tipd_IO4); w_26 : VitalWireDelay (IO5_ipd, IO5, tipd_IO5); w_27 : VitalWireDelay (IO6_ipd, IO6, tipd_IO6); w_28 : VitalWireDelay (IO7_ipd, IO7, tipd_IO7); END BLOCK; OENeg_nwv <= To_UX01(OENeg_ipd); CENeg_nwv <= To_UX01(CENeg_ipd); WENeg_nwv <= To_UX01(WENeg_ipd); A0_nwv <= To_UX01(A0_ipd); A1_nwv <= To_UX01(A1_ipd); A2_nwv <= To_UX01(A2_ipd); A3_nwv <= To_UX01(A3_ipd); A4_nwv <= To_UX01(A4_ipd); A5_nwv <= To_UX01(A5_ipd); A6_nwv <= To_UX01(A6_ipd); A7_nwv <= To_UX01(A7_ipd); A8_nwv <= To_UX01(A8_ipd); A9_nwv <= To_UX01(A9_ipd); A10_nwv <= To_UX01(A10_ipd); A11_nwv <= To_UX01(A11_ipd); A12_nwv <= To_UX01(A12_ipd); A13_nwv <= To_UX01(A13_ipd); A14_nwv <= To_UX01(A14_ipd); A15_nwv <= To_UX01(A15_ipd); A16_nwv <= To_UX01(A16_ipd); IO0_nwv <= To_UX01(IO0_ipd); IO1_nwv <= To_UX01(IO1_ipd); IO2_nwv <= To_UX01(IO2_ipd); IO3_nwv <= To_UX01(IO3_ipd); IO4_nwv <= To_UX01(IO4_ipd); IO5_nwv <= To_UX01(IO5_ipd); IO6_nwv <= To_UX01(IO6_ipd); IO7_nwv <= To_UX01(IO7_ipd); --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior: BLOCK PORT ( CENeg : IN std_ulogic := 'U'; OENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; A : IN std_logic_vector(16 DOWNTO 0) := (OTHERS => 'U'); IOIn : IN std_logic_vector(7 DOWNTO 0) := (OTHERS => 'U'); IOOut : OUT std_ulogic_vector(7 DOWNTO 0) := (OTHERS => 'Z') ); PORT MAP ( OENeg => OENeg_nwv, CENeg => CENeg_nwv, WENeg => WENeg_nwv, A(0) => A0_nwv, A(1) => A1_nwv, A(2) => A2_nwv, A(3) => A3_nwv, A(4) => A4_nwv, A(5) => A5_nwv, A(6) => A6_nwv, A(7) => A7_nwv, A(8) => A8_nwv, A(9) => A9_nwv, A(10) => A10_nwv, A(11) => A11_nwv, A(12) => A12_nwv, A(13) => A13_nwv, A(14) => A14_nwv, A(15) => A15_nwv, A(16) => A16_nwv, IOIn(0) => IO0_nwv, IOIn(1) => IO1_nwv, IOIn(2) => IO2_nwv, IOIn(3) => IO3_nwv, IOIn(4) => IO4_nwv, IOIn(5) => IO5_nwv, IOIn(6) => IO6_nwv, IOIn(7) => IO7_nwv, IOOut(0) => IO0, IOOut(1) => IO1, IOOut(2) => IO2, IOOut(3) => IO3, IOOut(4) => IO4, IOOut(5) => IO5, IOOut(6) => IO6, IOOut(7) => IO7 ); --zero delay signals SIGNAL DOut_zd : std_logic_vector(7 downto 0) := (OTHERS => 'Z'); SIGNAL IOOut_Pass : std_logic_vector(7 downto 0) := (OTHERS => 'Z'); -- State Machine : State_Type TYPE state_type IS (IDLE, WRT, SDPEN_ENTRY, SDPEN_LOAD, SDPEN_PROT, SDPDI_1, SDPDI_2, SDPDI_3, SDPDI_EXIT ); TYPE WriteBuffer IS ARRAY (0 TO 128) OF INTEGER RANGE -1 TO MaxData; TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; --------------------------------------------------------------------------- -- memory declaration --------------------------------------------------------------------------- SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); SHARED VARIABLE WRITE_BUFFER : WriteBuffer := (others => 0); SHARED VARIABLE PROT : BOOLEAN; -- states SIGNAL current_state : state_type; SIGNAL next_state : state_type; --Command Register SIGNAL write : std_logic := '0'; SIGNAL read : std_logic := '0'; SIGNAL write_tmp : std_logic := '0'; SIGNAL WEN : std_logic := '0'; SIGNAL IO_tmp : std_logic_vector (7 downto 0) := (others => '0'); SIGNAL RDY : std_logic := '0'; --FSM control signals SIGNAL WDONE : std_logic := '1'; -- Write. Done SIGNAL WSTART : std_logic := '0'; --Start Write SIGNAL WPDONE : std_logic := '1'; -- PageWrite. Done SIGNAL WPSTART : std_logic := '0'; --Start Page Write SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; -- timing check violation SIGNAL Viol : X01 := '0'; -- Access time variables SHARED VARIABLE OPENLATCH : BOOLEAN; SHARED VARIABLE FROMCE : BOOLEAN; SHARED VARIABLE FROMOE : BOOLEAN; BEGIN --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(A0_ipd, IO0_ipd, CENeg_ipd, OENeg_ipd, WENeg_ipd) -- Timing Check Variables VARIABLE Tviol_A0_WENeg : X01 := '0'; VARIABLE TD_A0_WENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg : X01 := '0'; VARIABLE TD_OENeg_WENeg : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg_Write : X01 := '0'; VARIABLE TD_OENeg_WENeg_Write : VitalTimingDataType; VARIABLE Tviol_OENeg_WENeg_DataPolling : X01 := '0'; VARIABLE TD_OENeg_WENeg_DataPolling : VitalTimingDataType; VARIABLE Tviol_WENeg_CENeg_setup : X01 := '0'; VARIABLE TD_WENeg_CENeg_setup : VitalTimingDataType; VARIABLE Tviol_WENeg_CENeg_hold : X01 := '0'; VARIABLE TD_WENeg_CENeg_hold : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_setup : X01 := '0'; VARIABLE TD_CENeg_WENeg_setup : VitalTimingDataType; VARIABLE Tviol_CENeg_WENeg_hold : X01 := '0'; VARIABLE TD_CENeg_WENeg_hold : VitalTimingDataType; VARIABLE Tviol_IO0_CENeg : X01 := '0'; VARIABLE TD_IO0_CENeg : VitalTimingDataType; VARIABLE Tviol_IO0_WENeg : X01 := '0'; VARIABLE TD_IO0_WENeg : VitalTimingDataType; VARIABLE Tviol_IO0_WENeg_Write : X01 := '0'; VARIABLE TD_IO0_WENeg_Write : VitalTimingDataType; VARIABLE Tviol_IO0_WENeg_DataPolling : X01 := '0'; VARIABLE TD_IO0_WENeg_DataPolling : VitalTimingDataType; VARIABLE Tviol_OENeg_CENeg : X01 := '0'; VARIABLE TD_OENeg_CENeg : VitalTimingDataType; VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_OENeg : X01 := '0'; VARIABLE PD_OENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between A0 and WE# VitalSetupHoldCheck ( TestSignal => A0_ipd, TestSignalName => "A0", RefSignal => WENeg_ipd, 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 Check between OE# and WE# / VitalSetupHoldCheck ( TestSignal => OENeg_ipd, TestSignalName => "OE#", RefSignal => WENeg_ipd, RefSignalName => "WE#", SetupHigh => tsetup_OENeg_WENeg, CheckEnabled => true, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg, Violation => Tviol_OENeg_WENeg ); -- Hold Check between OE# and WE# / VitalSetupHoldCheck ( TestSignal => OENeg_ipd, TestSignalName => "OE#", RefSignal => WENeg_ipd, RefSignalName => "WE#", HoldHigh => thold_OENeg_WENeg_Write_noedge_posedge, CheckEnabled => write = '1' AND NOT rising_edge(read), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg_Write, Violation => Tviol_OENeg_WENeg_Write ); -- Hold Check between OE# and WE# / VitalSetupHoldCheck ( TestSignal => OENeg_ipd, TestSignalName => "OE#", RefSignal => WENeg_ipd, RefSignalName => "WE#", HoldHigh => thold_OENeg_WENeg_DataPolling_noedge_posedge, CheckEnabled => rising_edge(read) AND write = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_WENeg_DataPolling, Violation => Tviol_OENeg_WENeg_DataPolling ); -- Setup Check between CE# and WE# \ VitalSetupHoldCheck ( TestSignal => CENeg_ipd, TestSignalName => "CE#", RefSignal => WENeg_ipd, RefSignalName => "WE#", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => true, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_setup, Violation => Tviol_CENeg_WENeg_setup ); -- Hold Check between CE# and WE# / VitalSetupHoldCheck ( TestSignal => CENeg_ipd, TestSignalName => "CE#", RefSignal => WENeg_ipd, RefSignalName => "WE#", HoldLow => thold_CENeg_WENeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_hold, Violation => Tviol_CENeg_WENeg_hold ); -- Setup Check between WE# and CE# \ VitalSetupHoldCheck ( TestSignal => WENeg_ipd, TestSignalName => "WE#", RefSignal => CENeg_ipd, RefSignalName => "CE#", SetupLow => tsetup_WENeg_CENeg, CheckEnabled => true, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_setup, Violation => Tviol_WENeg_CENeg_setup ); -- Hold Check between WE# and CE# / VitalSetupHoldCheck ( TestSignal => WENeg_ipd, TestSignalName => "WE#", RefSignal => CENeg_ipd, RefSignalName => "CE#", HoldLow => thold_WENeg_CENeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_hold, Violation => Tviol_WENeg_CENeg_hold ); -- Setup/Hold Check between IO0 and CE# \ VitalSetupHoldCheck ( TestSignal => IO0_ipd, TestSignalName => "IO0", RefSignal => CENeg_ipd, RefSignalName => "CE#", SetupHigh => tsetup_IO0_CENeg, SetupLow => tsetup_IO0_CENeg, HoldHigh => thold_IO0_CENeg, HoldLow => thold_IO0_CENeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_IO0_CENeg, Violation => Tviol_IO0_CENeg ); -- Setup Check between IO0 and WE# VitalSetupHoldCheck ( TestSignal => IO0_ipd, TestSignalName => "IO0", RefSignal => WENeg_ipd, RefSignalName => "WE#", SetupHigh => tsetup_IO0_WENeg, SetupLow => tsetup_IO0_WENeg, HoldHigh => thold_IO0_WENeg, HoldLow => thold_IO0_WENeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_IO0_WENeg, Violation => Tviol_IO0_WENeg ); -- Setup/Hold Check between IO0 and WE# VitalSetupHoldCheck ( TestSignal => IO0_ipd, TestSignalName => "IO0", RefSignal => WENeg_ipd, RefSignalName => "WE#", HoldHigh => thold_IO0_WENeg_Write_noedge_posedge, HoldLow => thold_IO0_WENeg_Write_noedge_posedge, CheckEnabled => write = '1' AND NOT rising_edge(read), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_IO0_WENeg_Write, Violation => Tviol_IO0_WENeg_Write ); -- Hold Check between IO0 and WE# VitalSetupHoldCheck ( TestSignal => IO0_ipd, TestSignalName => "IO0", RefSignal => WENeg_ipd, RefSignalName => "WE#", HoldHigh => thold_IO0_WENeg_DataPolling_noedge_posedge, HoldLow => thold_IO0_WENeg_DataPolling_noedge_posedge, CheckEnabled => rising_edge(read) AND write = '1', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_IO0_WENeg_DataPolling, Violation => Tviol_IO0_WENeg_DataPolling ); -- Hold Check between OE# and CE# VitalSetupHoldCheck ( TestSignal => OENeg_ipd, TestSignalName => "OE#", RefSignal => WENeg_ipd, RefSignalName => "CE#", HoldHigh => thold_OENeg_CENeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_OENeg_CENeg, Violation => Tviol_OENeg_CENeg ); -- Period Check CE# VitalPeriodPulseCheck ( TestSignal => CENeg_ipd, TestSignalName => "CE#", PulseWidthLow => tpw_CENeg_negedge, PeriodData => PD_CENeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CENeg, HeaderMsg => InstancePath & PartID, CheckEnabled => true ); -- Period Check WE# VitalPeriodPulseCheck ( TestSignal => WENeg_ipd, TestSignalName => "WE#", PulseWidthHigh => tpw_WENeg_posedge, PulseWidthLow => tpw_WENeg_negedge, PeriodData => PD_WENeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_WENeg, HeaderMsg => InstancePath & PartID, CheckEnabled => true ); -- Period Check OE# VitalPeriodPulseCheck ( TestSignal => OENeg_ipd, TestSignalName => "OE#", PulseWidthHigh => tpw_OENeg_DataPolling_posedge, PeriodData => PD_OENeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_OENeg, HeaderMsg => InstancePath & PartID, CheckEnabled => rising_edge(read) AND write = '1'); Violation := Tviol_A0_WENeg OR Tviol_OENeg_WENeg OR Tviol_OENeg_WENeg_Write OR Tviol_OENeg_WENeg_DataPolling OR Tviol_WENeg_CENeg_hold OR Tviol_WENeg_CENeg_setup OR Tviol_CENeg_WENeg_hold OR Tviol_CENeg_WENeg_setup OR Tviol_IO0_CENeg OR Tviol_IO0_WENeg OR Tviol_IO0_WENeg_Write OR Tviol_IO0_WENeg_DataPolling OR Tviol_OENeg_CENeg OR Pviol_CENeg OR Pviol_WENeg OR Pviol_OENeg; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; ---------------------------------------------------------------------------- -- process for FSM state transition ---------------------------------------------------------------------------- StateTransition : PROCESS(next_state) BEGIN current_state <= next_state; END PROCESS StateTransition; --latch address on rising edge and data on falling edge of write write_dc: PROCESS (WENeg, CENeg, OENeg) BEGIN IF (WENeg = '0') AND (CENeg = '0') AND (OENeg = '1') THEN write <= '1'; ELSE write <= '0'; 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 on falling edge of WE# or CE# what ever comes later --Latches data on rising edge of WE# or CE# what ever comes first -- also Write cycle decode --------------------------------------------------------------------------- BusCycleDecode : PROCESS(A, IOIn, WENeg, CENeg, OENeg, write) VARIABLE A_tmp1 : NATURAL RANGE 0 TO AddrRANGE; BEGIN IF (falling_edge(WENeg) AND CENeg='0' AND OENeg = '1' ) OR (falling_edge(CENeg) AND WENeg /= OENeg ) OR (falling_edge(OENeg) AND WENeg='1' AND CENeg = '0' ) OR ( A'EVENT AND CENeg='0' AND OENeg = '0') THEN A_tmp1 := to_nat(A(HiAddrBit downto 0)); Address <= A_tmp1; END IF; IF (rising_edge(WENeg) OR rising_edge(CENeg)) AND write = '1' THEN IO_tmp <= IOIn; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Write Cycle --------------------------------------------------------------------------- WriteTime : PROCESS(WSTART) VARIABLE wob : time; BEGIN wob := tdevice_WR; IF rising_edge(WSTART) AND WDONE = '1' THEN WDONE <= '0', '1' AFTER wob; END IF; END PROCESS WriteTime; --------------------------------------------------------------------------- -- Timing control for the Page Write Cycle --------------------------------------------------------------------------- PageWriteTime : PROCESS(WPSTART) VARIABLE wpob : time; BEGIN wpob := tdevice_BLC; IF rising_edge(WPSTART) THEN WPDONE <= '0', '1' AFTER wpob; END IF; END PROCESS PageWriteTime; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(write, IOIn, Address, CENeg, OENeg, WENeg, write_tmp, WDONE, WPDONE) VARIABLE DataByte : NATURAL RANGE 0 TO MaxData := 0; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- IF IOIn'EVENT THEN IF IOIn /= "XXXXXXXX" THEN DataByte := to_nat(IOIn); END IF; write_tmp <= '1', '0' AFTER 1 ns; END IF; CASE current_state IS WHEN IDLE => IF rising_edge(write) THEN IF ((Address = 16#5555#) AND (DataByte = 16#AA#))THEN next_state <= SDPEN_ENTRY; ELSIF NOT PROT AND NOT((Address = 16#5555#) AND (DataByte = 16#AA#)) THEN next_state <= WRT; END IF; ELSE next_state <= IDLE; END IF; WHEN WRT => IF rising_edge(WDONE) THEN next_state <= IDLE; END IF; WHEN SDPEN_ENTRY => IF rising_edge(write_tmp) THEN IF ((Address = 16#2AAA#) AND (DataByte = 16#55#))THEN next_state <= SDPEN_LOAD; ELSE next_state <= IDLE; END IF; END IF; WHEN SDPEN_LOAD => IF rising_edge(write_tmp) THEN IF ((Address = 16#5555#) AND (DataByte = 16#A0#))THEN next_state <= SDPEN_PROT; ELSIF ((Address = 16#5555#) AND (DataByte = 16#80#)) THEN next_state <= SDPDI_1; ELSE next_state <= IDLE; END IF; END IF; WHEN SDPEN_PROT => IF rising_edge(write) THEN next_state <= WRT; END IF; WHEN SDPDI_1 => IF rising_edge(write_tmp) THEN IF ((Address = 16#5555#) AND (DataByte = 16#AA#)) THEN next_state <= SDPDI_2; ELSE next_state <= IDLE; END IF; END IF; WHEN SDPDI_2 => IF rising_edge(write_tmp) THEN IF ((Address = 16#2AAA#) AND (DataByte = 16#55#)) THEN next_state <= SDPDI_3; ELSE next_state <= IDLE; END IF; END IF; WHEN SDPDI_3 => IF rising_edge(write_tmp) THEN IF ((Address = 16#5555#) AND (DataByte = 16#20#)) THEN next_state <= SDPDI_EXIT; ELSE next_state <= IDLE; END IF; END IF; WHEN SDPDI_EXIT => IF rising_edge(write) THEN next_state <= WRT; END IF; END CASE; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS(write,read, WDONE, current_state, CENeg_ipd, OENeg_ipd, Address, WENeg_ipd) VARIABLE oe : boolean := FALSE; VARIABLE Addr : NATURAL; VARIABLE byte_cnt : NATURAL; VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE; VARIABLE write_addr : NATURAL RANGE 0 TO AddrRANGE; VARIABLE data_out : std_logic_vector(7 downto 0); VARIABLE write_addr_vect : std_logic_vector(HiAddrBit downto 0); VARIABLE page_addr : std_logic_vector(HiAddrBit downto 0); VARIABLE wpage_bad_addr : std_logic; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- oe := rising_edge(read) OR (read = '1' AND Address'EVENT); read_addr := Address; write_addr := Address; CASE current_state IS WHEN IDLE => IF rising_edge(write) THEN WSTART <= '1', '0' AFTER 1 ns; WPSTART <= '1', '0' AFTER 1 ns; WEN <= '1'; RDY <= '1'; END IF; IF oe THEN --Read Memory array data_out := to_slv(Mem(read_addr),8); DOut_zd <= data_out; END IF; WHEN WRT => IF oe THEN data_out(7) := NOT IO_tmp(7); data_out(6) := NOT data_out(6); DOut_zd <= data_out; END IF; IF rising_edge (write) THEN data_out := IO_tmp; WEN <= '1'; WSTART <= '1', '0' AFTER 1 ns; WPSTART <= '1', '0' AFTER 1 ns; IF WPDONE = '1' OR byte_cnt > 128 THEN WEN <= '0'; RDY <= '0'; END IF; END IF; write_addr_vect := to_slv(write_addr,HiAddrBit+1); IF falling_edge(write) AND WPDONE = '0' AND byte_cnt = 0 AND WEN = '1' THEN WRITE_BUFFER(byte_cnt) := to_nat(IO_tmp); Mem(write_addr) := to_nat(IO_tmp); page_addr := write_addr_vect; byte_cnt := byte_cnt + 1; ELSIF falling_edge(write) AND WPDONE = '0' AND byte_cnt > 0 AND WEN = '1' AND write_addr_vect(HiAddrBit downto 7) = page_addr(HiAddrBit downto 7) THEN WRITE_BUFFER(byte_cnt) := to_nat(IO_tmp); Mem(write_addr) := to_nat(IO_tmp); byte_cnt := byte_cnt + 1; ELSIF write_addr_vect(HiAddrBit downto 7) /= page_addr(HiAddrBit downto 7) AND byte_cnt > 0 THEN wpage_bad_addr := '1'; END IF; IF WDONE = '1' OR wpage_bad_addr = '1' THEN byte_cnt := 0; WEN <= '0'; wpage_bad_addr := '0'; END IF; WHEN SDPEN_ENTRY => NULL; WHEN SDPEN_LOAD => NULL; WHEN SDPEN_PROT => PROT := TRUE; WHEN SDPDI_1 => NULL; WHEN SDPDI_2 => NULL; WHEN SDPDI_3 => NULL; WHEN SDPDI_EXIT => PROT := FALSE; END CASE; --Output Disable Control IF (CENeg_ipd = '1' OR OENeg_ipd = '1') THEN DOut_zd <= (OTHERS => 'Z'); END IF; END PROCESS Functional; --------------------------------------------------------------------------- ---- File Read Section - Preload Control --------------------------------------------------------------------------- MemPreload : PROCESS -- text file input variables FILE mem_file : text is mem_file_name; VARIABLE ind : NATURAL := 0; VARIABLE buf : line; BEGIN --------------------------------------------------------------------------- --s25320a memory preload file format ----------------------------------- --------------------------------------------------------------------------- -- / - comment -- @aaaaaa - stands for address -- dd -
is byte to be written at Mem(aaa++) -- (aaa is incremented at every load) -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! --------------------------------------------------------------------------- -- memory preload IF (mem_file_name /= "none" AND UserPreload) THEN ind := 0; Mem := (OTHERS => MaxData); WHILE (not ENDFILE (mem_file)) LOOP READLINE (mem_file, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 to 6)); --address IF ind > AddrRANGE THEN ASSERT false REPORT "Given preload address is out of" & "memory address range" SEVERITY warning; END IF; ELSE IF ind <= AddrRANGE THEN Mem(ind) := h(buf(1 to 2)); END IF; IF ind < AddrRANGE THEN ind := ind + 1; END IF; END IF; END LOOP; END IF; WAIT; END PROCESS MemPreload; DOutPassThrough : PROCESS(DOut_zd) VARIABLE ValidData : std_logic_vector(7 downto 0); VARIABLE CEDQ_t : TIME; VARIABLE OEDQ_t : TIME; VARIABLE ADDRDQ_t : TIME; BEGIN IF DOut_zd(0) /= 'Z' THEN OPENLATCH := TRUE; CEDQ_t := -CENeg'LAST_EVENT + tpd_CENeg_IO0(trz0); OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_IO0(trz0); ADDRDQ_t := -A'LAST_EVENT + tpd_A0_IO0(tr01); FROMOE := (OEDQ_t >= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t > OEDQ_t) AND (CEDQ_t > 0 ns); ValidData := "XXXXXXXX"; IF ((ADDRDQ_t > 0 ns) AND (((ADDRDQ_t > CEDQ_t) AND FROMCE) OR ((ADDRDQ_t > OEDQ_t) AND FROMOE))) THEN IOOut_Pass <= ValidData, DOut_zd AFTER ADDRDQ_t; ELSE IOOut_Pass <= DOut_zd; END IF; ELSE CEDQ_t := -CENeg'LAST_EVENT + tpd_CENeg_IO0(tr0z); OEDQ_t := -OENeg'LAST_EVENT + tpd_OENeg_IO0(tr0z); FROMOE := (OEDQ_t <= CEDQ_t) AND (OEDQ_t > 0 ns); FROMCE := (CEDQ_t < OEDQ_t) AND (CEDQ_t > 0 ns); IOOut_Pass <= DOut_zd; OPENLATCH := FALSE; END IF; END PROCESS DOutPassThrough; --------------------------------------------------------------------------- -- Path Delay Section for IOOut signal --------------------------------------------------------------------------- IO_Out_PathDelay_Gen : FOR i IN IOOut_Pass'RANGE GENERATE PROCESS(IOOut_Pass(i)) VARIABLE IO0_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => IOOut(i), OutSignalName => "IOOut", OutTemp => IOOut_Pass(i), GlitchData => IO0_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_IO0, PathCondition => (NOT OPENLATCH AND NOT FROMOE) OR (OPENLATCH AND FROMCE)), 1 => (InputChangeTime => OENeg'LAST_EVENT, PathDelay => tpd_OENeg_IO0, PathCondition => (NOT OPENLATCH AND NOT FROMOE) OR (OPENLATCH AND FROMOE)), 2 => (InputChangeTime => A'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_A0_IO0), PathCondition => (NOT FROMOE) AND (NOT FROMCE)) ) ); END PROCESS; END GENERATE IO_Out_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral;