------------------------------------------------------------------------------- -- File Name: s25fl128r00m.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2009 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.Colakovic 09 Jan 10 Initial Release ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH -- Technology: FLASH MEMORY -- Part: S25FL128R00M -- -- Description: 128 Megabit Serial Flash Memory with 104 MHz SPI Bus Interface -- ------------------------------------------------------------------------------- -- 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 s25fl128r00m IS GENERIC ( -- tipd delays: interconnect path delays tipd_SCK : VitalDelayType01 := VitalZeroDelay01; tipd_SI : VitalDelayType01 := VitalZeroDelay01; tipd_PO0 : VitalDelayType01 := VitalZeroDelay01; tipd_PO1 : VitalDelayType01 := VitalZeroDelay01; tipd_PO2 : VitalDelayType01 := VitalZeroDelay01; tipd_PO3 : VitalDelayType01 := VitalZeroDelay01; tipd_PO4 : VitalDelayType01 := VitalZeroDelay01; tipd_PO5 : VitalDelayType01 := VitalZeroDelay01; tipd_PO6 : VitalDelayType01 := VitalZeroDelay01; tipd_PO7 : VitalDelayType01 := VitalZeroDelay01; tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_SCK_PO7 : VitalDelayType01Z := UnitDelay01Z;--tV tpd_SCK_PO0 : VitalDelayType01Z := UnitDelay01Z;--tV tpd_CSNeg_PO7 : VitalDelayType01Z := UnitDelay01Z;--tDIS tpd_CSNeg_PO0 : VitalDelayType01Z := UnitDelay01Z;--tDIS tpd_HOLDNeg_PO7 : VitalDelayType01Z := UnitDelay01Z;--tLZ,tHZ tpd_HOLDNeg_PO0 : VitalDelayType01Z := UnitDelay01Z;--tLZ,tHZ --tsetup values tsetup_SI_SCK : VitalDelayType := UnitDelay; --tsuDAT / tsetup_PO0_SCK : VitalDelayType := UnitDelay; --tsuDAT / tsetup_CSNeg_SCK : VitalDelayType := UnitDelay; --tCSS / tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay; --tch / tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay; --tWPS \ --thold values thold_SI_SCK : VitalDelayType := UnitDelay; --thdDAT / thold_PO0_SCK : VitalDelayType := UnitDelay; --thdDAT / thold_CSNeg_SCK : VitalDelayType := UnitDelay; --tCSH / thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; --tCD / thold_WPNeg_CSNeg : VitalDelayType := UnitDelay; --tWPH \ --tpw values: pulse width tpw_SCK_serial_posedge : VitalDelayType := UnitDelay; -- tWH tpw_SCK_prl_posedge : VitalDelayType := UnitDelay; -- tWH tpw_SCK_serial_negedge : VitalDelayType := UnitDelay; -- tWL tpw_SCK_prl_negedge : VitalDelayType := UnitDelay; -- tWL tpw_CSNeg_serial_posedge : VitalDelayType := UnitDelay; --tCS tpw_CSNeg_prl_posedge : VitalDelayType := UnitDelay; --tCS -- tperiod min (calculated as 1/max freq) tperiod_SCK_serial_rd : VitalDelayType := UnitDelay;--fSCK=40MHz tperiod_SCK_prl_rd : VitalDelayType := UnitDelay; --fSCK=6MHz tperiod_SCK_serial_fast_rd : VitalDelayType := UnitDelay; --fSCK=104MHz tperiod_SCK_prl_fast_rd : VitalDelayType := UnitDelay;--fSCK=10MHz -- tdevice values: values for internal delays -- Page Program Operation tdevice_PP : VitalDelayType := 3 ms; --tPP --Sector Erase Operation tdevice_SE : VitalDelayType := 1 sec; --tSE --Bulk Erase Operation tdevice_BE : VitalDelayType := 256 sec; --tBE --Write Status Register Operation tdevice_WR : VitalDelayType := 100 ms; --tW --Deep Power Down tdevice_DP : VitalDelayType := 3 us; --tDP --Release from Software Protect Mode tdevice_RES : VitalDelayType := 30 us; --tRES --VCC (min) to CS# Low tdevice_PU : VitalDelayType := 15 ms; -- tPU -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- memory file to be loaded mem_file_name : STRING := "s25fl128r00m.mem"; UserPreload : BOOLEAN := FALSE; --TRUE; LongTimming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING ); PORT ( SCK : IN std_ulogic := 'U'; --serial clock input SI : IN std_ulogic := 'U'; --serial data input PO7 : INOUT std_ulogic := 'U'; --PO7/SO PO6 : INOUT std_ulogic := 'U'; -- PO5 : INOUT std_ulogic := 'U'; -- PO4 : INOUT std_ulogic := 'U'; -- PO3 : INOUT std_ulogic := 'U'; -- PO2 : INOUT std_ulogic := 'U'; -- PO1 : INOUT std_ulogic := 'U'; -- PO0 : INOUT std_ulogic := 'U'; -- CSNeg : IN std_ulogic := 'U'; -- chip select input HOLDNeg : IN std_ulogic := 'U'; -- hold input WPNeg : IN std_ulogic := 'U' -- write protect input ); ATTRIBUTE VITAL_LEVEL0 of s25fl128r00m : ENTITY IS TRUE; END s25fl128r00m; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of s25fl128r00m IS ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT PartID : STRING := "s25fl128r00m"; CONSTANT MaxData : NATURAL := 16#FF#; --255; CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 CONSTANT SecNum : NATURAL := 255; CONSTANT HiAddrBit : NATURAL := 23; CONSTANT AddrRANGE : NATURAL := 16#FFFFFF#; CONSTANT BYTE : NATURAL := 8; --Manufacturer Identification CONSTANT Manuf_ID : NATURAL := 16#01#; --Electronic Signature CONSTANT ES : NATURAL := 16#17#; --Device ID --Manufacturer Identification && Memory Type && Memory Capacity CONSTANT DeviceID : NATURAL := 16#2018#; CONSTANT ExtendedID : NATURAL := 16#0301#; CONSTANT DieRev : NATURAL := 16#02#; CONSTANT MaskRev : NATURAL := 16#00#; -- interconnect path delay signals SIGNAL SCK_ipd : std_ulogic := 'U'; SIGNAL SI_ipd : std_ulogic := 'U'; SIGNAL PO7_ipd : std_ulogic := 'U'; SIGNAL PO6_ipd : std_ulogic := 'U'; SIGNAL PO5_ipd : std_ulogic := 'U'; SIGNAL PO4_ipd : std_ulogic := 'U'; SIGNAL PO3_ipd : std_ulogic := 'U'; SIGNAL PO2_ipd : std_ulogic := 'U'; SIGNAL PO1_ipd : std_ulogic := 'U'; SIGNAL PO0_ipd : std_ulogic := 'U'; SIGNAL CSNeg_ipd : std_ulogic := 'U'; SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; --- internal delays SIGNAL PP_in : std_ulogic := '0'; SIGNAL PP_out : std_ulogic := '0'; SIGNAL PU_in : std_ulogic := '0'; SIGNAL PU_out : std_ulogic := '0'; SIGNAL SE_in : std_ulogic := '0'; SIGNAL SE_out : std_ulogic := '0'; SIGNAL BE_in : std_ulogic := '0'; SIGNAL BE_out : std_ulogic := '0'; SIGNAL WR_in : std_ulogic := '0'; SIGNAL WR_out : std_ulogic := '0'; SIGNAL DP_in : std_ulogic := '0'; SIGNAL DP_out : std_ulogic := '0'; SIGNAL RES_in : std_ulogic := '0'; SIGNAL RES_out : std_ulogic := '0'; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); WR :VitalBuf(WR_out, WR_in, (tdevice_WR ,UnitDelay)); DP :VitalBuf(DP_out, DP_in, (tdevice_DP ,UnitDelay)); RES :VitalBuf(RES_out, RES_in, (tdevice_RES ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); w_2 : VitalWireDelay (SI_ipd, SI, tipd_SI); w_3 : VitalWireDelay (PO7_ipd, PO7, tipd_PO7); w_4 : VitalWireDelay (PO6_ipd, PO6, tipd_PO6); w_5 : VitalWireDelay (PO5_ipd, PO5, tipd_PO5); w_6 : VitalWireDelay (PO4_ipd, PO4, tipd_PO4); w_7 : VitalWireDelay (PO3_ipd, PO3, tipd_PO3); w_8 : VitalWireDelay (PO2_ipd, PO2, tipd_PO2); w_9 : VitalWireDelay (PO1_ipd, PO1, tipd_PO1); w_10: VitalWireDelay (PO0_ipd, PO0, tipd_PO0); w_11: VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); w_12: VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); w_13: VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); END BLOCK; --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior: BLOCK PORT ( SCK : IN std_ulogic := 'U'; SI : IN std_ulogic := 'U'; PIn : IN std_logic_vector(7 downto 0) := (OTHERS => 'U'); POut : OUT std_logic_vector(7 downto 0) := (OTHERS => 'Z'); CSNeg : IN std_ulogic := 'U'; HOLDNeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U' ); PORT MAP ( SCK => SCK_ipd, SI => SI_ipd, PIn(7) => PO7_ipd, PIn(6) => PO6_ipd, PIn(5) => PO5_ipd, PIn(4) => PO4_ipd, PIn(3) => PO3_ipd, PIn(2) => PO2_ipd, PIn(1) => PO1_ipd, PIn(0) => PO0_ipd, POut(7) => PO7, POut(6) => PO6, POut(5) => PO5, POut(4) => PO4, POut(3) => PO3, POut(2) => PO2, POut(1) => PO1, POut(0) => PO0, CSNeg => CSNeg_ipd, HOLDNeg => HOLDNeg_ipd, WPNeg => WPNeg_ipd ); -- State Machine : State_Type TYPE state_type IS (IDLE, DP_DOWN_WAIT, DP_DOWN, WRITE_SR, SECTOR_ER, BULK_ER, PAGE_PG ); -- Instruction Type TYPE instruction_type IS (NONE, WREN, WRDI, WRSR, RDSR, READ, READ_ID, RDID, FAST_READ, SE, BE, PP, DP, RES_READ_ES, ENTER_PRL, EXIT_PRL ); TYPE WByteType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; --Flash Memory Array TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; --------------------------------------------------------------------------- -- memory declaration --------------------------------------------------------------------------- SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); -- states SIGNAL current_state : state_type; SIGNAL next_state : state_type; SIGNAL WByte : WByteType := (others => 0); SIGNAL Instruct : instruction_type; --zero delay signal SIGNAL POut_zd : std_logic_vector(7 downto 0):=(OTHERS=>'Z'); --HOLD delay on output data SIGNAL POut_z : std_logic_vector(7 downto 0):=(OTHERS=>'Z'); -- powerup SIGNAL PoweredUp : std_logic := '0'; SHARED VARIABLE Status_reg : std_logic_vector(7 downto 0) := (others => '0'); SIGNAL Status_reg_in : std_logic_vector(7 downto 0) := (others => '0'); SHARED VARIABLE Status_reg_temp : std_logic_vector(7 downto 0) := (others => '0'); ALIAS WIP :std_logic IS Status_reg(0); ALIAS WEL :std_logic IS Status_reg(1); ALIAS BP0 :std_logic IS Status_reg(2); ALIAS BP1 :std_logic IS Status_reg(3); ALIAS BP2 :std_logic IS Status_reg(4); ALIAS BP3 :std_logic IS Status_reg(5); ALIAS PE_ERR :std_logic IS Status_reg(6); ALIAS SRWD :std_logic IS Status_reg(7); --Command Register SIGNAL write : std_logic := '0'; SIGNAL read_out : std_logic := '0'; SIGNAL fast_rd : boolean := true; SIGNAL rd : boolean := false; SIGNAL frst_rd : boolean := false; SHARED VARIABLE no_frst_rd : boolean := false; --Parallel mode active SIGNAL PRL_ACT : std_logic := '0'; SHARED VARIABLE prl : boolean := false; SHARED VARIABLE serial : boolean := true; SHARED VARIABLE hold_mode : boolean := false; SIGNAL change_addr : std_logic := '0'; --FSM control signals SIGNAL PDONE : std_logic := '1'; -- Page Prog. Done SIGNAL PSTART : std_logic := '0'; --Start Page Programming SIGNAL WDONE : std_logic := '1'; -- Write. Done SIGNAL WSTART : std_logic := '0'; --Start Write SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL EDONE : std_logic := '1'; --Erase Done SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; SIGNAL Byte_number : NATURAL RANGE 0 TO 255 := 0; SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) := (OTHERS => '0'); SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; -- timing check violation SIGNAL Viol : X01 := '0'; PROCEDURE ADDRHILO_SEC( VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE Addr : NATURAL) IS VARIABLE sector : NATURAL RANGE 0 TO SecNum; BEGIN sector := Addr/16#10000#; AddrLOW := sector*16#10000#; AddrHIGH := sector*16#10000# + 16#0FFFF#; END ADDRHILO_SEC; PROCEDURE ADDRHILO_PG( VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE Addr : NATURAL) IS VARIABLE page : NATURAL RANGE 0 TO 65535; BEGIN page := Addr/16#100#; AddrLOW := Page*16#100#; AddrHIGH := Page*16#100# + 16#FF#; END AddrHILO_PG; BEGIN ---------------------------------------------------------------------------- --Power Up time; --------------------------------------------------------------------------- PoweredUp <= '1' AFTER tdevice_PU; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(SI_ipd, PIn, SCK_ipd, CSNeg_ipd, HOLDNeg_ipd, WPNeg_ipd) -- Timing Check Variables VARIABLE Tviol_SI_SCK : X01 := '0'; VARIABLE TD_SI_SCK : VitalTimingDataType; VARIABLE Tviol_PO0_SCK : X01 := '0'; VARIABLE TD_PO0_SCK : VitalTimingDataType; VARIABLE Tviol_HOLD_SCK : X01 := '0'; VARIABLE TD_HOLD_SCK : VitalTimingDataType; VARIABLE Tviol_CS_SCK : X01 := '0'; VARIABLE TD_CS_SCK : VitalTimingDataType; VARIABLE Tviol_WS_CS : X01 := '0'; VARIABLE TD_WS_CS : VitalTimingDataType; VARIABLE Tviol_WH_CS : X01 := '0'; VARIABLE TD_WH_CS : VitalTimingDataType; VARIABLE Pviol_CS_serial : X01 := '0'; VARIABLE PD_CS_serial : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CS_prl : X01 := '0'; VARIABLE PD_CS_prl : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_SCK_serial : X01 := '0'; VARIABLE PD_SCK_serial : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_SCK_prl : X01 := '0'; VARIABLE PD_SCK_prl : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_SCK_serial_rd : X01 := '0'; VARIABLE PD_SCK_serial_rd : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_SCK_prl_rd : X01 := '0'; VARIABLE PD_SCK_prl_rd : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_SCK_serial_fast_rd: X01 := '0'; VARIABLE PD_SCK_serial_fast_rd : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_SCK_prl_fast_rd: X01 := '0'; VARIABLE PD_SCK_prl_fast_rd : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- Setup/Hold Check between SI and SCK, serial mode VitalSetupHoldCheck ( TestSignal => SI_ipd, TestSignalName => "SI", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_SI_SCK, SetupLow => tsetup_SI_SCK, HoldHigh => thold_SI_SCK, HoldLow => thold_SI_SCK, CheckEnabled => serial, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_SI_SCK, Violation => Tviol_SI_SCK ); -- Setup/Hold Check between PO0 and SCK, parallel mode VitalSetupHoldCheck ( TestSignal => PIn, TestSignalName => "PO", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_PO0_SCK, SetupLow => tsetup_PO0_SCK, HoldHigh => thold_PO0_SCK, HoldLow => thold_PO0_SCK, CheckEnabled => prl AND POut_z /= PIn, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_PO0_SCK, Violation => Tviol_PO0_SCK ); -- Setup/Hold Check between HOLD# and SCK / VitalSetupHoldCheck ( TestSignal => HOLDNeg_ipd, TestSignalName => "HOLD#", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupLow => tsetup_HOLDNeg_SCK, SetupHigh => tsetup_HOLDNeg_SCK, HoldLow => thold_HOLDNeg_SCK, HoldHigh => thold_HOLDNeg_SCK, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_HOLD_SCK, Violation => Tviol_HOLD_SCK ); -- Setup/Hold Check between CS# and SCK VitalSetupHoldCheck ( TestSignal => CSNeg_ipd, TestSignalName => "CS#", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_CSNeg_SCK, SetupLow => tsetup_CSNeg_SCK, HoldHigh => thold_CSNeg_SCK, HoldLow => thold_CSNeg_SCK, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CS_SCK, Violation => Tviol_CS_SCK ); -- Setup Check between WP# and CS# \ VitalSetupHoldCheck ( TestSignal => WPNeg_ipd, TestSignalName => "WP#", RefSignal => CSNeg_ipd, RefSignalName => "CS#", SetupHigh => tsetup_WPNeg_CSNeg, CheckEnabled => true, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WS_CS, Violation => Tviol_WS_CS ); -- Hold Check between WP# and CS# / VitalSetupHoldCheck ( TestSignal => WPNeg_ipd, TestSignalName => "WP#", RefSignal => CSNeg_ipd, RefSignalName => "CS#", HoldHigh => thold_WPNeg_CSNeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WH_CS, Violation => Tviol_WH_CS ); -- Period Check CS#, serial mode VitalPeriodPulseCheck ( TestSignal => CSNeg_ipd, TestSignalName => "CS#", PulseWidthHigh => tpw_CSNeg_serial_posedge, PeriodData => PD_CS_serial, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CS_serial, HeaderMsg => InstancePath & PartID, CheckEnabled => serial ); -- Period Check CS#, parallel mode VitalPeriodPulseCheck ( TestSignal => CSNeg_ipd, TestSignalName => "CS#", PulseWidthHigh => tpw_CSNeg_prl_posedge, PeriodData => PD_CS_prl, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CS_prl, HeaderMsg => InstancePath & PartID, CheckEnabled => prl AND no_frst_rd ); -- Period Check SCK for everything but READ, serial mode VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", PulseWidthLow => tpw_SCK_serial_negedge, PulseWidthHigh => tpw_SCK_serial_posedge, PeriodData => PD_SCK_serial, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_serial, HeaderMsg => InstancePath & PartID, CheckEnabled => serial ); -- Period Check SCK for everything but READ, parallel mode VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", PulseWidthLow => tpw_SCK_prl_negedge, PulseWidthHigh => tpw_SCK_prl_posedge, PeriodData => PD_SCK_prl, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_prl, HeaderMsg => InstancePath & PartID, CheckEnabled => prl AND no_frst_rd); -- Period Check SCK for READ, serial mode VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", Period => tperiod_SCK_serial_rd, PeriodData => PD_SCK_serial_rd, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_serial_rd, HeaderMsg => InstancePath & PartID, CheckEnabled => serial AND rd ); -- Period Check SCK for READ, parallel mode VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", Period => tperiod_SCK_prl_rd, PeriodData => PD_SCK_prl_rd, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_prl_rd, HeaderMsg => InstancePath & PartID, CheckEnabled => prl AND rd AND no_frst_rd); -- Period Check SCK for other than READ, serial mode VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", Period => tperiod_SCK_serial_fast_rd, PeriodData => PD_SCK_serial_fast_rd, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_serial_fast_rd, HeaderMsg => InstancePath & PartID, CheckEnabled => serial AND fast_rd ); -- Period Check SCK for other than READ, parallel mode VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", Period => tperiod_SCK_prl_fast_rd, PeriodData => PD_SCK_prl_fast_rd, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_prl_fast_rd, HeaderMsg => InstancePath & PartID, CheckEnabled => prl AND fast_rd AND no_frst_rd); Violation := Tviol_SI_SCK OR Tviol_PO0_SCK OR Tviol_HOLD_SCK OR Tviol_CS_SCK OR Tviol_WS_CS OR Tviol_WH_CS OR Pviol_SCK_serial OR Pviol_SCK_prl OR Pviol_SCK_serial_rd OR Pviol_SCK_prl_rd OR Pviol_SCK_serial_fast_rd OR Pviol_SCK_prl_fast_rd OR Pviol_CS_serial OR Pviol_CS_prl; 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 FSM state transition ---------------------------------------------------------------------------- StateTransition : PROCESS(next_state, PoweredUp) BEGIN IF PoweredUp = '1' THEN current_state <= next_state; END IF; END PROCESS StateTransition; --------------------------------------------------------------------------- -- Write cycle decode --------------------------------------------------------------------------- BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_ipd, SI_ipd, RES_in) TYPE bus_cycle_type IS (STAND_BY, CODE_BYTE, ADDRESS_BYTES, DUMMY_BYTES, DATA_BYTES ); TYPE prl_data_type IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; VARIABLE bus_cycle_state : bus_cycle_type; VARIABLE data_cnt : NATURAL := 0; VARIABLE addr_cnt : NATURAL := 0; VARIABLE code_cnt : NATURAL := 0; VARIABLE dummy_cnt : NATURAL := 0; VARIABLE bit_cnt : NATURAL := 0; VARIABLE Data_in : std_logic_vector(2047 downto 0) := (others => '0'); VARIABLE prl_data_in : prl_data_type; VARIABLE code : std_logic_vector(7 downto 0); VARIABLE code_in : std_logic_vector(7 downto 0); VARIABLE Byte_slv : std_logic_vector(7 downto 0); VARIABLE addr_bytes : std_logic_vector(HiAddrBit downto 0); VARIABLE Address_in : std_logic_vector(23 downto 0); BEGIN IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES) AND NOT(bus_cycle_state = DUMMY_BYTES) THEN bus_cycle_state := STAND_BY; ELSE CASE bus_cycle_state IS WHEN STAND_BY => IF falling_edge(CSNeg_ipd) THEN Instruct <= NONE; write <= '1'; code_cnt := 0; addr_cnt := 0; data_cnt := 0; dummy_cnt := 0; bus_cycle_state := CODE_BYTE; END IF; WHEN CODE_BYTE => serial := TRUE; prl := FALSE; IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN IF code_cnt < 8 OR PE_ERR = '0' THEN Code_in(code_cnt) := SI_ipd; END IF; code_cnt := code_cnt + 1; IF code_cnt = BYTE THEN --MSB first FOR I IN 7 DOWNTO 0 LOOP code(i) := code_in(7-i); END LOOP; IF PE_ERR = '0' THEN CASE code IS WHEN "00000110" => Instruct <= WREN; bus_cycle_state := DATA_BYTES; WHEN "00000100" => Instruct <= WRDI; bus_cycle_state := DATA_BYTES; WHEN "00000001" => Instruct <= WRSR; bus_cycle_state := DATA_BYTES; WHEN "00000101" => Instruct <= RDSR; bus_cycle_state := DATA_BYTES; WHEN "00000011" => Instruct <= READ; bus_cycle_state := ADDRESS_BYTES; WHEN "00001011" => Instruct <= FAST_READ; IF PRL_ACT /= '1' THEN bus_cycle_state := ADDRESS_BYTES; END IF; WHEN "10011111" => Instruct <= RDID; bus_cycle_state := DATA_BYTES; WHEN "10010000" => Instruct <= READ_ID; bus_cycle_state := ADDRESS_BYTES; WHEN "10101011" => Instruct <= RES_READ_ES; bus_cycle_state := DUMMY_BYTES; WHEN "11011000" | "00100000" => Instruct <= SE; bus_cycle_state := ADDRESS_BYTES; WHEN "11000111" | "01100000" => Instruct <= BE; bus_cycle_state := DATA_BYTES; WHEN "00000010" => Instruct <= PP; bus_cycle_state := ADDRESS_BYTES; WHEN "10111001" => Instruct <= DP; bus_cycle_state := DATA_BYTES; WHEN "01010101" => Instruct <= ENTER_PRL; bus_cycle_state := DATA_BYTES; WHEN "01000101" => Instruct <= EXIT_PRL; bus_cycle_state := DATA_BYTES; WHEN others => null; END CASE; ELSE CASE code IS WHEN "00000110"|"00000100"|"00000001"| "00000011"|"00001011"|"10011111"|"00000010"| "10010000"|"10101011"|"11011000"|"00100000"| "10111001"|"01010101"|"01000101"|"11000111"| "01100000"=> ASSERT false REPORT "Device does not accept any "& "command other then RDSR while " & "P/E Error bit is set to 1" SEVERITY WARNING; WHEN "00000101" => Instruct <= RDSR; bus_cycle_state := DATA_BYTES; WHEN others => null; END CASE; END IF; END IF; END IF; WHEN ADDRESS_BYTES => IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN Address_in(addr_cnt) := SI_ipd; addr_cnt := addr_cnt + 1; IF addr_cnt = 3*BYTE THEN FOR I IN 23 DOWNTO 23-HiAddrBit LOOP addr_bytes(23-i) := Address_in(i); END LOOP; Address <= to_nat(addr_bytes); change_addr <= '1','0' AFTER 1 ns; IF Instruct = FAST_READ THEN bus_cycle_state := DUMMY_BYTES; ELSE bus_cycle_state := DATA_BYTES; END IF; END IF; END IF; WHEN DUMMY_BYTES => IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN dummy_cnt := dummy_cnt + 1; IF dummy_cnt = BYTE THEN IF Instruct = FAST_READ THEN bus_cycle_state := DATA_BYTES; END IF; ELSIF dummy_cnt = 3*BYTE THEN bus_cycle_state := DATA_BYTES; END IF; END IF; IF rising_edge(CSNeg_ipd) THEN IF (HOLDNeg_ipd = '1' AND dummy_cnt = 0 AND Instruct = RES_READ_ES) THEN write <= '0'; END IF; bus_cycle_state := STAND_BY; END IF; WHEN DATA_BYTES => IF PRL_ACT = '1' THEN prl := TRUE; serial := FALSE; ELSE prl := FALSE; serial := TRUE; END IF; IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' AND HOLDNeg_ipd = '1' THEN IF Instruct = READ OR Instruct = RES_READ_ES OR Instruct = FAST_READ OR Instruct = RDSR OR Instruct = RDID OR Instruct = READ_ID THEN read_out <= '1', '0' AFTER 1 ns; END IF; END IF; IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN IF serial = true THEN IF data_cnt > 2047 THEN --In case of serial mode and PP, --if more than 256 bytes are sent to the device IF bit_cnt = 0 THEN FOR I IN 0 TO (255*BYTE - 1) LOOP Data_in(i) := Data_in(i+8); END LOOP; END IF; Data_in(2040 + bit_cnt) := SI_ipd; bit_cnt := bit_cnt + 1; IF bit_cnt = 8 THEN bit_cnt := 0; END IF; data_cnt := data_cnt + 1; ELSE Data_in(data_cnt) := SI_ipd; data_cnt := data_cnt + 1; bit_cnt := 0; END IF; ELSE IF data_cnt > 255 THEN --In case of parallel mode and PP, --if more than 256 bytes are sent to the device FOR I IN 0 TO 254 LOOP prl_data_in(i) := prl_data_in(i+1); END LOOP; prl_data_in(255) := to_nat(PIn); data_cnt := data_cnt +1; ELSE prl_data_in(data_cnt) :=to_nat(PIn); data_cnt := data_cnt +1; END IF; no_frst_rd := true; END IF; END IF; IF rising_edge(CSNeg_ipd) THEN bus_cycle_state := STAND_BY; IF HOLDNeg_ipd = '1' THEN CASE Instruct IS WHEN WREN | WRDI | DP | BE | SE => IF data_cnt = 0 THEN write <= '0'; END IF; WHEN ENTER_PRL | EXIT_PRL => IF data_cnt = 0 THEN write <= '0'; IF Instruct = ENTER_PRL AND current_state /= DP_DOWN THEN PRL_ACT <= '1'; ELSIF Instruct = EXIT_PRL THEN PRL_ACT <= '0'; END IF; END IF; WHEN RES_READ_ES => write <= '0'; WHEN WRSR => IF data_cnt = 8 THEN write <= '0'; IF PRL_ACT = '0' THEN Status_reg_in <= Data_in(7 downto 0); ELSE Status_reg_temp := to_slv(prl_data_in(0),8); FOR i IN 0 TO 7 LOOP Status_reg_in(i) <= Status_reg_temp(7-i); END LOOP; END IF; --MSB first END IF; WHEN PP => IF data_cnt > 0 THEN IF serial = true THEN IF data_cnt mod 8 = 0 THEN write <= '0'; FOR I IN 0 TO 255 LOOP FOR J IN 7 DOWNTO 0 LOOP Byte_slv(j) := Data_in((i*8) + (7-j)); END LOOP; WByte(i) <= to_nat(Byte_slv); END LOOP; IF data_cnt > 256*BYTE THEN Byte_number <= 255; ELSE Byte_number <= data_cnt/8-1; END IF; END IF; ELSE write <= '0'; FOR I IN 0 TO 255 LOOP WByte(i) <= prl_data_in(i); END LOOP; IF data_cnt > 256 THEN Byte_number <= 255; ELSE Byte_number <= data_cnt - 1; END IF; END IF; END IF; WHEN others => null; END CASE; END IF; no_frst_rd := false; END IF; END CASE; END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Page Program --------------------------------------------------------------------------- ProgTime : PROCESS(PSTART) VARIABLE pob : time; BEGIN IF LongTimming THEN pob := tdevice_PP; ELSE pob := tdevice_PP / 100; END IF; IF rising_edge(PSTART) AND PDONE = '1' THEN IF Sec_Prot(SA) = '0' THEN PDONE <= '0', '1' AFTER pob; END IF; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Write Status Register --------------------------------------------------------------------------- WriteTime : PROCESS(WSTART) VARIABLE wob : time; BEGIN IF LongTimming THEN wob := tdevice_WR; ELSE wob := tdevice_WR / 100; END IF; IF rising_edge(WSTART) AND WDONE = '1' THEN WDONE <= '0', '1' AFTER wob; END IF; END PROCESS WriteTime; --------------------------------------------------------------------------- -- Timing control for the Bulk Erase --------------------------------------------------------------------------- ErsTime : PROCESS(ESTART) VARIABLE seo : time; VARIABLE beo : time; VARIABLE duration : time; BEGIN IF LongTimming THEN seo := tdevice_SE; beo := tdevice_BE; ELSE seo := tdevice_SE / 1000; beo := tdevice_BE / 1000; END IF; IF rising_edge(ESTART) AND EDONE = '1' THEN IF Instruct = BE THEN duration := beo; ELSE --Instruct = SE duration := seo; END IF; EDONE <= '0', '1' AFTER duration; END IF; END PROCESS ErsTime; CheckCEOnPowerUP :PROCESS(CSNeg_ipd) BEGIN IF CSNeg_ipd = '0' AND PoweredUp = '0' THEN REPORT InstancePath & partID & ": Device is selected during Power Up" SEVERITY WARNING; END IF; END PROCESS; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen :PROCESS(write, CSNeg, WDONE, PDONE, EDONE, DP_out) VARIABLE sect : NATURAL RANGE 0 TO SecNum; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- CASE current_state IS WHEN IDLE => IF falling_edge(write) THEN IF Instruct = WRSR AND WEL = '1' AND not(SRWD = '1' AND WPNeg = '0') THEN -- can not execute if HPM is entered -- or if WEL bit is zero next_state <= WRITE_SR; ELSIF Instruct = PP AND WEL = '1' THEN sect := Address / 16#10000#; IF Sec_Prot(sect) = '0' THEN next_state <= PAGE_PG; END IF; ELSIF Instruct = SE AND WEL = '1' THEN sect := Address / 16#10000#; IF Sec_Prot(sect) = '0' THEN next_state <= SECTOR_ER; END IF; ELSIF Instruct = BE AND WEL = '1' AND (BP0='0' AND BP1='0' AND BP2='0' AND BP3='0') THEN next_state <= BULK_ER; ELSIF Instruct = DP THEN next_state <= DP_DOWN_WAIT; ELSE next_state <= IDLE; END IF; END IF; WHEN WRITE_SR => IF rising_edge(WDONE) THEN next_state <= IDLE; END IF; WHEN PAGE_PG => IF rising_edge(PDONE) THEN next_state <= IDLE; END IF; WHEN BULK_ER | SECTOR_ER => IF rising_edge(EDONE) THEN next_state <= IDLE; END IF; WHEN DP_DOWN_WAIT => IF rising_edge(DP_out) THEN next_state <= DP_DOWN; END IF; WHEN DP_DOWN => IF falling_edge(write) AND Instruct = RES_READ_ES THEN next_state <= IDLE; END IF; END CASE; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS(write,read_out, WDONE, PDONE, EDONE, current_state, CSNeg_ipd, HOLDNeg_ipd, Instruct, Address, WByte, DP_out, RES_out, change_addr, PoweredUp, WPNeg_ipd) TYPE WDataType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; VARIABLE WData : WDataType:= (OTHERS => 0); VARIABLE oe : boolean := FALSE; VARIABLE AddrLo : NATURAL; VARIABLE AddrHi : NATURAL; VARIABLE Addr : NATURAL; VARIABLE Addr_tmp : NATURAL; VARIABLE read_cnt : NATURAL; VARIABLE prl_read_cnt : NATURAL; VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE; VARIABLE data_out : std_logic_vector(7 downto 0); VARIABLE ident_out : std_logic_vector(55 downto 0); 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 255; VARIABLE sect : NATURAL RANGE 0 TO SecNum; VARIABLE BP : std_logic_vector(3 downto 0) := "0000"; VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- oe := rising_edge(read_out) AND PoweredUp = '1'; IF Instruct'EVENT THEN read_cnt := 0; prl_read_cnt := 0; fast_rd <= true; rd <= false; frst_rd <= false; no_frst_rd := false; END IF; IF rising_edge(change_addr) THEN read_addr := Address; END IF; IF RES_out'EVENT AND RES_out = '1' THEN RES_in <= '0'; END IF; CASE current_state IS WHEN IDLE => IF falling_edge(write) THEN read_cnt := 0; prl_read_cnt := 0; IF RES_in = '1' AND Instruct /= DP THEN ASSERT false REPORT InstancePath & partID & "Command results" & " can be corrupted, a delay of tRES" & " currently in progress." SEVERITY WARNING; END IF; IF Instruct = WREN THEN WEL := '1'; ELSIF Instruct = WRDI THEN WEL := '0'; ELSIF Instruct = WRSR AND WEL = '1' AND not(SRWD = '1' AND WPNeg_ipd = '0') THEN -- can not execute if HPM is entered -- or if WEL bit is zero WSTART <= '1', '0' AFTER 1 ns; WIP := '1'; ELSIF Instruct = PP AND WEL = '1' THEN sect := Address / 16#10000#; IF Sec_Prot(sect) = '0' THEN PSTART <= '1', '0' AFTER 1 ns; WIP := '1'; SA <= sect; Addr := Address; Addr_tmp := Address; wr_cnt := Byte_number; FOR I IN wr_cnt DOWNTO 0 LOOP IF Viol /= '0' THEN WData(i) := -1; ELSE WData(i) := WByte(i); END IF; END LOOP; ELSE PE_ERR := '1'; END IF; ELSIF Instruct = SE AND WEL = '1' THEN sect := Address / 16#10000#; IF Sec_Prot(sect) = '0' THEN ESTART <= '1', '0' AFTER 1 ns; WIP := '1'; Addr := Address; ELSE PE_ERR := '1'; END IF; ELSIF Instruct = BE AND WEL = '1' THEN IF (BP0='0' AND BP1='0' AND BP2='0' AND BP3='0') THEN ESTART <= '1', '0' AFTER 1 ns; WIP := '1'; ELSE PE_ERR := '1'; END IF; ELSIF Instruct = DP THEN RES_in <= '0'; DP_in <= '1'; END IF; ELSIF oe AND RES_in = '0' THEN IF Instruct = RDSR THEN --Read Status Register IF serial = true THEN POut_zd(7) <= Status_reg(7-read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; POut_zd <= Status_reg; END IF; ELSIF Instruct = READ OR Instruct = FAST_READ THEN --Read Memory array IF Instruct = READ THEN fast_rd <= false; rd <= true; END IF; data_out := to_slv(Mem(read_addr),8); IF serial = true THEN POut_zd(7) <= data_out(7-read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; IF read_addr = AddrRANGE THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; POut_zd <= data_out; IF read_addr = AddrRANGE THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSIF Instruct = RDID THEN --Read Device ID --can be terminated by driving CSNeg high --at any time ident_out := to_slv(Manuf_ID,8) & to_slv(DeviceID,16) & to_slv(ExtendedID,16) & to_slv(DieRev,8) & to_slv(MaskRev,8); IF serial = true THEN POut_zd(7) <= ident_out(55-read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 56 THEN read_cnt := 0; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; IF prl_read_cnt = 0 THEN POut_zd <= ident_out(55 downto 48); prl_read_cnt := prl_read_cnt + 1; ELSIF prl_read_cnt = 1 THEN POut_zd <= ident_out(47 downto 40); prl_read_cnt := prl_read_cnt + 1; ELSIF prl_read_cnt = 2 THEN POut_zd <= ident_out(39 downto 32); prl_read_cnt := prl_read_cnt + 1; ELSIF prl_read_cnt = 3 THEN POut_zd <= ident_out(31 downto 24); prl_read_cnt := prl_read_cnt + 1; ELSIF prl_read_cnt = 4 THEN POut_zd <= ident_out(23 downto 16); prl_read_cnt := prl_read_cnt + 1; ELSIF prl_read_cnt = 5 THEN POut_zd <= ident_out(15 downto 8); prl_read_cnt := prl_read_cnt + 1; ELSIF prl_read_cnt = 6 THEN POut_zd <= ident_out(7 downto 0); prl_read_cnt := 0; END IF; END IF; ELSIF RES_in = '0' AND Instruct = READ_ID THEN --Read Manufacturer and Device ID IF read_addr = 0 THEN data_out := to_slv(Manuf_ID,8); IF serial = true THEN POut_zd(7) <= data_out(7 - read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; read_addr := read_addr + 1; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; POut_zd <= data_out; read_addr := read_addr + 1; END IF; ELSIF read_addr = 1 THEN data_out := to_slv(ES,8); IF serial = true THEN POut_zd(7) <= data_out(7 - read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; read_addr := 0; END IF; ELSE POut_zd <= data_out; read_addr := 0; END IF; END IF; END IF; ELSIF oe AND RES_in = '1' THEN IF serial = true THEN POut_zd(7) <= 'X'; read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; END IF; END IF; ASSERT false REPORT InstancePath & partID & "Command results" & " can be corrupted, a delay of tRES" & " currently in progress." SEVERITY WARNING; END IF; WHEN WRITE_SR => IF oe AND Instruct = RDSR THEN IF serial = true THEN POut_zd(7) <= Status_reg(7-read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; POut_zd <= Status_reg; END IF; END IF; IF WDONE = '1' THEN WIP := '0'; WEL := '0'; SRWD := Status_reg_in(0);--MSB first BP3 := Status_reg_in(2); BP2 := Status_reg_in(3); BP1 := Status_reg_in(4); BP0 := Status_reg_in(5); BP := BP3 & BP2 & BP1 & BP0; CASE BP IS WHEN "0000" => Sec_Prot := (others => '0'); WHEN "0001" => Sec_Prot(255 downto 254) := (others => '1'); Sec_Prot(253 downto 0) := (others => '0'); WHEN "0010" => Sec_Prot(255 downto 252) := (others => '1'); Sec_Prot(251 downto 0) := (others => '0'); WHEN "0011" => Sec_Prot(255 downto 248) := (others => '1'); Sec_Prot(247 downto 0) := (others => '0'); WHEN "0100" => Sec_Prot(255 downto 240) := (others => '1'); Sec_Prot(239 downto 0) := (others => '0'); WHEN "0101" => Sec_Prot(255 downto 224) := (others => '1'); Sec_Prot(223 downto 0) := (others => '0'); WHEN "0110" => Sec_Prot(255 downto 192) := (others => '1'); Sec_Prot(191 downto 0) := (others => '0'); WHEN "0111" => Sec_Prot(255 downto 128) := (others => '1'); Sec_Prot(127 downto 0) := (others => '0'); WHEN others => Sec_Prot := (others => '1'); END CASE; END IF; WHEN PAGE_PG => IF oe AND Instruct = RDSR THEN IF serial = true THEN POut_zd(7) <= Status_reg(7-read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; POut_zd <= Status_reg; END IF; END IF; ADDRHILO_PG(AddrLo, AddrHi, Addr); cnt := 0; FOR i IN 0 TO wr_cnt LOOP new_int := WData(i); old_int := Mem(Addr + i - cnt); 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; ELSE WData(i) := -1; END IF; Mem(Addr + i - cnt) := -1; IF (Addr + i) = AddrHi THEN Addr := AddrLo; cnt := i + 1; END IF; END LOOP; cnt :=0; IF PDONE = '1' THEN WIP := '0'; WEL := '0'; FOR i IN 0 TO wr_cnt LOOP Mem(Addr_tmp + i - cnt) := WData(i); IF (Addr_tmp + i) = AddrHi THEN Addr_tmp := AddrLo; cnt := i + 1; END IF; END LOOP; END IF; WHEN SECTOR_ER => IF oe AND Instruct = RDSR THEN IF serial = true THEN POut_zd(7) <= Status_reg(7-read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; POut_zd <= Status_reg; END IF; END IF; ADDRHILO_SEC(AddrLo, AddrHi, Addr); FOR i IN AddrLo TO AddrHi LOOP Mem(i) := -1; END LOOP; IF EDONE = '1' THEN WIP := '0'; WEL := '0'; FOR i IN AddrLo TO AddrHi LOOP Mem(i) := MaxData; END LOOP; END IF; WHEN BULK_ER => IF oe AND Instruct = RDSR THEN IF serial = true THEN POut_zd(7) <= Status_reg(7-read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; POut_zd <= Status_reg; END IF; END IF; FOR i IN 0 TO AddrRANGE LOOP Mem(i) := -1; END LOOP; IF EDONE = '1' THEN WIP := '0'; WEL := '0'; FOR i IN 0 TO AddrRANGE LOOP Mem(i) := MaxData; END LOOP; END IF; WHEN DP_DOWN_WAIT => IF rising_edge(DP_out) THEN DP_in <= '0'; ELSIF DP_in = '1' AND Instruct'EVENT THEN ASSERT false REPORT InstancePath & partID & "Command results" & " can be corrupted, a delay of tPD" & " currently in progress." SEVERITY WARNING; END IF; WHEN DP_DOWN => IF falling_edge(write) THEN IF Instruct = RES_READ_ES THEN RES_in <= '1'; END IF; ELSIF oe AND Instruct = RES_READ_ES THEN --Read Electronic Signature IF serial = TRUE THEN data_out := to_slv(ES,8); POut_zd(7) <= data_out(7 - read_cnt); read_cnt := read_cnt + 1; IF read_cnt = 8 THEN read_cnt := 0; END IF; ELSE frst_rd <= true; no_frst_rd := frst_rd; data_out := to_slv(ES,8); POut_zd <= data_out; END IF; END IF; END CASE; --Output Disable Control IF (CSNeg_ipd = '1') THEN IF serial = true THEN POut_zd(7) <= 'Z'; ELSE POut_zd <= "ZZZZZZZZ"; END IF; END IF; END PROCESS Functional; HOLD_FRAME_ON_PO_ZD : PROCESS(POut_zd, HOLDNeg_ipd) BEGIN IF (HOLDNeg_ipd = '0') THEN hold_mode := TRUE; IF serial = true THEN POut_z(7) <= 'Z'; ELSE POut_z <= "ZZZZZZZZ"; END IF; ELSE IF hold_mode THEN IF serial = true THEN POut_z(7) <= POut_zd(7) AFTER tpd_HOLDNeg_PO7(trz0); ELSE POut_z <= POut_zd AFTER tpd_HOLDNeg_PO0(trz0); END IF; hold_mode := FALSE; ELSE IF serial = true THEN POut_z(7) <= POut_zd(7); ELSE POut_z <= POut_zd; END IF; hold_mode := FALSE; END IF; END IF; END PROCESS HOLD_FRAME_ON_PO_ZD; --------------------------------------------------------------------------- ---- File Read Section - Preload Control --------------------------------------------------------------------------- MemPreload : PROCESS(PoweredUp) -- text file input variables FILE mem_file : text is mem_file_name; VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0; VARIABLE buf : line; BEGIN IF (PoweredUp = '1') THEN --Default values on start simulation --Sector protection preload Sec_Prot := (OTHERS => '0'); --Status Register preload Status_reg := (OTHERS => '0'); --------------------------------------------------------------------------- --s25fl128r00m memory preload file format --------------------------------------------------------------------------- --------------------------------------------------------------------------- -- / - comment -- @aaaaaa - stands for address -- dd -
is byte to be written at Mem(aaaaaa++) -- (aaaaaa 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 IF ind > AddrRANGE THEN ASSERT false REPORT "Given preload address is out of" & "memory address range" SEVERITY warning; ELSE ind := h(buf(2 to 7)); --address END IF; ELSE Mem(ind) := h(buf(1 to 2)); ind := ind + 1; END IF; END LOOP; END IF; END IF; END PROCESS MemPreload; PO7_OUT: PROCESS(POut_z(7)) VARIABLE PO7_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => POut(7), OutSignalName => "POut", OutTemp => POut_z(7), GlitchData => PO7_GlitchData, Paths => ( 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_PO7), PathCondition => POut_z(7) /= 'Z' AND serial), 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, PathDelay => tpd_CSNeg_PO7, PathCondition => CSNeg_ipd = '1' AND serial), 2 => (InputChangeTime => HOLDNeg_ipd'LAST_EVENT, PathDelay => tpd_HOLDNeg_PO7, PathCondition => serial) ) ); END PROCESS PO7_OUT; P_Out_PathDelay_Gen : FOR i IN 0 TO 7 GENERATE PROCESS(POut_z(i)) VARIABLE PO_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => POut(i), OutSignalName => "PO", OutTemp => POut_z(i), GlitchData => PO_GlitchData, Paths => ( 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_PO0), PathCondition => POut_z(i) /= 'Z' AND prl), 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, PathDelay => tpd_CSNeg_PO0, PathCondition => CSNeg_ipd = '1' AND prl), 2 => (InputChangeTime => HOLDNeg_ipd'LAST_EVENT, PathDelay => tpd_HOLDNeg_PO0, PathCondition => prl) ) ); END PROCESS; END GENERATE P_Out_PathDelay_Gen; END BLOCK behavior; END vhdl_behavioral;