------------------------------------------------------------------------------- -- File Name: s25fl128k.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2010 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 R. Prokopovic 10 Oct 08 Inital Release ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH -- Technology: FLASH MEMORY -- Part: S25FL128K -- -- Description: 128 Megabit Serial Flash Memory -- ------------------------------------------------------------------------------- -- 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 s25fl128k IS GENERIC ( --------------------------------------------------------------------------- -- TIMING GENERICS: --------------------------------------------------------------------------- -- tipd delays: interconnect path delays (delay between components) -- There should be one for each IN or INOUT pin in the port list -- They are given default values of zero delay. tipd_SCK : VitalDelayType01 := VitalZeroDelay01; tipd_SI : VitalDelayType01 := VitalZeroDelay01; tipd_SO : VitalDelayType01 := VitalZeroDelay01; tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; -- tpd delays: propagation delays (pin-to-pin delay within a component) tpd_SCK_SO_RDID_EQ_0 : VitalDelayType01Z := UnitDelay01Z;--tCLQV1 tpd_SCK_SO_RDID_EQ_1 : VitalDelayType01Z := UnitDelay01Z;--tCLQV2 tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tSHQZ tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tHLQZ -- tsetup values: setup times tsetup_CSNeg_SCK : VitalDelayType := UnitDelay;--tSLCH,tSHCH tsetup_SI_SCK_normal_noedge_posedge : VitalDelayType := UnitDelay;--tDVCH tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay;--tHLCH,tHHCH tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay;--tWHSL -- thold values: hold times thold_CSNeg_SCK : VitalDelayType := UnitDelay;--tSLCH,tSHCH thold_SI_SCK_normal_noedge_posedge : VitalDelayType := UnitDelay;--tCHDX thold_HOLDNeg_SCK : VitalDelayType := UnitDelay;--tCHHL,tCHHH thold_WPNeg_CSNeg : VitalDelayType := UnitDelay;--tSHWL --tpw values: pulse width tpw_SCK_slow_posedge : VitalDelayType := UnitDelay; -- tCH tpw_SCK_slow_negedge : VitalDelayType := UnitDelay; -- tCL tpw_SCK_fast_posedge : VitalDelayType := UnitDelay; -- tCH tpw_SCK_fast_negedge : VitalDelayType := UnitDelay; -- tCL tpw_SCK_quad_posedge : VitalDelayType := UnitDelay; -- tCH tpw_SCK_quad_negedge : VitalDelayType := UnitDelay; -- tCL tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tSHSL1 tpw_CSNeg_pger_posedge : VitalDelayType := UnitDelay; -- tSHSL2 -- tperiod min (calculated as 1/max freq) tperiod_SCK_slow : VitalDelayType := UnitDelay;-- tperiod_SCK_fast : VitalDelayType := UnitDelay;-- tperiod_SCK_quad : VitalDelayType := UnitDelay;-- -- tdevice values: values for internal delays -- VCC (min) to CS# Low tdevice_PU : VitalDelayType := 10 us; -- CS# High to Power Down Mode -- tDP tdevice_DP : VitalDelayType := 3 us; -- CS# High to StandBy mode without Electronic Signature read tdevice_RES1 : VitalDelayType := 3 us; -- CS# High to StandBy mode with Electronic Signature read tdevice_RES2 : VitalDelayType := 1.8 us; -- CS# High to next Instruction after Suspend tdevice_PRGSUSP : VitalDelayType := 20 us; -- CS# High to next Instruction after Suspend tdevice_ERSSUSP : VitalDelayType := 20 us; -- CS# High to next Instruction after Suspend tdevice_SUSP_DLY : VitalDelayType := 20 us; -- Resume Suspend to Program/Erase time tdevice_PRGRES : VitalDelayType := 200 ns; -- Resume Suspend to Program/Erase time tdevice_ERSRES : VitalDelayType := 200 ns; -- Page Program Time tdevice_PP : VitalDelayType := 3 ms; -- Byte Program Time (First Byte) tdevice_BP1 : VitalDelayType := 50 us; -- Additional Byte Program Time (After First Byte) tdevice_BP2 : VitalDelayType := 12 us; -- Sector Erase Time (4KB) tdevice_SE : VitalDelayType := 400 ms; -- Block Erase Time (32KB) tdevice_BE1 : VitalDelayType := 800 ms; -- Block Erase Time (64KB) tdevice_BE2 : VitalDelayType := 1000 ms; -- Chip Erase Time tdevice_CE : VitalDelayType := 40 sec; -- Write Status Register Time tdevice_WRR : VitalDelayType := 15 ms; -- Write Volatile Status Register Time tdevice_VRR : VitalDelayType := 50 ns; --------------------------------------------------------------------------- -- CONTROL GENERICS: --------------------------------------------------------------------------- -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- memory file to be loaded mem_file_name : STRING := "s25fl128k.mem"; screg_file_name : STRING := "s25fl128kscreg.mem"; UserPreload : BOOLEAN := FALSE; --TRUE; LongTimming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( -- Data Inputs/Outputs SI : INOUT std_ulogic := 'U'; -- serial data input/IO0 SO : INOUT std_ulogic := 'U'; -- serial data output/IO1 -- Controls SCK : IN std_ulogic := 'U'; -- serial clock input CSNeg : IN std_ulogic := 'U'; -- chip select input WPNeg : INOUT std_ulogic := 'U'; -- write protect input/IO2 HOLDNeg : INOUT std_ulogic := 'U' -- hold input/IO3 ); ATTRIBUTE VITAL_LEVEL0 of s25fl128k : ENTITY IS TRUE; END s25fl128k; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of s25fl128k IS ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; --------------------------------------------------------------------------- -- CONSTANT AND SIGNAL DECLARATION --------------------------------------------------------------------------- --Declaration of constants - memory characteristics -- The constant declared here are used to enable the creation of models -- of memories within a family with a minimum amount of editing CONSTANT PartID : STRING := "s25fl128k"; CONSTANT MaxData : NATURAL := 16#FF#; CONSTANT AddrRANGE : NATURAL := 16#FFFFFF#; CONSTANT PageNum : NATURAL := 16#FFFF#; CONSTANT SecSize_4 : NATURAL := 16#FFF#; CONSTANT SecSize_32 : NATURAL := 16#7FFF#; CONSTANT SecSize_64 : NATURAL := 16#FFFF#; CONSTANT Blk_4_Num : NATURAL := 4095; CONSTANT Blk_64_Num : NATURAL := 255; CONSTANT Blk_32_Num : NATURAL := 511; CONSTANT SFDP_HiAddr : NATURAL := 16#FF#; CONSTANT SFDP_LoAddr : NATURAL := 16#00#; CONSTANT SecReg_HiAddr : NATURAL := 16#FF#; CONSTANT SecReg_LoAddr : NATURAL := 16#00#; CONSTANT SCREG_LoAddr : NATURAL := 16#000#; CONSTANT SCREG_HiAddr : NATURAL := 16#2FF#; CONSTANT BYTE : NATURAL := 8; -- Manufacturer Identification and Device Identification CONSTANT Manuf_ID : NATURAL := 16#EF#; CONSTANT Device_ID1 : NATURAL := 16#17#; CONSTANT Device_ID2 : NATURAL := 16#40#; CONSTANT Device_ID3 : NATURAL := 16#18#; CONSTANT Unique_id_1 : NATURAL := 16#ABAB#;--this is 64bit ID number CONSTANT Unique_id_2 : NATURAL := 16#00#;--this is 64bit ID number -- Declaration of signals that will hold the delayed values of ports SIGNAL SI_ipd : std_ulogic := 'U'; SIGNAL SO_ipd : std_ulogic := 'U'; SIGNAL SCK_ipd : std_ulogic := 'U'; SIGNAL CSNeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; SIGNAL WPNeg_pullup : std_ulogic := 'U'; -- internal delays SIGNAL PP_in : std_ulogic := '0'; SIGNAL PP_out : std_ulogic := '0'; SIGNAL BP1_in : std_ulogic := '0'; SIGNAL BP1_out : std_ulogic := '0'; SIGNAL BP2_in : std_ulogic := '0'; SIGNAL BP2_out : std_ulogic := '0'; SIGNAL SE_in : std_ulogic := '0'; SIGNAL SE_out : std_ulogic := '0'; SIGNAL BE1_in : std_ulogic := '0'; SIGNAL BE1_out : std_ulogic := '0'; SIGNAL BE2_in : std_ulogic := '0'; SIGNAL BE2_out : std_ulogic := '0'; SIGNAL CE_in : std_ulogic := '0'; SIGNAL CE_out : std_ulogic := '0'; SIGNAL WRR_in : std_ulogic := '0'; SIGNAL WRR_out : std_ulogic := '0'; SIGNAL ERSSUSP_in : std_ulogic := '0'; SIGNAL ERSSUSP_out : std_ulogic := '0'; SIGNAL ERSRES_in : std_ulogic := '0'; SIGNAL ERSRES_out : std_ulogic := '0'; SIGNAL PRGSUSP_in : std_ulogic := '0'; SIGNAL PRGSUSP_out : std_ulogic := '0'; SIGNAL PRGRES_in : std_ulogic := '0'; SIGNAL PRGRES_out : std_ulogic := '0'; SIGNAL PU_in : std_ulogic := '0'; SIGNAL PU_out : std_ulogic := '0'; SIGNAL RES1_in : std_ulogic := '0'; SIGNAL RES1_out : std_ulogic := '0'; SIGNAL RES2_in : std_ulogic := '0'; SIGNAL RES2_out : std_ulogic := '0'; SIGNAL DP_in : std_ulogic := '0'; SIGNAL DP_out : std_ulogic := '0'; SIGNAL SUSP_FL_IN : std_ulogic := '0'; SIGNAL SUSP_FL_OUT : std_ulogic := '0'; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays -- Because a tdevice generics is used, there must be a VITAL_primitives -- assotiated with them PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); BP1 :VitalBuf(BP1_out, BP1_in, (tdevice_BP1 ,UnitDelay)); BP2 :VitalBuf(BP2_out, BP2_in, (tdevice_BP2 ,UnitDelay)); SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); BE1 :VitalBuf(BE1_out, BE1_in, (tdevice_BE1 ,UnitDelay)); BE2 :VitalBuf(BE2_out, BE2_in, (tdevice_BE2 ,UnitDelay)); WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay)); ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay)); ERSRES :VitalBuf(ERSRES_out, ERSRES_in, (tdevice_ERSRES ,UnitDelay)); PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay)); PRGRES :VitalBuf(PRGRES_out, PRGRES_in, (tdevice_PRGRES ,UnitDelay)); PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); RES1 :VitalBuf(RES1_out, RES1_in, (tdevice_RES1 ,UnitDelay)); CE :VitalBuf(CE_out, CE_in, (tdevice_CE ,UnitDelay)); DP :VitalBuf(DP_out, DP_in, (tdevice_DP ,UnitDelay)); RES2 :VitalBuf(RES2_out, RES2_in, (tdevice_RES2 ,UnitDelay)); SUSP_DLY :VitalBuf(SUSP_FL_OUT, SUSP_FL_IN, (tdevice_SUSP_DLY,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (SI_ipd, SI, tipd_SI); w_2 : VitalWireDelay (SO_ipd, SO, tipd_SO); w_3 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); w_4 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); w_6 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); w_7 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); END BLOCK; --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior: BLOCK PORT ( SIIn : IN std_ulogic := 'U'; SIOut : OUT std_ulogic := 'U'; SOIn : IN std_logic := 'U'; SOut : OUT std_logic := 'U'; SCK : IN std_ulogic := 'U'; CSNeg : IN std_ulogic := 'U'; HOLDNegIn : IN std_ulogic := 'U'; HOLDNegOut : OUT std_ulogic := 'U'; WPNegIn : IN std_ulogic := 'U'; WPNegOut : OUT std_ulogic := 'U' ); PORT MAP ( SIIn => SI_ipd, SIOut => SI, SOIn => SO_ipd, SOut => SO, SCK => SCK_ipd, CSNeg => CSNeg_ipd, HOLDNegIn => HOLDNeg_ipd, HOLDNegOut => HOLDNeg, WPNegIn => WPNeg_ipd, WPNegOut => WPNeg ); -- State Machine : State_Type TYPE state_type IS (IDLE, WRITE_SR, PAGE_PG, PG_SUSP, SECTOR_ERS, BULK_ERS, ERS_SUSP, ERS_SUSP_PG, PG_SUSP_ERS, DP_DOWN, WRITE_SR_V ); -- Instruction Type TYPE instruction_type IS ( NONE, WREN , -- 06h WRENV , -- 50h WRDI , -- 04h RDSR , -- 05h RDSR2 , -- 35h WRR , -- 01h READ , -- 03h FAST_READ , -- 0Bh FAST_DREAD , -- 3Bh FAST_QREAD , -- 6Bh FAST_DREAD_2 , -- BBh FAST_QREAD_4 , -- EBh W_QREAD , -- E7h WOCT_QREAD , -- E3h SET_BURST_WRAP , -- 77h CONT_RD_RST , -- FFh or FFFFH PP , -- 02h QPP , -- 32h SE , -- 20h BE_32 , -- 52h BE_64 , -- D8h CE , -- C7h or 60h ERS_PG_SUSP , -- 75h ERS_PG_RES , -- 7Ah DP , -- B9h RES_RD_ID , -- ABh RDID , -- 90h RDID_DUAL , -- 92h RDID_QUAD , -- 94h RD_UNIQ_ID , -- 4Bh RDIDJ , -- 9Fh RD_SFDP , -- 5Ah ERS_SCREG , -- 44h PG_SCREG , -- 42h RD_SCREG -- 48h ); 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; -- SFDP Memory Array TYPE SFDPArray IS ARRAY (SFDP_LoAddr TO SFDP_HiAddr) OF INTEGER RANGE -1 TO MaxData; -- Security Register Array TYPE SCREGArray IS ARRAY (SecReg_LoAddr TO SecReg_HiAddr) OF INTEGER RANGE -1 TO MaxData; ----------------------------------------------------------------------- -- memory declaration ----------------------------------------------------------------------- -- Memory SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); -- Security Register 1 SHARED VARIABLE Security_Reg1 : SCREGArray := (OTHERS => MaxData); -- Security Register 2 SHARED VARIABLE Security_Reg2 : SCREGArray := (OTHERS => MaxData); -- Security Register 3 SHARED VARIABLE Security_Reg3 : SCREGArray := (OTHERS => MaxData); --SFDP Array SHARED VARIABLE SFDP_array : SFDPArray := (OTHERS => 0); -- Programming Buffer SIGNAL WByte : WByteType := (OTHERS => MaxData); -- states SIGNAL current_state : state_type; SIGNAL next_state : state_type; SIGNAL Instruct : instruction_type; --zero delay signal SIGNAL SOut_zd : std_logic := 'Z'; SIGNAL SIOut_zd : std_logic := 'Z'; SIGNAL HOLDNegOut_zd : std_logic := 'Z'; SIGNAL WPNegOut_zd : std_logic := 'Z'; --HOLD delay on output data SIGNAL SOut_z : std_logic := 'Z'; SIGNAL SIOut_z : std_logic := 'Z'; -- powerup SIGNAL PoweredUp : std_logic := '0'; ----------------------------------------------------------------------- -- Registers ----------------------------------------------------------------------- -- Status register 1 SHARED VARIABLE Status_reg1 : std_logic_vector(7 downto 0) := (others => '0'); SIGNAL Status_reg1_in : std_logic_vector(7 downto 0) := (others => '0'); -- Status Register Protect Bit 0 ALIAS SRP0 :std_logic IS Status_reg1(7); -- Sector/Block protect bit ALIAS SEC :std_logic IS Status_reg1(6); -- Top Bottom Bit ALIAS TB :std_logic IS Status_reg1(5); -- Status Register Block Protection Bits ALIAS BP2 :std_logic IS Status_reg1(4); ALIAS BP1 :std_logic IS Status_reg1(3); ALIAS BP0 :std_logic IS Status_reg1(2); -- Status Register Write Enable Latch Bit ALIAS WEL :std_logic IS Status_reg1(1); -- Status Register Busy Bit ALIAS BUSY :std_logic IS Status_reg1(0); -- Status register 2 SHARED VARIABLE Status_reg2 : std_logic_vector(7 downto 0) := (others => '0'); SIGNAL Status_reg2_in : std_logic_vector(7 downto 0) := (others => '0'); -- Suspend status bit ALIAS SUS :std_logic IS Status_reg2(7); -- Complement protect bit ALIAS CMP :std_logic IS Status_reg2(6); -- Security Register Lock bits ALIAS LB3 :std_logic IS Status_reg2(5); ALIAS LB2 :std_logic IS Status_reg2(4); ALIAS LB1 :std_logic IS Status_reg2(3); -- Quad enable bit ALIAS QE :std_logic IS Status_reg2(1); -- Status register protect bit ALIAS SRP1 :std_logic IS Status_reg2(0); -- Sector is protect if Sec_Prot(Blk_4_Num) = '1' SHARED VARIABLE Sec_Prot : std_logic_vector(Blk_4_Num downto 0) := (OTHERS => '0'); --Command Register SIGNAL write : std_logic := '0'; SIGNAL read_out : std_logic := '0'; SIGNAL pg_screg_flag : boolean := false; SIGNAL ers_screg_flag : boolean := false; SIGNAL slow_read : boolean := false; SIGNAL dual_read : boolean := false; SIGNAL fast_rd : boolean := true; SIGNAL quad_read : boolean := false; SIGNAL read_id : boolean := false; SIGNAL sr_read : boolean := false; SHARED VARIABLE pp_quad : boolean := false; SHARED VARIABLE hold_mode : boolean := false; SHARED VARIABLE res_flag : boolean := false; SHARED VARIABLE wren_vlt_flag : boolean := false; --FSM control signals SIGNAL PDONE : std_logic := '1'; SIGNAL PSTART : std_logic := '0'; SIGNAL PGSUSP : std_logic := '0'; SIGNAL PGRES : std_logic := '0'; SIGNAL WDONE : std_logic := '1'; SIGNAL WSTART : std_logic := '0'; SIGNAL VLTSTART : std_logic := '0'; SIGNAL VLTDONE : std_logic := '1'; SIGNAL EDONE : std_logic := '1'; SIGNAL ESTART : std_logic := '0'; SIGNAL ESUSP : std_logic := '0'; SIGNAL ERES : std_logic := '0'; SHARED VARIABLE read_cnt : NATURAL := 0; SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ; SHARED VARIABLE wrap_byte : std_logic_vector(7 downto 0); SIGNAL change_addr : std_logic := '0'; SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; SIGNAL change_prot_bits : std_logic := '0'; SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000"; SHARED VARIABLE LB_bits : std_logic_vector(2 downto 0) := "000"; SIGNAL Byte_number : NATURAL RANGE 0 TO 255 := 0; -- Sector and subsector addresses SIGNAL SA : NATURAL RANGE 0 TO Blk_4_Num := 0; SHARED VARIABLE sect : NATURAL RANGE 0 TO Blk_4_Num; SHARED VARIABLE sect_tmp_pg : NATURAL RANGE 0 TO Blk_4_Num; SHARED VARIABLE sect_tmp_ers: NATURAL RANGE 0 TO Blk_4_Num; SHARED VARIABLE w_size : NATURAL RANGE 0 TO 64; -- timing check violation SIGNAL Viol : X01 := '0'; PROCEDURE ADDRHILO_SEC64 ( 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 Blk_64_Num; BEGIN sector := Addr/16#10000#; AddrLOW := sector*16#10000#; AddrHIGH := sector*16#10000# + 16#0FFFF#; END ADDRHILO_SEC64; PROCEDURE ADDRHILO_SEC32 ( 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 Blk_32_Num; BEGIN sector := Addr/16#8000#; AddrLOW := sector*16#8000#; AddrHIGH := sector*16#8000# + 16#7FFF#; END ADDRHILO_SEC32; PROCEDURE ADDRHILO_SEC4 ( 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 Blk_4_Num; BEGIN sector := Addr/16#1000#; AddrLOW := sector*16#1000#; AddrHIGH := sector*16#1000# + 16#0FFF#; END ADDRHILO_SEC4; 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 PageNum; BEGIN page := Addr/16#100#; AddrLOW := Page*16#100#; AddrHIGH := Page*16#100# + 16#FF#; END AddrHILO_PG; PROCEDURE ADDRHILO_WRAP( VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; VARIABLE Address : NATURAL; VARIABLE Wrap_size: NATURAL) IS VARIABLE Addr_tmp : NATURAL; VARIABLE Sect_wrap: NATURAL; BEGIN Addr_tmp := Address; Sect_wrap := Addr_tmp/Wrap_size; AddrLOW := Sect_wrap*Wrap_size; AddrHIGH := Sect_wrap*Wrap_size + (Wrap_size - 1); END ADDRHILO_WRAP; BEGIN --------------------------------------------------------------------------- --Power Up time --------------------------------------------------------------------------- PoweredUp <= '1' AFTER tdevice_PU; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(SIIn,SOIn,SCK_ipd,CSNeg_ipd,HOLDNegIn,WPNegIn) -- Timing Check Variables -- Setup/Hold Checks variables VARIABLE Tviol_CSNeg_SCK : X01 := '0'; VARIABLE TD_CSNeg_SCK : VitalTimingDataType; VARIABLE Tviol_SI_SCK : X01 := '0'; VARIABLE TD_SI_SCK : VitalTimingDataType; VARIABLE Tviol_SOIn_SCK : X01 := '0'; VARIABLE TD_SOIn_SCK : VitalTimingDataType; VARIABLE Tviol_HOLDNeg_SCK : X01 := '0'; VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType; VARIABLE Tviol_HOLDNegIn_SCK : X01 := '0'; VARIABLE TD_HOLDNegIn_SCK : VitalTimingDataType; VARIABLE Tviol_WPNegIn_SCK : X01 := '0'; VARIABLE TD_WPNegIn_SCK : VitalTimingDataType; VARIABLE Tviol_WPNeg_CSNeg_setup : X01 := '0'; VARIABLE TD_WPNeg_CSNeg_setup : VitalTimingDataType; VARIABLE Tviol_WPNeg_CSNeg_hold : X01 := '0'; VARIABLE TD_WPNeg_CSNeg_hold : VitalTimingDataType; --Pulse Width and Period Check Variables VARIABLE Pviol_SCK_slow : X01 := '0'; VARIABLE PD_SCK_slow : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Pviol_SCK_fast : X01 := '0'; VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Pviol_SCK_quad : X01 := '0'; VARIABLE PD_SCK_quad : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Pviol_CSNeg_read : X01 := '0'; VARIABLE PD_CSNeg_read : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Pviol_CSNeg_pgers : X01 := '0'; VARIABLE PD_CSNeg_pgers : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Pviol_SCK_slow_p : X01 := '0'; VARIABLE PD_SCK_slow_p : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Pviol_SCK_fast_p : X01 := '0'; VARIABLE PD_SCK_fast_p : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Pviol_SCK_quad_p : X01 := '0'; VARIABLE PD_SCK_quad_p : VitalPeriodDataType:= VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF (TimingChecksOn) THEN -- 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_CSNeg_SCK, Violation => Tviol_CSNeg_SCK ); -- Setup/Hold Check between SI and SCK / VitalSetupHoldCheck ( TestSignal => SIIn, TestSignalName => "SI", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, SetupLow => tsetup_SI_SCK_normal_noedge_posedge, HoldHigh => thold_SI_SCK_normal_noedge_posedge, HoldLow => thold_SI_SCK_normal_noedge_posedge, CheckEnabled => SIOut_z /= SIIn AND (NOT dual_read) AND (NOT quad_read), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_SI_SCK, Violation => Tviol_SI_SCK ); VitalSetupHoldCheck ( TestSignal => SOIn, TestSignalName => "SO", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, SetupLow => tsetup_SI_SCK_normal_noedge_posedge, HoldHigh => thold_SI_SCK_normal_noedge_posedge, HoldLow => thold_SI_SCK_normal_noedge_posedge, CheckEnabled => SOut_z /= SOIn AND QE = '1' AND (read_out = '0'), RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_SOIn_SCK, Violation => Tviol_SOIn_SCK ); VitalSetupHoldCheck ( TestSignal => HOLDNegIn, TestSignalName => "HOLD#", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, SetupLow => tsetup_SI_SCK_normal_noedge_posedge, HoldHigh => thold_SI_SCK_normal_noedge_posedge, HoldLow => thold_SI_SCK_normal_noedge_posedge, CheckEnabled => HOLDNegOut_zd /= HOLDNegIn, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_HOLDNegIn_SCK, Violation => Tviol_HOLDNegIn_SCK ); VitalSetupHoldCheck ( TestSignal => WPNegIn, TestSignalName => "WP#", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, SetupLow => tsetup_SI_SCK_normal_noedge_posedge, HoldHigh => thold_SI_SCK_normal_noedge_posedge, HoldLow => thold_SI_SCK_normal_noedge_posedge, CheckEnabled => WPNegOut_zd /= WPNegIn, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNegIn_SCK, Violation => Tviol_WPNegIn_SCK ); -- Setup/Hold Check between HOLD# and SCK / VitalSetupHoldCheck ( TestSignal => HOLDNegIn, TestSignalName => "HOLD#", RefSignal => SCK_ipd, RefSignalName => "SCK", SetupHigh => tsetup_HOLDNeg_SCK, SetupLow => tsetup_HOLDNeg_SCK, HoldHigh => thold_HOLDNeg_SCK, HoldLow => thold_HOLDNeg_SCK, CheckEnabled => QE = '0' AND HOLDNegIn /= 'X', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_HOLDNeg_SCK, Violation => Tviol_HOLDNeg_SCK ); -- Setup Check between WP# and CS# \ VitalSetupHoldCheck ( TestSignal => WPNegIn, TestSignalName => "WP#", RefSignal => CSNeg_ipd, RefSignalName => "CS#", SetupHigh => tsetup_WPNeg_CSNeg, CheckEnabled => QE = '0', RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_CSNeg_setup, Violation => Tviol_WPNeg_CSNeg_setup ); -- Hold Check between WP# and CS# / VitalSetupHoldCheck ( TestSignal => WPNegIn, TestSignalName => "WP#", RefSignal => CSNeg_ipd, RefSignalName => "CS#", HoldHigh => thold_WPNeg_CSNeg, CheckEnabled => QE = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_CSNeg_hold, Violation => Tviol_WPNeg_CSNeg_hold ); --Pulse Width and Period Check Variables VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", PulseWidthLow => tpw_SCK_slow_negedge, PulseWidthHigh => tpw_SCK_slow_posedge, PeriodData => PD_SCK_slow, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_slow, HeaderMsg => InstancePath & PartID, CheckEnabled => slow_read ); VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", PulseWidthLow => tpw_SCK_fast_negedge, PulseWidthHigh => tpw_SCK_fast_posedge, PeriodData => PD_SCK_fast, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_fast, HeaderMsg => InstancePath & PartID, CheckEnabled => fast_rd ); VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", PulseWidthLow => tpw_SCK_quad_negedge, PulseWidthHigh => tpw_SCK_quad_posedge, PeriodData => PD_SCK_quad, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_quad, HeaderMsg => InstancePath & PartID, CheckEnabled => quad_read OR pp_quad ); -- Pulse Width Check CS# for READ, serial mode VitalPeriodPulseCheck ( TestSignal => CSNeg_ipd, TestSignalName => "CS#", PulseWidthHigh => tpw_CSNeg_read_posedge, PeriodData => PD_CSNeg_read, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CSNeg_read, HeaderMsg => InstancePath & PartID, CheckEnabled => slow_read OR fast_rd OR dual_read OR quad_read ); -- Pulse Width Check CS# for Program/Erase, serial mode VitalPeriodPulseCheck ( TestSignal => CSNeg_ipd, TestSignalName => "CS#", PulseWidthHigh => tpw_CSNeg_pger_posedge, PeriodData => PD_CSNeg_pgers, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CSNeg_pgers, HeaderMsg => InstancePath & PartID, CheckEnabled => true); -- Period Check SCK for READ, serial mode VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", Period => tperiod_SCK_slow, PeriodData => PD_SCK_slow_p, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_slow_p, HeaderMsg => InstancePath & PartID, CheckEnabled => slow_read ); VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", Period => tperiod_SCK_fast, PeriodData => PD_SCK_fast_p, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_fast_p, HeaderMsg => InstancePath & PartID, CheckEnabled => fast_rd OR dual_read ); VitalPeriodPulseCheck ( TestSignal => SCK_ipd, TestSignalName => "SCK", Period => tperiod_SCK_quad, PeriodData => PD_SCK_quad_p, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_SCK_quad_p, HeaderMsg => InstancePath & PartID, CheckEnabled => pp_quad OR quad_read ); Violation := Tviol_CSNeg_SCK OR Tviol_SI_SCK OR Tviol_HOLDNeg_SCK OR Tviol_WPNeg_CSNeg_setup OR Tviol_WPNeg_CSNeg_hold OR Tviol_HOLDNegIn_SCK OR Tviol_WPNegIn_SCK OR Tviol_SOIn_SCK OR Pviol_SCK_slow OR Pviol_SCK_fast OR Pviol_CSNeg_read OR Pviol_CSNeg_pgers OR Pviol_SCK_slow_p OR Pviol_SCK_fast_p OR Pviol_SCK_quad_p OR Pviol_SCK_quad; 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 IF next_state'EVENT THEN current_state <= next_state; END IF; END IF; END PROCESS StateTransition; --------------------------------------------------------------------------- -- Write cycle decode --------------------------------------------------------------------------- BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd) TYPE bus_cycle_type IS (STAND_BY, OPCODE_BYTE, ADDRESS_BYTES, DUMMY_BYTES, MODE_BYTE, DATA_BYTES ); TYPE quad_data_type IS ARRAY (0 TO 511) OF INTEGER RANGE 0 TO 15; VARIABLE bus_cycle_state : bus_cycle_type; VARIABLE opcode_cnt : NATURAL := 0; VARIABLE addr_cnt : NATURAL := 0; VARIABLE mode_cnt : NATURAL := 0; VARIABLE wrap_cnt : NATURAL := 0; VARIABLE dummy_cnt : NATURAL := 0; VARIABLE data_cnt : NATURAL := 0; VARIABLE bit_cnt : NATURAL := 0; VARIABLE Data_in : std_logic_vector(2047 downto 0) := (others => '0'); VARIABLE opcode : std_logic_vector(7 downto 0); VARIABLE opcode_in : std_logic_vector(7 downto 0); VARIABLE opcode_double : std_logic_vector(15 downto 0); VARIABLE opcode_double_in : std_logic_vector(15 downto 0); VARIABLE addr_bytes : std_logic_vector(23 downto 0); VARIABLE Address_in : std_logic_vector(23 downto 0); VARIABLE mode_bits : std_logic_vector(7 downto 0); VARIABLE mode_in : std_logic_vector(7 downto 0); -- VARIABLE wrap_byte : std_logic_vector(7 downto 0); VARIABLE wrap_in : std_logic_vector(7 downto 0); VARIABLE quad_data_in : quad_data_type; VARIABLE quad_nybble : std_logic_vector(3 downto 0); VARIABLE Quad_slv : std_logic_vector(3 downto 0); VARIABLE Byte_slv : std_logic_vector(7 downto 0); BEGIN IF falling_edge(CSNeg_ipd) THEN IF (bus_cycle_state = STAND_BY) THEN bus_cycle_state := OPCODE_BYTE; Instruct <= NONE; write <= '1'; opcode_cnt := 0; addr_cnt := 0; data_cnt := 0; mode_cnt := 0; wrap_cnt := 0; dummy_cnt := 0; ELSIF (bus_cycle_state = DATA_BYTES AND mode_bits(5 DOWNTO 4) = "10") THEN bus_cycle_state := ADDRESS_BYTES; dummy_cnt := 0; opcode_cnt := 0; END IF; END IF; IF rising_edge(SCK_ipd) AND (PoweredUp = '1') THEN IF (CSNeg_ipd = '0') THEN CASE (bus_cycle_state) IS WHEN OPCODE_BYTE => IF (HOLDNeg_pullup = '1' AND QE='0') OR QE='1' THEN opcode_in(opcode_cnt) := SIIn; opcode_cnt := opcode_cnt + 1; IF opcode_cnt = BYTE THEN FOR I IN 7 DOWNTO 0 LOOP opcode(i) := opcode_in(7-i); END LOOP; CASE opcode IS WHEN "00000110" => -- 06H Instruct <= WREN; bus_cycle_state := DATA_BYTES; WHEN "01010000" => Instruct <= WRENV; bus_cycle_state := DATA_BYTES; WHEN "00000100" => --04h Instruct <= WRDI; bus_cycle_state := DATA_BYTES; WHEN "00000101" => -- 05h Instruct <= RDSR; bus_cycle_state := DATA_BYTES; WHEN "00110101" => -- 35h Instruct <= RDSR2; bus_cycle_state := DATA_BYTES; WHEN "00000001" => -- 01h Instruct <= WRR; bus_cycle_state := DATA_BYTES; WHEN "00000011" => -- 03h Instruct <= READ; bus_cycle_state := ADDRESS_BYTES; WHEN "00001011" => -- 0Bh Instruct <= FAST_READ; bus_cycle_state := ADDRESS_BYTES; WHEN "00111011" => -- 3Bh Instruct <= FAST_DREAD; bus_cycle_state := ADDRESS_BYTES; WHEN "01101011" => -- 6Bh Instruct <= FAST_QREAD; IF (QE = '1') THEN bus_cycle_state := ADDRESS_BYTES; ELSE bus_cycle_state := STAND_BY; END IF; WHEN "10111011" => -- BBh Instruct <= FAST_DREAD_2; bus_cycle_state := ADDRESS_BYTES; WHEN "11101011" => -- EBh Instruct <= FAST_QREAD_4; IF (QE = '1') THEN bus_cycle_state := ADDRESS_BYTES; ELSE bus_cycle_state := STAND_BY; END IF; WHEN "11100111" => --E7h Instruct <= W_QREAD; IF (QE = '1') THEN bus_cycle_state := ADDRESS_BYTES; ELSE bus_cycle_state := STAND_BY; END IF; WHEN "11100011" => -- E3h Instruct <= WOCT_QREAD; IF (QE = '1') THEN bus_cycle_state := ADDRESS_BYTES; ELSE bus_cycle_state := STAND_BY; END IF; WHEN "01110111" => -- 77h Instruct <= SET_BURST_WRAP; IF (QE = '1') THEN bus_cycle_state := DUMMY_BYTES; ELSE bus_cycle_state := STAND_BY; END IF; WHEN "11111111" => -- FFh Instruct <= CONT_RD_RST; bus_cycle_state := MODE_BYTE; WHEN "00000010" => -- 02H Instruct <= PP; bus_cycle_state := ADDRESS_BYTES; WHEN "00110010" => -- 32h Instruct <= QPP; IF (QE = '1') THEN bus_cycle_state := ADDRESS_BYTES; ELSE bus_cycle_state := STAND_BY; END IF; WHEN "00100000" => -- 20h Instruct <= SE; bus_cycle_state := ADDRESS_BYTES; WHEN "01010010" => -- 52h Instruct <= BE_32; bus_cycle_state := ADDRESS_BYTES; WHEN "11011000" => -- D8h Instruct <= BE_64; bus_cycle_state := ADDRESS_BYTES; WHEN "11000111" | "01100000" => -- C7 or 60h Instruct <= CE; bus_cycle_state := DATA_BYTES; WHEN "01110101" => -- 75h Instruct <= ERS_PG_SUSP; bus_cycle_state := DATA_BYTES; WHEN "01111010" => -- 7Ah Instruct <= ERS_PG_RES; bus_cycle_state := DATA_BYTES; WHEN "10111001" => -- B9h Instruct <= DP; bus_cycle_state := DATA_BYTES; WHEN "10101011" => -- ABh Instruct <= RES_RD_ID; bus_cycle_state := DUMMY_BYTES; WHEN "10010000" => -- 90h Instruct <= RDID; bus_cycle_state := ADDRESS_BYTES; WHEN "10010010" => -- 92h Instruct <= RDID_DUAL; bus_cycle_state := ADDRESS_BYTES; WHEN "10010100" => -- 94h Instruct <= RDID_QUAD; IF (QE = '1') THEN bus_cycle_state := ADDRESS_BYTES; ELSE bus_cycle_state := STAND_BY; END IF; WHEN "01001011" => -- 4Bh Instruct <= RD_UNIQ_ID; bus_cycle_state := DUMMY_BYTES; WHEN "10011111" => -- 9Fh Instruct <= RDIDJ; bus_cycle_state := DATA_BYTES; WHEN "01011010" => -- 5Ah Instruct <= RD_SFDP; bus_cycle_state := ADDRESS_BYTES; WHEN "01000100" => -- 44h Instruct <= ERS_SCREG; bus_cycle_state := ADDRESS_BYTES; WHEN "01000010" => -- 42h Instruct <= PG_SCREG; bus_cycle_state := ADDRESS_BYTES; WHEN "01001000" => -- 48h Instruct <= RD_SCREG; bus_cycle_state := ADDRESS_BYTES; WHEN OTHERS => NULL; END CASE; END IF; ELSE REPORT "Device is in HOLD mode, opcode" SEVERITY NOTE; END IF; WHEN ADDRESS_BYTES => IF (HOLDNeg_pullup = '1' AND QE='0') OR QE='1' THEN IF (Instruct = READ OR Instruct = FAST_READ OR Instruct = FAST_DREAD OR Instruct = RDID OR Instruct = SE OR Instruct = PP OR Instruct = RD_SCREG OR Instruct = PG_SCREG OR Instruct = RD_SFDP OR Instruct = BE_32 OR Instruct = BE_64 OR Instruct = ERS_SCREG OR ((Instruct = QPP OR Instruct = FAST_QREAD) AND QE = '1')) THEN Address_in(addr_cnt) := SIIn; addr_cnt := addr_cnt + 1; IF addr_cnt = 3*BYTE THEN FOR I IN 23 DOWNTO 0 LOOP addr_bytes(23-i) := Address_in(i); END LOOP; Address <= to_nat(addr_bytes); change_addr <= '1','0' AFTER 1 ns; IF (Instruct = PP OR Instruct = QPP OR Instruct = READ OR Instruct = SE OR Instruct = BE_32 OR Instruct = BE_64 OR Instruct = RDID OR Instruct = PG_SCREG OR Instruct = ERS_SCREG) THEN bus_cycle_state := DATA_BYTES; ELSE bus_cycle_state := DUMMY_BYTES; END IF; END IF; ELSIF (Instruct = RDID_DUAL OR Instruct = FAST_DREAD_2) THEN IF (SOIn /= 'Z') THEN Address_in(2*addr_cnt) := SOIn; Address_in(2*addr_cnt + 1):= SIIn; read_cnt := 0; addr_cnt := addr_cnt + 1; IF (addr_cnt = (3*BYTE)/2) THEN addr_cnt := 0; FOR I IN 23 DOWNTO 0 LOOP addr_bytes(23-i) := Address_in(i); END LOOP; Address <= to_nat(addr_bytes); change_addr <= '1','0' AFTER 1 ns; bus_cycle_state := MODE_BYTE; END IF; ELSIF (mode_bits(5 downto 4) = "10") THEN opcode_double_in(opcode_cnt) := SIIn; opcode_cnt := opcode_cnt + 1; IF (opcode_cnt = 2*BYTE) THEN FOR I IN 15 DOWNTO 0 LOOP opcode_double(i) := opcode_double_in(15-i); END LOOP; IF (opcode_double="1111111111111111") THEN Instruct <= CONT_RD_RST; bus_cycle_state := MODE_BYTE; END IF; END IF; END IF; ELSIF (QE = '1' AND (Instruct = FAST_QREAD_4 OR Instruct = W_QREAD OR Instruct = WOCT_QREAD OR Instruct = RDID_QUAD)) THEN IF (SOIn /= 'Z') THEN Address_in(4*addr_cnt) := HOLDNegIn; Address_in(4*addr_cnt+1) := WPNegIn; Address_in(4*addr_cnt+2) := SOIn; Address_in(4*addr_cnt+3) := SIIn; read_cnt := 0; addr_cnt := addr_cnt + 1; IF (addr_cnt = (3*BYTE)/4) THEN addr_cnt := 0; FOR I IN 23 DOWNTO 0 LOOP addr_bytes(23-i) := Address_in(i); END LOOP; Address <= to_nat(addr_bytes); change_addr <= '1','0' AFTER 1 ns; bus_cycle_state := MODE_BYTE; END IF; ELSIF (mode_bits(5 downto 4) = "10") THEN opcode_in(opcode_cnt) := SIIn; opcode_cnt := opcode_cnt + 1; IF (opcode_cnt = BYTE) THEN FOR I IN 7 DOWNTO 0 LOOP opcode(i) := opcode_in(7-i); END LOOP; IF (opcode = "11111111") THEN Instruct <= CONT_RD_RST; bus_cycle_state := MODE_BYTE; END IF; END IF; END IF; END IF; ELSE REPORT "Device is in HOLD mode, addr" SEVERITY NOTE; END IF; WHEN MODE_BYTE => IF (QE = '1' OR (HOLDNeg_pullup = '1' AND QE = '0')) THEN IF (Instruct = SET_BURST_WRAP AND QE = '1') THEN wrap_in(4*wrap_cnt) := HOLDNegIn; wrap_in(4*wrap_cnt+1) := WPNegIn; wrap_in(4*wrap_cnt+2) := SOIn; wrap_in(4*wrap_cnt+3) := SIIn; wrap_cnt := wrap_cnt + 1; IF (wrap_cnt = BYTE/4) THEN wrap_cnt := 0; FOR I IN 7 DOWNTO 0 LOOP wrap_byte(i) := wrap_in(7-i); END LOOP; bus_cycle_state := DATA_BYTES; END IF; CASE (wrap_byte(6 DOWNTO 5)) IS WHEN "00" => w_size := 8; WHEN "01" => w_size := 16; WHEN "10" => w_size := 32; WHEN "11" => w_size := 64; WHEN OTHERS => NULL; END CASE; ELSIF ((Instruct = FAST_QREAD_4 OR Instruct = WOCT_QREAD OR Instruct = W_QREAD OR Instruct = RDID_QUAD ) AND QE = '1') THEN mode_in(4*mode_cnt) := HOLDNegIn; mode_in(4*mode_cnt+1) := WPNegIn; mode_in(4*mode_cnt+2) := SOIn; mode_in(4*mode_cnt+3) := SIIn; mode_cnt := mode_cnt + 1; IF (mode_cnt = BYTE/4) THEN mode_cnt := 0; FOR I IN 7 DOWNTO 0 LOOP mode_bits(i) := mode_in(7-i); END LOOP; IF (Instruct = WOCT_QREAD) THEN bus_cycle_state := DATA_BYTES; ELSE bus_cycle_state := DUMMY_BYTES; END IF; END IF; ELSIF (Instruct = RDID_DUAL OR Instruct = FAST_DREAD_2) THEN mode_in(2*mode_cnt) := SOIn; mode_in(2*mode_cnt+1) := SIIn; mode_cnt := mode_cnt + 1; IF (mode_cnt = BYTE/2) THEN mode_cnt := 0; FOR I IN 7 DOWNTO 0 LOOP mode_bits(i) := mode_in(7-i); END LOOP; bus_cycle_state := DATA_BYTES; END IF; END IF; ELSE REPORT "Device is in HOLD mode, mode" SEVERITY NOTE; END IF; WHEN DUMMY_BYTES => IF (QE = '1' OR (HOLDNeg_pullup = '1' AND QE = '0')) THEN IF ((Instruct = FAST_QREAD_4 OR Instruct = RDID_QUAD) AND QE = '1') THEN dummy_cnt := dummy_cnt + 1; IF (dummy_cnt = BYTE/2) THEN bus_cycle_state := DATA_BYTES; END IF; ELSIF (Instruct = W_QREAD AND QE = '1') THEN dummy_cnt := dummy_cnt + 1; IF (dummy_cnt = BYTE/4) THEN bus_cycle_state := DATA_BYTES; END IF; ELSIF (Instruct = SET_BURST_WRAP AND QE = '1') THEN dummy_cnt := dummy_cnt + 1; IF (dummy_cnt = 3*BYTE/4) THEN bus_cycle_state := MODE_BYTE; END IF; ELSIF (Instruct = FAST_QREAD AND QE = '1') THEN dummy_cnt := dummy_cnt + 1; IF (dummy_cnt = BYTE) THEN bus_cycle_state := DATA_BYTES; END IF; ELSIF (Instruct=FAST_READ OR Instruct=RD_SFDP OR Instruct = FAST_DREAD OR Instruct=RD_SCREG) THEN dummy_cnt := dummy_cnt + 1; IF (dummy_cnt = BYTE) THEN bus_cycle_state := DATA_BYTES; END IF; ELSIF (Instruct = RD_UNIQ_ID) THEN dummy_cnt := dummy_cnt + 1; IF (dummy_cnt = 4*BYTE) THEN bus_cycle_state := DATA_BYTES; END IF; ELSE -- for RES_RD_ID dummy_cnt := dummy_cnt + 1; IF (dummy_cnt = 3*BYTE) THEN bus_cycle_state := DATA_BYTES; END IF; END IF; ELSE REPORT "Device is in HOLD mode, dummy" SEVERITY NOTE; END IF; -- end of DUMMY_BYTES WHEN DATA_BYTES => IF (Instruct = PP OR Instruct = WRR OR Instruct = PG_SCREG) THEN IF ((HOLDNeg_pullup = '1' AND QE='0') OR QE='1') 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) := SIIn; 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) := SIIn; data_cnt := data_cnt + 1; bit_cnt := 0; END IF; ELSE REPORT "Device is in HOLD mode, data" SEVERITY NOTE; END IF; ELSIF (Instruct = QPP AND QE ='1') THEN pp_quad := TRUE; quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; IF (data_cnt > 511) THEN --In case of quad mode and QPP,IF more than -- 256 bytes are sent to the device FOR I IN 0 TO 510 LOOP quad_data_in(i) := quad_data_in(i+1); END LOOP; quad_data_in(511) := to_nat(quad_nybble); data_cnt := data_cnt +1; ELSE IF (quad_nybble /= "ZZZZ") THEN quad_data_in(data_cnt) := to_nat(quad_nybble); END IF; data_cnt := data_cnt +1; END IF; END IF; WHEN OTHERS => NULL; END CASE; END IF; END IF; IF falling_edge(SCK_ipd) AND (bus_cycle_state = DATA_BYTES AND CSNeg_ipd ='0') THEN IF (((Instruct = RDSR OR Instruct = RDSR2 OR Instruct = FAST_READ OR Instruct = FAST_DREAD OR Instruct = FAST_DREAD_2 OR Instruct = RES_RD_ID OR Instruct = RDID OR Instruct = RDID_DUAL OR Instruct = RD_UNIQ_ID OR Instruct = RDIDJ OR Instruct = RD_SFDP OR Instruct = RD_SCREG OR Instruct = READ) AND ((HOLDNeg_pullup ='1' AND QE='0') OR QE='1')) OR ((Instruct = FAST_QREAD OR Instruct = FAST_QREAD_4 OR Instruct = W_QREAD OR Instruct = RDID_QUAD OR Instruct = WOCT_QREAD) AND QE='1')) THEN read_out <= '1', '0' AFTER 1 ns; END IF; END IF; IF rising_edge(CSNeg_ipd) THEN IF (bus_cycle_state=MODE_BYTE AND Instruct = CONT_RD_RST) THEN mode_bits(5 downto 4) := "11"; mode_bits(7 downto 6) := "00"; mode_bits(3 downto 0) := "0000"; bus_cycle_state := STAND_BY; ELSIF (bus_cycle_state=DATA_BYTES AND NOT (mode_bits(5 downto 4)="10")) THEN bus_cycle_state := STAND_BY; CASE (Instruct) IS WHEN WREN | WRDI | SET_BURST_WRAP | SE | BE_32 | BE_64 | CE | ERS_PG_RES | DP | ERS_SCREG => IF (data_cnt = 0) THEN write <= '0'; END IF; WHEN WRENV => write <= '0'; wren_vlt_flag := TRUE; WHEN RES_RD_ID => write <= '0'; res_flag := TRUE; WHEN WRR => IF (data_cnt = 8) THEN --If CS# is driven high after eight --cycle,only the Status Register is --written to. write <= '0'; FOR i IN 0 TO 7 LOOP Status_reg1_in(i) <= Data_in(7-i); END LOOP; ELSIF (data_cnt = 16) THEN --After the 16th cycle both the --Status and Configuration Registers --are written to. write <= '0'; FOR i IN 0 TO 7 LOOP Status_reg1_in(i) <= Data_in(7-i); END LOOP; FOR j IN 0 TO 7 LOOP Status_reg2_in(j) <= Data_in(15-j); END LOOP; END IF; WHEN PP | PG_SCREG => IF (data_cnt > 0) 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; END IF; WHEN QPP => IF (data_cnt >0) THEN IF ((data_cnt mod 2) = 0) THEN write <= '0'; FOR I IN 0 TO 255 LOOP FOR J IN 1 DOWNTO 0 LOOP Quad_slv := to_slv(quad_data_in((i*2) + (1-j)),4); Byte_slv(4*j+3 DOWNTO 4*j) := Quad_slv; END LOOP; WByte(i) <= to_nat(Byte_slv); END LOOP; IF (data_cnt > 256*BYTE/4) THEN Byte_number <= 255; ELSE Byte_number <= ((data_cnt/2) - 1); END IF; END IF; END IF; WHEN others => null; END CASE; ELSIF (bus_cycle_state=DATA_BYTES AND (mode_bits(5 DOWNTO 4)="10")) THEN bus_cycle_state := DATA_BYTES; ELSE bus_cycle_state := STAND_BY; IF (HOLDNeg_pullup ='1' AND (Instruct = RES_RD_ID) AND (dummy_cnt = 0)) THEN write <= '0'; res_flag := FALSE; END IF; END IF; END IF; -- end of rising_edge_CSNeg_ipd END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Page Program --------------------------------------------------------------------------- ProgTime : PROCESS(PSTART, PGSUSP, PGRES) VARIABLE pob : time; VARIABLE elapsed : time; VARIABLE start : time; VARIABLE duration : time; BEGIN IF Instruct = PP OR Instruct = QPP OR Instruct = PG_SCREG THEN IF LongTimming THEN pob := tdevice_PP; ELSE pob := tdevice_PP / 10; END IF; END IF; IF rising_edge(PSTART) AND PDONE = '1' THEN elapsed := 0 ns; PDONE <= '0', '1' AFTER pob; start := NOW; ELSIF PGSUSP'EVENT AND PGSUSP = '1' AND PDONE /= '1' THEN elapsed := NOW - start; duration := pob - elapsed; PDONE <= '0'; ELSIF PGRES'EVENT AND PGRES = '1' AND PDONE /= '1'THEN start := NOW; PDONE <= '0', '1' AFTER duration; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Write Status Register --------------------------------------------------------------------------- WriteTime : PROCESS(WSTART) VARIABLE wob : time; BEGIN IF LongTimming THEN wob := tdevice_WRR; ELSE wob := tdevice_WRR / 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 Write Status Register when Write Enable for -- Volatile Status Register was issued --------------------------------------------------------------------------- WriteTimeVlt : PROCESS(VLTSTART) VARIABLE wvob : time; BEGIN wvob := tdevice_VRR; IF rising_edge(VLTSTART) AND VLTDONE = '1' THEN VLTDONE <= '0' , '1' AFTER wvob; END IF; END PROCESS WriteTimeVlt; --------------------------------------------------------------------------- -- Timing control for the Erase Operation --------------------------------------------------------------------------- ErsTime : PROCESS(ESTART, ESUSP, ERES) VARIABLE seo : time; VARIABLE beo32 : time; VARIABLE beo64 : time; VARIABLE ceo : time; VARIABLE elapsed : time; VARIABLE start : time; VARIABLE duration : time; BEGIN IF LongTimming THEN seo := tdevice_SE; beo32 := tdevice_BE1; beo64 := tdevice_BE2; ceo := tdevice_CE; ELSE seo := tdevice_SE / 100; beo32 := tdevice_BE1 / 100; beo64 := tdevice_BE2 / 100; ceo := tdevice_CE / 100; END IF; IF rising_edge(ESTART) AND EDONE = '1' THEN IF Instruct = CE THEN duration := ceo; ELSIF Instruct = BE_64 THEN duration := beo64; ELSIF Instruct = BE_32 THEN duration := beo32; ELSIF Instruct = BE_64 THEN duration := beo64; ELSE -- sector erase 4KB, instruct SE duration := seo; END IF; elapsed := 0 ns; EDONE <= '0', '1' AFTER duration; start := NOW; ELSIF ESUSP'EVENT AND ESUSP = '1' AND EDONE /= '1' THEN elapsed := NOW - start; duration := duration - elapsed; EDONE <= '0'; ELSIF ERES'EVENT AND ERES = '1' AND EDONE /= '1' THEN start := NOW; EDONE <= '0', '1' AFTER duration; END IF; END PROCESS ErsTime; CheckCEOnPowerUP :PROCESS(CSNeg_ipd) BEGIN IF (PoweredUp = '0' AND falling_edge(CSNeg_ipd)) 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(PoweredUp, write, CSNeg_ipd, WDONE, ERSSUSP_out, RES1_out, ERSRES_out, PRGSUSP_out, EDONE,PRGRES_out, DP_out, PDONE, VLTDONE,RES2_out) BEGIN IF rising_edge(PoweredUp) THEN next_state <= IDLE; ELSE CASE current_state IS WHEN IDLE => IF falling_edge(write) THEN IF (Instruct = WRR AND (SRP1='0' AND (SRP0='0' OR (SRP0='1' AND WPNeg ='1')))) THEN IF (WEL='1' AND NOT (wren_vlt_flag)) THEN next_state <= WRITE_SR; ELSIF (WEL='0' AND wren_vlt_flag) THEN next_state <= WRITE_SR_V; END IF; ELSIF (Instruct = PP AND WEL='1') THEN sect := Address / 16#1000#; sect_tmp_pg := sect; IF (Sec_Prot(sect) = '0') THEN next_state <= PAGE_PG; END IF; ELSIF (Instruct = QPP AND WEL='1' AND QE='1') THEN sect := Address / 16#1000#; sect_tmp_pg := sect; IF (Sec_Prot(sect) = '0') THEN next_state <= PAGE_PG; END IF; ELSIF (Instruct = PG_SCREG AND WEL='1') THEN sect := Address / 16#1000#; IF ((sect < 4 AND sect > 0) AND LB_bits(sect-1)='0') THEN next_state <= PAGE_PG; END IF; ELSIF (Instruct = ERS_SCREG AND WEL='1') THEN sect := Address / 16#1000#; IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN next_state <= SECTOR_ERS; END IF; ELSIF ((Instruct = SE OR Instruct = BE_32 OR Instruct = BE_64) AND WEL='1') THEN sect := Address / 16#1000#; sect_tmp_ers := sect; IF (Sec_Prot(sect) = '0') THEN next_state <= SECTOR_ERS; END IF; ELSIF (Instruct = CE AND WEL='1' AND ((CMP='0' AND BP2='0' AND BP1='0' AND BP0='0') OR (CMP='1' AND BP2='1' AND BP1='1' AND BP0='1'))) THEN next_state <= BULK_ERS; ELSE next_state <= IDLE; END IF; ELSIF rising_edge(DP_out) THEN next_state <= DP_DOWN; END IF; WHEN WRITE_SR => IF rising_edge(WDONE) THEN next_state <= IDLE; END IF; -- end of WRITE_SR WHEN WRITE_SR_V => IF rising_edge(VLTDONE) THEN next_state <= IDLE; END IF; WHEN PAGE_PG => IF (PRGSUSP_out'event AND PRGSUSP_out = '1') THEN next_state <= PG_SUSP; ELSIF rising_edge(PDONE) THEN next_state <= IDLE; END IF; -- end of PAGE_PG WHEN PG_SUSP => IF (PRGRES_out'event AND PRGRES_out = '1') THEN next_state <= PAGE_PG; ELSIF falling_edge(write) THEN IF (Instruct = SE OR Instruct = BE_32 OR Instruct = BE_64) THEN sect := Address / 16#1000#; IF ((Sec_Prot(sect) = '0') AND (sect /= sect_tmp_pg)) THEN next_state <= PG_SUSP_ERS; END IF; END IF; END IF; -- end of PG_SUSP WHEN PG_SUSP_ERS => IF rising_edge(EDONE) THEN next_state <= PG_SUSP; ELSE next_state <= PG_SUSP_ERS; END IF; WHEN BULK_ERS => IF rising_edge(EDONE) THEN next_state <= IDLE; END IF; WHEN SECTOR_ERS => IF (ERSSUSP_out'event AND ERSSUSP_out = '1') THEN next_state <= ERS_SUSP; ELSIF rising_edge(EDONE) THEN next_state <= IDLE; END IF; WHEN ERS_SUSP => IF (ERSRES_out'event AND ERSRES_out = '1') THEN next_state <= SECTOR_ERS; ELSIF falling_edge(write) THEN IF (Instruct = PP OR (Instruct = QPP AND QE='1')) THEN sect := Address / 16#1000#; IF ((Sec_Prot(sect) = '0') AND (sect /= sect_tmp_ers)) THEN next_state <= ERS_SUSP_PG; END IF; ELSIF (Instruct = PG_SCREG) THEN sect := Address / 16#1000#; IF ((sect < 4 AND sect > 0) AND LB_bits(sect-1)='0') THEN next_state <= ERS_SUSP_PG; END IF; END IF; END IF; WHEN ERS_SUSP_PG => IF rising_edge(PDONE) THEN next_state <= ERS_SUSP; ELSE next_state <= ERS_SUSP_PG; END IF; WHEN DP_DOWN => IF rising_edge(RES1_out) OR rising_edge(RES2_out) THEN next_state <= IDLE; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- --FSM Output generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS(read_out, Instruct, SCK_ipd, change_addr, write, Address, PDONE, WDONE, EDONE, ERSSUSP_out, PoweredUp, CSNeg_ipd, RES1_out, ERSRES_out, PRGSUSP_out,PRGRES_out, VLTDONE, current_state, DP_out, RES2_out,SUSP_FL_OUT) VARIABLE WData : WByteType:= (OTHERS => MaxData); VARIABLE oe : boolean := FALSE; VARIABLE AddrLo : NATURAL; VARIABLE AddrHi : NATURAL; VARIABLE AddrLo_ers : NATURAL; VARIABLE AddrHi_ers : NATURAL; VARIABLE AddrLo_wrap : NATURAL; VARIABLE AddrHi_wrap : NATURAL; VARIABLE Addr : NATURAL; VARIABLE Addr_w : NATURAL; VARIABLE Addr_ers : NATURAL; VARIABLE Addr_tmp : NATURAL; VARIABLE Addr_tmp_2 : NATURAL; VARIABLE Addr_tmp_3 : NATURAL; VARIABLE Addr_screg : NATURAL; VARIABLE Addr_screg_tmp : NATURAL; VARIABLE data_out : std_logic_vector(7 downto 0); VARIABLE ident_out : std_logic_vector(23 downto 0); VARIABLE ident_out2 : std_logic_vector(15 downto 0); VARIABLE uniq_id : std_logic_vector(63 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 cnt : NATURAL RANGE 0 TO 256 := 0; BEGIN oe := rising_edge(read_out) AND PoweredUp = '1'; IF Instruct'EVENT THEN read_cnt := 0; fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; read_id <= false; pp_quad := FALSE; IF (current_state = IDLE AND DP_in = '1') THEN REPORT "Command results can be corrupted " SEVERITY WARNING; END IF; END IF; IF rising_edge(PoweredUp) THEN WEL := '0'; BUSY := '0'; SUS := '0'; change_prot_bits <= '1', '0' AFTER 1 ns; END IF; IF change_addr'EVENT THEN read_addr := Address; END IF; IF RES1_out'EVENT AND RES1_out = '1' THEN RES1_in <= '0'; END IF; IF RES2_out'EVENT AND RES2_out = '1' THEN RES2_in <= '0'; END IF; IF SUSP_FL_OUT'EVENT AND SUSP_FL_OUT = '1' THEN SUSP_FL_IN <= '0'; END IF; CASE current_state IS WHEN IDLE => fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; read_id <= false; sr_read <= false; res_flag := FALSE; pg_screg_flag <= false; ers_screg_flag <= false; IF falling_edge(write) AND DP_in ='0' THEN read_cnt := 0; IF (Instruct = WREN) THEN WEL := '1'; ELSIF (Instruct = WRDI) THEN WEL := '0'; ELSIF (Instruct = WRR) THEN IF(SRP1='0' AND (SRP0='0' OR (SRP0='1' AND WPNeg='1'))) THEN IF WEL='1' AND NOT (wren_vlt_flag) THEN WSTART <= '1', '0' AFTER 5 ns; BUSY := '1'; ELSIF (WEL='0' AND wren_vlt_flag) THEN VLTSTART <= '1', '0' AFTER 5 ns; END IF; ELSE WEL := '0'; END IF; ELSIF ((Instruct = PP OR (Instruct = QPP AND QE='1')) AND WEL='1' AND PDONE='1') THEN sect := Address / 16#1000#; IF (Sec_Prot(sect) = '0') THEN PSTART <= '1', '0' AFTER 5 ns; PGSUSP <= '0'; PGRES <= '0'; BUSY := '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 WEL := '0'; END IF; ELSIF (Instruct = PG_SCREG AND WEL='1') THEN sect := Address / 16#1000#; IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN PSTART <= '1', '0' AFTER 5 ns; PGSUSP <= '0'; PGRES <= '0'; BUSY := '1'; SA <= sect; wr_cnt := Byte_number; Addr_screg := Address mod 16#1000#; Addr_screg_tmp := Address mod 16#1000#; pg_screg_flag <= true; 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 WEL := '0'; END IF; ELSIF ((Instruct = SE OR Instruct = BE_32 OR Instruct = BE_64) AND WEL='1') THEN sect := Address / 16#1000#; IF (Sec_Prot(sect) = '0') THEN ESTART <= '1', '0' AFTER 5 ns; ESUSP <= '0'; ERES <= '0'; BUSY := '1'; Addr_ers := Address; ELSE WEL := '0'; END IF; ELSIF (Instruct = CE AND WEL='1') THEN IF ((CMP='0' AND BP2='0' AND BP1='0' AND BP0='0') OR (CMP='1' AND BP2='1' AND BP1='1' AND BP0='1')) THEN ESTART <= '1', '0' AFTER 5 ns; ESUSP <= '0'; ERES <= '0'; BUSY := '1'; ELSE WEL := '0'; END IF; ELSIF (Instruct = ERS_SCREG AND WEL='1') THEN sect := Address / 16#1000#; IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN ESTART <= '1', '0' AFTER 5 ns; ESUSP <= '0'; ERES <= '0'; BUSY := '1'; SA <= sect; ers_screg_flag <= true; ELSE WEL := '0'; END IF; ELSIF (Instruct = DP) THEN RES2_in <= '0'; RES1_in <= '0'; DP_in <= '1'; END IF; -- end of falling_edge_write ELSIF (oe AND DP_in='0') THEN IF (Instruct = RDSR) THEN --Read Status Register sr_read <= true; SOut_zd <= Status_reg1(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDSR2) THEN sr_read <= true; SOut_zd <= Status_reg2(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN IF (Instruct = READ) THEN fast_rd <= false; dual_read <= false; slow_read <= true; quad_read <= false; sr_read <= false; ELSE fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; END IF; IF (Mem(read_addr) /= -1) THEN data_out := to_slv(Mem(read_addr),8); SOut_zd <= data_out(7-read_cnt); ELSE SOut_zd <= 'U'; END IF; 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; ELSIF (Instruct=FAST_DREAD OR Instruct=FAST_DREAD_2) THEN fast_rd <= false; dual_read <= true; slow_read <= false; quad_read <= false; sr_read <= false; data_out := to_slv(Mem(read_addr),8); SOut_zd <= data_out(7-2*read_cnt); SIOut_zd <= data_out(6-2*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN read_cnt := 0; IF (read_addr = AddrRANGE) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSIF ((Instruct=FAST_QREAD OR Instruct=FAST_QREAD_4 OR Instruct=W_QREAD OR Instruct=WOCT_QREAD) AND QE='1') THEN IF ((Instruct=W_QREAD AND (Address mod 2 /= 0) ) OR (Instruct=WOCT_QREAD AND (Address mod 16 /= 0))) THEN read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN read_cnt := 0; REPORT "Word Read can't execute Wrong Address" SEVERITY NOTE; END IF; ELSE fast_rd <= false; dual_read <= false; slow_read <= false; quad_read <= true; sr_read <= false; Addr_w := Address; data_out := to_slv(Mem(read_addr),8); HOLDNegOut_zd <= data_out(7-4*read_cnt); WPNegOut_zd <= data_out(6-4*read_cnt); SOut_zd <= data_out(5-4*read_cnt); SIOut_zd <= data_out(4-4*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN read_cnt := 0; IF (wrap_byte(4)='0' AND (Instruct=FAST_QREAD_4 OR Instruct=W_QREAD)) THEN ADDRHILO_WRAP(AddrLo_wrap,AddrHi_wrap, Addr_w,w_size); IF (read_addr = AddrHi_wrap) THEN read_addr := AddrLo_wrap; ELSE read_addr := read_addr + 1; END IF; ELSE IF (read_addr = AddrRANGE) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; END IF; END IF; ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR Instruct=RDID_QUAD) THEN IF (read_addr mod 2 = 0) THEN ident_out2 := to_slv(Manuf_ID,8) & to_slv(Device_ID1,8); ELSE ident_out2 := to_slv(Device_ID1,8) & to_slv(Manuf_ID,8); END IF; read_id <= true; IF (Instruct = RDID) THEN fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; SOut_zd <= ident_out2(15-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 16) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDID_DUAL) THEN fast_rd <= false; dual_read <= true; slow_read <= false; quad_read <= false; sr_read <= false; SOut_zd <= ident_out2(15-2*read_cnt); SIOut_zd <= ident_out2(14-2*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSE -- (Instruct = RDID_QUAD) fast_rd <= false; dual_read <= false; slow_read <= false; quad_read <= true; sr_read <= false; HOLDNegOut_zd <= ident_out2(15-4*read_cnt); WPNegOut_zd <= ident_out2(14-4*read_cnt); SOut_zd <= ident_out2(13-4*read_cnt); SIOut_zd <= ident_out2(12-4*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN read_cnt := 0; END IF; END IF; ELSIF (Instruct = RD_UNIQ_ID) THEN -- unique ID number is not in data sheet read_id <= true; uniq_id := to_slv(Unique_id_2,32)& to_slv(Unique_id_1,32); SOut_zd <= uniq_id(63-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 64) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDIDJ) THEN read_id <= true; ident_out := to_slv(Manuf_ID,8) & to_slv(Device_ID2,8) & to_slv(Device_ID3,8); SOut_zd <= ident_out(23-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 24) THEN read_cnt := 0; END IF; ELSIF (Instruct = RD_SFDP) THEN IF (read_addr / 16#100# = 0) THEN Addr_tmp_2 := (read_addr mod 16#100#); data_out := to_slv(SFDP_array(Addr_tmp_2),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; IF (read_addr = SFDP_HiAddr) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; REPORT "Given SFDP address is out of range" SEVERITY NOTE; END IF; END IF; ELSIF (Instruct = RD_SCREG) THEN Addr_tmp_2 := read_addr / 16#100#; Addr_tmp_3 := read_addr mod 16#100#; IF (Addr_tmp_2 = 16) THEN -- Security Register No.1 data_out := to_slv(Security_Reg1(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSIF (Addr_tmp_2 = 32) THEN -- Security Register No.2 data_out := to_slv(Security_Reg2(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSIF (Addr_tmp_2 = 48) THEN -- Security Register No.2 data_out := to_slv(Security_Reg3(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; REPORT "Security Reg address is out of range " SEVERITY NOTE; END IF; END IF; IF (read_cnt = 8) THEN read_cnt := 0; IF (read_addr mod 256 = SecReg_HiAddr) THEN read_addr := (read_addr/256)*(SecReg_HiAddr+1); ELSE read_addr := read_addr + 1; END IF; END IF; ELSIF Instruct = RES_RD_ID THEN read_id <= true; data_out := to_slv(Device_ID1,8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; END IF; -- end of oe ELSIF rising_edge(DP_out) THEN DP_in <= '0'; END IF; -- end of IDLE state WHEN WRITE_SR => IF (WDONE ='1') THEN BUSY := '0'; WEL := '0'; SRP0 := Status_reg1_in(7); SEC := Status_reg1_in(6); TB := Status_reg1_in(5); BP2 := Status_reg1_in(4); BP1 := Status_reg1_in(3); BP0 := Status_reg1_in(2); BP_bits := BP2 & BP1 & BP0; CMP := Status_reg2_in(6); QE := Status_reg2_in(1); -- SRP1 bit will only change value from '0' to '1' -- if SRP1 is '1' than Status Register is protected --and is not possible to write it SRP1 := Status_reg2_in(0); IF LB3 = '0' THEN LB3 := Status_reg2_in(5); ELSE REPORT "LB bit is set to '1', no change allowed" SEVERITY NOTE; END IF; IF LB2 = '0' THEN LB2 := Status_reg2_in(4); ELSE REPORT "LB bit is set to '1', no change allowed" SEVERITY NOTE; END IF; IF LB1 = '0' THEN LB1 := Status_reg2_in(3); ELSE REPORT "LB bit is set to '1', no change allowed" SEVERITY NOTE; END IF; LB_bits := LB3 & LB2 & LB1; change_prot_bits <= '1' , '0' AFTER 2 ns; END IF; -- end of WDONE IF (oe AND Instruct = RDSR) THEN --Read Status Register 1 sr_read <= true; SOut_zd <= Status_reg1(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; END IF; -- end of WRITE_SR WHEN WRITE_SR_V => IF (VLTDONE = '1') THEN SRP0 := Status_reg1_in(7); SEC := Status_reg1_in(6); TB := Status_reg1_in(5); BP2 := Status_reg1_in(4); BP1 := Status_reg1_in(3); BP0 := Status_reg1_in(2); BP_bits := BP2 & BP1 & BP0; CMP := Status_reg2_in(6); QE := Status_reg2_in(1); -- SRP1 bit will only change value from '0' to '1' -- if SRP1 is '1' than Status Register is protected --and is not possible to write it SRP1 := Status_reg2_in(0); IF LB3 = '0' THEN LB3 := Status_reg2_in(5); ELSIF LB2 = '0' THEN LB2 := Status_reg2_in(4); ELSIF LB1 = '0' THEN LB1 := Status_reg2_in(3); ELSE REPORT "LB bit is set to '1', no change allowed" SEVERITY NOTE; END IF; change_prot_bits <= '1' , '0' AFTER 2 ns; wren_vlt_flag := FALSE; END IF; WHEN PAGE_PG | ERS_SUSP_PG => IF current_state'event AND PDONE = '0' THEN IF (Instruct /= PG_SCREG) THEN ADDRHILO_PG(AddrLo, AddrHi, Addr); END IF; cnt := 0; FOR i IN 0 TO wr_cnt LOOP new_int := WData(i); IF (Instruct = PG_SCREG) THEN IF (sect = 1) THEN old_int := Security_Reg1(Addr_screg + i - cnt); ELSIF (sect = 2) THEN old_int := Security_Reg2(Addr_screg + i - cnt); ELSE old_int := Security_Reg3(Addr_screg + i - cnt); END IF; ELSE old_int := Mem(Addr + i - cnt); END IF; 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; IF (Instruct = PG_SCREG) THEN IF (sect = 1) THEN Security_Reg1(Addr_screg + i - cnt) := - 1; ELSIF (sect = 2) THEN Security_Reg2(Addr_screg + i - cnt) := - 1; ELSE Security_Reg3(Addr_screg + i - cnt) := - 1; END IF; ELSE Mem(Addr + i - cnt) := - 1; END IF; IF (Instruct /= PG_SCREG) THEN IF ((Addr + i) = AddrHi) THEN Addr := AddrLo; cnt := i + 1; END IF; ELSE IF Addr_screg + i = SecReg_HiAddr THEN Addr_screg := SecReg_LoAddr; cnt := i + 1; END IF; END IF; END LOOP; cnt := 0; END IF; IF (PDONE = '1') THEN IF (current_state /= ERS_SUSP_PG) THEN BUSY := '0'; END IF; WEL := '0'; FOR I IN 0 TO wr_cnt LOOP IF pg_screg_flag THEN IF (sect = 1) THEN Security_Reg1(Addr_screg_tmp + i - cnt) :=WData(i); ELSIF (sect = 2) THEN Security_Reg2(Addr_screg_tmp + i - cnt) :=WData(i); ELSE Security_Reg3(Addr_screg_tmp + i - cnt) :=WData(i); END IF; IF ((Addr_screg_tmp + i) = SecReg_HiAddr) THEN Addr_screg_tmp := SecReg_LoAddr; cnt := i + 1; END IF; ELSE Mem(Addr_tmp + i - cnt) := WData(i); IF ((Addr_tmp + i) = AddrHi) THEN Addr_tmp := AddrLo; cnt := i + 1; END IF; END IF; END LOOP; END IF; -- end of PDONE IF (Instruct = ERS_PG_SUSP AND current_state = PAGE_PG AND SUSP_FL_IN = '0') THEN PGSUSP <= '1', '0' AFTER 1 ns; PRGSUSP_in <= '1'; END IF; IF (oe AND Instruct = RDSR) THEN --Read Status Register 1 sr_read <= true; SOut_zd <= Status_reg1(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; END IF; WHEN PG_SUSP => fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; BUSY := '0'; IF (PRGSUSP_out = '1' AND (Instruct /= ERS_PG_RES)) THEN PRGSUSP_in <= '0'; --The BUSY bit in the Status Register will indicate that --the device is ready for another operation. -- BUSY := '0'; --The SuspEND (SUS) bit in the Status Register2 will --be set to the logical “1” state to indicate that the --program operation has been suspENDed. SUS := '1'; END IF; IF (PRGRES_out'event AND PRGRES_out = '1') THEN PRGRES_in <= '0'; BUSY := '1'; END IF; IF (SUS = '1') THEN IF falling_edge(write) THEN IF (Instruct = ERS_PG_RES) THEN SUS := '0'; PRGRES_in <= '1'; SUSP_FL_IN <= '1'; PGRES <= '1', '0' AFTER 5 ns; ELSIF ((Instruct = SE OR Instruct = BE_32 OR Instruct = BE_64) AND WEL='1') THEN sect := Address / 16#1000#; IF (sect /= sect_tmp_pg AND Sec_Prot(sect) = '0') THEN ESTART <= '1', '0' AFTER 5 ns; ESUSP <= '0'; ERES <= '0'; BUSY := '1'; Addr_ers := Address; ELSE BUSY := '0'; REPORT "Can't erase sector,protected or susp." SEVERITY NOTE; END IF; END IF; ELSIF (oe) THEN IF (Instruct = RDSR) THEN --Read Status Register 1 sr_read <= true; SOut_zd <= Status_reg1(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDSR2) THEN --Read Status Register 2 sr_read <= true; SOut_zd <= Status_reg2(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN IF (sect_tmp_pg /= read_addr / 16#1000#) THEN IF (Instruct = READ) THEN fast_rd <= false; dual_read <= false; slow_read <= true; quad_read <= false; sr_read <= false; ELSE fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; END IF; IF (Mem(read_addr) /= -1) THEN data_out := to_slv(Mem(read_addr),8); SOut_zd <= data_out(7-read_cnt); ELSE SOut_zd <= 'U'; END IF; 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 read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN REPORT "Can't read suspended sector" SEVERITY NOTE; read_cnt := 0; END IF; END IF; ELSIF (Instruct=FAST_DREAD OR Instruct=FAST_DREAD_2) THEN IF sect_tmp_pg /= (read_addr / 16#1000#) THEN fast_rd <= false; dual_read <= true; slow_read <= false; quad_read <= false; sr_read <= false; IF (Mem(read_addr) /= -1) THEN data_out := to_slv(Mem(read_addr),8); SOut_zd <= data_out(7-2*read_cnt); SIOut_zd <= data_out(6-2*read_cnt); ELSE SOut_zd <= 'U'; SIOut_zd <= 'U'; END if; read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN read_cnt := 0; IF (read_addr = AddrRANGE) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN REPORT "Can't read suspended sector" SEVERITY NOTE; read_cnt := 0; END IF; END IF; ELSIF ((Instruct=FAST_QREAD OR Instruct=W_QREAD OR Instruct=FAST_QREAD_4 OR Instruct=WOCT_QREAD) AND QE = '1') THEN IF sect_tmp_pg /= (read_addr / 16#1000#) THEN IF ((Instruct=W_QREAD AND Address mod 2 /= 0) OR (Instruct=WOCT_QREAD AND Address mod 16 /= 0)) THEN read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN read_cnt := 0; REPORT "Word Read - Wrong Read Address" SEVERITY NOTE; END IF; ELSE fast_rd <= false; dual_read <= false; slow_read <= false; quad_read <= true; sr_read <= false; Addr_w := Address; data_out := to_slv(Mem(read_addr),8); HOLDNegOut_zd <= data_out(7-4*read_cnt); WPNegOut_zd <= data_out(6-4*read_cnt); SOut_zd <= data_out(5-4*read_cnt); SIOut_zd <= data_out(4-4*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN read_cnt := 0; IF (wrap_byte(4)= '0' AND (Instruct=FAST_QREAD_4 OR Instruct=W_QREAD)) THEN ADDRHILO_WRAP(AddrLo_wrap, AddrHi_wrap, Addr_w,w_size); IF (read_addr = AddrHi_wrap) THEN read_addr := AddrLo_wrap; ELSE read_addr := read_addr + 1; END IF; ELSE IF (read_addr = AddrRANGE) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; END IF; END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN REPORT "Can't read suspended sector" SEVERITY NOTE; read_cnt := 0; END IF; END IF; ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR Instruct=RDID_QUAD) THEN IF (read_addr mod 2 = 0) THEN ident_out2 := to_slv(Manuf_ID,8) & to_slv(Device_ID1,8); ELSE ident_out2 := to_slv(Device_ID1,8)& to_slv(Manuf_ID,8); END IF; read_id <= true; IF (Instruct = RDID) THEN fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; SOut_zd <= ident_out2(15-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 16) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDID_DUAL) THEN fast_rd <= false; dual_read <= true; slow_read <= false; quad_read <= false; sr_read <= false; SOut_zd <= ident_out2(15-2*read_cnt); SIOut_zd <= ident_out2(14-2*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSE -- (Instruct = RDID_QUAD) fast_rd <= false; dual_read <= false; slow_read <= false; quad_read <= true; sr_read <= false; HOLDNegOut_zd <= ident_out2(15-4*read_cnt); WPNegOut_zd <= ident_out2(14-4*read_cnt); SOut_zd <= ident_out2(13-4*read_cnt); SIOut_zd <= ident_out2(12-4*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN read_cnt := 0; END IF; END IF; ELSIF (Instruct = RD_UNIQ_ID) THEN -- unique ID number is not in data sheet read_id <= true; uniq_id := to_slv(Unique_id_2,32)& to_slv(Unique_id_1,32); SOut_zd <= uniq_id(63-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 64) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDIDJ) THEN read_id <= true; ident_out := to_slv(Manuf_ID,8) & to_slv(Device_ID2,8) & to_slv(Device_ID3,8); SOut_zd <= ident_out(23-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 24) THEN read_cnt := 0; END IF; ELSIF (Instruct = RD_SFDP) THEN IF (read_addr / 16#100# = 0) THEN Addr_tmp_2 := (read_addr mod 16#100#); data_out := to_slv(SFDP_array(Addr_tmp_2),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; IF (read_addr = SFDP_HiAddr) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; REPORT "SFDP address is out of range" SEVERITY NOTE; END IF; END IF; ELSIF (Instruct = RD_SCREG) THEN Addr_tmp_2 := read_addr / 16#100#; Addr_tmp_3 := read_addr mod 16#100#; IF (Addr_tmp_2 = 16) THEN -- Security Register No.1 data_out := to_slv(Security_Reg1(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSIF (Addr_tmp_2 = 32) THEN -- Security Register No.2 data_out := to_slv(Security_Reg2(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSIF (Addr_tmp_2 = 48) THEN -- Security Register No.2 data_out := to_slv(Security_Reg3(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; REPORT "Security Reg addr is out of range " SEVERITY NOTE; END if; END IF; IF (read_cnt = 8) THEN read_cnt := 0; IF (read_addr mod 256) = SecReg_HiAddr THEN read_addr:=(read_addr/256)* (SecReg_HiAddr+1); ELSE read_addr := read_addr + 1; END IF; END IF; END IF; END IF; END IF; WHEN SECTOR_ERS | PG_SUSP_ERS => IF (current_state'event AND EDONE = '0') THEN IF (Instruct = SE) THEN ADDRHILO_SEC4(AddrLo_ers, AddrHi_ers, Addr_ers); ELSIF (Instruct = BE_32) THEN ADDRHILO_SEC32(AddrLo_ers, AddrHi_ers, Addr_ers); ELSIF (Instruct = BE_64) THEN ADDRHILO_SEC64(AddrLo_ers, AddrHi_ers, Addr_ers); END IF; IF (Instruct /= ERS_SCREG) THEN FOR I IN AddrLo_ers TO AddrHi_ers LOOP Mem(i) := -1; END LOOP; ELSE IF (sect = 1) THEN FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP Security_Reg1(i) := -1; END LOOP; ELSIF (sect = 2) THEN FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP Security_Reg2(i) := -1; END LOOP; ELSE FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP Security_Reg3(i) := -1; END LOOP; END IF; END IF; END IF; IF (EDONE = '1') THEN IF (current_state /= PG_SUSP_ERS) THEN BUSY := '0'; END IF; WEL := '0'; IF (ers_screg_flag) THEN IF (sect = 1) THEN FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP Security_Reg1(i) := MaxData; END LOOP; ELSIF (sect = 2) THEN FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP Security_Reg2(i) := MaxData; END LOOP; ELSE FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP Security_Reg3(i) := MaxData; END LOOP; END IF; ELSE FOR I IN AddrLo_ers TO AddrHi_ers LOOP Mem(i) := MaxData; END LOOP; END IF; END IF; IF (Instruct = ERS_PG_SUSP AND current_state = SECTOR_ERS AND SUSP_FL_IN = '0') THEN ESUSP <= '1', '0' AFTER 1 ns; ERSSUSP_in <= '1'; END IF; IF (oe AND Instruct = RDSR) THEN --Read Status Register 1 sr_read <= true; SOut_zd <= Status_reg1(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; END IF; WHEN BULK_ERS => IF (current_state'event AND EDONE = '0') THEN FOR I IN 0 TO AddrRANGE LOOP Mem(i) := -1; END LOOP; END IF; IF (EDONE = '1') THEN BUSY := '0'; WEL := '0'; FOR I IN 0 TO AddrRANGE LOOP Mem(i) := MaxData; END LOOP; END IF; IF (oe AND Instruct = RDSR) THEN --Read Status Register 1 sr_read <= true; SOut_zd <= Status_reg1(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; END IF; WHEN ERS_SUSP => fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; pg_screg_flag <= false; BUSY := '0'; IF (ERSSUSP_out = '1' AND (Instruct /= ERS_PG_RES)) THEN ERSSUSP_in <= '0'; --The BUSY bit in the Status Register will indicate that --the device is ready for another operation. -- BUSY := '0'; --The SuspEND (SUS) bit in the Status Register2 will --be set to the logical “1” state to indicate that the --program operation has been suspENDed. SUS := '1'; END IF; IF (ERSRES_out'event AND ERSRES_out = '1') THEN ERSRES_in <= '0'; BUSY := '1'; END IF; IF (SUS = '1') THEN IF falling_edge(write) THEN IF (Instruct = ERS_PG_RES) THEN SUS := '0'; ERSRES_in <= '1'; SUSP_FL_IN <= '1'; ERES <= '1', '0' AFTER 5 ns; ELSIF ((Instruct = PP OR (Instruct=QPP AND QE='1')) AND WEL ='1') THEN sect := Address / 16#1000#; IF (sect /= sect_tmp_ers AND Sec_Prot(sect)='0') THEN PSTART <= '1', '0' AFTER 5 ns; PGSUSP <= '0'; PGRES <= '0'; BUSY := '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 BUSY := '0'; REPORT "Can't program sector,protected or susp" SEVERITY NOTE; END IF; ELSIF (Instruct = PG_SCREG) THEN sect := Address / 16#1000#; IF ((sect <= 3 AND sect >=1) AND LB_bits(sect-1)='0') THEN PSTART <= '1', '0' AFTER 5 ns; PGSUSP <= '0'; PGRES <= '0'; BUSY := '1'; SA <= sect; wr_cnt := Byte_number; Addr_screg := Address mod 16#1000#; Addr_screg_tmp := Address mod 16#1000#; pg_screg_flag <= true; 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 WEL := '0'; END IF; END IF; ELSIF (oe) THEN IF (Instruct = RDSR) THEN --Read Status Register 1 sr_read <= true; SOut_zd <= Status_reg1(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDSR2) THEN --Read Status Register 2 sr_read <= true; SOut_zd <= Status_reg2(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN IF sect /= (read_addr / 16#1000#) THEN IF (Instruct = READ) THEN fast_rd <= false; dual_read <= false; slow_read <= true; quad_read <= false; sr_read <= true; ELSE fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; END IF; IF (Mem(read_addr) /= -1) THEN data_out := to_slv(Mem(read_addr),8); SOut_zd <= data_out(7-read_cnt); ELSE SOut_zd <= 'U'; END IF; 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 read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN REPORT "Can't read suspended sector" SEVERITY NOTE; read_cnt := 0; END IF; END IF; ELSIF (Instruct = FAST_DREAD OR Instruct = FAST_DREAD_2) THEN IF sect_tmp_ers /= (read_addr / 16#1000#) THEN fast_rd <= false; dual_read <= true; slow_read <= false; quad_read <= false; sr_read <= false; IF (Mem(read_addr) /= -1) THEN data_out := to_slv(Mem(read_addr),8); SOut_zd <= data_out(7-2*read_cnt); SIOut_zd <= data_out(6-2*read_cnt); ELSE SOut_zd <= 'U'; SIOut_zd <= 'U'; END IF; read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN read_cnt := 0; IF (read_addr = AddrRANGE) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN REPORT "Can't read suspended sector" SEVERITY NOTE; read_cnt := 0; END IF; END IF; ELSIF ((Instruct=FAST_QREAD OR Instruct=W_QREAD OR Instruct=FAST_QREAD_4 OR Instruct=WOCT_QREAD) AND QE = '1') THEN IF sect_tmp_ers /= (read_addr / 16#1000#) THEN IF ((Instruct=W_QREAD AND Address mod 2 /= 0) OR (Instruct=WOCT_QREAD AND Address mod 16 /=0)) THEN read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN read_cnt := 0; REPORT "Bad Word Read- Wrong Address" SEVERITY NOTE; END IF; ELSE fast_rd <= false; dual_read <= false; slow_read <= false; quad_read <= true; sr_read <= false; data_out := to_slv(Mem(read_addr),8); Addr_w := Address; HOLDNegOut_zd <= data_out(7-4*read_cnt); WPNegOut_zd <= data_out(6-4*read_cnt); SOut_zd <= data_out(5-4*read_cnt); SIOut_zd <= data_out(4-4*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN read_cnt := 0; IF (wrap_byte(4)='0' AND (Instruct=FAST_QREAD_4 OR Instruct=W_QREAD)) THEN ADDRHILO_WRAP(AddrLo_wrap, AddrHi_wrap,Addr_w,w_size); IF (read_addr = AddrHi_wrap) THEN read_addr := AddrLo_wrap; ELSE read_addr := read_addr + 1; END IF; ELSE IF (read_addr = AddrRANGE) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; END IF; END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 2) THEN REPORT "Can't read suspended sector" SEVERITY NOTE; read_cnt := 0; END IF; END IF; ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR Instruct=RDID_QUAD) THEN IF (read_addr mod 2 = 0) THEN ident_out2 := to_slv(Manuf_ID,8) & to_slv(Device_ID1,8); ELSE ident_out2 := to_slv(Device_ID1,8) & to_slv(Manuf_ID,8); END IF; read_id <= true; IF (Instruct = RDID) THEN fast_rd <= true; dual_read <= false; slow_read <= false; quad_read <= false; sr_read <= false; SOut_zd <= ident_out2(15-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 16) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDID_DUAL) THEN fast_rd <= false; dual_read <= true; slow_read <= false; quad_read <= false; sr_read <= false; SOut_zd <= ident_out2(15-2*read_cnt); SIOut_zd <= ident_out2(14-2*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; ELSE -- (Instruct = RDID_QUAD) fast_rd <= false; dual_read <= false; slow_read <= false; quad_read <= true; sr_read <= false; HOLDNegOut_zd <= ident_out2(15-4*read_cnt); WPNegOut_zd <= ident_out2(14-4*read_cnt); SOut_zd <= ident_out2(13-4*read_cnt); SIOut_zd <= ident_out2(12-4*read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 4) THEN read_cnt := 0; END IF; END IF; ELSIF (Instruct = RD_UNIQ_ID) THEN -- unique ID number is not in data sheet read_id <= true; uniq_id := to_slv(Unique_id_2,32)& to_slv(Unique_id_1,32); SOut_zd <= uniq_id(63-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 64) THEN read_cnt := 0; END IF; ELSIF (Instruct = RDIDJ) THEN read_id <= true; ident_out := to_slv(Manuf_ID,8) & to_slv(Device_ID2,8) & to_slv(Device_ID3,8); SOut_zd <= ident_out(23-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 24) THEN read_cnt := 0; END IF; ELSIF (Instruct = RD_SFDP) THEN IF (read_addr / 16#100# = 0) THEN Addr_tmp_2 := (read_addr mod 16#100#); data_out := to_slv(SFDP_array(Addr_tmp_2),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; IF (read_addr = SFDP_HiAddr) THEN read_addr := 0; ELSE read_addr := read_addr + 1; END IF; END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; REPORT "Given SFDP address is out of range" SEVERITY NOTE; END IF; END IF; ELSIF (Instruct = RD_SCREG) THEN Addr_tmp_2 := read_addr / 16#100#; Addr_tmp_3 := read_addr mod 16#100#; IF (Addr_tmp_2 = 16) THEN -- Security Register No.1 data_out :=to_slv(Security_Reg1(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSIF (Addr_tmp_2 = 32) THEN -- Security Register No.2 data_out :=to_slv(Security_Reg2(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; ELSIF (Addr_tmp_2 = 48) THEN -- Security Register No.2 data_out :=to_slv(Security_Reg3(Addr_tmp_3),8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; -- END IF; ELSE read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; REPORT "Security Reg addr is out of range" SEVERITY NOTE; END IF; END IF; IF (read_cnt = 8) THEN read_cnt := 0; IF (read_addr mod 256 = SecReg_HiAddr) THEN read_addr := (read_addr/256)* (SecReg_HiAddr+1); ELSE read_addr := read_addr + 1; END IF; END IF; END IF; END IF; END IF; WHEN DP_DOWN => IF (oe AND Instruct = RES_RD_ID) THEN read_id <= true; data_out := to_slv(Device_ID1,8); SOut_zd <= data_out(7-read_cnt); read_cnt := read_cnt + 1; IF (read_cnt = 8) THEN read_cnt := 0; END IF; END IF; IF falling_edge(write) THEN IF (Instruct = RES_RD_ID) THEN IF res_flag = true THEN RES2_in <= '1'; ELSE RES1_in <= '1'; END IF; ELSE REPORT "Device is in DPD Mode No instructions allowed" SEVERITY NOTE; END IF; END IF; END CASE; --Output Disable Control IF (CSNeg_ipd = '1') THEN SIOut_zd <= 'Z'; HOLDNegOut_zd <= 'Z'; WPNegOut_zd <= 'Z'; SOut_zd <= 'Z'; END IF; END PROCESS Functional; --------------------------------------------------------------------------- -- SFDP Process --------------------------------------------------------------------------- SFDPPreload: PROCESS BEGIN ----------------------------------------------------------------------- --SFDP array data ----------------------------------------------------------------------- SFDP_array(16#00#) := 16#53#; SFDP_array(16#01#) := 16#46#; SFDP_array(16#02#) := 16#44#; SFDP_array(16#03#) := 16#50#; SFDP_array(16#04#) := 16#01#; SFDP_array(16#05#) := 16#01#; SFDP_array(16#06#) := 16#00#; SFDP_array(16#07#) := 16#FF#; SFDP_array(16#08#) := 16#EF#; SFDP_array(16#09#) := 16#00#; SFDP_array(16#0A#) := 16#01#; SFDP_array(16#0B#) := 16#04#; SFDP_array(16#0C#) := 16#80#; SFDP_array(16#0D#) := 16#00#; SFDP_array(16#0E#) := 16#00#; SFDP_array(16#0F#) := 16#FF#; SFDP_array(16#10#) := 16#EF#; SFDP_array(16#11#) := 16#00#; SFDP_array(16#12#) := 16#01#; SFDP_array(16#13#) := 16#00#; SFDP_array(16#14#) := 16#90#; SFDP_array(16#15#) := 16#00#; SFDP_array(16#16#) := 16#00#; SFDP_array(16#17#) := 16#FF#; FOR I IN 24 TO 127 LOOP SFDP_array(i) := MaxData; END LOOP; SFDP_array(16#80#) := 16#E5#; SFDP_array(16#81#) := 16#20#; SFDP_array(16#82#) := 16#F1#; SFDP_array(16#83#) := 16#FF#; SFDP_array(16#84#) := 16#FF#; SFDP_array(16#85#) := 16#FF#; SFDP_array(16#86#) := 16#FF#; SFDP_array(16#87#) := 16#07#; SFDP_array(16#88#) := 16#44#; SFDP_array(16#89#) := 16#EB#; SFDP_array(16#8A#) := 16#08#; SFDP_array(16#8B#) := 16#6B#; SFDP_array(16#8C#) := 16#08#; SFDP_array(16#8D#) := 16#3B#; SFDP_array(16#8E#) := 16#80#; SFDP_array(16#8F#) := 16#BB#; FOR I IN 144 TO 255 LOOP SFDP_array(i) := MaxData; END LOOP; WAIT; END PROCESS SFDPPreload; --------------------------------------------------------------------------- -- Sector Protection Bits --------------------------------------------------------------------------- Protect : PROCESS(change_prot_bits) BEGIN IF rising_edge(change_prot_bits) THEN CASE BP_bits IS WHEN "000" => IF (CMP = '0') THEN Sec_Prot := (others => '0'); ELSE Sec_Prot := (others => '1'); END IF; WHEN "001" => IF (CMP = '0') THEN IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(4095 downto 4032) := (others => '1'); Sec_Prot(4031 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(63 downto 0) := (others => '1'); Sec_Prot(4095 downto 64) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4095) := '1'; Sec_Prot(4094 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(0) := '1'; Sec_Prot(4095 downto 1) := (others => '0'); END IF; ELSE IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(4031 downto 0) := (others => '1'); Sec_Prot(4095 downto 4032) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(4095 downto 64) := (others => '1'); Sec_Prot(63 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4094 downto 0) := (others => '1'); Sec_Prot(4095) := '0'; ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(4095 downto 1) := (others => '1'); Sec_Prot(0) := '0'; END IF; END IF; WHEN "010" => IF (CMP = '0') THEN IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(4095 downto 3968) := (others => '1'); Sec_Prot(3967 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(127 downto 0) := (others => '1'); Sec_Prot(4095 downto 128) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4095 downto 4094) := (others => '1'); Sec_Prot(4093 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(1 downto 0) := (others => '1'); Sec_Prot(4095 downto 2) := (others => '0'); END IF; ELSE IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(3967 downto 0) := (others => '1'); Sec_Prot(4095 downto 3968) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(4095 downto 128) := (others => '1'); Sec_Prot(127 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4093 downto 0) := (others => '1'); Sec_Prot(4095 downto 4094) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(4095 downto 2) := (others => '1'); Sec_Prot(1 downto 0) := (others => '0'); END IF; END IF; WHEN "011" => IF (CMP = '0') THEN IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(4095 downto 3840) := (others => '1'); Sec_Prot(3839 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(255 downto 0) := (others => '1'); Sec_Prot(4095 downto 256) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4095 downto 4092) := (others => '1'); Sec_Prot(4091 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(3 downto 0) := (others => '1'); Sec_Prot(4095 downto 4) := (others => '0'); END IF; ELSE IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(3839 downto 0) := (others => '1'); Sec_Prot(4095 downto 3840) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(4095 downto 256) := (others => '1'); Sec_Prot(255 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4091 downto 0) := (others => '1'); Sec_Prot(4095 downto 4092) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(4095 downto 4) := (others => '1'); Sec_Prot(3 downto 0) := (others => '0'); END IF; END IF; WHEN "100" => IF (CMP = '0') THEN IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(4095 downto 3584) := (others => '1'); Sec_Prot(3583 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(511 downto 0) := (others => '1'); Sec_Prot(4095 downto 512) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4095 downto 4088) := (others => '1'); Sec_Prot(4087 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(7 downto 0) := (others => '1'); Sec_Prot(4095 downto 8) := (others => '0'); END IF; ELSE IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(3583 downto 0) := (others => '1'); Sec_Prot(4095 downto 3584) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(4095 downto 512) := (others => '1'); Sec_Prot(511 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4087 downto 0) := (others => '1'); Sec_Prot(4095 downto 4088) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(4095 downto 8) := (others => '1'); Sec_Prot(7 downto 0) := (others => '0'); END IF; END IF; WHEN "101" => IF (CMP = '0') THEN IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(4095 downto 3072) := (others => '1'); Sec_Prot(3071 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(1023 downto 0) := (others => '1'); Sec_Prot(4095 downto 1024) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4095 downto 4088) := (others => '1'); Sec_Prot(4087 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(7 downto 0) := (others => '1'); Sec_Prot(4095 downto 8) := (others => '0'); END IF; ELSE IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN Sec_Prot(3071 downto 0) := (others => '1'); Sec_Prot(4095 downto 3072) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN Sec_Prot(4095 downto 1024) := (others => '1'); Sec_Prot(1023 downto 0) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN Sec_Prot(4087 downto 0) := (others => '1'); Sec_Prot(4095 downto 4088) := (others => '0'); ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN Sec_Prot(4095 downto 8) := (others => '1'); Sec_Prot(7 downto 0) := (others => '0'); END IF; END IF; WHEN "110" => IF (CMP = '0') THEN IF (SEC = '0' AND TB = '0') THEN Sec_Prot(4095 downto 2048) := (others => '1'); Sec_Prot(2047 downto 0) := (others => '0'); ELSIF (SEC = '0' AND TB = '1') THEN Sec_Prot(2047 downto 0) := (others => '1'); Sec_Prot(4095 downto 2048) := (others => '0'); END IF; ELSE IF (SEC = '0' AND TB = '0') THEN Sec_Prot(4095 downto 2048) := (others => '0'); Sec_Prot(2047 downto 0) := (others => '1'); ELSIF (SEC = '0' AND TB = '1') THEN Sec_Prot(4095 downto 2048) := (others => '1'); Sec_Prot(2047 downto 0) := (others => '0'); END IF; END IF; WHEN "111" => IF (CMP = '0') THEN Sec_Prot(4095 downto 0) := (others => '1'); ELSE Sec_Prot(4095 downto 0) := (others => '0'); END IF; WHEN OTHERS => Sec_Prot := (OTHERS => '1'); END CASE; -- end of CASE BP_bits END IF; END PROCESS Protect; HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNegIn) BEGIN IF (HOLDNegIn = '0' AND QE /= '1') THEN hold_mode := TRUE; SIOut_z <= 'Z'; SOut_z <= 'Z'; ELSE IF hold_mode THEN SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); hold_mode := FALSE; ELSE SIOut_z <= SIOut_zd; SOut_z <= SOut_zd; hold_mode := FALSE; END IF; END IF; END PROCESS HOLD_FRAME_ON_PO_ZD; HOLD_PULL_UP : PROCESS(HOLDNegIn) BEGIN IF (QE = '0') THEN IF (HOLDNegIn = 'Z') THEN HOLDNeg_pullup <= '1'; ELSE HOLDNeg_pullup <= HOLDNegIn; END IF; END IF; END PROCESS HOLD_PULL_UP; WP_PULL_UP : PROCESS(WPNegIn) BEGIN IF (QE = '0') THEN IF (WPNegIn = 'Z') THEN WPNeg_pullup <= '1'; ELSE WPNeg_pullup <= WPNegIn; END IF; END IF; END PROCESS WP_PULL_UP; --------------------------------------------------------------------------- ---- File Read Section - Preload Control --------------------------------------------------------------------------- MemPreload: PROCESS -- text file input variables FILE mem_file : text is mem_file_name; FILE screg_file : text is screg_file_name; VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE:= 0; VARIABLE screg_ind: NATURAL RANGE 16#00# TO 16#2FF#:= 16#00#; VARIABLE buf : line; BEGIN -- memory preload IF (mem_file_name (1 to 4)/= "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 7)); --address 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; ----------------------------------------------------------------------- -- Security Register Preload ----------------------------------------------------------------------- IF (screg_file_name(1 to 4) /= "none" AND UserPreload) THEN ind := 0; Security_Reg1 := (OTHERS => MaxData); Security_Reg2 := (OTHERS => MaxData); Security_Reg3 := (OTHERS => MaxData); WHILE (not ENDFILE (screg_file)) LOOP READLINE (screg_file, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN screg_ind := h(buf(2 to 4)); --address ELSE IF screg_ind <= 16#0FF# THEN Security_Reg1(screg_ind) := h(buf(1 to 2)); ELSIF screg_ind>=16#100# AND screg_ind<=16#1FF# THEN Security_Reg2(screg_ind-16#100#) := h(buf(1 to 2)); ELSIF screg_ind>=16#200# AND screg_ind<=16#2FF# THEN Security_Reg3(screg_ind-16#200#) := h(buf(1 to 2)); END IF; IF (screg_ind mod 16#100#) < 16#FF# THEN screg_ind := screg_ind + 1; END IF; END IF; END LOOP; END IF; WAIT; END PROCESS MemPreload; --------------------------------------------------------------------------- -- Path Delay Section --------------------------------------------------------------------------- S_Out_PathDelay_Gen : PROCESS(SOut_z) VARIABLE SO_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => SOut, OutSignalName => "SO", OutTemp => SOut_z, Mode => VitalTransport, GlitchData => SO_GlitchData, Paths => ( 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), PathCondition => SOut_z /= 'Z' AND NOT(read_id)), 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), PathCondition => SOut_z /= 'Z' AND read_id), 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, PathDelay => tpd_CSNeg_SO, PathCondition => CSNeg_ipd = '1'), 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, PathDelay => tpd_HOLDNeg_SO, PathCondition => QE = '0') ) ); END PROCESS; SI_Out_PathDelay : PROCESS(SIOut_z) VARIABLE SI_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => SIOut, OutSignalName => "SI", OutTemp => SIOut_z, Mode => VitalTransport, GlitchData => SI_GlitchData, Paths => ( 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), PathCondition => SIOut_z /= 'Z' AND NOT(read_id)), 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), PathCondition => SIOut_z /= 'Z' AND read_id), 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, PathDelay => tpd_CSNeg_SO, PathCondition => CSNeg_ipd = '1' AND SIOut_zd = 'Z'), 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, PathDelay => tpd_HOLDNeg_SO, PathCondition => SIOut_z /= 'Z' AND QE = '0') ) ); END PROCESS; HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) VARIABLE HOLD_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => HOLDNegOut, OutSignalName => "HOLDNeg", OutTemp => HOLDNegOut_zd, GlitchData => HOLD_GlitchData, Paths => ( 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), PathCondition => HOLDNegOut_zd /= 'Z' --AND quad_read AND QE = '1' AND NOT(read_id)), 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), PathCondition => HOLDNegOut_zd /= 'Z' --AND quad_read AND QE = '1' AND read_id), 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, PathDelay => tpd_CSNeg_SO, PathCondition => CSNeg_ipd = '1' AND --quad_read AND HOLDNegOut_zd = 'Z' AND QE = '1') ) ); END PROCESS; WP_Out_PathDelay : PROCESS(WPNegOut_zd) VARIABLE WP_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => WPNegOut, OutSignalName => "WPNeg", OutTemp => WPNegOut_zd, GlitchData => WP_GlitchData, Paths => ( 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), PathCondition => WPNegOut_zd /= 'Z' --AND quad_read AND QE = '1' AND NOT(read_id)), 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), PathCondition => WPNegOut_zd /= 'Z' -- AND quad_read AND QE = '1' AND read_id), 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, PathDelay => tpd_CSNeg_SO, PathCondition => CSNeg_ipd = '1' AND --quad_read AND WPNegOut_zd = 'Z' AND QE = '1') ) ); END PROCESS; END BLOCK behavior; END vhdl_behavioral;