git-svn-id: http://moon:8086/svn/vhdl/trunk@1290 cc03376c-175c-47c8-b038-4cd826a8556b
3787 lines
178 KiB
VHDL
3787 lines
178 KiB
VHDL
-------------------------------------------------------------------------------
|
|
-- File Name: s25fl128k.vhd
|
|
-------------------------------------------------------------------------------
|
|
-- Copyright (C) 2010 Spansion, LLC.
|
|
--
|
|
-- 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; |