git-svn-id: http://moon:8086/svn/vhdl/trunk@1290 cc03376c-175c-47c8-b038-4cd826a8556b
13905 lines
659 KiB
VHDL
13905 lines
659 KiB
VHDL
-------------------------------------------------------------------------------
|
|
-- File Name: s25fl512s.vhd
|
|
-------------------------------------------------------------------------------
|
|
-- Copyright (C) 2011 Spansion, LLC.
|
|
--
|
|
-- MODIFICATION HISTORY:
|
|
--
|
|
-- version: | author: | mod date: | changes made:
|
|
-- V1.0 V.Mancev 09 Nov 26 Inital Release
|
|
-- V1.1 V.Mancev 10 Mar 04 addr_cnt for second read in
|
|
-- high performance read continuous
|
|
-- mode can change its value only
|
|
-- when CSNeg = '0'
|
|
-- V1.2 V.Mancev 10 July 28 During the QUAD mode HOLD# input
|
|
-- is not monitored for its normal
|
|
-- function
|
|
-- V1.3 V.Mancev 10 Oct 28 Latest datasheet aligned
|
|
-- V1.4 V.Mancev 10 Nov 15 QUAD Program operation during Erase
|
|
-- Suspend is added
|
|
-- Warning for Resume to Suspend time
|
|
-- is added
|
|
-- During Erase Suspend, after Program
|
|
-- operation is completed, WEL bit is
|
|
-- cleared
|
|
-- Implemetation of Software Reset is
|
|
-- Changed
|
|
-- V1.2 V.Mancev 11 July 11 Latest datasheet aligned
|
|
-- V1.3 V.Mancev 22 July 11 Corrections for P4E and P4E4
|
|
-- V1.4 V. Mancev 18 Nov 11 Time tHO is changed to 1 ns
|
|
-- (customer's request)
|
|
-- BRWR instruction is corrected
|
|
-- V1.5 S.Petrovic 02 Jun 12 QPP Instruction is allowed on
|
|
-- previously programmed page
|
|
-------------------------------------------------------------------------------
|
|
-- PART DESCRIPTION:
|
|
--
|
|
-- Library: FLASH
|
|
-- Technology: FLASH MEMORY
|
|
-- Part: S25FL512S
|
|
--
|
|
-- Description: 512 Megabit Serial Flash Memory
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
-- Comments :
|
|
-- For correct simulation, simulator resolution should be set to 1 ps
|
|
-- A device ordering (trim) option determines whether a feature is enabled
|
|
-- or not, or provide relevant parameters:
|
|
-- -15th character in TimingModel determines if enhanced high
|
|
-- performance option is available
|
|
-- (0,2,3,R,A,B,C,D) EHPLC
|
|
-- (Y,Z,S,T,K,L) Security EHPLC
|
|
-- (4,6,7,8,9,Q) HPLC
|
|
-- -15th character in TimingModel determines if RESET# input
|
|
-- is available
|
|
-- (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available
|
|
-- (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive
|
|
-- state,inside the package.
|
|
--
|
|
--------------------------------------------------------------------------------
|
|
-- 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 s25fl512s 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;
|
|
tipd_RSTNeg : VitalDelayType01 := VitalZeroDelay01;
|
|
|
|
-- tpd delays: propagation delays (pin-to-pin delay within a component)
|
|
tpd_SCK_SO_normal : VitalDelayType01Z := UnitDelay01Z; -- tV, tHO
|
|
tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tDIS
|
|
tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;--
|
|
tpd_RSTNeg_SO : VitalDelayType01Z := UnitDelay01Z;--
|
|
-- DDR operation values
|
|
tpd_SCK_SO_DDR : VitalDelayType01Z := UnitDelay01Z;--tV(66MHz)
|
|
|
|
-- tsetup values: setup times
|
|
-- setup time is minimum time before the referent signal edge the
|
|
-- input should be stable
|
|
tsetup_CSNeg_SCK_normal_noedge_posedge
|
|
: VitalDelayType := UnitDelay; -- tCSS /
|
|
tsetup_CSNeg_SCK_DDR_noedge_posedge
|
|
: VitalDelayType := UnitDelay; -- tCSS /
|
|
tsetup_SI_SCK_normal_noedge_posedge: VitalDelayType
|
|
:= UnitDelay; -- tSU:DAT /
|
|
tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPS \
|
|
tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay;
|
|
tsetup_RSTNeg_CSNeg : VitalDelayType := UnitDelay; -- tRP
|
|
-- DDR operation values
|
|
tsetup_SI_SCK_DDR_noedge_posedge: VitalDelayType
|
|
:= UnitDelay; -- tSU /
|
|
tsetup_SI_SCK_DDR_noedge_negedge: VitalDelayType
|
|
:= UnitDelay; -- tSU \
|
|
|
|
-- thold values: hold times
|
|
-- hold time is minimum time the input should be present stable
|
|
-- after the referent signal edge
|
|
thold_CSNeg_SCK_normal_noedge_posedge
|
|
: VitalDelayType := UnitDelay; -- tCSH /
|
|
thold_CSNeg_SCK_DDR_noedge_posedge
|
|
: VitalDelayType := UnitDelay; -- tCSH /
|
|
thold_SI_SCK_normal_noedge_posedge: VitalDelayType
|
|
:= UnitDelay; -- tHD:DAT /
|
|
thold_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPH /
|
|
thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; --
|
|
thold_CSNeg_RSTNeg : VitalDelayType := UnitDelay; -- tRPH
|
|
-- DDR operation values
|
|
thold_SI_SCK_DDR_noedge_posedge: VitalDelayType
|
|
:= UnitDelay; -- tHD /
|
|
thold_SI_SCK_DDR_noedge_negedge: VitalDelayType
|
|
:= UnitDelay; -- tHD \
|
|
|
|
--tpw values: pulse width
|
|
tpw_SCK_serial_posedge : VitalDelayType := UnitDelay; -- tWH
|
|
tpw_SCK_dual_posedge : VitalDelayType := UnitDelay; -- tWH
|
|
tpw_SCK_fast_posedge : VitalDelayType := UnitDelay; -- tWH
|
|
tpw_SCK_quadpg_posedge : VitalDelayType := UnitDelay; -- tWH
|
|
tpw_SCK_serial_negedge : VitalDelayType := UnitDelay; -- tWL
|
|
tpw_SCK_dual_negedge : VitalDelayType := UnitDelay; -- tWL
|
|
tpw_SCK_fast_negedge : VitalDelayType := UnitDelay; -- tWL
|
|
tpw_SCK_quadpg_negedge : VitalDelayType := UnitDelay; -- tWL
|
|
tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tCS
|
|
tpw_CSNeg_pgers_posedge : VitalDelayType := UnitDelay; -- tCS
|
|
tpw_RSTNeg_negedge : VitalDelayType := UnitDelay; -- tRP
|
|
tpw_RSTNeg_posedge : VitalDelayType := UnitDelay; -- tRS
|
|
-- DDR operation values
|
|
tpw_SCK_DDR_posedge : VitalDelayType := UnitDelay; -- tWH(66MHz)
|
|
tpw_SCK_DDR_negedge : VitalDelayType := UnitDelay; -- tWL(66Hz)
|
|
|
|
-- tperiod min (calculated as 1/max freq)
|
|
tperiod_SCK_serial_rd : VitalDelayType := UnitDelay; --fSCK=50MHz
|
|
tperiod_SCK_fast_rd : VitalDelayType := UnitDelay; --fSCK=133MHz
|
|
tperiod_SCK_dual_rd : VitalDelayType := UnitDelay; --fSCK=104MHz
|
|
tperiod_SCK_quadpg : VitalDelayType := UnitDelay; --fSCK=80MHz
|
|
-- DDR operation values
|
|
tperiod_SCK_DDR_rd : VitalDelayType := UnitDelay; --fSCK=66MHz
|
|
|
|
-- tdevice values: values for internal delays
|
|
--timing values that are internal to the model and not associated
|
|
--with any port.
|
|
tdevice_PP : VitalDelayType := 750 us; --tPP
|
|
-- Typical Byte Programming Time
|
|
tdevice_BP : VitalDelayType := 400 us; --tBP
|
|
-- Sector Erase Operation
|
|
tdevice_SE : VitalDelayType := 1875 ms; --tSE
|
|
-- Bulk Erase Operation
|
|
tdevice_BE : VitalDelayType := 460 sec; --tBE
|
|
-- WRR Cycle Time
|
|
tdevice_WRR : VitalDelayType := 200 ms; --tW
|
|
-- Erase Suspend/Erase Resume Time
|
|
tdevice_ERSSUSP : VitalDelayType := 40 us; --tESL
|
|
-- Program Suspend/Program Resume Time
|
|
tdevice_PRGSUSP : VitalDelayType := 40 us; --tPSL
|
|
-- VCC (min) to CS# Low
|
|
tdevice_PU : VitalDelayType := 300 us; --tPU
|
|
-- PPB Erase Time
|
|
tdevice_PPBERASE :VitalDelayType := 15 ms;
|
|
-- Password Unlock Time
|
|
tdevice_PASSULCK :VitalDelayType := 1 us;
|
|
-- Password Unlock Time
|
|
tdevice_PASSACC :VitalDelayType := 100 us;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- 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 := "s25fl512s.mem";
|
|
otp_file_name : STRING := "s25fl512sOTP.mem";
|
|
|
|
UserPreload : BOOLEAN := FALSE; --TRUE;
|
|
LongTimming : BOOLEAN := TRUE;
|
|
|
|
-- For FMF SDF technology file usage
|
|
TimingModel : STRING
|
|
);
|
|
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
|
|
RSTNeg : IN std_ulogic := 'U'; -- hardware reset pin
|
|
WPNeg : INOUT std_ulogic := 'U'; -- write protect input/IO2
|
|
HOLDNeg : INOUT std_ulogic := 'U' -- hold input/IO3
|
|
);
|
|
|
|
ATTRIBUTE VITAL_LEVEL0 of s25fl512s : ENTITY IS TRUE;
|
|
END s25fl512s;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- ARCHITECTURE DECLARATION
|
|
-------------------------------------------------------------------------------
|
|
ARCHITECTURE vhdl_behavioral_dynamic_memory_allocation of s25fl512s IS
|
|
ATTRIBUTE VITAL_LEVEL0 OF
|
|
vhdl_behavioral_dynamic_memory_allocation : 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 := "s25fl512s";
|
|
CONSTANT MaxData : NATURAL := 16#FF#; --255;
|
|
CONSTANT MemSize : NATURAL := 16#3FFFFFF#;
|
|
CONSTANT SecNum : NATURAL := 255;
|
|
CONSTANT SecSize : NATURAL := 16#3FFFF#; --256KB
|
|
CONSTANT PageNum : NATURAL := 16#1FFFF#;
|
|
CONSTANT PageSize : NATURAL := 512;
|
|
CONSTANT AddrRANGE : NATURAL := 16#3FFFFFF#;
|
|
CONSTANT HiAddrBit : NATURAL := 31;
|
|
CONSTANT OTPSize : NATURAL := 1023;
|
|
CONSTANT OTPLoAddr : NATURAL := 16#000#;
|
|
CONSTANT OTPHiAddr : NATURAL := 16#3FF#;
|
|
CONSTANT BYTE : NATURAL := 8;
|
|
|
|
--Manufacturer Identification
|
|
CONSTANT Manuf_ID : NATURAL := 16#01#;
|
|
CONSTANT DeviceID : NATURAL := 16#19#;
|
|
--Electronic Signature
|
|
CONSTANT ESignature : NATURAL := 16#19#;
|
|
--Device ID
|
|
--Manufacturer Identification && Memory Type && Memory Capacity
|
|
CONSTANT Jedec_ID : NATURAL := 16#01#; -- first byte of Device ID
|
|
CONSTANT DeviceID1 : NATURAL := 16#02#;
|
|
CONSTANT DeviceID2 : NATURAL := 16#20#;
|
|
CONSTANT ExtendedBytes : NATURAL := 16#4D#;
|
|
CONSTANT ExtendedID : NATURAL := 16#00#;
|
|
CONSTANT DieRev : NATURAL := 16#00#;
|
|
CONSTANT MaskRev : NATURAL := 16#00#;
|
|
|
|
-- 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 RSTNeg_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';
|
|
SIGNAL RSTNeg_pullup : std_ulogic := 'U';
|
|
|
|
-- internal delays
|
|
SIGNAL PP_in : std_ulogic := '0';
|
|
SIGNAL PP_out : std_ulogic := '0';
|
|
SIGNAL BP_in : std_ulogic := '0';
|
|
SIGNAL BP_out : std_ulogic := '0';
|
|
SIGNAL SE_in : std_ulogic := '0';
|
|
SIGNAL SE_out : std_ulogic := '0';
|
|
SIGNAL BE_in : std_ulogic := '0';
|
|
SIGNAL BE_out : std_ulogic := '0';
|
|
SIGNAL WRR_in : std_ulogic := '0';
|
|
SIGNAL WRR_out : std_ulogic := '0';
|
|
SIGNAL ERSSUSP_in : std_ulogic := '0';
|
|
SIGNAL ERSSUSP_out : std_ulogic := '0';
|
|
SIGNAL PRGSUSP_in : std_ulogic := '0';
|
|
SIGNAL PRGSUSP_out : std_ulogic := '0';
|
|
SIGNAL PU_in : std_ulogic := '0';
|
|
SIGNAL PU_out : std_ulogic := '0';
|
|
SIGNAL RST_in : std_ulogic := '0';-- Hardware Reset Timeout
|
|
SIGNAL RST_out : std_ulogic := '1';--
|
|
SIGNAL PPBERASE_in : std_ulogic := '0';
|
|
SIGNAL PPBERASE_out : std_ulogic := '0';
|
|
SIGNAL PASSULCK_in : std_ulogic := '0';
|
|
SIGNAL PASSULCK_out : std_ulogic := '0';
|
|
SIGNAL PASSACC_in : std_ulogic := '0';
|
|
SIGNAL PASSACC_out : std_ulogic := '0';
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Memory data initial value.
|
|
-- Default value may be overridden by conigure_memory procedure
|
|
---------------------------------------------------------------------------
|
|
SHARED VARIABLE max_data : NATURAL := 16#FF#;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Handle dynamic memory allocation
|
|
---------------------------------------------------------------------------
|
|
-- Partition dynamically allocated space for performance
|
|
|
|
SHARED VARIABLE corrupt_Sec : std_logic_vector(SecNum downto 0)
|
|
:=(OTHERS=>'0');
|
|
|
|
-- ------------------------------------------------------------------------
|
|
-- Data types required to implement link list structure
|
|
-- ------------------------------------------------------------------------
|
|
TYPE mem_data_t;
|
|
TYPE mem_data_pointer_t IS ACCESS mem_data_t;
|
|
TYPE mem_data_t IS RECORD
|
|
key_address : INTEGER;
|
|
val_data : INTEGER;
|
|
successor : mem_data_pointer_t;
|
|
END RECORD;
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- Array of linked lists.
|
|
-- Support memory region partitioning for faster access.
|
|
-- ---------------------------------------------------------------------
|
|
TYPE mem_data_pointer_array_t IS
|
|
ARRAY(NATURAL RANGE <>) OF mem_data_pointer_t;
|
|
|
|
SHARED VARIABLE linked_list :
|
|
mem_data_pointer_array_t(0 TO SecNum);
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- Override mechanism provided for default parameter values
|
|
-- ---------------------------------------------------------------------
|
|
PROCEDURE configure_memory(
|
|
max_data_c : IN INTEGER) IS
|
|
BEGIN
|
|
max_data := max_data_c;
|
|
END PROCEDURE configure_memory;
|
|
|
|
-- Asure proper initialization
|
|
PROCEDURE initialize IS
|
|
VARIABLE I : INTEGER;
|
|
BEGIN
|
|
FOR I IN 0 TO SecNum LOOP
|
|
linked_list(I) := NULL;
|
|
END LOOP;
|
|
END PROCEDURE initialize;
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- Create linked listed
|
|
-- ---------------------------------------------------------------------
|
|
PROCEDURE create_list(
|
|
key_address : IN INTEGER;
|
|
val_data : IN INTEGER;
|
|
root : INOUT mem_data_pointer_t) IS
|
|
BEGIN
|
|
root := NEW mem_data_t;
|
|
root.successor := NULL;
|
|
root.key_address := key_address;
|
|
root.val_data := val_data;
|
|
END PROCEDURE create_list;
|
|
|
|
-- --------------------------------------------------------------------
|
|
-- Iterate through linked listed comapring key values
|
|
-- Stop when key value greater or equal
|
|
-- --------------------------------------------------------------------
|
|
PROCEDURE position_list(
|
|
key_address : IN INTEGER;
|
|
root : INOUT mem_data_pointer_t;
|
|
found : INOUT mem_data_pointer_t;
|
|
prev : INOUT mem_data_pointer_t) IS
|
|
BEGIN
|
|
found := root;
|
|
prev := NULL;
|
|
WHILE ((found /= NULL) AND (found.key_address < key_address)) LOOP
|
|
prev := found;
|
|
found := found.successor;
|
|
END LOOP;
|
|
END PROCEDURE position_list;
|
|
|
|
-- -------------------------------------------------------------------
|
|
-- Add new element to a linked list
|
|
-- -------------------------------------------------------------------
|
|
PROCEDURE insert_list(
|
|
key_address : IN INTEGER;
|
|
val_data : IN INTEGER;
|
|
root : INOUT mem_data_pointer_t) IS
|
|
|
|
VARIABLE new_element : mem_data_pointer_t;
|
|
VARIABLE found : mem_data_pointer_t;
|
|
VARIABLE prev : mem_data_pointer_t;
|
|
BEGIN
|
|
position_list(key_address, root, found, prev);
|
|
|
|
-- Insert at list tail
|
|
IF (found = NULL) THEN
|
|
prev.successor := NEW mem_data_t;
|
|
prev.successor.key_address := key_address;
|
|
prev.successor.val_data := val_data;
|
|
prev.successor.successor := NULL;
|
|
ELSE
|
|
-- Element exists, update memory data value
|
|
IF (found.key_address = key_address) THEN
|
|
found.val_data := val_data;
|
|
ELSE
|
|
-- No element found, allocate and link
|
|
new_element := NEW mem_data_t;
|
|
new_element.key_address := key_address;
|
|
new_element.val_data := val_data;
|
|
new_element.successor := found;
|
|
-- Possible root position
|
|
IF (prev /= NULL) THEN
|
|
prev.successor := new_element;
|
|
ELSE
|
|
root := new_element;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END PROCEDURE insert_list;
|
|
|
|
-- --------------------------------------------------------------------
|
|
-- Remove element from a linked list
|
|
-- --------------------------------------------------------------------
|
|
PROCEDURE remove_list(
|
|
key_address : IN INTEGER;
|
|
root : INOUT mem_data_pointer_t) IS
|
|
|
|
VARIABLE found : mem_data_pointer_t;
|
|
VARIABLE prev : mem_data_pointer_t;
|
|
BEGIN
|
|
position_list(key_address, root, found, prev);
|
|
IF (found /= NULL) THEN
|
|
-- Key value match
|
|
IF (found.key_address = key_address) THEN
|
|
-- Handle root position removal
|
|
IF (prev /= NULL) THEN
|
|
prev.successor := found.successor;
|
|
ELSE
|
|
root := found.successor;
|
|
END IF;
|
|
DEALLOCATE(found);
|
|
END IF;
|
|
END IF;
|
|
END PROCEDURE remove_list;
|
|
|
|
-- -------------------------------------------------------------------
|
|
-- Remove range of elements from a linked list
|
|
-- Higher performance than one-by-one removal
|
|
-- -------------------------------------------------------------------
|
|
PROCEDURE remove_list_range(
|
|
address_low : IN INTEGER;
|
|
address_high : IN INTEGER;
|
|
root : INOUT mem_data_pointer_t) IS
|
|
|
|
VARIABLE iter : mem_data_pointer_t;
|
|
VARIABLE prev : mem_data_pointer_t;
|
|
VARIABLE link_element : mem_data_pointer_t;
|
|
BEGIN
|
|
iter := root;
|
|
prev := NULL;
|
|
-- Find first linked list element belonging to
|
|
-- a specified address range [address_low, address_high]
|
|
WHILE ((iter /= NULL) AND NOT (
|
|
(iter.key_address >= address_low) AND
|
|
(iter.key_address <= address_high))) LOOP
|
|
prev := iter;
|
|
iter := iter.successor;
|
|
END LOOP;
|
|
-- Continue until address_high reached
|
|
-- Deallocate linked list elements pointed by iterator
|
|
IF (iter /= NULL) THEN
|
|
WHILE ((iter /= NULL) AND
|
|
(iter.key_address >= address_low) AND
|
|
(iter.key_address <= address_high)) LOOP
|
|
link_element := iter.successor;
|
|
DEALLOCATE(iter);
|
|
iter := link_element;
|
|
END LOOP;
|
|
-- Handle possible root value change
|
|
IF prev /= NULL THEN
|
|
prev.successor := link_element;
|
|
ELSE
|
|
root := link_element;
|
|
END IF;
|
|
END IF;
|
|
END PROCEDURE remove_list_range;
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- Address range to be erased
|
|
-- ---------------------------------------------------------------------
|
|
PROCEDURE erase_mem(
|
|
address_low : IN INTEGER;
|
|
address_high : IN INTEGER;
|
|
linked_list : INOUT mem_data_pointer_t) IS
|
|
|
|
BEGIN
|
|
remove_list_range(
|
|
address_low,
|
|
address_high,
|
|
linked_list
|
|
);
|
|
END PROCEDURE erase_mem;
|
|
|
|
-- --------------------------------------------------------------------
|
|
-- Memory READ operation performed above dynamically allocated space
|
|
-- --------------------------------------------------------------------
|
|
PROCEDURE read_mem(
|
|
linked_list : INOUT mem_data_pointer_t;
|
|
data : INOUT INTEGER;
|
|
address : IN INTEGER) IS
|
|
|
|
VARIABLE found : mem_data_pointer_t;
|
|
VARIABLE prev : mem_data_pointer_t;
|
|
VARIABLE mem_data : INTEGER;
|
|
BEGIN
|
|
IF (linked_list = NULL) THEN
|
|
-- Not allocated, not written, initial value
|
|
mem_data := max_data ;
|
|
ELSE
|
|
position_list(address, linked_list, found, prev);
|
|
IF (found /= NULL) THEN
|
|
IF found.key_address = address THEN
|
|
-- Allocated, val_data stored
|
|
mem_data := found.val_data;
|
|
ELSE
|
|
-- Not allocated, not written, initial value
|
|
mem_data := max_data ;
|
|
END IF;
|
|
ELSE
|
|
-- Not allocated, not written, initial value
|
|
mem_data := max_data ;
|
|
END IF;
|
|
END IF;
|
|
data := mem_data;
|
|
END PROCEDURE read_mem;
|
|
|
|
-- ------------------------------------------------------------------
|
|
-- Memory WRITE operation performed above dynamically allocated space
|
|
-- ------------------------------------------------------------------
|
|
PROCEDURE write_mem(
|
|
linked_list : INOUT mem_data_pointer_t;
|
|
address : IN INTEGER;
|
|
data : IN INTEGER) IS
|
|
|
|
BEGIN
|
|
IF (data /= max_data ) THEN
|
|
-- Handle possible root value update
|
|
IF (linked_list /= NULL) THEN
|
|
insert_list(address, data, linked_list);
|
|
ELSE
|
|
create_list(address, data, linked_list);
|
|
END IF;
|
|
ELSE
|
|
-- Deallocate if initial value written
|
|
-- No linked list, NOP, initial value implicit
|
|
IF (linked_list /= NULL) THEN
|
|
remove_list(address, linked_list);
|
|
END IF;
|
|
END IF;
|
|
END PROCEDURE write_mem;
|
|
|
|
PROCEDURE READ_DATA(
|
|
sectoraddr : IN NATURAL RANGE 0 TO Secnum;
|
|
addressinsec : IN NATURAL RANGE 0 TO SecSize;
|
|
ReadData : INOUT INTEGER) IS
|
|
BEGIN
|
|
read_mem(linked_list(sectoraddr),
|
|
ReadData,
|
|
addressinsec
|
|
);
|
|
IF (ReadData = MaxData AND Corrupt_Sec(sectoraddr) = '1') THEN
|
|
ReadData := -1;
|
|
ELSIF (ReadData = MaxData+1) AND Corrupt_Sec(sectoraddr) = '1' THEN
|
|
ReadData := MaxData;
|
|
END IF;
|
|
END READ_DATA;
|
|
|
|
PROCEDURE WRITE_DATA(
|
|
sectoraddr : IN NATURAL RANGE 0 TO Secnum;
|
|
addressinsec : IN NATURAL RANGE 0 TO SecSize;
|
|
WriteData : IN INTEGER) IS
|
|
BEGIN
|
|
IF (WriteData = MaxData AND Corrupt_Sec(sectoraddr) = '1') THEN
|
|
write_mem(linked_list(sectoraddr),
|
|
addressinsec,
|
|
WriteData+1
|
|
);
|
|
ELSE
|
|
write_mem(linked_list(sectoraddr),
|
|
addressinsec,
|
|
WriteData
|
|
);
|
|
END IF;
|
|
END WRITE_DATA;
|
|
|
|
FUNCTION ReturnSectorID(ADDR : NATURAL) RETURN NATURAL IS
|
|
VARIABLE result : NATURAL;
|
|
BEGIN
|
|
IF ADDR <= AddrRange THEN
|
|
result := ADDR / (SecSize+1);
|
|
ELSE
|
|
result := SecNum+1;
|
|
END IF;
|
|
RETURN result;
|
|
END ReturnSectorID;
|
|
|
|
FUNCTION ReturnSectorIDRdPswdMd(TBPROT : std_logic) RETURN NATURAL IS
|
|
VARIABLE result : NATURAL;
|
|
BEGIN
|
|
result := SecNum;
|
|
IF TBPROT = '0' THEN
|
|
result := 0;
|
|
END IF;
|
|
RETURN result;
|
|
END ReturnSectorIDRdPswdMd;
|
|
|
|
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));
|
|
BP :VitalBuf(BP_out, BP_in, (tdevice_BP ,UnitDelay));
|
|
SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay));
|
|
BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay));
|
|
WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay));
|
|
ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay));
|
|
PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay));
|
|
PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay));
|
|
PPBERASE :VitalBuf(PPBERASE_out,PPBERASE_in,(tdevice_PPBERASE,UnitDelay));
|
|
PASSULCK :VitalBuf(PASSULCK_out,PASSULCK_in,(tdevice_PASSULCK,UnitDelay));
|
|
PASSACC :VitalBuf(PASSACC_out, PASSACC_in, (tdevice_PASSACC ,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_5 : VitalWireDelay (RSTNeg_ipd, RSTNeg, tipd_RSTNeg);
|
|
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';
|
|
RSTNeg : 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,
|
|
RSTNeg => RSTNeg_ipd,
|
|
HOLDNegIn => HOLDNeg_ipd,
|
|
HOLDNegOut => HOLDNeg,
|
|
WPNegIn => WPNeg_ipd,
|
|
WPNegOut => WPNeg
|
|
);
|
|
|
|
-- State Machine : State_Type
|
|
TYPE state_type IS (IDLE,
|
|
RESET_STATE,
|
|
AUTOBOOT,
|
|
WRITE_SR,
|
|
PAGE_PG,
|
|
OTP_PG,
|
|
PG_SUSP,
|
|
SECTOR_ERS,
|
|
BULK_ERS,
|
|
ERS_SUSP,
|
|
ERS_SUSP_PG,
|
|
ERS_SUSP_PG_SUSP,
|
|
PASS_PG,
|
|
PASS_UNLOCK,
|
|
PPB_PG,
|
|
PPB_ERS,
|
|
AUTOBOOT_PG,
|
|
ASP_PG,
|
|
PLB_PG,
|
|
DYB_PG,
|
|
NVDLR_PG
|
|
);
|
|
|
|
-- Instruction Type
|
|
TYPE instruction_type IS ( NONE,
|
|
WREN, -- Write Enable
|
|
WRDI, -- Write Disable
|
|
WRR, -- Write Register
|
|
READ, -- Read Normal (3Byte Address)
|
|
RD4, -- Read Normal (4Byte +)
|
|
OTPR, -- OTP Read
|
|
RDSR, -- Read Status Register 1
|
|
RDSR2, -- Read Status Register 2
|
|
RDCR, -- Read Configuration Register 1
|
|
REMS, -- Read ID (SST)
|
|
RDID, -- Read ID JEDEC
|
|
RES, -- Read ID
|
|
FSTRD, -- Fast Read (3Byte Address)
|
|
FSTRD4, -- Fast Read (4Byte +)
|
|
DDRFR, -- Fast Read DDR (3Byte Address)
|
|
DDRFR4, -- Fast Read DDR (4Byte +)
|
|
DOR, -- Read Dual Out (3Byte Address)
|
|
DOR4, -- Read Dual Out (4Byte +)
|
|
DIOR, -- Read Dual I/O (3Byte Address)
|
|
DIOR4, -- Read Dual I/O (4Byte +)
|
|
DDRDIOR, -- Read DDR Dual I/O (3Byte)
|
|
DDRDIOR4, -- Read DDR Dual I/O (4Byte +)
|
|
QOR, -- Read Quad Out (3Byte Address)
|
|
QOR4, -- Read Quad Out (4Byte +)
|
|
QIOR, -- Read Quad I/O (3Byte Address)
|
|
QIOR4, -- Read Quad I/O (4Byte +)
|
|
DDRQIOR, -- Read DDR Quad I/O (3Byte)
|
|
DDRQIOR4, -- Read DDR Quad I/O (4Byte +)
|
|
PP, -- Program Page (3Byte Address)
|
|
PP4, -- Program Page (4Byte +)
|
|
QPP, -- Quad Page Program (3Byte)
|
|
QPP4, -- Quad Page Program (4Byte +)
|
|
OTPP, -- OTP Program
|
|
PGSP, -- Program Suspend
|
|
PGRS, -- Program Resume
|
|
BE, -- Bulk Erase
|
|
SE, -- Erase 128/256KB (3Byte)
|
|
SE4, -- Erase 128/256KB (4Byte +)
|
|
P4E, -- 4KB-sector Erase (3Byte Addr)
|
|
P4E4, -- 4KB-sector Erase (4Byte Addr)
|
|
ERSP, -- Erase Suspend
|
|
ERRS, -- Erase Resume
|
|
ABRD, -- AutoBoot Register Read
|
|
ABWR, -- AutoBoot Register Write
|
|
BRRD, -- Bank Register Read
|
|
BRWR, -- Bank Register Write
|
|
BRAC, -- Bank Register Access
|
|
DLPRD, -- Read Data Learning Pattern
|
|
PNVDLR, -- Program NVDLP Reg
|
|
WVDLR, -- Write Volatile DLP Reg
|
|
ASPRD, -- ASP Read
|
|
ASPP, -- ASP Program
|
|
DYBRD, -- DYB Read
|
|
DYBWR, -- DYB Write
|
|
PPBRD, -- PPB Read
|
|
PPBP, -- PPB Program
|
|
PPBERS, -- PPB Erase
|
|
PLBWR, -- PPB Lock Bit Write
|
|
PLBRD, -- PPB Lock Bit Read
|
|
PASSRD, -- Password Read
|
|
PASSP, -- Password Program
|
|
PASSU, -- Password Unlock
|
|
RESET, -- Reset
|
|
MBR, -- Mode Bit Reset
|
|
MPM, -- Multi-I/O-High Perf Mode
|
|
CLSR -- Clear Status Register
|
|
);
|
|
|
|
TYPE WByteType IS ARRAY (0 TO 511) OF INTEGER RANGE -1 TO MaxData;
|
|
-- OTP Memory Array
|
|
TYPE OTPArray IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER
|
|
RANGE -1 TO MaxData;
|
|
--CFI Array (Common Flash Interface Query codes)
|
|
TYPE CFItype IS ARRAY (16#00# TO 16#55#) OF
|
|
INTEGER RANGE -1 TO 16#FF#;
|
|
-----------------------------------------------------------------------
|
|
-- memory declaration
|
|
-----------------------------------------------------------------------
|
|
-- OTP Sector
|
|
SHARED VARIABLE OTPMem : OTPArray := (OTHERS => MaxData);
|
|
--CFI Array
|
|
SHARED VARIABLE CFI_array : CFItype := (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 Write Disable Bit
|
|
ALIAS SRWD :std_logic IS Status_reg1(7);
|
|
-- Status Register Programming Error Bit
|
|
ALIAS P_ERR :std_logic IS Status_reg1(6);
|
|
-- Status Register Erase Error Bit
|
|
ALIAS E_ERR :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 Write In Progress Bit
|
|
ALIAS WIP :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');
|
|
|
|
-- Status Register Write Enable Latch Bit
|
|
ALIAS ES :std_logic IS Status_reg2(1);
|
|
-- Status Register Write In Progress Bit
|
|
ALIAS PS :std_logic IS Status_reg2(0);
|
|
|
|
-- *** Configuration Register 1 ***
|
|
SHARED VARIABLE Config_reg1 : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL Config_reg1_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- Latency code
|
|
ALIAS LC1 :std_logic IS Config_reg1(7);
|
|
ALIAS LC0 :std_logic IS Config_reg1(6);
|
|
-- Configuration Register TBPROT bit
|
|
ALIAS TBPROT :std_logic IS Config_reg1(5);
|
|
-- Configuration Register LOCK bit
|
|
ALIAS LOCK :std_logic IS Config_reg1(4);
|
|
-- Configuration Register BPNV bit
|
|
ALIAS BPNV :std_logic IS Config_reg1(3);
|
|
-- Configuration Register QUAD bit
|
|
ALIAS QUAD :std_logic IS Config_reg1(1);
|
|
-- Configuration Register FREEZE bit
|
|
ALIAS FREEZE :std_logic IS Config_reg1(0);
|
|
|
|
-- *** VDLR Register ***
|
|
SHARED VARIABLE VDLR_reg : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL VDLR_reg_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- *** NVDLR Register ***
|
|
SHARED VARIABLE NVDLR_reg : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL NVDLR_reg_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- *** AutoBoot Register ***
|
|
SHARED VARIABLE AutoBoot_reg : std_logic_vector(31 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL AutoBoot_reg_in : std_logic_vector(31 downto 0)
|
|
:= (others => '0');
|
|
|
|
--AutoBoot Enable Bit
|
|
ALIAS ABE :std_logic IS AutoBoot_reg(0);
|
|
|
|
-- *** Bank Address Register ***
|
|
SHARED VARIABLE Bank_Addr_reg : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL Bank_Addr_reg_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
--Bank Address Register EXTADD bit
|
|
ALIAS EXTADD :std_logic IS Bank_Addr_reg(7);
|
|
|
|
-- *** ASP Register ***
|
|
SHARED VARIABLE ASP_reg : std_logic_vector(15 downto 0);
|
|
SIGNAL ASP_reg_in : std_logic_vector(15 downto 0)
|
|
:= (others => '1');
|
|
--Read Password Mode Enable Bit
|
|
ALIAS RPME :std_logic IS ASP_reg(5);
|
|
--PPB OTP Bit
|
|
ALIAS PPBOTP :std_logic IS ASP_reg(3);
|
|
-- Password Protection Mode Lock Bit
|
|
ALIAS PWDMLB :std_logic IS ASP_reg(2);
|
|
--Persistent Protection Mode Lock Bit
|
|
ALIAS PSTMLB :std_logic IS ASP_reg(1);
|
|
|
|
-- *** Password Register ***
|
|
SHARED VARIABLE Password_reg : std_logic_vector(63 downto 0)
|
|
:= (others => '1');
|
|
SIGNAL Password_reg_in : std_logic_vector(63 downto 0)
|
|
:= (others => '1');
|
|
-- *** PPB Lock Register ***
|
|
SHARED VARIABLE PPBL : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL PPBL_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
--Persistent Protection Mode Lock Bit
|
|
ALIAS PPB_LOCK : std_logic IS PPBL(0);
|
|
SIGNAL PPB_LOCK_temp : std_ulogic := '0';
|
|
-- *** PPB Access Register ***
|
|
SHARED VARIABLE PPBAR : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
SIGNAL PPBAR_in : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
-- PPB_bits(Sec)
|
|
SHARED VARIABLE PPB_bits : std_logic_vector(SecNum downto 0)
|
|
:= (OTHERS => '1');
|
|
-- *** DYB Access Register ***
|
|
SHARED VARIABLE DYBAR : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
SIGNAL DYBAR_in : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
-- DYB(Sec)
|
|
SHARED VARIABLE DYB_bits : std_logic_vector(SecNum downto 0);
|
|
|
|
-- The Lock Protection Registers for OTP Memory space
|
|
SHARED VARIABLE LOCK_BYTE1 :std_logic_vector(7 downto 0);
|
|
SHARED VARIABLE LOCK_BYTE2 :std_logic_vector(7 downto 0);
|
|
SHARED VARIABLE LOCK_BYTE3 :std_logic_vector(7 downto 0);
|
|
SHARED VARIABLE LOCK_BYTE4 :std_logic_vector(7 downto 0);
|
|
|
|
--Command Register
|
|
SIGNAL write : std_logic := '0';
|
|
SIGNAL cfg_write : std_logic := '0';
|
|
SIGNAL read_out : std_logic := '0';
|
|
|
|
SIGNAL rd : boolean := false;
|
|
SIGNAL dual : boolean := false;
|
|
SIGNAL fast_rd : boolean := true;
|
|
SIGNAL ddr : boolean := false;
|
|
SIGNAL any_read : boolean := false;
|
|
|
|
SIGNAL quadpg : boolean := false;
|
|
|
|
SIGNAL oe : boolean := false;
|
|
SIGNAL oe_z : boolean := false;
|
|
|
|
SHARED VARIABLE hold_mode : boolean := false;
|
|
|
|
--FSM control signals
|
|
SIGNAL PDONE : std_logic := '1'; --Page Prog. Done
|
|
SIGNAL PSTART : std_logic := '0'; --Start Page Programming
|
|
SIGNAL PGSUSP : std_logic := '0'; --Suspend Program
|
|
SIGNAL PGRES : std_logic := '0'; --Resume Program
|
|
|
|
SIGNAL RES_TO_SUSP_MIN_TIME : std_logic := '0';--Resume to Suspend Flag
|
|
SIGNAL RES_TO_SUSP_TYP_TIME : std_logic := '0';--Resume to Suspend Flag
|
|
|
|
SIGNAL WDONE : std_logic := '1'; --Write operation Done
|
|
SIGNAL WSTART : std_logic := '0'; --Start Write operation
|
|
|
|
SIGNAL ESTART : std_logic := '0'; --Start Erase operation
|
|
SIGNAL EDONE : std_logic := '1'; --Erase operation Done
|
|
SIGNAL ESUSP : std_logic := '0'; --Suspend Erase
|
|
SIGNAL ERES : std_logic := '0'; --Resume Erase
|
|
|
|
--reset timing
|
|
SIGNAL RST : std_logic := '0';
|
|
SIGNAL Reseted : std_logic := '0'; --Reset Timing Control
|
|
--Lock Bit is enabled for customer programming
|
|
SIGNAL WRLOCKENABLE : BOOLEAN := TRUE;
|
|
--Flag that mark if ASP Register is allready programmed
|
|
SIGNAL ASPOTPFLAG : BOOLEAN := FALSE;
|
|
SIGNAL ASP_INIT : NATURAL RANGE 0 TO 1;
|
|
SIGNAL INITIAL_CONFIG : std_logic := '0';
|
|
|
|
SHARED VARIABLE SecAddr : NATURAL RANGE 0 TO SecNum:= 0;
|
|
|
|
SHARED VARIABLE Sec_addr : NATURAL := 0;
|
|
|
|
SHARED VARIABLE Page_addr : NATURAL;
|
|
SHARED VARIABLE pgm_page : NATURAL;
|
|
|
|
SHARED VARIABLE QPP_page : std_logic_vector(PageNum downto 0)
|
|
:= (OTHERS => '0');
|
|
|
|
--Flag for Password unlock command
|
|
SIGNAL PASS_UNLOCKED : boolean := FALSE;
|
|
SIGNAL PASS_TEMP : std_logic_vector(63 downto 0)
|
|
:= (others => '1');
|
|
|
|
SHARED VARIABLE DOUBLE : BOOLEAN := FALSE;
|
|
SHARED VARIABLE EHP : BOOLEAN := FALSE;
|
|
|
|
SHARED VARIABLE read_cnt : NATURAL := 0;
|
|
SHARED VARIABLE byte_cnt : NATURAL := 1;
|
|
SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ;
|
|
|
|
SHARED VARIABLE start_delay : NATURAL RANGE 0 TO 7;
|
|
SHARED VARIABLE ABSD : NATURAL RANGE 0 TO 7;
|
|
SIGNAL start_autoboot : std_logic := '0';
|
|
|
|
SIGNAL change_addr : std_logic := '0';
|
|
SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0;
|
|
SIGNAL SectorSuspend : NATURAL RANGE 0 TO SecNum := 0;
|
|
|
|
-- Sector address
|
|
SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0;
|
|
|
|
-- Sector is protect if Sec_Prot(SecNum) = '1'
|
|
SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) :=
|
|
(OTHERS => '0');
|
|
|
|
SIGNAL change_BP : std_logic := '0';
|
|
SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000";
|
|
|
|
SHARED VARIABLE CFI_array_tmp : std_logic_vector(647 downto 0);
|
|
|
|
SIGNAL Byte_number : NATURAL RANGE 0 TO 511 := 0;
|
|
|
|
TYPE bus_cycle_type IS (STAND_BY,
|
|
OPCODE_BYTE,
|
|
ADDRESS_BYTES,
|
|
DUMMY_BYTES,
|
|
MODE_BYTE,
|
|
DATA_BYTES
|
|
);
|
|
SHARED VARIABLE bus_cycle_state : bus_cycle_type;
|
|
-- switch between Data bytes and Dummy bytes
|
|
SHARED VARIABLE DummyBytes_act : X01 := '0';
|
|
SIGNAL dummy_cnt_act_temp : NATURAL := 0;
|
|
SIGNAL dummy_cnt_act : NATURAL := 0;
|
|
--Read Password Protection Mode Active flag
|
|
SIGNAL RdPswdProtMode : std_ulogic := '0';
|
|
--Read Password Protection Mode Support flag
|
|
SIGNAL RdPswdProtEnable : std_ulogic := '0';
|
|
SIGNAL BAR_ACC : std_ulogic := '0';
|
|
|
|
SHARED VARIABLE Latency_code : NATURAL RANGE 0 TO 7;
|
|
SHARED VARIABLE opcode_cnt : NATURAL := 0;
|
|
SHARED VARIABLE addr_cnt : NATURAL := 0;
|
|
SHARED VARIABLE mode_cnt : NATURAL := 0;
|
|
SHARED VARIABLE dummy_cnt : NATURAL := 0;
|
|
SHARED VARIABLE data_cnt : NATURAL := 0;
|
|
|
|
-- timing check violation
|
|
SIGNAL Viol : X01 := '0';
|
|
|
|
PROCEDURE ADDRHILO_SEC(
|
|
VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE Addr : NATURAL) IS
|
|
VARIABLE sector : NATURAL RANGE 0 TO SecNum;
|
|
BEGIN
|
|
sector := Addr/16#40000#;
|
|
AddrLOW := sector*16#40000#;
|
|
AddrHIGH := sector*16#40000# + 16#3FFFF#;
|
|
END ADDRHILO_SEC;
|
|
|
|
PROCEDURE ADDRHILO_PG(
|
|
VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE Sec_address : INOUT NATURAL RANGE 0 TO SecSize;
|
|
VARIABLE Page_address : INOUT NATURAL;
|
|
VARIABLE Addr : NATURAL) IS
|
|
VARIABLE page : NATURAL RANGE 0 TO PageNum;
|
|
VARIABLE Sec : NATURAL RANGE 0 TO SecNum;
|
|
VARIABLE Sec_addr_tmp : NATURAL RANGE 0 TO ADDRRange;
|
|
BEGIN
|
|
Sec := Addr/(SecSize+1);
|
|
Sec_addr_tmp := Sec*(SecSize+1);
|
|
page := Addr/PageSize;
|
|
AddrLOW := Page*PageSize;
|
|
AddrLOW := AddrLOW - Sec_addr_tmp;
|
|
AddrHIGH := AddrLOW + PageSize-1;
|
|
Sec_address := Addr - Sec_addr_tmp;
|
|
Page_address := page;
|
|
END ADDRHILO_PG;
|
|
|
|
BEGIN
|
|
---------------------------------------------------------------------------
|
|
--Power Up time
|
|
---------------------------------------------------------------------------
|
|
|
|
PoweredUp <= '1' AFTER tdevice_PU;
|
|
|
|
TimingModelSel: PROCESS
|
|
BEGIN
|
|
--Enhanced High Performance Flag
|
|
IF (TimingModel(15) = '0' OR TimingModel(15) = '2' OR
|
|
TimingModel(15) = '3' OR TimingModel(15) = 'R' OR
|
|
TimingModel(15) = 'A' OR TimingModel(15) = 'B' OR
|
|
TimingModel(15) = 'C' OR TimingModel(15) = 'D' OR
|
|
TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR
|
|
TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR
|
|
TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN
|
|
EHP := TRUE;
|
|
IF (TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR
|
|
TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR
|
|
TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN
|
|
RdPswdProtEnable <= '1';
|
|
END IF;
|
|
ELSIF (TimingModel(15) = '4' OR TimingModel(15) = '6' OR
|
|
TimingModel(15) = '7' OR TimingModel(15) = '8' OR
|
|
TimingModel(15) = '9' OR TimingModel(15) = 'Q') THEN
|
|
EHP := FALSE;
|
|
END IF;
|
|
|
|
IF (TimingModel(15) ='0' OR TimingModel(15) ='2' OR
|
|
TimingModel(15) ='3' OR TimingModel(15) ='R' OR
|
|
TimingModel(15) ='A' OR TimingModel(15) ='B' OR
|
|
TimingModel(15) ='C' OR TimingModel(15) ='D' OR
|
|
TimingModel(15) ='4' OR TimingModel(15) ='6' OR
|
|
TimingModel(15) ='7' OR TimingModel(15) ='8' OR
|
|
TimingModel(15) ='9' OR TimingModel(15) ='Q') THEN
|
|
ASP_INIT <= 1;
|
|
ELSIF (TimingModel(15) ='Y' OR TimingModel(15) ='Z' OR
|
|
TimingModel(15) ='S' OR TimingModel(15) ='T' OR
|
|
TimingModel(15) ='K' OR TimingModel(15) ='L') THEN
|
|
ASP_INIT <= 0;
|
|
END IF;
|
|
WAIT;
|
|
END PROCESS;
|
|
|
|
RSTtiming: PROCESS(RSTNeg_pullup,Instruct)
|
|
BEGIN
|
|
IF falling_edge(RSTNeg_pullup) THEN
|
|
RST <= '1', '0' AFTER 200 ns;
|
|
ELSIF Instruct = RESET THEN
|
|
Reseted <= '0', '1' AFTER 10 ns;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
DUMMYcnt: PROCESS(dummy_cnt_act_temp)
|
|
BEGIN
|
|
dummy_cnt_act <= dummy_cnt_act_temp;
|
|
END PROCESS;
|
|
|
|
ReadPasswordProtectionMode: PROCESS(PPB_LOCK_temp,
|
|
ASP_reg_in(2), ASP_reg_in(5))
|
|
BEGIN
|
|
IF (PPB_LOCK = '0' AND PWDMLB = '0' AND RPME = '0' AND
|
|
RdPswdProtEnable = '1') THEN
|
|
RdPswdProtMode <= '1';
|
|
ABE := '0';
|
|
ELSE
|
|
RdPswdProtMode <= '0';
|
|
END IF;
|
|
END PROCESS;
|
|
---------------------------------------------------------------------------
|
|
-- autoboot control logic
|
|
---------------------------------------------------------------------------
|
|
AutoBootControl: PROCESS(SCK_ipd, current_state)
|
|
BEGIN
|
|
IF (current_state = AUTOBOOT) THEN
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF (start_delay > 0) THEN
|
|
start_delay := start_delay - 1;
|
|
END IF;
|
|
END IF;
|
|
|
|
IF (start_delay = 0) THEN
|
|
start_autoboot <= '1';
|
|
ELSE
|
|
start_autoboot <= '0';
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- VITAL Timing Checks Procedures
|
|
---------------------------------------------------------------------------
|
|
VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, RSTNeg_ipd,
|
|
HOLDNegIn, WPNegIn)
|
|
|
|
-- Timing Check Variables
|
|
-- Setup/Hold Checks variables
|
|
VARIABLE Tviol_CSNeg_SCK_normal : X01 := '0';
|
|
VARIABLE TD_CSNeg_SCK_normal : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_CSNeg_SCK_DDR : X01 := '0';
|
|
VARIABLE TD_CSNeg_SCK_DDR : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_CSNeg_RSTNeg : X01 := '0';
|
|
VARIABLE TD_CSNeg_RSTNeg : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_SI_SCK : X01 := '0';
|
|
VARIABLE TD_SI_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;
|
|
|
|
VARIABLE Tviol_HOLDNeg_SCK : X01 := '0';
|
|
VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_SI_SCK_DDR_R : X01 := '0';
|
|
VARIABLE TD_SI_SCK_DDR_R : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_SI_SCK_DDR_F : X01 := '0';
|
|
VARIABLE TD_SI_SCK_DDR_F : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_RSTNeg_CSNeg : X01 := '0';
|
|
VARIABLE TD_RSTNeg_CSNeg : VitalTimingDataType;
|
|
|
|
--Pulse Width and Period Check Variables
|
|
VARIABLE Pviol_SCK_serial : X01 := '0';
|
|
VARIABLE PD_SCK_serial : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_dual : X01 := '0';
|
|
VARIABLE PD_SCK_dual : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_fast : X01 := '0';
|
|
VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_quadpg : X01 := '0';
|
|
VARIABLE PD_SCK_quadpg : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_DDR : X01 := '0';
|
|
VARIABLE PD_SCK_DDR : 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_RSTNeg : X01 := '0';
|
|
VARIABLE PD_RSTNeg : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_serial_rd : X01 := '0';
|
|
VARIABLE PD_SCK_serial_rd : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_fast_rd : X01 := '0';
|
|
VARIABLE PD_SCK_fast_rd : VitalPeriodDataType:=VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_dual_rd : X01 := '0';
|
|
VARIABLE PD_SCK_dual_rd : VitalPeriodDataType:=VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_DDR_rd : X01 := '0';
|
|
VARIABLE PD_SCK_DDR_rd : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_quad_pg : X01 := '0';
|
|
VARIABLE PD_SCK_quad_pg : 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_normal_noedge_posedge,
|
|
SetupLow => tsetup_CSNeg_SCK_normal_noedge_posedge,
|
|
HoldHigh => thold_CSNeg_SCK_normal_noedge_posedge,
|
|
HoldLow => thold_CSNeg_SCK_normal_noedge_posedge,
|
|
CheckEnabled => ddr = false,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_CSNeg_SCK_normal,
|
|
Violation => Tviol_CSNeg_SCK_normal
|
|
);
|
|
|
|
-- Setup/Hold Check between CS# and SCK
|
|
VitalSetupHoldCheck (
|
|
TestSignal => CSNeg_ipd,
|
|
TestSignalName => "CS#",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupHigh => tsetup_CSNeg_SCK_DDR_noedge_posedge,
|
|
SetupLow => tsetup_CSNeg_SCK_DDR_noedge_posedge,
|
|
HoldHigh => thold_CSNeg_SCK_DDR_noedge_posedge,
|
|
HoldLow => thold_CSNeg_SCK_DDR_noedge_posedge,
|
|
CheckEnabled => ddr,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_CSNeg_SCK_DDR,
|
|
Violation => Tviol_CSNeg_SCK_DDR
|
|
);
|
|
|
|
-- Hold Check between CSNeg and RSTNeg
|
|
VitalSetupHoldCheck (
|
|
TestSignal => CSNeg,
|
|
TestSignalName => "CSNeg",
|
|
RefSignal => RSTNeg,
|
|
RefSignalName => "RSTNeg",
|
|
HoldHigh => thold_CSNeg_RSTNeg,
|
|
CheckEnabled => TRUE,
|
|
RefTransition => '\',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_CSNeg_RSTNeg,
|
|
Violation => Tviol_CSNeg_RSTNeg
|
|
);
|
|
|
|
-- Setup/Hold Check between SI and SCK, serial mode
|
|
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 => NOT(DOUBLE) AND SIOut_z /= SIIn,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_SI_SCK,
|
|
Violation => Tviol_SI_SCK
|
|
);
|
|
|
|
-- Setup Check between WP# and CS# \
|
|
VitalSetupHoldCheck (
|
|
TestSignal => WPNegIn,
|
|
TestSignalName => "WP#",
|
|
RefSignal => CSNeg_ipd,
|
|
RefSignalName => "CS#",
|
|
SetupHigh => tsetup_WPNeg_CSNeg,
|
|
CheckEnabled => true,
|
|
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 => SRWD = '1' AND WEL = '1',
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_WPNeg_CSNeg_hold,
|
|
Violation => Tviol_WPNeg_CSNeg_hold
|
|
);
|
|
|
|
-- Setup/Hold Check between HOLD# and SCK /
|
|
VitalSetupHoldCheck (
|
|
TestSignal => HOLDNegIn,
|
|
TestSignalName => "HOLD#",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupLow => tsetup_HOLDNeg_SCK,
|
|
SetupHigh => tsetup_HOLDNeg_SCK,
|
|
HoldLow => thold_HOLDNeg_SCK,
|
|
HoldHigh => thold_HOLDNeg_SCK,
|
|
CheckEnabled => QUAD = '0'
|
|
AND HOLDNegOut_zd /= HOLDNegIn,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_HOLDNeg_SCK,
|
|
Violation => Tviol_HOLDNeg_SCK
|
|
);
|
|
|
|
-- Setup/Hold Check between SI and SCK, DDR mode
|
|
VitalSetupHoldCheck (
|
|
TestSignal => SIIn,
|
|
TestSignalName => "SI",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupHigh => tsetup_SI_SCK_DDR_noedge_posedge,
|
|
SetupLow => tsetup_SI_SCK_DDR_noedge_posedge,
|
|
HoldHigh => thold_SI_SCK_DDR_noedge_posedge,
|
|
HoldLow => thold_SI_SCK_DDR_noedge_posedge,
|
|
CheckEnabled => DOUBLE AND dual = false
|
|
AND SIOut_z /= SIIn,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_SI_SCK_DDR_R,
|
|
Violation => Tviol_SI_SCK_DDR_R
|
|
);
|
|
|
|
-- Setup/Hold Check between SI and SCK, DDR mode
|
|
VitalSetupHoldCheck (
|
|
TestSignal => SIIn,
|
|
TestSignalName => "SI",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupHigh => tsetup_SI_SCK_DDR_noedge_negedge,
|
|
SetupLow => tsetup_SI_SCK_DDR_noedge_negedge,
|
|
HoldHigh => thold_SI_SCK_DDR_noedge_negedge,
|
|
HoldLow => thold_SI_SCK_DDR_noedge_negedge,
|
|
CheckEnabled => ddr AND dual = false
|
|
AND SIOut_z /= SIIn,
|
|
RefTransition => '\',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_SI_SCK_DDR_F,
|
|
Violation => Tviol_SI_SCK_DDR_F
|
|
);
|
|
|
|
-- Setup Check between RSTNeg and SCK, DDR fast mode
|
|
VitalSetupHoldCheck (
|
|
TestSignal => RSTNeg,
|
|
TestSignalName => "RSTNeg",
|
|
RefSignal => CSNeg,
|
|
RefSignalName => "CSNeg",
|
|
SetupHigh => tsetup_RSTNeg_CSNeg,
|
|
CheckEnabled => TRUE,
|
|
RefTransition => '\',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_RSTNeg_CSNeg,
|
|
Violation => Tviol_RSTNeg_CSNeg
|
|
);
|
|
|
|
--Pulse Width and Period Check Variables
|
|
-- Pulse Width Check SCK for READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_serial_negedge,
|
|
PulseWidthHigh => tpw_SCK_serial_posedge,
|
|
PeriodData => PD_SCK_serial,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_serial,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => rd);
|
|
|
|
-- Pulse Width Check SCK for DUAL_READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_dual_negedge,
|
|
PulseWidthHigh => tpw_SCK_dual_posedge,
|
|
PeriodData => PD_SCK_dual,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_dual,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => dual);
|
|
|
|
-- Pulse Width Check SCK for FAST_READ, serial mode
|
|
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 );
|
|
|
|
-- Pulse Width Check SCK for QPP
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_quadpg_negedge,
|
|
PulseWidthHigh => tpw_SCK_quadpg_posedge,
|
|
PeriodData => PD_SCK_quadpg,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_quadpg,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => quadpg);
|
|
|
|
-- 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 => any_read );
|
|
|
|
-- Pulse Width Check CS# for Program/Erase, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => CSNeg_ipd,
|
|
TestSignalName => "CS#",
|
|
PulseWidthHigh => tpw_CSNeg_pgers_posedge,
|
|
PeriodData => PD_CSNeg_pgers,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_CSNeg_pgers,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => NOT(any_read));
|
|
|
|
-- Pulse Width Check RSTNeg
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => RSTNeg_ipd,
|
|
TestSignalName => "RSTNeg",
|
|
PulseWidthLow => tpw_RSTNeg_negedge,
|
|
PulseWidthHigh => tpw_RSTNeg_posedge,
|
|
CheckEnabled => TRUE,
|
|
HeaderMsg => InstancePath & PartID,
|
|
PeriodData => PD_RSTNeg,
|
|
Violation => Pviol_RSTNeg
|
|
);
|
|
|
|
-- Pulse Width Check SCK for DDR READ
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_DDR_negedge,
|
|
PulseWidthHigh => tpw_SCK_DDR_posedge,
|
|
PeriodData => PD_SCK_DDR,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_DDR,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => ddr);
|
|
|
|
-- Period Check SCK for READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_serial_rd,
|
|
PeriodData => PD_SCK_serial_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_serial_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => rd );
|
|
|
|
-- Period Check SCK for FAST READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_fast_rd,
|
|
PeriodData => PD_SCK_fast_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_fast_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => fast_rd );
|
|
|
|
-- Period Check SCK for DUAL READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_dual_rd,
|
|
PeriodData => PD_SCK_dual_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_dual_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => dual );
|
|
|
|
-- Period Check SCK for QPP
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_quadpg,
|
|
PeriodData => PD_SCK_quad_pg,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_quad_pg,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => quadpg );
|
|
|
|
-- Period Check SCK for DDR READ
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_DDR_rd,
|
|
PeriodData => PD_SCK_DDR_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_DDR_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => ddr );
|
|
|
|
Violation := Tviol_CSNeg_SCK_normal OR
|
|
Tviol_CSNeg_SCK_DDR OR
|
|
Tviol_CSNeg_RSTNeg OR
|
|
Tviol_SI_SCK OR
|
|
Tviol_WPNeg_CSNeg_setup OR
|
|
Tviol_WPNeg_CSNeg_hold OR
|
|
Tviol_HOLDNeg_SCK OR
|
|
Tviol_SI_SCK_DDR_R OR
|
|
Tviol_SI_SCK_DDR_F OR
|
|
Tviol_RSTNeg_CSNeg OR
|
|
Pviol_SCK_serial OR
|
|
Pviol_SCK_dual OR
|
|
Pviol_SCK_fast OR
|
|
Pviol_SCK_quadpg OR
|
|
Pviol_CSNeg_read OR
|
|
Pviol_CSNeg_pgers OR
|
|
Pviol_SCK_DDR OR
|
|
Pviol_SCK_serial_rd OR
|
|
Pviol_SCK_fast_rd OR
|
|
Pviol_SCK_dual_rd OR
|
|
Pviol_SCK_quad_pg OR
|
|
Pviol_SCK_DDR_rd;
|
|
|
|
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, RST, PoweredUp, RST_out)
|
|
|
|
BEGIN
|
|
IF PoweredUp = '1' THEN
|
|
IF RSTNeg_pullup = '1' and RST_out= '1' THEN
|
|
IF next_state'EVENT THEN
|
|
current_state <= next_state;
|
|
END IF;
|
|
ELSIF RSTNeg_pullup = '0' AND falling_edge(RST) THEN
|
|
--no state transition while RESET# low
|
|
current_state <= RESET_STATE;
|
|
RST_in <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS StateTransition;
|
|
|
|
Threset : PROCESS(RST_in)
|
|
BEGIN
|
|
IF rising_edge(RST_in) THEN
|
|
RST_out <= '0', '1' AFTER (thold_CSNeg_RSTNeg-200 ns);
|
|
END IF;
|
|
END PROCESS Threset;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Write cycle decode
|
|
---------------------------------------------------------------------------
|
|
|
|
BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RST_out,
|
|
WPNeg_pullup)
|
|
|
|
TYPE quad_data_type IS ARRAY (0 TO 1023) OF INTEGER RANGE 0 TO 15;
|
|
|
|
VARIABLE bit_cnt : NATURAL := 0;
|
|
VARIABLE Data_in : std_logic_vector(4095 downto 0)
|
|
:= (others => '0');
|
|
|
|
VARIABLE opcode : std_logic_vector(7 downto 0);
|
|
VARIABLE opcode_in : std_logic_vector(7 downto 0);
|
|
VARIABLE addr_bytes : std_logic_vector(31 downto 0);
|
|
VARIABLE hiaddr_bytes : std_logic_vector(31 downto 0);
|
|
VARIABLE Address_in : std_logic_vector(31 downto 0);
|
|
VARIABLE mode_bytes : std_logic_vector(7 downto 0);
|
|
VARIABLE mode_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);
|
|
|
|
VARIABLE CLK_PER : time;
|
|
VARIABLE LAST_CLK : time;
|
|
VARIABLE Check_freq : boolean := FALSE;
|
|
|
|
BEGIN
|
|
|
|
IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES)
|
|
AND NOT(bus_cycle_state = DUMMY_BYTES) THEN
|
|
bus_cycle_state := STAND_BY;
|
|
ELSE
|
|
CASE bus_cycle_state IS
|
|
WHEN STAND_BY =>
|
|
IF falling_edge(CSNeg_ipd) THEN
|
|
Instruct <= NONE;
|
|
write <= '1';
|
|
cfg_write <= '0';
|
|
opcode_cnt:= 0;
|
|
addr_cnt := 0;
|
|
mode_cnt := 0;
|
|
dummy_cnt := 0;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
data_cnt := 0;
|
|
DOUBLE := FALSE;
|
|
CLK_PER := 0 ns;
|
|
LAST_CLK := 0 ns;
|
|
IF current_state = AUTOBOOT THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := OPCODE_BYTE;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN OPCODE_BYTE =>
|
|
IF rising_edge(SCK_ipd) THEN
|
|
|
|
Latency_code := to_nat(LC1 & LC0);
|
|
CLK_PER := NOW - LAST_CLK;
|
|
LAST_CLK := NOW;
|
|
IF Check_freq THEN
|
|
IF (CLK_PER < 20 ns AND Latency_code = 3) OR
|
|
(CLK_PER < 12.5 ns AND Latency_code = 0) OR
|
|
(CLK_PER < 11.1 ns AND Latency_code = 1) OR
|
|
(CLK_PER < 9.6 ns AND Latency_code = 2) THEN
|
|
ASSERT FALSE
|
|
REPORT "More wait states are required for " &
|
|
"this clock frequency value"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
Check_freq := FALSE;
|
|
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN
|
|
--One-byte of instruction opcode is shifted into the
|
|
--device on the SI serial input pin with the most
|
|
--significant bit (MSB) first.Each bit input on the
|
|
--SI serial input pin is latched on the rising edge of
|
|
--the SCK serial clock signal.
|
|
opcode_in(opcode_cnt) := SIIn;
|
|
opcode_cnt := opcode_cnt + 1;
|
|
IF opcode_cnt = BYTE THEN
|
|
--MSB first
|
|
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 "00000100" => --04h
|
|
Instruct <= WRDI;
|
|
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 "00010011" => --13h
|
|
Instruct <= RD4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "01001011" => --4Bh
|
|
Instruct <= OTPR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00000101" => --05h
|
|
Instruct <= RDSR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00000111" => --07h
|
|
Instruct <= RDSR2;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00110101" => --35h
|
|
Instruct <= RDCR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10010000" => --90h
|
|
Instruct <= REMS;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "10011111" => --9Fh
|
|
Instruct <= RDID;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10101011" => --ABh
|
|
Instruct <= RES;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
WHEN "00001011" => --0Bh
|
|
Instruct <= FSTRD;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00001100" => --0Ch
|
|
Instruct <= FSTRD4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00001101" => --0Dh
|
|
Instruct <= DDRFR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00001110" => --0Eh
|
|
Instruct <= DDRFR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00111011" => --3Bh
|
|
Instruct <= DOR;
|
|
Check_freq := TRUE;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00111100" => --3Ch
|
|
Instruct <= DOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111011" => --BBh
|
|
Instruct <= DIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111100" => --BCh
|
|
Instruct <= DIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111101" => --BDh
|
|
Instruct <= DDRDIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111110" => --BEh
|
|
Instruct <= DDRDIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "01101011" => --6Bh
|
|
Instruct <= QOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "01101100" => --6Ch
|
|
Instruct <= QOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101011" => --EBh
|
|
Instruct <= QIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101100" => --ECh
|
|
Instruct <= QIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101101" => --EDh
|
|
Instruct <= DDRQIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101110" => --EEh
|
|
Instruct <= DDRQIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00000010" => --02h
|
|
Instruct <= PP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00010010" => --12h
|
|
Instruct <= PP4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00110010" => --32h
|
|
Instruct <= QPP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
quadpg <= TRUE;
|
|
WHEN "00111000" => --38h
|
|
Instruct <= QPP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
quadpg <= TRUE;
|
|
WHEN "00110100" => --34h
|
|
Instruct <= QPP4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
quadpg <= TRUE;
|
|
WHEN "01000010" => --42h
|
|
Instruct <= OTPP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "10000101" => --85h
|
|
Instruct <= PGSP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10001010" => --8Ah
|
|
Instruct <= PGRS;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11000111" => --C7h
|
|
Instruct <= BE;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01100000" => --60h
|
|
Instruct <= BE;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11011000" => --D8h
|
|
Instruct <= SE;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11011100" => --DCh
|
|
Instruct <= SE4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00100000" => --20h
|
|
Instruct <= P4E;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00100001" => --21h
|
|
Instruct <= P4E4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "01110101" => --75h
|
|
Instruct <= ERSP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01111010" => --7Ah
|
|
Instruct <= ERRS;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010100" => --14h
|
|
Instruct <= ABRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010101" => --15h
|
|
Instruct <= ABWR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010110" => --16h
|
|
Instruct <= BRRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010111" => --17h
|
|
Instruct <= BRWR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10111001" => --B9h
|
|
Instruct <= BRAC;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00101011" => --2Bh
|
|
Instruct <= ASPRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00101111" => --2Fh
|
|
Instruct <= ASPP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11100000" => --E0h
|
|
Instruct <= DYBRD;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100001" => --E1h
|
|
Instruct <= DYBWR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100010" => --E2h
|
|
Instruct <= PPBRD;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100011" => --E3h
|
|
Instruct <= PPBP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100100" => --E4h
|
|
Instruct <= PPBERS;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10100110" => --A6h
|
|
Instruct <= PLBWR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10100111" => --A7h
|
|
Instruct <= PLBRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11100111" => --E7h
|
|
Instruct <= PASSRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11101000" => --E8h
|
|
Instruct <= PASSP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11101001" => --E9h
|
|
Instruct <= PASSU;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11110000" => --F0h
|
|
Instruct <= RESET;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11111111" => --FFh
|
|
Instruct <= MBR;
|
|
bus_cycle_state := MODE_BYTE;
|
|
WHEN "01000001" => -- 41h
|
|
Instruct <= DLPRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01000011" => -- 43h
|
|
Instruct <= PNVDLR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01001010" => -- 4Ah
|
|
Instruct <= WVDLR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00110000" => --30h
|
|
Instruct <= CLSR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN others =>
|
|
null;
|
|
|
|
END CASE;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ADDRESS_BYTES =>
|
|
IF Instruct= DDRFR OR Instruct= DDRFR4 OR Instruct= DDRDIOR
|
|
OR Instruct = DDRDIOR4 OR Instruct = DDRQIOR OR
|
|
Instruct = DDRQIOR4 THEN
|
|
DOUBLE := TRUE;
|
|
ELSE
|
|
DOUBLE := FALSE;
|
|
END IF;
|
|
|
|
IF (rising_edge(SCK_ipd) AND NOT(DOUBLE) AND
|
|
(CSNeg_ipd= '0')) THEN
|
|
IF (((Instruct=FSTRD AND EXTADD= '0' )
|
|
OR (Instruct=DOR AND EXTADD= '0')
|
|
OR Instruct=OTPR) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1'))
|
|
OR (Instruct=QOR AND QUAD= '1' AND EXTADD='0') THEN
|
|
--Instruction + 3 Bytes Address + Dummy Byte
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF (Instruct=FSTRD OR Instruct=DOR OR
|
|
Instruct=QOR) THEN
|
|
IF (Latency_code = 3) THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF ((((Instruct=FSTRD4) OR (Instruct=DOR4) OR
|
|
((Instruct=FSTRD) AND EXTADD= '1') OR
|
|
((Instruct=DOR) AND EXTADD= '1')) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR
|
|
((Instruct=QOR4) AND QUAD='1') OR
|
|
((Instruct=QOR) AND QUAD='1' AND EXTADD='1')) THEN
|
|
--Instruction + 4 Bytes Address + Dummy Byte
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
IF addr_cnt = 4*BYTE THEN
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF Latency_code = 3 THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF (DOUBLE AND NOT(hold_mode) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = DIOR AND EXTADD= '0' AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN
|
|
-- DUAL I/O High Performance Read (3Bytes Address)
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF ((Instruct = DIOR4 OR
|
|
(Instruct = DIOR AND EXTADD= '1')) AND
|
|
((HOLDNeg_pullup = '1' AND QUAD = '0') OR
|
|
QUAD = '1')) THEN
|
|
-- DUAL I/O High Performance Read (4Bytes Address)
|
|
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 = (4*BYTE) / 2 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF (Instruct = QIOR AND EXTADD= '0') THEN
|
|
-- QUAD I/O High Performance Read (3Bytes Address)
|
|
IF QUAD = '1' 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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := MODE_BYTE;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF (Instruct = QIOR4 OR
|
|
(Instruct = QIOR AND EXTADD= '1')) THEN
|
|
-- QUAD I/O High Performance Read (4Bytes Address)
|
|
IF QUAD = '1' 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 = (4*BYTE) / 4 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i)
|
|
:= Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := MODE_BYTE;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF (((Instruct = RD4 OR Instruct = PP4 OR
|
|
Instruct = SE4 OR Instruct = PPBRD OR
|
|
Instruct = DYBRD OR Instruct = DYBWR OR
|
|
Instruct = PPBP OR Instruct = P4E4 OR
|
|
(Instruct = READ AND EXTADD= '1' ) OR
|
|
(Instruct = PP AND EXTADD= '1' ) OR
|
|
(Instruct = P4E AND EXTADD= '1' ) OR
|
|
(Instruct = SE AND EXTADD= '1' )) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1'))
|
|
OR (QUAD ='1' AND (Instruct=QPP4 OR
|
|
(Instruct = QPP AND EXTADD= '1' ))))THEN
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
IF addr_cnt = 4*BYTE THEN
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') AND EXTADD= '0') 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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (SCK_ipd'EVENT AND DOUBLE AND addr_cnt /= 0 ) OR
|
|
(rising_edge(SCK_ipd) AND DOUBLE AND addr_cnt = 0 ) THEN
|
|
IF (Instruct=DDRFR AND EXTADD= '0' ) THEN
|
|
--Fast DDR Read Mode
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = 3*BYTE THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 23 DOWNTO 0 LOOP
|
|
addr_bytes(23-i) := Address_in(i);
|
|
END LOOP;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRFR4 OR
|
|
(Instruct=DDRFR AND EXTADD= '1' )) THEN
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = 4*BYTE THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
addr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct= DDRDIOR AND EXTADD= '0' ) THEN
|
|
--Dual I/O DDR Read Mode
|
|
Address_in(2*addr_cnt) := SOIn;
|
|
Address_in(2*addr_cnt+1):= SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRDIOR4 OR
|
|
(Instruct=DDRDIOR AND EXTADD= '1' )) THEN
|
|
--Dual I/O DDR Read Mode
|
|
Address_in(2*addr_cnt) := SOIn;
|
|
Address_in(2*addr_cnt+1) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = (4*BYTE)/2 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
addr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRQIOR AND EXTADD= '0' ) AND
|
|
QUAD = '1' THEN
|
|
--Quad I/O DDR Read Mode
|
|
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;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 5 ns;
|
|
bus_cycle_state := MODE_BYTE;
|
|
END IF;
|
|
ELSIF QUAD = '1' AND (Instruct=DDRQIOR4 OR
|
|
(Instruct=DDRQIOR AND EXTADD= '1' )) 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;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = (4*BYTE)/4 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
addr_bytes(31-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;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN MODE_BYTE =>
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF ((Instruct=DIOR OR Instruct = DIOR4) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) 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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
IF Latency_code = 0 OR Latency_code = 3 THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=QIOR OR Instruct = QIOR4)
|
|
AND QUAD = '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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
ELSIF Instruct=DDRFR OR Instruct = DDRFR4 THEN
|
|
mode_in(2*mode_cnt) := SIIn;
|
|
ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
mode_in(4*mode_cnt) := SOIn;
|
|
mode_in(4*mode_cnt+1) := SIIn;
|
|
ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
mode_in(0) := HOLDNegIn;
|
|
mode_in(1) := WPNegIn;
|
|
mode_in(2) := SOIn;
|
|
mode_in(3) := SIIn;
|
|
END IF;
|
|
dummy_cnt := 0;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
ELSIF falling_edge(SCK_ipd) THEN
|
|
IF Instruct=DDRFR OR Instruct = DDRFR4 THEN
|
|
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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
mode_in(4) := HOLDNegIn;
|
|
mode_in(5) := WPNegIn;
|
|
mode_in(6) := SOIn;
|
|
mode_in(7) := SIIn;
|
|
FOR I IN 7 DOWNTO 0 LOOP
|
|
mode_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN DUMMY_BYTES =>
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
IF (((Instruct=FSTRD OR Instruct=FSTRD4 OR
|
|
Instruct=DOR OR Instruct=DOR4 OR
|
|
Instruct=OTPR) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR
|
|
((Instruct = QOR OR Instruct = QOR4) AND
|
|
QUAD = '1'))THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF dummy_cnt = BYTE THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF EHP THEN
|
|
IF ((Latency_code = 3 AND dummy_cnt=1) OR
|
|
(Latency_code = 0 AND dummy_cnt=2) OR
|
|
(Latency_code = 1 AND dummy_cnt=4) OR
|
|
(Latency_code = 2 AND dummy_cnt=5)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSE
|
|
IF ((Latency_code = 3 AND dummy_cnt = 4) OR
|
|
(Latency_code = 0 AND dummy_cnt = 5) OR
|
|
(Latency_code = 1 AND dummy_cnt = 6) OR
|
|
(Latency_code = 2 AND dummy_cnt = 7)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct=RES THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF dummy_cnt = 3*BYTE THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (Instruct = DIOR OR Instruct = DIOR4) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF EHP THEN
|
|
IF ((Latency_code = 1 AND dummy_cnt = 1) OR
|
|
(Latency_code = 2 AND dummy_cnt = 2)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSE
|
|
IF ((Latency_code = 3 AND dummy_cnt = 4) OR
|
|
(Latency_code = 0 AND dummy_cnt = 4) OR
|
|
(Latency_code = 1 AND dummy_cnt = 5) OR
|
|
(Latency_code = 2 AND dummy_cnt = 6)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF EHP THEN
|
|
IF ((Latency_code = 3 AND dummy_cnt = 2) OR
|
|
(Latency_code = 0 AND dummy_cnt = 4) OR
|
|
(Latency_code = 1 AND dummy_cnt = 5) OR
|
|
(Latency_code = 2 AND dummy_cnt = 6)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSE
|
|
IF ((Latency_code = 3 AND dummy_cnt = 4) OR
|
|
(Latency_code = 0 AND dummy_cnt = 6) OR
|
|
(Latency_code = 1 AND dummy_cnt = 7) OR
|
|
(Latency_code = 2 AND dummy_cnt = 8)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF ((Instruct = QIOR OR Instruct = QIOR4) AND
|
|
QUAD = '1') THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF ((Latency_code = 3 AND dummy_cnt = 1) OR
|
|
(Latency_code = 0 AND dummy_cnt = 4) OR
|
|
(Latency_code = 1 AND dummy_cnt = 4) OR
|
|
(Latency_code = 2 AND dummy_cnt = 5)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (Instruct = DDRQIOR OR Instruct = DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF ((Latency_code = 3 AND dummy_cnt = 3) OR
|
|
(Latency_code = 0 AND dummy_cnt = 6) OR
|
|
(Latency_code = 1 AND dummy_cnt = 7) OR
|
|
(Latency_code = 2 AND dummy_cnt = 8)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF falling_edge(SCK_ipd) THEN
|
|
IF NOT(hold_mode) THEN
|
|
IF (DOUBLE AND VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN DATA_BYTES =>
|
|
IF rising_edge(CSNeg_ipd) THEN
|
|
IF ((mode_bytes(7 downto 4) = "1010" AND
|
|
(Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QIOR OR Instruct = QIOR4)) OR
|
|
((mode_bytes(7 downto 4) =
|
|
NOT(mode_bytes(3 downto 0))) AND
|
|
(Instruct = DDRFR OR Instruct = DDRFR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct = DDRQIOR4))) THEN
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
END IF;
|
|
IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' AND
|
|
NOT(DOUBLE) THEN
|
|
IF ((Instruct = READ OR Instruct=RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = RDSR OR Instruct = RDSR2 OR
|
|
Instruct = RDCR OR Instruct = OTPR OR
|
|
Instruct = DOR OR Instruct = DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = ABRD OR Instruct = BRRD OR
|
|
Instruct = ASPRD OR Instruct = DYBRD OR
|
|
Instruct = PPBRD OR
|
|
Instruct = PASSRD OR Instruct = RDID OR
|
|
Instruct = RES OR Instruct = REMS OR
|
|
Instruct = PLBRD OR Instruct = DLPRD)
|
|
AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1'))
|
|
OR (current_state = AUTOBOOT AND start_delay = 0)OR
|
|
((Instruct=QOR OR Instruct=QIOR OR Instruct=QOR4
|
|
OR Instruct= QIOR4) AND QUAD = '1') THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
ELSIF SCK_ipd'EVENT AND CSNeg_ipd = '0' AND DOUBLE THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF QUAD = '1' AND (Instruct=QPP OR Instruct = QPP4)THEN
|
|
quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn;
|
|
IF data_cnt > (PageSize*2-1) THEN
|
|
--In case of quad mode and QPP,
|
|
--if more than 512 bytes are sent to the device
|
|
FOR I IN 0 TO (PageSize*2-2) LOOP
|
|
quad_data_in(i) := quad_data_in(i+1);
|
|
END LOOP;
|
|
quad_data_in((PageSize*2-1)) :=
|
|
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;
|
|
ELSIF ((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') THEN
|
|
IF data_cnt > (PageSize*8-1) THEN
|
|
--In case of serial mode and PP,
|
|
-- if more than 512 bytes are sent to the device
|
|
-- previously latched data are discarded and last
|
|
-- 512 data bytes are guaranteed to be programmed
|
|
-- correctly within the same page.
|
|
IF bit_cnt = 0 THEN
|
|
FOR I IN 0 TO ((PageSize-1)*BYTE - 1) LOOP
|
|
Data_in(i) := Data_in(i+8);
|
|
END LOOP;
|
|
END IF;
|
|
Data_in((PageSize-1)*BYTE + 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;
|
|
END IF;
|
|
END IF;
|
|
|
|
IF rising_edge(CSNeg_ipd) THEN
|
|
CASE Instruct IS
|
|
WHEN WREN | WRDI | BE | SE | SE4 | CLSR | RESET |
|
|
PPBP | PPBERS | PGSP | PGRS | ERSP | BRAC |
|
|
ERRS | P4E | P4E4 | PLBWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') THEN
|
|
IF data_cnt = 0 THEN
|
|
write <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN WRR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') THEN
|
|
IF ((data_cnt mod 8) = 0 AND data_cnt > 0) THEN
|
|
IF data_cnt = 8 THEN
|
|
--If CS# is driven high after eight
|
|
--cycle,only the Status Register is
|
|
--written to.
|
|
write <= '0';
|
|
IF BAR_ACC = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
Status_reg1_in(i) <=
|
|
Data_in(7-i);
|
|
END LOOP;
|
|
ELSIF P_ERR = '0' AND E_ERR = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
Bank_Addr_reg_in(i) <=
|
|
Data_in(7-i);
|
|
END LOOP;
|
|
END IF;
|
|
ELSIF data_cnt = 16 THEN
|
|
--After the 16th cycle both the
|
|
--Status and Configuration Registers
|
|
--are written to.
|
|
write <= '0';
|
|
IF BAR_ACC = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
cfg_write <= '1';
|
|
FOR i IN 0 TO 7 LOOP
|
|
Status_reg1_in(i) <=
|
|
Data_in(7-i);
|
|
Config_reg1_in(i) <=
|
|
Data_in(15-i);
|
|
END LOOP;
|
|
END LOOP;
|
|
ELSIF P_ERR = '0' AND E_ERR = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
Bank_Addr_reg_in(i) <=
|
|
Data_in(7-i);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PP | PP4 | OTPP =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt > 0 THEN
|
|
IF (data_cnt mod 8) = 0 THEN
|
|
write <= '0';
|
|
FOR I IN 0 TO (PageSize-1) LOOP
|
|
FOR J IN 7 DOWNTO 0 LOOP
|
|
IF Data_in((i*8) + (7-j))
|
|
/= 'X' THEN
|
|
Byte_slv(j) :=
|
|
Data_in((i*8) + (7-j));
|
|
END IF;
|
|
END LOOP;
|
|
WByte(i) <=
|
|
to_nat(Byte_slv);
|
|
END LOOP;
|
|
IF data_cnt > PageSize*BYTE THEN
|
|
Byte_number <= PageSize-1;
|
|
ELSE
|
|
Byte_number <= data_cnt/8-1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN QPP | QPP4=>
|
|
IF data_cnt > 0 THEN
|
|
IF data_cnt mod 2 = 0 THEN
|
|
quadpg <= FALSE;
|
|
write <= '0';
|
|
FOR I IN 0 TO (PageSize-1) 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 > PageSize*2 THEN
|
|
Byte_number <= PageSize-1;
|
|
ELSE
|
|
Byte_number <= data_cnt/2-1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ABWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 32 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 31 LOOP
|
|
AutoBoot_reg_in(J) <=
|
|
Data_in(31-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN BRWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
Bank_Addr_reg_in(J) <=
|
|
Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ASPP =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 16 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 15 LOOP
|
|
ASP_reg_in(J) <=
|
|
Data_in(15-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN DYBWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
DYBAR_in(J) <=
|
|
Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PNVDLR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
NVDLR_reg_in(J) <= Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN WVDLR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
VDLR_reg_in(J) <= Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PASSP =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 64 THEN
|
|
write <= '0';
|
|
FOR J IN 1 TO 8 LOOP
|
|
FOR K IN 1 TO 8 LOOP
|
|
Password_reg_in(J*8-K) <=
|
|
Data_in(8*(J-1)+K-1);
|
|
END LOOP;
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PASSU =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 64 THEN
|
|
write <= '0';
|
|
FOR J IN 1 TO 8 LOOP
|
|
FOR K IN 1 TO 8 LOOP
|
|
PASS_TEMP(J*8-K) <=
|
|
Data_in(8*(J-1)+K-1);
|
|
END LOOP;
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN others =>
|
|
null;
|
|
|
|
END CASE;
|
|
END IF;
|
|
END CASE;
|
|
END IF;
|
|
|
|
END PROCESS BusCycleDecode;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Timing control for the Page Program
|
|
---------------------------------------------------------------------------
|
|
ProgTime : PROCESS(PSTART, PGSUSP, PGRES, RST, Reseted)
|
|
VARIABLE pob : time;
|
|
VARIABLE elapsed : time;
|
|
VARIABLE start : time;
|
|
VARIABLE duration : time;
|
|
BEGIN
|
|
IF rising_edge(PSTART) AND PDONE = '1' THEN
|
|
IF Instruct = PP OR Instruct = PP4 OR Instruct = OTPP OR
|
|
Instruct = QPP OR Instruct = QPP4 THEN
|
|
pob := tdevice_PP;
|
|
ELSE
|
|
pob := tdevice_BP;
|
|
END IF;
|
|
elapsed := 0 ns;
|
|
start := NOW;
|
|
PDONE <= '0', '1' AFTER pob;
|
|
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;
|
|
|
|
IF (RST'EVENT AND RST = '0') THEN
|
|
PDONE <= '1'; -- reset done, programing terminated
|
|
ELSIF rising_edge(Reseted) THEN
|
|
PDONE <= '1'; -- reset done, programing terminated
|
|
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;
|
|
|
|
IF (RST'EVENT AND RST = '0') THEN
|
|
WDONE <= '1'; -- reset done, programing terminated
|
|
ELSIF rising_edge(Reseted) THEN
|
|
WDONE <= '1'; -- reset done, programing terminated
|
|
END IF;
|
|
|
|
END PROCESS WriteTime;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Timing control for the Bulk Erase
|
|
---------------------------------------------------------------------------
|
|
ErsTime : PROCESS(ESTART, ESUSP, ERES, RST, Reseted)
|
|
VARIABLE seo : time;
|
|
VARIABLE beo : time;
|
|
VARIABLE elapsed : time;
|
|
VARIABLE start : time;
|
|
VARIABLE duration : time;
|
|
BEGIN
|
|
IF LongTimming THEN
|
|
seo := tdevice_SE;
|
|
beo := tdevice_BE;
|
|
ELSE
|
|
seo := tdevice_SE / 1000;
|
|
beo := tdevice_BE / 1000;
|
|
END IF;
|
|
IF rising_edge(ESTART) AND EDONE = '1' THEN
|
|
IF Instruct = BE THEN
|
|
duration := beo;
|
|
ELSE --Instruct = SE OR SE4
|
|
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;
|
|
|
|
IF (RST'EVENT AND RST = '0') THEN
|
|
EDONE <= '1'; -- reset done, eras terminated
|
|
ELSIF rising_edge(Reseted) THEN
|
|
EDONE <= '1'; -- reset done, erase terminated
|
|
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, RSTNeg_pullup, WDONE, PDONE,
|
|
ERSSUSP_out, PRGSUSP_out, EDONE, RST_out, PPBERASE_in,
|
|
PASSULCK_in)
|
|
|
|
VARIABLE sect : NATURAL RANGE 0 TO SecNum;
|
|
|
|
BEGIN
|
|
|
|
IF rising_edge(PoweredUp) THEN
|
|
IF ABE = '1' AND RPME /= '0' THEN
|
|
--Autoboot is enabled and The Read Password feature is not enabled
|
|
next_state <= AUTOBOOT;
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&"000000000");
|
|
start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
ELSE
|
|
IF RST_out= '0' then
|
|
next_state <= current_state;
|
|
ELSIF falling_edge(write) AND Instruct = RESET THEN
|
|
IF ABE = '1' AND RPME /= '0' THEN
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&
|
|
"000000000");
|
|
start_delay:= to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
next_state <= AUTOBOOT;
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
ELSE
|
|
CASE current_state IS
|
|
WHEN RESET_STATE =>
|
|
IF rising_edge(RST_out) THEN
|
|
IF ABE = '1' AND RPME /= '0'
|
|
AND RdPswdProtMode = '0' THEN
|
|
next_state <= AUTOBOOT;
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&
|
|
"000000000");
|
|
start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN IDLE =>
|
|
IF falling_edge(write) AND RdPswdProtMode = '0' THEN
|
|
IF (Instruct = WRR AND WEL = '1' AND BAR_ACC = '0') THEN
|
|
IF ((not(SRWD = '1' AND WPNeg_pullup = '0') AND
|
|
QUAD = '0') OR QUAD = '1') THEN
|
|
-- can not execute if HPM is entered
|
|
-- or if WEL bit is zero
|
|
IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR
|
|
(BPNV ='1' AND Config_reg1_in(3)='0')) AND
|
|
cfg_write = '1' THEN
|
|
ASSERT cfg_write = '0'
|
|
REPORT "Changing value of Configuration " &
|
|
"Register OTP bit from 1 to 0 is " &
|
|
"not allowed!!!"
|
|
SEVERITY WARNING;
|
|
ELSE
|
|
next_state <= WRITE_SR;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct = PP OR Instruct = QPP OR
|
|
Instruct = PP4 OR Instruct = QPP4) AND
|
|
WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
next_state <= PAGE_PG;
|
|
IF (Instruct = QPP OR Instruct = QPP4) AND
|
|
QPP_page(pgm_page) = '1' THEN
|
|
REPORT "WARNING:The same page must not be" &
|
|
" programmed more than once!!!"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct=OTPP AND WEL = '1' AND FREEZE = '0' THEN
|
|
IF ((((Address >= 16#10# AND Address <= 16#13#) OR
|
|
(Address >= 16#20# AND Address <= 16#FF#))
|
|
AND LOCK_BYTE1(Address/32) = '1') OR
|
|
((Address >= 16#100# AND Address <= 16#1FF#)
|
|
AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR
|
|
((Address >= 16#200# AND Address <= 16#2FF#)
|
|
AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR
|
|
((Address >= 16#300# AND Address <= 16#3FF#)
|
|
AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND
|
|
(Address + Byte_number <= OTPHiAddr) THEN
|
|
next_state <= OTP_PG;
|
|
END IF;
|
|
ELSIF (Instruct= SE OR Instruct= SE4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
IF (Sec_Prot(sect) = '0' AND PPB_bits(sect)='1'
|
|
AND DYB_bits(sect)='1') THEN
|
|
next_state <= SECTOR_ERS;
|
|
END IF;
|
|
ELSIF (Instruct=P4E OR Instruct=P4E4) AND WEL='1' THEN
|
|
--A P4E instruction applied to a sector that
|
|
--is larger than 4 KB will not be executed
|
|
--and will not set the E_ERR status.
|
|
REPORT "Warning! Parameter 4KB-sector Erase "&
|
|
"Instruction is not allowed for "&
|
|
"512Mbit memory size!!! "&
|
|
"Instruction is ignored!!!"
|
|
SEVERITY warning;
|
|
ELSIF Instruct = BE AND WEL = '1' AND
|
|
(BP0='0' AND BP1='0' AND BP2='0') THEN
|
|
next_state <= BULK_ERS;
|
|
ELSIF Instruct = ABWR AND WEL = '1' THEN
|
|
--Autoboot Register Write Command
|
|
next_state <= AUTOBOOT_PG;
|
|
ELSIF Instruct = ASPP AND WEL = '1' THEN
|
|
--ASP Register Program Command
|
|
IF not(ASPOTPFLAG) THEN
|
|
next_state <= ASP_PG;
|
|
END IF;
|
|
ELSIF Instruct = PLBWR AND WEL = '1' AND
|
|
RdPswdProtEnable = '0' THEN
|
|
next_state <= PLB_PG;
|
|
ELSIF Instruct = PASSP AND WEL = '1' THEN
|
|
IF not(PWDMLB='0' AND PSTMLB='1') THEN
|
|
next_state <= PASS_PG;
|
|
END IF;
|
|
ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN
|
|
next_state <= PASS_UNLOCK;
|
|
ELSIF Instruct = PPBP AND WEL = '1' THEN
|
|
next_state <= PPB_PG;
|
|
ELSIF (Instruct=PPBERS AND WEL='1' AND PPBOTP='1') THEN
|
|
next_state <= PPB_ERS;
|
|
ELSIF Instruct = DYBWR AND WEL = '1' THEN
|
|
next_state <= DYB_PG;
|
|
ELSIF Instruct = PNVDLR AND WEL = '1' THEN
|
|
next_state <= NVDLR_PG;
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
END IF;
|
|
IF falling_edge(write) AND RdPswdProtMode = '1' AND
|
|
WIP = '0' THEN
|
|
IF Instruct = PASSU THEN
|
|
next_state <= PASS_UNLOCK;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT =>
|
|
IF rising_edge(CSNeg_ipd) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN WRITE_SR =>
|
|
IF rising_edge(WDONE) 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;
|
|
|
|
WHEN PG_SUSP =>
|
|
IF falling_edge(write) THEN
|
|
IF Instruct = PGRS THEN
|
|
next_state <= PAGE_PG;
|
|
ELSE
|
|
next_state <= PG_SUSP;
|
|
END IF;
|
|
ELSE
|
|
next_state <= PG_SUSP;
|
|
END IF;
|
|
|
|
WHEN OTP_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
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 falling_edge(write) THEN
|
|
IF (Instruct = PP OR Instruct = QPP OR
|
|
Instruct = PP4 OR Instruct = QPP4) AND
|
|
WEL = '1' THEN
|
|
IF SectorSuspend /= (Address/(SecSize+1)) THEN
|
|
pgm_page := Address / PageSize;
|
|
IF PPB_bits(Address/SecSize)='1' AND
|
|
DYB_bits(Address/SecSize)='1' THEN
|
|
next_state <= ERS_SUSP_PG;
|
|
IF (Instruct = QPP OR Instruct = QPP4) AND
|
|
QPP_page(pgm_page) = '1' THEN
|
|
REPORT "WARNING:The same page must " &
|
|
"not be programmed more than once!!!"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct = DYBWR AND WEL = '1') THEN
|
|
next_state <= DYB_PG;
|
|
ELSIF Instruct = ERRS THEN
|
|
next_state <= SECTOR_ERS;
|
|
END IF;
|
|
ELSE
|
|
next_state <= ERS_SUSP;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG =>
|
|
IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN
|
|
next_state <= ERS_SUSP_PG_SUSP;
|
|
ELSIF rising_edge(PDONE) THEN
|
|
next_state <= ERS_SUSP;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG_SUSP =>
|
|
IF falling_edge(write) THEN
|
|
IF Instruct = PGRS THEN
|
|
next_state <= ERS_SUSP_PG;
|
|
ELSE
|
|
next_state <= ERS_SUSP_PG_SUSP;
|
|
END IF;
|
|
ELSE
|
|
next_state <= ERS_SUSP_PG_SUSP;
|
|
END IF;
|
|
|
|
WHEN PASS_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PASS_UNLOCK =>
|
|
IF falling_edge(PASSULCK_in) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PPB_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PPB_ERS =>
|
|
IF falling_edge(PPBERASE_in) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PLB_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN DYB_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
IF ES = '1' THEN
|
|
next_state <= ERS_SUSP;
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ASP_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN NVDLR_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
END CASE;
|
|
END IF;
|
|
END IF;
|
|
|
|
END PROCESS StateGen;
|
|
|
|
ReadEnable: PROCESS (read_out)
|
|
BEGIN
|
|
oe_z <= rising_edge(read_out) AND PoweredUp = '1';
|
|
|
|
IF read_out'EVENT AND read_out = '0' AND PoweredUp = '1' THEN
|
|
oe <= TRUE, FALSE AFTER 1 ns;
|
|
END IF;
|
|
END PROCESS ReadEnable;
|
|
|
|
---------------------------------------------------------------------------
|
|
--FSM Output generation and general funcionality
|
|
---------------------------------------------------------------------------
|
|
Functional : PROCESS(write,current_state,start_autoboot,CSNeg_ipd,
|
|
HOLDNeg_pullup, Instruct, Address, WByte,change_addr,
|
|
PoweredUp, WPNeg_pullup, WDONE, PDONE, EDONE,
|
|
PRGSUSP_out,ERSSUSP_out, PASSACC_out, oe, oe_z)
|
|
|
|
VARIABLE WData : WByteType:= (OTHERS => MaxData);
|
|
|
|
VARIABLE AddrLo : NATURAL;
|
|
VARIABLE AddrHi : NATURAL;
|
|
VARIABLE Addr : NATURAL;
|
|
VARIABLE Addr_tmp : NATURAL;
|
|
|
|
VARIABLE data_out : std_logic_vector(7 downto 0);
|
|
VARIABLE ident_out : std_logic_vector(647 downto 0);
|
|
|
|
VARIABLE ExtendedID : NATURAL;
|
|
|
|
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 old_pass : std_logic_vector(63 downto 0);
|
|
VARIABLE new_pass : std_logic_vector(63 downto 0);
|
|
VARIABLE wr_cnt : NATURAL RANGE 0 TO 511;
|
|
--Data Learning Pattern Enable
|
|
VARIABLE dlp_act : BOOLEAN := FALSE;
|
|
|
|
VARIABLE sect : NATURAL RANGE 0 TO SecNum;
|
|
VARIABLE cnt : NATURAL RANGE 0 TO 512 := 0;
|
|
VARIABLE mem_data : INTEGER;
|
|
|
|
BEGIN
|
|
|
|
-----------------------------------------------------------------------
|
|
-- Functionality Section
|
|
-----------------------------------------------------------------------
|
|
|
|
IF Instruct'EVENT THEN
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
fast_rd <= true;
|
|
dual <= false;
|
|
rd <= false;
|
|
any_read <= false;
|
|
END IF;
|
|
|
|
IF PASSACC_out'EVENT AND PASSACC_out = '1' THEN
|
|
WIP := '0';
|
|
PASSACC_in <= '0';
|
|
END IF;
|
|
|
|
IF rising_edge(PoweredUp) THEN
|
|
--the default condition after power-up
|
|
--The Bank Address Register is loaded to all zeroes
|
|
Bank_Addr_reg := (others => '0');
|
|
--The Configuration Register FREEZE bit is cleared.
|
|
FREEZE := '0';
|
|
--The WEL bit is cleared.
|
|
WEL := '0';
|
|
--When BPNV is set to '1'. the BP2-0 bits in Status Register are
|
|
--volatile and will be reset binary 111 after power-on reset
|
|
IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN
|
|
BP0 := '1';
|
|
BP1 := '1';
|
|
BP2 := '1';
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
--As shipped from the factory, all devices default ASP to the
|
|
--Persistent Protection mode, with all sectors unprotected,
|
|
--when power is applied. The device programmer or host system must
|
|
--then choose which sector protection method to use.
|
|
--For Persistent Protection mode, PPBLOCK defaults to "1"
|
|
PPB_LOCK := '1';
|
|
PPB_LOCK_temp <= '1';
|
|
DYB_bits := (OTHERS => '1');
|
|
END IF;
|
|
|
|
IF falling_edge(write) AND Instruct = RESET THEN
|
|
--The Configuration Register is set for Address mode
|
|
Bank_Addr_reg := (others => '0');
|
|
--P_ERR bit is cleared
|
|
P_ERR := '0';
|
|
--E_ERR bit is cleared
|
|
E_ERR := '0';
|
|
--The WEL bit is cleared.
|
|
WEL := '0';
|
|
--The WIP bit is cleared.
|
|
WIP := '0';
|
|
--The ES bit is cleared.
|
|
ES := '0';
|
|
--The PS bit is cleared.
|
|
PS := '0';
|
|
|
|
DummyBytes_act := '0';
|
|
--When BPNV is set to '1'. the BP2-0 bits in Status
|
|
--Register are volatile and will be reseted after
|
|
--reset command
|
|
IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN
|
|
BP0 := '1';
|
|
BP1 := '1';
|
|
BP2 := '1';
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
|
|
IF change_addr'EVENT THEN
|
|
read_addr := Address;
|
|
END IF;
|
|
|
|
CASE current_state IS
|
|
WHEN IDLE =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF falling_edge(write) AND RdPswdProtMode = '1' THEN
|
|
IF Instruct = PASSU THEN
|
|
IF WIP = '0' THEN
|
|
PASSULCK_in <= '1';
|
|
ELSE
|
|
REPORT "The PASSU command cannot be accepted"&
|
|
" any faster than once every 100us"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
ELSIF Instruct = CLSR THEN
|
|
--The Clear Status Register Command resets bit SR1[5]
|
|
--(Erase Fail Flag) and bit SR1[6] (Program Fail Flag)
|
|
E_ERR := '0';
|
|
P_ERR := '0';
|
|
END IF;
|
|
END IF;
|
|
IF falling_edge(write) AND RdPswdProtMode = '0' THEN
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
IF Instruct = WREN THEN
|
|
WEL := '1';
|
|
ELSIF Instruct = WRDI THEN
|
|
WEL := '0';
|
|
ELSIF Instruct = WRR AND WEL = '1' AND BAR_ACC = '0' THEN
|
|
IF (not(SRWD = '1' AND WPNeg_pullup = '0') AND
|
|
QUAD ='0') OR QUAD ='1' THEN
|
|
-- can not execute if Hardware Protection Mode
|
|
-- is entered or if WEL bit is zero
|
|
|
|
IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR
|
|
(BPNV ='1' AND Config_reg1_in(3)='0')) AND
|
|
cfg_write = '1' THEN
|
|
P_ERR := '1';
|
|
ELSE
|
|
WSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
P_ERR := '1';
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF (Sec_Prot(sect)= '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
P_ERR := '1';
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF Instruct = OTPP AND WEL = '1' THEN
|
|
-- As long as the FREEZE bit remains cleared to a logic '0'
|
|
--the OTP address space is programmable.
|
|
IF FREEZE = '0' THEN
|
|
IF ((((Address >= 16#0010# AND Address <= 16#13#)OR
|
|
(Address >= 16#0020# AND Address <= 16#FF#))
|
|
AND LOCK_BYTE1(Address/32) = '1') OR
|
|
((Address >= 16#100# AND Address <= 16#1FF#)
|
|
AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR
|
|
((Address >= 16#200# AND Address <= 16#2FF#)
|
|
AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR
|
|
((Address >= 16#300# AND Address <= 16#3FF#)
|
|
AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND
|
|
(Address + Byte_number <= OTPHiAddr) THEN
|
|
PSTART <= '1', '0' AFTER 1 ns;
|
|
WIP := '1';
|
|
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;
|
|
ELSIF (Address < 16#0010# OR (Address > 16#0013# AND
|
|
Address < 16#0020#) OR Address > 16#3FF# ) THEN
|
|
P_ERR := '1';
|
|
WEL := '0';
|
|
IF Address < 16#0020# THEN
|
|
ASSERT false
|
|
REPORT "Given address is in" &
|
|
"reserved address range"
|
|
SEVERITY warning;
|
|
ELSIF Address > 16#3FF# THEN
|
|
ASSERT false
|
|
REPORT "Given address is out of" &
|
|
"OTP address range"
|
|
SEVERITY warning;
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSIF (Instruct = SE OR Instruct = SE4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
SectorSuspend <= sect;
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
ESTART <= '1', '0' AFTER 5 ns;
|
|
ESUSP <= '0';
|
|
ERES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
Addr := Address;
|
|
ELSE
|
|
E_ERR := '1';
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF (Instruct = P4E OR Instruct = P4E4) AND WEL = '1' THEN
|
|
WEL := '0';
|
|
ELSIF Instruct = BE AND WEL = '1' THEN
|
|
IF (BP0='0' AND BP1='0' AND BP2='0') THEN
|
|
ESTART <= '1', '0' AFTER 5 ns;
|
|
ESUSP <= '0';
|
|
ERES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
ELSE
|
|
--The Bulk Erase command will not set E_ERR if a
|
|
--protected sector is found during the command
|
|
--execution.
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF Instruct = PASSP AND WEL = '1' THEN
|
|
IF not(PWDMLB='0' AND PSTMLB='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSE
|
|
REPORT "Password programming is not allowed" &
|
|
" in Password Protection Mode."
|
|
SEVERITY warning;
|
|
END IF;
|
|
ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN
|
|
PASSULCK_in <= '1';
|
|
ELSIF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
IF (P_ERR = '0' AND E_ERR = '0') THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = ASPP AND WEL = '1' THEN
|
|
IF not(ASPOTPFLAG) THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
REPORT "Once the Protection Mode is selected," &
|
|
"no further changes to the ASP register" &
|
|
"is allowed."
|
|
SEVERITY warning;
|
|
END IF;
|
|
ELSIF Instruct = ABWR AND WEL = '1' THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = PPBP AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
Addr := Address;
|
|
pgm_page := Address/PageSize;
|
|
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = PPBERS AND WEL = '1' THEN
|
|
IF PPBOTP = '1' THEN
|
|
PPBERASE_in <= '1';
|
|
WIP := '1';
|
|
ELSE
|
|
E_ERR := '1';
|
|
END IF;
|
|
ELSIF Instruct = PLBWR AND WEL = '1' AND
|
|
RdPswdProtEnable = '0' THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = DYBWR AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
Addr := Address;
|
|
pgm_page := Address/PageSize;
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = PNVDLR AND WEL = '1' THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = WVDLR AND WEL = '1' THEN
|
|
VDLR_reg := VDLR_reg_in;
|
|
WEL := '0';
|
|
ELSIF Instruct = CLSR THEN
|
|
--The Clear Status Register Command resets bit SR1[5]
|
|
--(Erase Fail Flag) and bit SR1[6] (Program Fail Flag)
|
|
E_ERR := '0';
|
|
P_ERR := '0';
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = RES OR Instruct = DLPRD THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct = DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
ELSIF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF ((bus_cycle_state = DUMMY_BYTES OR
|
|
DummyBytes_act='1') AND VDLR_reg/="00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct = DDRFR OR Instruct = DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
dlp_act := FALSE;
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
SecAddr := ReturnSectorIDRdPswdMd(TBPROT);
|
|
IF RdPswdProtMode = '0' THEN
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
END IF;
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
IF mem_data /= -1 THEN
|
|
data_out := to_slv((mem_data),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;
|
|
END IF;
|
|
ELSIF Instruct = DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct = DDRDIOR OR Instruct = DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
SecAddr := ReturnSectorIDRdPswdMd(TBPROT);
|
|
IF RdPswdProtMode = '0' THEN
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
END IF;
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF ((Instruct = DDRQIOR OR Instruct = DDRQIOR4) AND
|
|
QUAD = '1') THEN
|
|
IF EHP THEN
|
|
IF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
SecAddr := ReturnSectorIDRdPswdMd(TBPROT);
|
|
IF RdPswdProtMode = '0' THEN
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
END IF;
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = OTPR THEN
|
|
IF (read_addr>=OTPLoAddr) AND
|
|
(read_addr<=OTPHiAddr) AND RdPswdProtMode = '0' THEN
|
|
--Read OTP Memory array
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
data_out := to_slv(OTPMem(read_addr),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
ELSIF (read_addr > OTPHiAddr)
|
|
OR RdPswdProtMode = '1' THEN
|
|
--OTP Read operation will not wrap to the
|
|
--starting address after the OTP address is at
|
|
--its maximum or Read Password Protection Mode
|
|
--is selected; instead, the data beyond the
|
|
--maximum OTP address will be undefined.
|
|
SOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = REMS THEN
|
|
--Read Manufacturer and Device ID
|
|
IF read_addr MOD 2 = 0 THEN
|
|
data_out := to_slv(Manuf_ID,8);
|
|
SOut_zd <= data_out(7 - read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
ELSE
|
|
data_out := to_slv(DeviceID,8);
|
|
SOut_zd <= data_out(7 - read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = RDID THEN
|
|
ident_out := CFI_array_tmp;
|
|
IF read_cnt < 648 THEN
|
|
SOut_zd <= ident_out(647-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
ELSE
|
|
--Continued shifting of output beyond the end of
|
|
--the defined ID-CFI address space will provide
|
|
--undefined data.
|
|
SOut_zd <= 'U';
|
|
END IF;
|
|
ELSIF Instruct = RES THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
data_out := to_slv(ESignature,8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = DLPRD THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= VDLR_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = ABRD THEN
|
|
--Read AutoBoot register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= AutoBoot_reg(31-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 32 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = ASPRD THEN
|
|
--Read ASP Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= ASP_reg(15-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 16 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = PASSRD THEN
|
|
--Read Password Register
|
|
IF not (PWDMLB='0' AND PSTMLB='1') THEN
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Password_reg((8*byte_cnt-1)-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
byte_cnt := byte_cnt + 1;
|
|
IF byte_cnt = 9 THEN
|
|
byte_cnt := 1;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 64 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
IF read_cnt = 0 THEN
|
|
ASSERT false
|
|
REPORT "Verification of password is not " &
|
|
" allowed in Password Protection Mode."
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = PLBRD THEN
|
|
--Read PPB Lock Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= PPBL(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = DYBRD THEN
|
|
--Read DYB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
DYBAR(7 downto 0) := "UUUUUUUU";
|
|
IF RdPswdProtMode = '0' THEN
|
|
IF DYB_bits(sect) = '1' THEN
|
|
DYBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
DYBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
END IF;
|
|
SOut_zd <= DYBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = PPBRD THEN
|
|
--Read PPB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
PPBAR(7 downto 0) := "UUUUUUUU";
|
|
IF RdPswdProtMode = '0' THEN
|
|
IF PPB_bits(sect) = '1' THEN
|
|
PPBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
PPBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
END IF;
|
|
SOut_zd <= PPBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT =>
|
|
IF start_autoboot = '1' THEN
|
|
IF (oe) THEN
|
|
any_read <= true;
|
|
IF QUAD = '1' THEN
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= false; --max SCK frequency is 104MHz
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
ELSE
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= true; --max SCK frequency is 133MHz
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF QUAD = '1' THEN
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= false; --max SCK frequency is 104MHz
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
ELSE
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= true; --max SCK frequency is 133MHz
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN WRITE_SR =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF WDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
SRWD := Status_reg1_in(7);--MSB first
|
|
|
|
IF LOCK='0' THEN
|
|
IF FREEZE='0' THEN
|
|
--The Freeze Bit, when set to 1, locks the current
|
|
--state of the BP2-0 bits in Status Register and
|
|
--the TBPROT bit in the Config Register
|
|
--As long as the FREEZE bit remains cleared to logic
|
|
--'0', the other bits of the Configuration register
|
|
--including FREEZE are writeable.
|
|
BP2 := Status_reg1_in(4);
|
|
BP1 := Status_reg1_in(3);
|
|
BP0 := Status_reg1_in(2);
|
|
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
|
|
IF TBPROT = '0' AND INITIAL_CONFIG = '0' THEN
|
|
TBPROT := Config_reg1_in(5);
|
|
END IF;
|
|
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
|
|
LC1 := Config_reg1_in(7);
|
|
LC0 := Config_reg1_in(6);
|
|
QUAD := Config_reg1_in(1);
|
|
|
|
IF FREEZE = '0' THEN
|
|
FREEZE := Config_reg1_in(0);
|
|
END IF;
|
|
|
|
IF WRLOCKENABLE AND LOCK = '0' THEN
|
|
LOCK := Config_reg1_in(4);
|
|
WRLOCKENABLE <= false;
|
|
END IF;
|
|
|
|
IF BPNV = '0' THEN
|
|
BPNV := Config_reg1_in(3);
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PAGE_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF falling_edge(PDONE) THEN
|
|
IF (Instruct = QPP OR Instruct = QPP4) THEN
|
|
QPP_page(pgm_page) := '1';
|
|
END IF;
|
|
|
|
ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr);
|
|
cnt := 0;
|
|
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
new_int := WData(i);
|
|
SecAddr := ReturnSectorID(Addr);
|
|
READ_DATA(SecAddr,
|
|
Sec_addr+i-cnt,
|
|
mem_data);
|
|
old_int := mem_data;
|
|
|
|
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;
|
|
|
|
write_mem(linked_list(SecAddr),
|
|
Sec_addr + i - cnt,
|
|
-1);
|
|
IF (Sec_addr + i) = AddrHi THEN
|
|
Sec_addr := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
cnt :=0;
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr);
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
SecAddr := ReturnSectorID(Addr);
|
|
WRITE_DATA(SecAddr,
|
|
Sec_addr + i - cnt,
|
|
WData(i));
|
|
IF (Sec_addr + i) = AddrHi THEN
|
|
Sec_addr := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
|
|
ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN
|
|
IF RES_TO_SUSP_MIN_TIME = '0' THEN
|
|
PGSUSP <= '1', '0' AFTER 1 ns;
|
|
PRGSUSP_in <= '1';
|
|
ASSERT RES_TO_SUSP_TYP_TIME = '0'
|
|
REPORT "Typical periods are needed for " &
|
|
"Program to progress to completion"
|
|
SEVERITY warning;
|
|
ELSE
|
|
ASSERT FALSE
|
|
REPORT "Minimum for tPRS is not satisfied! " &
|
|
"PGSP command is ignored"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PG_SUSP =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN
|
|
PRGSUSP_in <= '0';
|
|
--The RDY/BSY bit in the Status Register will indicate that
|
|
--the device is ready for another operation.
|
|
WIP := '0';
|
|
--The Program Suspend (PS) bit in the Status Register will
|
|
--be set to the logical “1” state to indicate that the
|
|
--program operation has been suspended.
|
|
PS := '1';
|
|
END IF;
|
|
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
--Read Array Operations
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF pgm_page /= read_addr/PageSize THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:= VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
read_cnt:=read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF pgm_page /= read_addr/PageSize THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency"&
|
|
" is set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:=VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
SIOut_zd<=data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF pgm_page /= read_addr/PageSize THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF EHP THEN
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
HOLDNegOut_zd <= 'U';
|
|
WPNegOut_zd <= 'U';
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 2 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
ELSIF falling_edge(write) THEN
|
|
IF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
-- Write to the lower address bits of the BAR
|
|
IF (P_ERR = '0' AND E_ERR = '0')THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = PGRS THEN
|
|
PGRES <= '1', '0' AFTER 5 ns;
|
|
PS := '0';
|
|
WIP := '1';
|
|
RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns;
|
|
RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us;
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND
|
|
RdPswdProtMode = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG_SUSP =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN
|
|
PRGSUSP_in <= '0';
|
|
--The RDY/BSY bit in the Status Register will indicate that
|
|
--the device is ready for another operation.
|
|
WIP := '0';
|
|
--The Program Suspend (PS) bit in the Status Register will
|
|
--be set to the logical “1” state to indicate that the
|
|
--program operation has been suspended.
|
|
PS := '1';
|
|
END IF;
|
|
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
--Read Array Operations
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF (SectorSuspend /= read_addr/(SecSize+1) AND
|
|
pgm_page /= read_addr/PageSize) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:= VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
read_cnt:=read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF (SectorSuspend /= read_addr/(SecSize+1) AND
|
|
pgm_page /= read_addr/PageSize) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency"&
|
|
" is set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:=VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
SIOut_zd<=data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF (SectorSuspend /= read_addr/(SecSize+1) AND
|
|
pgm_page /= read_addr/PageSize) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF EHP THEN
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
HOLDNegOut_zd <= 'U';
|
|
WPNegOut_zd <= 'U';
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 2 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
ELSIF falling_edge(write) THEN
|
|
IF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
-- Write to the lower address bits of the BAR
|
|
IF (P_ERR = '0' AND E_ERR = '0')THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = PGRS THEN
|
|
PGRES <= '1', '0' AFTER 5 ns;
|
|
PS := '0';
|
|
WIP := '1';
|
|
RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns;
|
|
RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us;
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND
|
|
RdPswdProtMode = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN OTP_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF Address + wr_cnt <= OTPHiAddr THEN
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
new_int := WData(i);
|
|
old_int := OTPMem(Addr + i);
|
|
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;
|
|
|
|
OTPMem(Addr + i) := -1;
|
|
END LOOP;
|
|
ELSE
|
|
ASSERT false
|
|
REPORT "Programming will reach over address limit"&
|
|
" of OTP array"
|
|
SEVERITY warning;
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
OTPMem(Addr_tmp + i) := WData(i);
|
|
END LOOP;
|
|
LOCK_BYTE1 := to_slv(OTPMem(16#10#),8);
|
|
LOCK_BYTE2 := to_slv(OTPMem(16#11#),8);
|
|
LOCK_BYTE3 := to_slv(OTPMem(16#12#),8);
|
|
LOCK_BYTE4 := to_slv(OTPMem(16#13#),8);
|
|
END IF;
|
|
|
|
WHEN SECTOR_ERS =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
SecAddr := ReturnSectorID(Addr);
|
|
Corrupt_Sec(SecAddr) := '1';
|
|
erase_mem(
|
|
0,
|
|
SecSize,
|
|
linked_list(SecAddr)
|
|
);
|
|
|
|
IF EDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
Corrupt_Sec(SecAddr) := '0';
|
|
erase_mem(
|
|
0,
|
|
SecSize,
|
|
linked_list(SecAddr)
|
|
);
|
|
ELSIF Instruct = ERSP AND ERSSUSP_in = '0' THEN
|
|
ESUSP <= '1', '0' AFTER 10 ns;
|
|
ERSSUSP_in <= '1';
|
|
ASSERT RES_TO_SUSP_TYP_TIME = '0'
|
|
REPORT "Typical periods are needed for " &
|
|
"Program to progress to completion"
|
|
SEVERITY warning;
|
|
END IF;
|
|
|
|
WHEN BULK_ERS =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF falling_edge(EDONE) THEN
|
|
FOR i IN 0 TO SecNum LOOP
|
|
IF PPB_bits(i) = '1' AND DYB_bits(i) = '1' THEN
|
|
Corrupt_Sec(i) := '1';
|
|
erase_mem(
|
|
0,
|
|
SecSize,
|
|
linked_list(i)
|
|
);
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
IF EDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN 0 TO SecNum LOOP
|
|
IF PPB_bits(i) = '1' AND DYB_bits(i) = '1' THEN
|
|
Corrupt_Sec(i) := '0';
|
|
erase_mem(
|
|
0,
|
|
SecSize,
|
|
linked_list(i)
|
|
);
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF ERSSUSP_out = '1' THEN
|
|
ERSSUSP_in <= '0';
|
|
--The Erase Suspend (ES) bit in the Status Register will
|
|
--be set to the logical “1” state to indicate that the
|
|
--erase operation has been suspended.
|
|
ES := '1';
|
|
--The WIP bit in the Status Register will indicate that
|
|
--the device is ready for another operation.
|
|
WIP := '0';
|
|
END IF;
|
|
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = DYBRD THEN
|
|
--Read DYB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF DYB_bits(sect) = '1' THEN
|
|
DYBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
DYBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
SOut_zd <= DYBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = PPBRD THEN
|
|
--Read PPB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
PPBAR(7 downto 0) := "UUUUUUUU";
|
|
IF RdPswdProtMode = '0' THEN
|
|
IF PPB_bits(sect) = '1' THEN
|
|
PPBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
PPBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
END IF;
|
|
SOut_zd <= PPBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
--Read Array Operations
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF SectorSuspend /= read_addr/(SecSize+1) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:= VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
read_cnt:=read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF SectorSuspend /= read_addr/(SecSize+1) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency"&
|
|
" is set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:=VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
SIOut_zd<=data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF SectorSuspend /= read_addr/(SecSize+1) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF EHP THEN
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
data_out := to_slv((mem_data),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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
HOLDNegOut_zd <= 'U';
|
|
WPNegOut_zd <= 'U';
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 2 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF falling_edge(write) THEN
|
|
IF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF SectorSuspend /= sect THEN
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
WIP := '1' ;
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF SectorSuspend /= sect THEN
|
|
IF (Sec_Prot(sect)='0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
WIP := '1' ;
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSIF Instruct = WREN THEN
|
|
WEL := '1';
|
|
ELSIF Instruct = CLSR THEN
|
|
--The Clear Status Register Command resets bit SR1[5]
|
|
--(Erase Fail Flag) and bit SR1[6] (Program Fail Flag)
|
|
E_ERR := '0';
|
|
P_ERR := '0';
|
|
ELSIF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
-- Write to the lower address bits of the BAR
|
|
IF (P_ERR = '0' AND E_ERR = '0')THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = DYBWR AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = ERRS THEN
|
|
ERES <= '1', '0' AFTER 5 ns;
|
|
ES := '0';
|
|
WIP := '1';
|
|
Addr := SectorSuspend*(SecSize+1);
|
|
ADDRHILO_SEC(AddrLo, AddrHi, Addr);
|
|
RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us;
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND
|
|
RdPswdProtMode = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF (Instruct = QPP OR Instruct = QPP4) THEN
|
|
QPP_page(pgm_page) := '1';
|
|
END IF;
|
|
|
|
ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr);
|
|
cnt := 0;
|
|
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
new_int := WData(i);
|
|
SecAddr := ReturnSectorID(Addr + i - cnt);
|
|
Sec_addr := Addr + i - cnt - SecAddr*(SecSize+1);
|
|
READ_DATA(SecAddr,Sec_addr,mem_data);
|
|
old_int := mem_data;
|
|
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 (Addr + i) = AddrHi THEN
|
|
Addr := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
cnt :=0;
|
|
|
|
IF PDONE = '1' THEN
|
|
ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr);
|
|
SecAddr := ReturnSectorID(Addr);
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
WRITE_DATA(SecAddr,
|
|
Sec_addr + i - cnt,
|
|
WData(i));
|
|
IF (Sec_addr + i) = AddrHi THEN
|
|
Sec_addr := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN
|
|
IF RES_TO_SUSP_MIN_TIME = '0' THEN
|
|
PGSUSP <= '1', '0' AFTER 1 ns;
|
|
PRGSUSP_in <= '1';
|
|
ASSERT RES_TO_SUSP_TYP_TIME = '0'
|
|
REPORT "Typical periods are needed for " &
|
|
"Program to progress to completion"
|
|
SEVERITY warning;
|
|
ELSE
|
|
ASSERT FALSE
|
|
REPORT "Minimum for tPRS is not satisfied! " &
|
|
"PGSP command is ignored"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PASS_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
new_pass := Password_reg_in;
|
|
old_pass := Password_reg;
|
|
FOR j IN 0 TO 63 LOOP
|
|
IF old_pass(j) = '0' THEN
|
|
new_pass(j) := '0';
|
|
END IF;
|
|
END LOOP;
|
|
|
|
IF PDONE = '1' THEN
|
|
Password_reg := new_pass;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN PASS_UNLOCK =>
|
|
WIP := '1';
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PASS_TEMP = Password_reg THEN
|
|
PASS_UNLOCKED <= TRUE;
|
|
ELSE
|
|
PASS_UNLOCKED <= FALSE;
|
|
END IF;
|
|
|
|
IF PASSULCK_out = '1' THEN
|
|
IF PASS_UNLOCKED AND PWDMLB = '0' THEN
|
|
PPB_LOCK := '1';
|
|
PPB_LOCK_temp <= '1';
|
|
WIP := '0';
|
|
ELSE
|
|
P_ERR := '1';
|
|
REPORT "Incorrect Password!"
|
|
SEVERITY warning;
|
|
PASSACC_in <= '1';
|
|
END IF;
|
|
WEL := '0';
|
|
PASSULCK_in <= '0';
|
|
END IF;
|
|
|
|
WHEN PPB_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
IF PPB_LOCK /= '0' THEN
|
|
PPB_bits(sect):= '0';
|
|
WIP := '0';
|
|
WEL := '0';
|
|
ELSE
|
|
P_ERR := '0';
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PPB_ERS =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PPBERASE_out = '1' THEN
|
|
IF PPB_LOCK /= '0' AND PPBOTP = '1' THEN
|
|
PPB_bits:= (OTHERS => '1');
|
|
ELSE
|
|
E_ERR := '1';
|
|
END IF;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
PPBERASE_in <= '0';
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
AutoBoot_reg := AutoBoot_reg_in;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN PLB_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
PPB_LOCK := '0';
|
|
PPB_LOCK_temp <= '0';
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN DYB_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
DYBAR := DYBAR_in;
|
|
IF DYBAR = "11111111" THEN
|
|
DYB_bits(sect):= '1';
|
|
ELSIF DYBAR = "00000000" THEN
|
|
DYB_bits(sect):= '0';
|
|
ELSE
|
|
P_ERR := '1';
|
|
END IF;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN ASP_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
|
|
IF (RPME = '0' AND ASP_reg_in(5) = '1') THEN
|
|
P_ERR := '1';
|
|
REPORT "RPME bit is allready programmed"
|
|
SEVERITY warning;
|
|
ELSE
|
|
RPME := ASP_reg_in(5);
|
|
END IF;
|
|
|
|
IF (PPBOTP = '0' AND ASP_reg_in(3) ='1') THEN
|
|
P_ERR := '1';
|
|
REPORT "PPBOTP bit is allready programmed"
|
|
SEVERITY warning;
|
|
ELSE
|
|
PPBOTP := ASP_reg_in(3);
|
|
END IF;
|
|
|
|
IF (PWDMLB = '1' AND PSTMLB = '1') THEN
|
|
IF (ASP_reg_in(2) = '0' AND ASP_reg_in(1) = '0') THEN
|
|
REPORT "ASPR[2:1] = 00 Illegal condition"
|
|
SEVERITY warning;
|
|
P_ERR := '1';
|
|
ELSE
|
|
IF (ASP_reg_in(2) /= '1' OR
|
|
ASP_reg_in(1) /= '1') THEN
|
|
ASPOTPFLAG <= TRUE;
|
|
END IF;
|
|
PWDMLB := ASP_reg_in(2);
|
|
PSTMLB := ASP_reg_in(1);
|
|
END IF;
|
|
END IF;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN NVDLR_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
IF NVDLR_reg = "00000000" THEN
|
|
NVDLR_reg :=NVDLR_reg_in;
|
|
VDLR_reg := NVDLR_reg_in;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
ELSE
|
|
WIP := '0';
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
REPORT "NVDLR is allready programmed"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN RESET_STATE =>
|
|
--the default condition hardware reset
|
|
--The Bank Address Register is loaded to all zeroes
|
|
Bank_Addr_reg := (others => '0');
|
|
IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN
|
|
BP0 := '1';
|
|
BP1 := '1';
|
|
BP2 := '1';
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
--Resets the Status register 1
|
|
P_ERR := '0';
|
|
E_ERR := '0';
|
|
WEL := '0';
|
|
WIP := '0';
|
|
--Resets the Status register 2
|
|
ES := '0';
|
|
PS := '0';
|
|
--Resets the Configuration register 1
|
|
FREEZE := '0';
|
|
--On reset cycles the data pattern reverts back
|
|
--to what is in the NVDLR
|
|
VDLR_reg := NVDLR_reg;
|
|
dlp_act := FALSE;
|
|
--Loads the Program Buffer with all ones
|
|
WData := (OTHERS => MaxData);
|
|
|
|
IF PWDMLB = '0' THEN
|
|
PPB_LOCK := '0';
|
|
PPB_LOCK_temp <= '0';
|
|
ELSE
|
|
PPB_LOCK := '1';
|
|
PPB_LOCK_temp <= '1';
|
|
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;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- CFI Process
|
|
---------------------------------------------------------------------------
|
|
CFIPreload: PROCESS
|
|
|
|
BEGIN
|
|
------------------------------------------------------------------------
|
|
--CFI array data
|
|
------------------------------------------------------------------------
|
|
-- Manufacturer and Device ID
|
|
CFI_array(16#00#) := 16#01#;
|
|
CFI_array(16#01#) := 16#02#;
|
|
CFI_array(16#02#) := 16#20#;
|
|
CFI_array(16#03#) := 16#00#;
|
|
CFI_array(16#04#) := 16#00#;--Uniform 256KB sectors
|
|
CFI_array(16#05#) := 16#80#;
|
|
CFI_array(16#06#) := 16#00#;
|
|
CFI_array(16#07#) := 16#00#;
|
|
CFI_array(16#08#) := 16#00#;
|
|
CFI_array(16#09#) := 16#00#;
|
|
CFI_array(16#0A#) := 16#00#;
|
|
CFI_array(16#0B#) := 16#00#;
|
|
CFI_array(16#0C#) := 16#00#;
|
|
CFI_array(16#0D#) := 16#00#;
|
|
CFI_array(16#0E#) := 16#00#;
|
|
CFI_array(16#0F#) := 16#00#;
|
|
--CFI Query Identification String
|
|
CFI_array(16#10#) := 16#51#;
|
|
CFI_array(16#11#) := 16#52#;
|
|
CFI_array(16#12#) := 16#59#;
|
|
CFI_array(16#13#) := 16#02#;
|
|
CFI_array(16#14#) := 16#00#;
|
|
CFI_array(16#15#) := 16#40#;
|
|
CFI_array(16#16#) := 16#00#;
|
|
CFI_array(16#17#) := 16#53#;
|
|
CFI_array(16#18#) := 16#46#;
|
|
CFI_array(16#19#) := 16#51#;
|
|
CFI_array(16#1A#) := 16#00#;
|
|
--CFI system interface string
|
|
CFI_array(16#1B#) := 16#27#;
|
|
CFI_array(16#1C#) := 16#36#;
|
|
CFI_array(16#1D#) := 16#00#;
|
|
CFI_array(16#1E#) := 16#00#;
|
|
CFI_array(16#1F#) := 16#06#;
|
|
CFI_array(16#20#) := 16#09#;-- 512B page
|
|
CFI_array(16#21#) := 16#09#;-- 256KB
|
|
CFI_array(16#22#) := 16#11#;
|
|
CFI_array(16#23#) := 16#02#;
|
|
CFI_array(16#24#) := 16#02#;
|
|
CFI_array(16#25#) := 16#03#;
|
|
CFI_array(16#26#) := 16#03#;
|
|
-- Device Geometry Definition
|
|
CFI_array(16#27#) := 16#1A#;
|
|
CFI_array(16#28#) := 16#02#;
|
|
CFI_array(16#29#) := 16#01#;
|
|
CFI_array(16#2A#) := 16#09#;
|
|
CFI_array(16#2B#) := 16#00#;
|
|
CFI_array(16#2C#) := 16#01#;
|
|
CFI_array(16#2D#) := 16#FF#;
|
|
CFI_array(16#2E#) := 16#00#;
|
|
CFI_array(16#2F#) := 16#00#;
|
|
CFI_array(16#30#) := 16#04#;
|
|
CFI_array(16#31#) := 16#FF#;
|
|
CFI_array(16#32#) := 16#FF#;
|
|
CFI_array(16#33#) := 16#FF#;
|
|
CFI_array(16#34#) := 16#FF#;
|
|
CFI_array(16#35#) := 16#FF#;
|
|
CFI_array(16#36#) := 16#FF#;
|
|
CFI_array(16#37#) := 16#FF#;
|
|
CFI_array(16#38#) := 16#FF#;
|
|
CFI_array(16#39#) := 16#FF#;
|
|
CFI_array(16#3A#) := 16#FF#;
|
|
CFI_array(16#3B#) := 16#FF#;
|
|
CFI_array(16#3C#) := 16#FF#;
|
|
CFI_array(16#3D#) := 16#FF#;
|
|
CFI_array(16#3E#) := 16#FF#;
|
|
CFI_array(16#3F#) := 16#FF#;
|
|
-- CFI Primary Vendor-Specific Extended Query
|
|
CFI_array(16#40#) := 16#50#;
|
|
CFI_array(16#41#) := 16#52#;
|
|
CFI_array(16#42#) := 16#49#;
|
|
CFI_array(16#43#) := 16#31#;
|
|
CFI_array(16#44#) := 16#33#;
|
|
CFI_array(16#45#) := 16#21#;
|
|
CFI_array(16#46#) := 16#02#;
|
|
CFI_array(16#47#) := 16#01#;
|
|
CFI_array(16#48#) := 16#00#;
|
|
CFI_array(16#49#) := 16#08#;
|
|
|
|
CFI_array(16#4A#) := 16#00#;
|
|
CFI_array(16#4B#) := 16#01#;
|
|
CFI_array(16#4C#) := 16#04#;
|
|
CFI_array(16#4D#) := 16#00#;
|
|
CFI_array(16#4E#) := 16#00#;
|
|
CFI_array(16#4F#) := 16#07#;
|
|
CFI_array(16#50#) := 16#01#;
|
|
|
|
CFI_array_tmp :=to_slv(CFI_array(16#00#), 8) &
|
|
to_slv(CFI_array(16#01#), 8) &
|
|
to_slv(CFI_array(16#02#), 8) &
|
|
to_slv(CFI_array(16#03#), 8) &
|
|
to_slv(CFI_array(16#04#), 8) &
|
|
to_slv(CFI_array(16#05#), 8) &
|
|
to_slv(CFI_array(16#06#), 8) &
|
|
to_slv(CFI_array(16#07#), 8) &
|
|
to_slv(CFI_array(16#08#), 8) &
|
|
to_slv(CFI_array(16#09#), 8) &
|
|
to_slv(CFI_array(16#0A#), 8) &
|
|
to_slv(CFI_array(16#0B#), 8) &
|
|
to_slv(CFI_array(16#0C#), 8) &
|
|
to_slv(CFI_array(16#0D#), 8) &
|
|
to_slv(CFI_array(16#0E#), 8) &
|
|
to_slv(CFI_array(16#0F#), 8) &
|
|
to_slv(CFI_array(16#10#), 8) &
|
|
to_slv(CFI_array(16#11#), 8) &
|
|
to_slv(CFI_array(16#12#), 8) &
|
|
to_slv(CFI_array(16#13#), 8) &
|
|
to_slv(CFI_array(16#14#), 8) &
|
|
to_slv(CFI_array(16#15#), 8) &
|
|
to_slv(CFI_array(16#16#), 8) &
|
|
to_slv(CFI_array(16#17#), 8) &
|
|
to_slv(CFI_array(16#18#), 8) &
|
|
to_slv(CFI_array(16#19#), 8) &
|
|
to_slv(CFI_array(16#1A#), 8) &
|
|
to_slv(CFI_array(16#1B#), 8) &
|
|
to_slv(CFI_array(16#1C#), 8) &
|
|
to_slv(CFI_array(16#1D#), 8) &
|
|
to_slv(CFI_array(16#1E#), 8) &
|
|
to_slv(CFI_array(16#1F#), 8) &
|
|
to_slv(CFI_array(16#20#), 8) &
|
|
to_slv(CFI_array(16#21#), 8) &
|
|
to_slv(CFI_array(16#22#), 8) &
|
|
to_slv(CFI_array(16#23#), 8) &
|
|
to_slv(CFI_array(16#24#), 8) &
|
|
to_slv(CFI_array(16#25#), 8) &
|
|
to_slv(CFI_array(16#26#), 8) &
|
|
to_slv(CFI_array(16#27#), 8) &
|
|
to_slv(CFI_array(16#28#), 8) &
|
|
to_slv(CFI_array(16#29#), 8) &
|
|
to_slv(CFI_array(16#2A#), 8) &
|
|
to_slv(CFI_array(16#2B#), 8) &
|
|
to_slv(CFI_array(16#2C#), 8) &
|
|
to_slv(CFI_array(16#2D#), 8) &
|
|
to_slv(CFI_array(16#2E#), 8) &
|
|
to_slv(CFI_array(16#2F#), 8) &
|
|
to_slv(CFI_array(16#30#), 8) &
|
|
to_slv(CFI_array(16#31#), 8) &
|
|
to_slv(CFI_array(16#32#), 8) &
|
|
to_slv(CFI_array(16#33#), 8) &
|
|
to_slv(CFI_array(16#34#), 8) &
|
|
to_slv(CFI_array(16#35#), 8) &
|
|
to_slv(CFI_array(16#36#), 8) &
|
|
to_slv(CFI_array(16#37#), 8) &
|
|
to_slv(CFI_array(16#38#), 8) &
|
|
to_slv(CFI_array(16#39#), 8) &
|
|
to_slv(CFI_array(16#3A#), 8) &
|
|
to_slv(CFI_array(16#3B#), 8) &
|
|
to_slv(CFI_array(16#3C#), 8) &
|
|
to_slv(CFI_array(16#3D#), 8) &
|
|
to_slv(CFI_array(16#3E#), 8) &
|
|
to_slv(CFI_array(16#3F#), 8) &
|
|
to_slv(CFI_array(16#40#), 8) &
|
|
to_slv(CFI_array(16#41#), 8) &
|
|
to_slv(CFI_array(16#42#), 8) &
|
|
to_slv(CFI_array(16#43#), 8) &
|
|
to_slv(CFI_array(16#44#), 8) &
|
|
to_slv(CFI_array(16#45#), 8) &
|
|
to_slv(CFI_array(16#46#), 8) &
|
|
to_slv(CFI_array(16#47#), 8) &
|
|
to_slv(CFI_array(16#48#), 8) &
|
|
to_slv(CFI_array(16#49#), 8) &
|
|
to_slv(CFI_array(16#4A#), 8) &
|
|
to_slv(CFI_array(16#4B#), 8) &
|
|
to_slv(CFI_array(16#4C#), 8) &
|
|
to_slv(CFI_array(16#4D#), 8) &
|
|
to_slv(CFI_array(16#4E#), 8) &
|
|
to_slv(CFI_array(16#4F#), 8) &
|
|
to_slv(CFI_array(16#50#), 8);
|
|
|
|
WAIT;
|
|
|
|
END PROCESS CFIPreload;
|
|
|
|
AspRegInit: PROCESS(ASP_INIT)
|
|
BEGIN
|
|
IF ASP_INIT = 0 THEN
|
|
ASP_reg := to_slv(16#FE4F#,16);
|
|
ELSE
|
|
ASP_reg := to_slv(16#FE7F#,16);
|
|
END IF;
|
|
END PROCESS AspRegInit;
|
|
|
|
Protect : PROCESS(change_BP)
|
|
BEGIN
|
|
IF rising_edge(change_BP) THEN
|
|
|
|
CASE BP_bits IS
|
|
WHEN "000" =>
|
|
Sec_Prot := (OTHERS => '0');
|
|
WHEN "001" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*63/64)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*63/64 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/64 - 1 downto 0)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/64)
|
|
:= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "010" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*31/32)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*31/32 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/32 - 1 downto 0)
|
|
:= (others => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/32)
|
|
:= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "011" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*15/16)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*15/16 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/16 - 1 downto 0)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/16)
|
|
:= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "100" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*7/8)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*7/8 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/8 - 1 downto 0) := (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/8):= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "101" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*3/4)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*3/4 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/4 - 1 downto 0) := (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/4):= (OTHERS => '0');
|
|
END IF;
|
|
|
|
WHEN "110" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '0');
|
|
END IF;
|
|
|
|
WHEN OTHERS =>
|
|
Sec_Prot := (OTHERS => '1');
|
|
END CASE;
|
|
END IF;
|
|
END PROCESS Protect;
|
|
|
|
HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup)
|
|
BEGIN
|
|
IF (HOLDNeg_pullup = '0' AND QUAD /= '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 (QUAD = '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 (QUAD = '0') THEN
|
|
IF (WPNegIn = 'Z') THEN
|
|
WPNeg_pullup <= '1';
|
|
ELSE
|
|
WPNeg_pullup <= WPNegIn;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS WP_PULL_UP;
|
|
|
|
RST_PULL_UP : PROCESS(RSTNeg)
|
|
BEGIN
|
|
IF (RSTNeg = 'Z') THEN
|
|
RSTNeg_pullup <= '1';
|
|
ELSE
|
|
RSTNeg_pullup <= RSTNeg;
|
|
END IF;
|
|
END PROCESS RST_PULL_UP;
|
|
|
|
---------------------------------------------------------------------------
|
|
---- File Read Section - Preload Control
|
|
---------------------------------------------------------------------------
|
|
MemPreload : PROCESS
|
|
|
|
-- text file input variables
|
|
FILE mem_file : text is mem_file_name;
|
|
FILE otp_file : text is otp_file_name;
|
|
VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0;
|
|
VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0;
|
|
VARIABLE index : NATURAL RANGE 0 TO SecSize:=0;
|
|
VARIABLE otp_ind : NATURAL RANGE 16#000# TO 16#3FF# := 16#000#;
|
|
VARIABLE buf : line;
|
|
VARIABLE reported : NATURAL;
|
|
VARIABLE mem_data : INTEGER;
|
|
|
|
BEGIN
|
|
---------------------------------------------------------------------------
|
|
--s25fl512s memory preload file format
|
|
-----------------------------------
|
|
---------------------------------------------------------------------------
|
|
-- / - comment
|
|
-- @aaaaaa - <aaaaaa> stands for address
|
|
-- dd - <dd> is byte to be written at Mem(aaaaaa++)
|
|
-- (aaaaaa is incremented at every load)
|
|
-- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!!
|
|
---------------------------------------------------------------------------
|
|
-- memory preload
|
|
configure_memory(16#FF#);
|
|
initialize;
|
|
IF (mem_file_name /= "none" AND UserPreload ) THEN
|
|
ind := 0;
|
|
reported := 0;
|
|
WHILE (not ENDFILE (mem_file)) LOOP
|
|
READLINE (mem_file, buf);
|
|
IF buf(1) = '/' THEN --comment
|
|
NEXT;
|
|
ELSIF buf(1) = '@' THEN --address
|
|
ind := h(buf(2 to 8));
|
|
ELSE
|
|
IF ind <= AddrRANGE THEN
|
|
mem_data := h(buf(1 to 2));
|
|
IF ind=0 THEN
|
|
S_ind := 0;
|
|
index := 0;
|
|
ELSIF ind < SecSize+1 THEN
|
|
S_ind := 0;
|
|
index := ind;
|
|
ELSE
|
|
S_ind := NATURAL(ind / (SecSize +1));
|
|
index := ind - S_ind*(SecSize+1);
|
|
END IF;
|
|
WRITE_DATA(S_ind,index,mem_data);
|
|
IF ind < AddrRANGE THEN
|
|
ind := ind + 1;
|
|
END IF;
|
|
ELSIF reported = 0 THEN
|
|
REPORT " Memory address out of range"
|
|
SEVERITY warning;
|
|
reported := 1;
|
|
END IF;
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
---------------------------------------------------------------------------
|
|
--s25fl512s_otp memory preload file format
|
|
---------------------------------------------------------------------------
|
|
-- / - comment
|
|
-- @aaa - <aaa> stands for address
|
|
-- dd - <dd> is byte to be written at OTPMem(aaa++)
|
|
-- (aaa is incremented at every load)
|
|
-- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!!
|
|
---------------------------------------------------------------------------
|
|
|
|
-- memory preload
|
|
IF (otp_file_name /= "none" AND UserPreload) THEN
|
|
otp_ind := 16#000#;
|
|
OTPMem := (OTHERS => MaxData);
|
|
WHILE (not ENDFILE (otp_file)) LOOP
|
|
READLINE (otp_file, buf);
|
|
IF buf(1) = '/' THEN
|
|
NEXT;
|
|
ELSIF buf(1) = '@' THEN
|
|
IF otp_ind > 16#3FF# OR otp_ind < 16#000# THEN
|
|
ASSERT false
|
|
REPORT "Given preload address is out of" &
|
|
"OTP address range"
|
|
SEVERITY warning;
|
|
ELSE
|
|
otp_ind := h(buf(2 to 4)); --address
|
|
END IF;
|
|
ELSE
|
|
OTPMem(otp_ind) := h(buf(1 to 2));
|
|
otp_ind := otp_ind + 1;
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
LOCK_BYTE1 := to_slv(OTPMem(16#10#),8);
|
|
LOCK_BYTE2 := to_slv(OTPMem(16#11#),8);
|
|
LOCK_BYTE3 := to_slv(OTPMem(16#12#),8);
|
|
LOCK_BYTE4 := to_slv(OTPMem(16#13#),8);
|
|
|
|
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_normal),
|
|
PathCondition => NOT(ddr)),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => (ddr OR fast_rd)),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1'),
|
|
3 => (InputChangeTime => HOLDNegIn'LAST_EVENT,
|
|
PathDelay => tpd_HOLDNeg_SO,
|
|
PathCondition => QUAD = '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_normal),
|
|
PathCondition => dual AND NOT(ddr)),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => dual AND ddr),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1'),
|
|
3 => (InputChangeTime => HOLDNegIn'LAST_EVENT,
|
|
PathDelay => tpd_HOLDNeg_SO,
|
|
PathCondition => dual AND QUAD = '0')
|
|
)
|
|
);
|
|
END PROCESS;
|
|
|
|
HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd)
|
|
|
|
VARIABLE HOLD_GlitchData : VitalGlitchDataType;
|
|
BEGIN
|
|
VitalPathDelay01Z (
|
|
OutSignal => HOLDNegOut,
|
|
OutSignalName => "HOLDNeg",
|
|
OutTemp => HOLDNegOut_zd,
|
|
Mode => VitalTransport,
|
|
GlitchData => HOLD_GlitchData,
|
|
Paths => (
|
|
0 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal),
|
|
PathCondition => dual AND not(ddr) AND QUAD = '1'),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => ddr AND QUAD = '1'),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1' AND
|
|
HOLDNegOut_zd = 'Z' AND QUAD = '1')
|
|
)
|
|
);
|
|
END PROCESS;
|
|
|
|
WP_Out_PathDelay : PROCESS(WPNegOut_zd)
|
|
|
|
VARIABLE WP_GlitchData : VitalGlitchDataType;
|
|
BEGIN
|
|
VitalPathDelay01Z (
|
|
OutSignal => WPNegOut,
|
|
OutSignalName => "WPNeg",
|
|
OutTemp => WPNegOut_zd,
|
|
Mode => VitalTransport,
|
|
GlitchData => WP_GlitchData,
|
|
Paths => (
|
|
0 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal),
|
|
PathCondition => dual AND not(ddr) AND QUAD = '1'),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => ddr AND QUAD = '1'),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1' AND
|
|
WPNegOut_zd = 'Z' AND QUAD = '1')
|
|
)
|
|
);
|
|
END PROCESS;
|
|
|
|
END BLOCK behavior;
|
|
END vhdl_behavioral_dynamic_memory_allocation;
|
|
ARCHITECTURE vhdl_behavioral_static_memory_allocation of s25fl512s IS
|
|
ATTRIBUTE VITAL_LEVEL0 OF
|
|
vhdl_behavioral_static_memory_allocation : 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 := "s25fl512s";
|
|
CONSTANT MaxData : NATURAL := 16#FF#; --255;
|
|
CONSTANT MemSize : NATURAL := 16#3FFFFFF#;
|
|
CONSTANT SecNum : NATURAL := 255;
|
|
CONSTANT SecSize : NATURAL := 16#3FFFF#; --256KB
|
|
CONSTANT PageNum : NATURAL := 16#1FFFF#;
|
|
CONSTANT PageSize : NATURAL := 512;
|
|
CONSTANT AddrRANGE : NATURAL := 16#3FFFFFF#;
|
|
CONSTANT HiAddrBit : NATURAL := 31;
|
|
CONSTANT OTPSize : NATURAL := 1023;
|
|
CONSTANT OTPLoAddr : NATURAL := 16#000#;
|
|
CONSTANT OTPHiAddr : NATURAL := 16#3FF#;
|
|
CONSTANT BYTE : NATURAL := 8;
|
|
|
|
--Manufacturer Identification
|
|
CONSTANT Manuf_ID : NATURAL := 16#01#;
|
|
CONSTANT DeviceID : NATURAL := 16#19#;
|
|
--Electronic Signature
|
|
CONSTANT ESignature : NATURAL := 16#19#;
|
|
--Device ID
|
|
--Manufacturer Identification && Memory Type && Memory Capacity
|
|
CONSTANT Jedec_ID : NATURAL := 16#01#; -- first byte of Device ID
|
|
CONSTANT DeviceID1 : NATURAL := 16#02#;
|
|
CONSTANT DeviceID2 : NATURAL := 16#20#;
|
|
CONSTANT ExtendedBytes : NATURAL := 16#4D#;
|
|
CONSTANT ExtendedID : NATURAL := 16#00#;
|
|
CONSTANT DieRev : NATURAL := 16#00#;
|
|
CONSTANT MaskRev : NATURAL := 16#00#;
|
|
|
|
-- 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 RSTNeg_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';
|
|
SIGNAL RSTNeg_pullup : std_ulogic := 'U';
|
|
|
|
-- internal delays
|
|
SIGNAL PP_in : std_ulogic := '0';
|
|
SIGNAL PP_out : std_ulogic := '0';
|
|
SIGNAL BP_in : std_ulogic := '0';
|
|
SIGNAL BP_out : std_ulogic := '0';
|
|
SIGNAL SE_in : std_ulogic := '0';
|
|
SIGNAL SE_out : std_ulogic := '0';
|
|
SIGNAL BE_in : std_ulogic := '0';
|
|
SIGNAL BE_out : std_ulogic := '0';
|
|
SIGNAL WRR_in : std_ulogic := '0';
|
|
SIGNAL WRR_out : std_ulogic := '0';
|
|
SIGNAL ERSSUSP_in : std_ulogic := '0';
|
|
SIGNAL ERSSUSP_out : std_ulogic := '0';
|
|
SIGNAL PRGSUSP_in : std_ulogic := '0';
|
|
SIGNAL PRGSUSP_out : std_ulogic := '0';
|
|
SIGNAL PU_in : std_ulogic := '0';
|
|
SIGNAL PU_out : std_ulogic := '0';
|
|
SIGNAL RST_in : std_ulogic := '0';-- Hardware Reset Timeout
|
|
SIGNAL RST_out : std_ulogic := '1';--
|
|
SIGNAL PPBERASE_in : std_ulogic := '0';
|
|
SIGNAL PPBERASE_out : std_ulogic := '0';
|
|
SIGNAL PASSULCK_in : std_ulogic := '0';
|
|
SIGNAL PASSULCK_out : std_ulogic := '0';
|
|
SIGNAL PASSACC_in : std_ulogic := '0';
|
|
SIGNAL PASSACC_out : std_ulogic := '0';
|
|
|
|
FUNCTION ReturnSectorID(ADDR : NATURAL) RETURN NATURAL IS
|
|
VARIABLE result : NATURAL;
|
|
BEGIN
|
|
IF ADDR <= AddrRange THEN
|
|
result := ADDR / (SecSize+1);
|
|
ELSE
|
|
result := SecNum+1;
|
|
END IF;
|
|
RETURN result;
|
|
END ReturnSectorID;
|
|
|
|
FUNCTION ReturnSectorIDRdPswdMd(TBPROT : std_logic) RETURN NATURAL IS
|
|
VARIABLE result : NATURAL;
|
|
BEGIN
|
|
result := SecNum;
|
|
IF TBPROT = '0' THEN
|
|
result := 0;
|
|
END IF;
|
|
RETURN result;
|
|
END ReturnSectorIDRdPswdMd;
|
|
|
|
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));
|
|
BP :VitalBuf(BP_out, BP_in, (tdevice_BP ,UnitDelay));
|
|
SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay));
|
|
BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay));
|
|
WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay));
|
|
ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay));
|
|
PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay));
|
|
PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay));
|
|
PPBERASE :VitalBuf(PPBERASE_out,PPBERASE_in,(tdevice_PPBERASE,UnitDelay));
|
|
PASSULCK :VitalBuf(PASSULCK_out,PASSULCK_in,(tdevice_PASSULCK,UnitDelay));
|
|
PASSACC :VitalBuf(PASSACC_out, PASSACC_in, (tdevice_PASSACC ,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_5 : VitalWireDelay (RSTNeg_ipd, RSTNeg, tipd_RSTNeg);
|
|
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';
|
|
RSTNeg : 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,
|
|
RSTNeg => RSTNeg_ipd,
|
|
HOLDNegIn => HOLDNeg_ipd,
|
|
HOLDNegOut => HOLDNeg,
|
|
WPNegIn => WPNeg_ipd,
|
|
WPNegOut => WPNeg
|
|
);
|
|
|
|
-- State Machine : State_Type
|
|
TYPE state_type IS (IDLE,
|
|
RESET_STATE,
|
|
AUTOBOOT,
|
|
WRITE_SR,
|
|
PAGE_PG,
|
|
OTP_PG,
|
|
PG_SUSP,
|
|
SECTOR_ERS,
|
|
BULK_ERS,
|
|
ERS_SUSP,
|
|
ERS_SUSP_PG,
|
|
ERS_SUSP_PG_SUSP,
|
|
PASS_PG,
|
|
PASS_UNLOCK,
|
|
PPB_PG,
|
|
PPB_ERS,
|
|
AUTOBOOT_PG,
|
|
ASP_PG,
|
|
PLB_PG,
|
|
DYB_PG,
|
|
NVDLR_PG
|
|
);
|
|
|
|
-- Instruction Type
|
|
TYPE instruction_type IS ( NONE,
|
|
WREN, -- Write Enable
|
|
WRDI, -- Write Disable
|
|
WRR, -- Write Register
|
|
READ, -- Read Normal (3Byte Address)
|
|
RD4, -- Read Normal (4Byte +)
|
|
OTPR, -- OTP Read
|
|
RDSR, -- Read Status Register 1
|
|
RDSR2, -- Read Status Register 2
|
|
RDCR, -- Read Configuration Register 1
|
|
REMS, -- Read ID (SST)
|
|
RDID, -- Read ID JEDEC
|
|
RES, -- Read ID
|
|
FSTRD, -- Fast Read (3Byte Address)
|
|
FSTRD4, -- Fast Read (4Byte +)
|
|
DDRFR, -- Fast Read DDR (3Byte Address)
|
|
DDRFR4, -- Fast Read DDR (4Byte +)
|
|
DOR, -- Read Dual Out (3Byte Address)
|
|
DOR4, -- Read Dual Out (4Byte +)
|
|
DIOR, -- Read Dual I/O (3Byte Address)
|
|
DIOR4, -- Read Dual I/O (4Byte +)
|
|
DDRDIOR, -- Read DDR Dual I/O (3Byte)
|
|
DDRDIOR4, -- Read DDR Dual I/O (4Byte +)
|
|
QOR, -- Read Quad Out (3Byte Address)
|
|
QOR4, -- Read Quad Out (4Byte +)
|
|
QIOR, -- Read Quad I/O (3Byte Address)
|
|
QIOR4, -- Read Quad I/O (4Byte +)
|
|
DDRQIOR, -- Read DDR Quad I/O (3Byte)
|
|
DDRQIOR4, -- Read DDR Quad I/O (4Byte +)
|
|
PP, -- Program Page (3Byte Address)
|
|
PP4, -- Program Page (4Byte +)
|
|
QPP, -- Quad Page Program (3Byte)
|
|
QPP4, -- Quad Page Program (4Byte +)
|
|
OTPP, -- OTP Program
|
|
PGSP, -- Program Suspend
|
|
PGRS, -- Program Resume
|
|
BE, -- Bulk Erase
|
|
SE, -- Erase 128/256KB (3Byte)
|
|
SE4, -- Erase 128/256KB (4Byte +)
|
|
P4E, -- 4KB-sector Erase (3Byte Addr)
|
|
P4E4, -- 4KB-sector Erase (4Byte Addr)
|
|
ERSP, -- Erase Suspend
|
|
ERRS, -- Erase Resume
|
|
ABRD, -- AutoBoot Register Read
|
|
ABWR, -- AutoBoot Register Write
|
|
BRRD, -- Bank Register Read
|
|
BRWR, -- Bank Register Write
|
|
BRAC, -- Bank Register Access
|
|
DLPRD, -- Read Data Learning Pattern
|
|
PNVDLR, -- Program NVDLP Reg
|
|
WVDLR, -- Write Volatile DLP Reg
|
|
ASPRD, -- ASP Read
|
|
ASPP, -- ASP Program
|
|
DYBRD, -- DYB Read
|
|
DYBWR, -- DYB Write
|
|
PPBRD, -- PPB Read
|
|
PPBP, -- PPB Program
|
|
PPBERS, -- PPB Erase
|
|
PLBWR, -- PPB Lock Bit Write
|
|
PLBRD, -- PPB Lock Bit Read
|
|
PASSRD, -- Password Read
|
|
PASSP, -- Password Program
|
|
PASSU, -- Password Unlock
|
|
RESET, -- Reset
|
|
MBR, -- Mode Bit Reset
|
|
MPM, -- Multi-I/O-High Perf Mode
|
|
CLSR -- Clear Status Register
|
|
);
|
|
|
|
TYPE WByteType IS ARRAY (0 TO 511) OF INTEGER RANGE -1 TO MaxData;
|
|
-- Flash Memory Array
|
|
TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData;
|
|
-- OTP Memory Array
|
|
TYPE OTPArray IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER
|
|
RANGE -1 TO MaxData;
|
|
--CFI Array (Common Flash Interface Query codes)
|
|
TYPE CFItype IS ARRAY (16#00# TO 16#55#) OF
|
|
INTEGER RANGE -1 TO 16#FF#;
|
|
-----------------------------------------------------------------------
|
|
-- memory declaration
|
|
-----------------------------------------------------------------------
|
|
-- Memory
|
|
SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData);
|
|
-- OTP Sector
|
|
SHARED VARIABLE OTPMem : OTPArray := (OTHERS => MaxData);
|
|
--CFI Array
|
|
SHARED VARIABLE CFI_array : CFItype := (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 Write Disable Bit
|
|
ALIAS SRWD :std_logic IS Status_reg1(7);
|
|
-- Status Register Programming Error Bit
|
|
ALIAS P_ERR :std_logic IS Status_reg1(6);
|
|
-- Status Register Erase Error Bit
|
|
ALIAS E_ERR :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 Write In Progress Bit
|
|
ALIAS WIP :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');
|
|
|
|
-- Status Register Write Enable Latch Bit
|
|
ALIAS ES :std_logic IS Status_reg2(1);
|
|
-- Status Register Write In Progress Bit
|
|
ALIAS PS :std_logic IS Status_reg2(0);
|
|
|
|
-- *** Configuration Register 1 ***
|
|
SHARED VARIABLE Config_reg1 : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL Config_reg1_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- Latency code
|
|
ALIAS LC1 :std_logic IS Config_reg1(7);
|
|
ALIAS LC0 :std_logic IS Config_reg1(6);
|
|
-- Configuration Register TBPROT bit
|
|
ALIAS TBPROT :std_logic IS Config_reg1(5);
|
|
-- Configuration Register LOCK bit
|
|
ALIAS LOCK :std_logic IS Config_reg1(4);
|
|
-- Configuration Register BPNV bit
|
|
ALIAS BPNV :std_logic IS Config_reg1(3);
|
|
-- Configuration Register QUAD bit
|
|
ALIAS QUAD :std_logic IS Config_reg1(1);
|
|
-- Configuration Register FREEZE bit
|
|
ALIAS FREEZE :std_logic IS Config_reg1(0);
|
|
|
|
-- *** VDLR Register ***
|
|
SHARED VARIABLE VDLR_reg : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL VDLR_reg_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- *** NVDLR Register ***
|
|
SHARED VARIABLE NVDLR_reg : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL NVDLR_reg_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
|
|
-- *** AutoBoot Register ***
|
|
SHARED VARIABLE AutoBoot_reg : std_logic_vector(31 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL AutoBoot_reg_in : std_logic_vector(31 downto 0)
|
|
:= (others => '0');
|
|
|
|
--AutoBoot Enable Bit
|
|
ALIAS ABE :std_logic IS AutoBoot_reg(0);
|
|
|
|
-- *** Bank Address Register ***
|
|
SHARED VARIABLE Bank_Addr_reg : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL Bank_Addr_reg_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
--Bank Address Register EXTADD bit
|
|
ALIAS EXTADD :std_logic IS Bank_Addr_reg(7);
|
|
|
|
-- *** ASP Register ***
|
|
SHARED VARIABLE ASP_reg : std_logic_vector(15 downto 0);
|
|
SIGNAL ASP_reg_in : std_logic_vector(15 downto 0)
|
|
:= (others => '1');
|
|
--Read Password Mode Enable Bit
|
|
ALIAS RPME :std_logic IS ASP_reg(5);
|
|
--PPB OTP Bit
|
|
ALIAS PPBOTP :std_logic IS ASP_reg(3);
|
|
-- Password Protection Mode Lock Bit
|
|
ALIAS PWDMLB :std_logic IS ASP_reg(2);
|
|
--Persistent Protection Mode Lock Bit
|
|
ALIAS PSTMLB :std_logic IS ASP_reg(1);
|
|
|
|
-- *** Password Register ***
|
|
SHARED VARIABLE Password_reg : std_logic_vector(63 downto 0)
|
|
:= (others => '1');
|
|
SIGNAL Password_reg_in : std_logic_vector(63 downto 0)
|
|
:= (others => '1');
|
|
-- *** PPB Lock Register ***
|
|
SHARED VARIABLE PPBL : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
SIGNAL PPBL_in : std_logic_vector(7 downto 0)
|
|
:= (others => '0');
|
|
--Persistent Protection Mode Lock Bit
|
|
ALIAS PPB_LOCK : std_logic IS PPBL(0);
|
|
SIGNAL PPB_LOCK_temp : std_ulogic := '0';
|
|
|
|
-- *** PPB Access Register ***
|
|
SHARED VARIABLE PPBAR : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
SIGNAL PPBAR_in : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
-- PPB_bits(Sec)
|
|
SHARED VARIABLE PPB_bits : std_logic_vector(SecNum downto 0)
|
|
:= (OTHERS => '1');
|
|
-- *** DYB Access Register ***
|
|
SHARED VARIABLE DYBAR : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
SIGNAL DYBAR_in : std_logic_vector(7 downto 0)
|
|
:= (others => '1');
|
|
-- DYB(Sec)
|
|
SHARED VARIABLE DYB_bits : std_logic_vector(SecNum downto 0);
|
|
|
|
-- The Lock Protection Registers for OTP Memory space
|
|
SHARED VARIABLE LOCK_BYTE1 :std_logic_vector(7 downto 0);
|
|
SHARED VARIABLE LOCK_BYTE2 :std_logic_vector(7 downto 0);
|
|
SHARED VARIABLE LOCK_BYTE3 :std_logic_vector(7 downto 0);
|
|
SHARED VARIABLE LOCK_BYTE4 :std_logic_vector(7 downto 0);
|
|
|
|
--Command Register
|
|
SIGNAL write : std_logic := '0';
|
|
SIGNAL cfg_write : std_logic := '0';
|
|
SIGNAL read_out : std_logic := '0';
|
|
|
|
SIGNAL rd : boolean := false;
|
|
SIGNAL dual : boolean := false;
|
|
SIGNAL fast_rd : boolean := true;
|
|
SIGNAL ddr : boolean := false;
|
|
SIGNAL any_read : boolean := false;
|
|
|
|
SIGNAL quadpg : boolean := false;
|
|
|
|
SIGNAL oe : boolean := false;
|
|
SIGNAL oe_z : boolean := false;
|
|
|
|
SHARED VARIABLE hold_mode : boolean := false;
|
|
|
|
--FSM control signals
|
|
SIGNAL PDONE : std_logic := '1'; --Page Prog. Done
|
|
SIGNAL PSTART : std_logic := '0'; --Start Page Programming
|
|
SIGNAL PGSUSP : std_logic := '0'; --Suspend Program
|
|
SIGNAL PGRES : std_logic := '0'; --Resume Program
|
|
|
|
SIGNAL RES_TO_SUSP_MIN_TIME : std_logic := '0';--Resume to Suspend Flag
|
|
SIGNAL RES_TO_SUSP_TYP_TIME : std_logic := '0';--Resume to Suspend Flag
|
|
|
|
SIGNAL WDONE : std_logic := '1'; --Write operation Done
|
|
SIGNAL WSTART : std_logic := '0'; --Start Write operation
|
|
|
|
SIGNAL ESTART : std_logic := '0'; --Start Erase operation
|
|
SIGNAL EDONE : std_logic := '1'; --Erase operation Done
|
|
SIGNAL ESUSP : std_logic := '0'; --Suspend Erase
|
|
SIGNAL ERES : std_logic := '0'; --Resume Erase
|
|
|
|
--reset timing
|
|
SIGNAL RST : std_logic := '0';
|
|
SIGNAL Reseted : std_logic := '0'; --Reset Timing Control
|
|
--Lock Bit is enabled for customer programming
|
|
SIGNAL WRLOCKENABLE : BOOLEAN := TRUE;
|
|
--Flag that mark if ASP Register is allready programmed
|
|
SIGNAL ASPOTPFLAG : BOOLEAN := FALSE;
|
|
SIGNAL ASP_INIT : NATURAL RANGE 0 TO 1;
|
|
SIGNAL INITIAL_CONFIG : std_logic := '0';
|
|
|
|
SHARED VARIABLE SecAddr : NATURAL RANGE 0 TO SecNum:= 0;
|
|
|
|
SHARED VARIABLE Sec_addr : NATURAL := 0;
|
|
|
|
SHARED VARIABLE Page_addr : NATURAL;
|
|
SHARED VARIABLE pgm_page : NATURAL;
|
|
|
|
SHARED VARIABLE QPP_page : std_logic_vector(PageNum downto 0)
|
|
:= (OTHERS => '0');
|
|
|
|
--Flag for Password unlock command
|
|
SIGNAL PASS_UNLOCKED : boolean := FALSE;
|
|
SIGNAL PASS_TEMP : std_logic_vector(63 downto 0)
|
|
:= (others => '1');
|
|
|
|
SHARED VARIABLE DOUBLE : BOOLEAN := FALSE;
|
|
SHARED VARIABLE EHP : BOOLEAN := FALSE;
|
|
|
|
SHARED VARIABLE read_cnt : NATURAL := 0;
|
|
SHARED VARIABLE byte_cnt : NATURAL := 1;
|
|
SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ;
|
|
SHARED VARIABLE read_addr_tmp : NATURAL RANGE 0 TO AddrRANGE ;
|
|
|
|
SHARED VARIABLE start_delay : NATURAL RANGE 0 TO 7;
|
|
SHARED VARIABLE ABSD : NATURAL RANGE 0 TO 7;
|
|
SIGNAL start_autoboot : std_logic := '0';
|
|
|
|
SIGNAL change_addr : std_logic := '0';
|
|
SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0;
|
|
SIGNAL SectorSuspend : NATURAL RANGE 0 TO SecNum := 0;
|
|
|
|
-- Sector address
|
|
SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0;
|
|
|
|
-- Sector is protect if Sec_Prot(SecNum) = '1'
|
|
SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) :=
|
|
(OTHERS => '0');
|
|
|
|
SIGNAL change_BP : std_logic := '0';
|
|
SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000";
|
|
|
|
SHARED VARIABLE CFI_array_tmp : std_logic_vector(647 downto 0);
|
|
|
|
SIGNAL Byte_number : NATURAL RANGE 0 TO 511 := 0;
|
|
|
|
TYPE bus_cycle_type IS (STAND_BY,
|
|
OPCODE_BYTE,
|
|
ADDRESS_BYTES,
|
|
DUMMY_BYTES,
|
|
MODE_BYTE,
|
|
DATA_BYTES
|
|
);
|
|
SHARED VARIABLE bus_cycle_state : bus_cycle_type;
|
|
-- switch between Data bytes and Dummy bytes
|
|
SHARED VARIABLE DummyBytes_act : X01 := '0';
|
|
SIGNAL dummy_cnt_act_temp : NATURAL := 0;
|
|
SIGNAL dummy_cnt_act : NATURAL := 0;
|
|
--Read Password Protection Mode Active flag
|
|
SIGNAL RdPswdProtMode : std_ulogic := '0';
|
|
--Read Password Protection Mode Support flag
|
|
SIGNAL RdPswdProtEnable : std_ulogic := '0';
|
|
SIGNAL BAR_ACC : std_ulogic := '0';
|
|
|
|
SHARED VARIABLE Latency_code : NATURAL RANGE 0 TO 7;
|
|
SHARED VARIABLE opcode_cnt : NATURAL := 0;
|
|
SHARED VARIABLE addr_cnt : NATURAL := 0;
|
|
SHARED VARIABLE mode_cnt : NATURAL := 0;
|
|
SHARED VARIABLE dummy_cnt : NATURAL := 0;
|
|
SHARED VARIABLE data_cnt : NATURAL := 0;
|
|
|
|
-- timing check violation
|
|
SIGNAL Viol : X01 := '0';
|
|
|
|
PROCEDURE ADDRHILO_SEC(
|
|
VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE Addr : NATURAL) IS
|
|
VARIABLE sector : NATURAL RANGE 0 TO SecNum;
|
|
BEGIN
|
|
sector := Addr/16#40000#;
|
|
AddrLOW := sector*16#40000#;
|
|
AddrHIGH := sector*16#40000# + 16#3FFFF#;
|
|
END ADDRHILO_SEC;
|
|
|
|
PROCEDURE ADDRHILO_PG(
|
|
VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange;
|
|
VARIABLE Addr : NATURAL) IS
|
|
VARIABLE page : NATURAL RANGE 0 TO PageNum;
|
|
BEGIN
|
|
page := Addr/PageSize;
|
|
AddrLOW := Page*PageSize;
|
|
AddrHIGH := Page*PageSize + (PageSize-1);
|
|
END AddrHILO_PG;
|
|
|
|
BEGIN
|
|
---------------------------------------------------------------------------
|
|
--Power Up time
|
|
---------------------------------------------------------------------------
|
|
|
|
PoweredUp <= '1' AFTER tdevice_PU;
|
|
|
|
TimingModelSel: PROCESS
|
|
BEGIN
|
|
--Enhanced High Performance Flag
|
|
IF (TimingModel(15) = '0' OR TimingModel(15) = '2' OR
|
|
TimingModel(15) = '3' OR TimingModel(15) = 'R' OR
|
|
TimingModel(15) = 'A' OR TimingModel(15) = 'B' OR
|
|
TimingModel(15) = 'C' OR TimingModel(15) = 'D' OR
|
|
TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR
|
|
TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR
|
|
TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN
|
|
EHP := TRUE;
|
|
IF (TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR
|
|
TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR
|
|
TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN
|
|
RdPswdProtEnable <= '1';
|
|
END IF;
|
|
ELSIF (TimingModel(15) = '4' OR TimingModel(15) = '6' OR
|
|
TimingModel(15) = '7' OR TimingModel(15) = '8' OR
|
|
TimingModel(15) = '9' OR TimingModel(15) = 'Q') THEN
|
|
EHP := FALSE;
|
|
END IF;
|
|
|
|
IF (TimingModel(15) ='0' OR TimingModel(15) ='2' OR
|
|
TimingModel(15) ='3' OR TimingModel(15) ='R' OR
|
|
TimingModel(15) ='A' OR TimingModel(15) ='B' OR
|
|
TimingModel(15) ='C' OR TimingModel(15) ='D' OR
|
|
TimingModel(15) ='4' OR TimingModel(15) ='6' OR
|
|
TimingModel(15) ='7' OR TimingModel(15) ='8' OR
|
|
TimingModel(15) ='9' OR TimingModel(15) ='Q') THEN
|
|
ASP_INIT <= 1;
|
|
ELSIF (TimingModel(15) ='Y' OR TimingModel(15) ='Z' OR
|
|
TimingModel(15) ='S' OR TimingModel(15) ='T' OR
|
|
TimingModel(15) ='K' OR TimingModel(15) ='L') THEN
|
|
ASP_INIT <= 0;
|
|
END IF;
|
|
WAIT;
|
|
END PROCESS;
|
|
|
|
RSTtiming: PROCESS(RSTNeg_pullup,Instruct)
|
|
BEGIN
|
|
IF falling_edge(RSTNeg_pullup) THEN
|
|
RST <= '1', '0' AFTER 200 ns;
|
|
ELSIF Instruct = RESET THEN
|
|
Reseted <= '0', '1' AFTER 10 ns;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
DUMMYcnt: PROCESS(dummy_cnt_act_temp)
|
|
BEGIN
|
|
dummy_cnt_act <= dummy_cnt_act_temp;
|
|
END PROCESS;
|
|
|
|
ReadPasswordProtectionMode: PROCESS(PPB_LOCK_temp,
|
|
ASP_reg_in(2), ASP_reg_in(5))
|
|
BEGIN
|
|
IF (PPB_LOCK = '0' AND PWDMLB = '0' AND RPME = '0' AND
|
|
RdPswdProtEnable = '1') THEN
|
|
RdPswdProtMode <= '1';
|
|
ABE := '0';
|
|
ELSE
|
|
RdPswdProtMode <= '0';
|
|
END IF;
|
|
END PROCESS;
|
|
---------------------------------------------------------------------------
|
|
-- autoboot control logic
|
|
---------------------------------------------------------------------------
|
|
AutoBootControl: PROCESS(SCK_ipd, current_state)
|
|
BEGIN
|
|
IF (current_state = AUTOBOOT) THEN
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF (start_delay > 0) THEN
|
|
start_delay := start_delay - 1;
|
|
END IF;
|
|
END IF;
|
|
|
|
IF (start_delay = 0) THEN
|
|
start_autoboot <= '1';
|
|
ELSE
|
|
start_autoboot <= '0';
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- VITAL Timing Checks Procedures
|
|
---------------------------------------------------------------------------
|
|
VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, RSTNeg_ipd,
|
|
HOLDNegIn, WPNegIn)
|
|
|
|
-- Timing Check Variables
|
|
-- Setup/Hold Checks variables
|
|
VARIABLE Tviol_CSNeg_SCK_normal : X01 := '0';
|
|
VARIABLE TD_CSNeg_SCK_normal : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_CSNeg_SCK_DDR : X01 := '0';
|
|
VARIABLE TD_CSNeg_SCK_DDR : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_CSNeg_RSTNeg : X01 := '0';
|
|
VARIABLE TD_CSNeg_RSTNeg : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_SI_SCK : X01 := '0';
|
|
VARIABLE TD_SI_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;
|
|
|
|
VARIABLE Tviol_HOLDNeg_SCK : X01 := '0';
|
|
VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_SI_SCK_DDR_R : X01 := '0';
|
|
VARIABLE TD_SI_SCK_DDR_R : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_SI_SCK_DDR_F : X01 := '0';
|
|
VARIABLE TD_SI_SCK_DDR_F : VitalTimingDataType;
|
|
|
|
VARIABLE Tviol_RSTNeg_CSNeg : X01 := '0';
|
|
VARIABLE TD_RSTNeg_CSNeg : VitalTimingDataType;
|
|
|
|
--Pulse Width and Period Check Variables
|
|
VARIABLE Pviol_SCK_serial : X01 := '0';
|
|
VARIABLE PD_SCK_serial : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_dual : X01 := '0';
|
|
VARIABLE PD_SCK_dual : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_fast : X01 := '0';
|
|
VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_quadpg : X01 := '0';
|
|
VARIABLE PD_SCK_quadpg : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_DDR : X01 := '0';
|
|
VARIABLE PD_SCK_DDR : 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_RSTNeg : X01 := '0';
|
|
VARIABLE PD_RSTNeg : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_serial_rd : X01 := '0';
|
|
VARIABLE PD_SCK_serial_rd : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_fast_rd : X01 := '0';
|
|
VARIABLE PD_SCK_fast_rd : VitalPeriodDataType:=VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_dual_rd : X01 := '0';
|
|
VARIABLE PD_SCK_dual_rd : VitalPeriodDataType:=VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_DDR_rd : X01 := '0';
|
|
VARIABLE PD_SCK_DDR_rd : VitalPeriodDataType:= VitalPeriodDataInit;
|
|
|
|
VARIABLE Pviol_SCK_quad_pg : X01 := '0';
|
|
VARIABLE PD_SCK_quad_pg : 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_normal_noedge_posedge,
|
|
SetupLow => tsetup_CSNeg_SCK_normal_noedge_posedge,
|
|
HoldHigh => thold_CSNeg_SCK_normal_noedge_posedge,
|
|
HoldLow => thold_CSNeg_SCK_normal_noedge_posedge,
|
|
CheckEnabled => ddr = false,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_CSNeg_SCK_normal,
|
|
Violation => Tviol_CSNeg_SCK_normal
|
|
);
|
|
|
|
-- Setup/Hold Check between CS# and SCK
|
|
VitalSetupHoldCheck (
|
|
TestSignal => CSNeg_ipd,
|
|
TestSignalName => "CS#",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupHigh => tsetup_CSNeg_SCK_DDR_noedge_posedge,
|
|
SetupLow => tsetup_CSNeg_SCK_DDR_noedge_posedge,
|
|
HoldHigh => thold_CSNeg_SCK_DDR_noedge_posedge,
|
|
HoldLow => thold_CSNeg_SCK_DDR_noedge_posedge,
|
|
CheckEnabled => ddr,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_CSNeg_SCK_DDR,
|
|
Violation => Tviol_CSNeg_SCK_DDR
|
|
);
|
|
|
|
-- Hold Check between CSNeg and RSTNeg
|
|
VitalSetupHoldCheck (
|
|
TestSignal => CSNeg,
|
|
TestSignalName => "CSNeg",
|
|
RefSignal => RSTNeg,
|
|
RefSignalName => "RSTNeg",
|
|
HoldHigh => thold_CSNeg_RSTNeg,
|
|
CheckEnabled => TRUE,
|
|
RefTransition => '\',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_CSNeg_RSTNeg,
|
|
Violation => Tviol_CSNeg_RSTNeg
|
|
);
|
|
|
|
-- Setup/Hold Check between SI and SCK, serial mode
|
|
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 => NOT(DOUBLE) AND SIOut_z /= SIIn,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_SI_SCK,
|
|
Violation => Tviol_SI_SCK
|
|
);
|
|
|
|
-- Setup Check between WP# and CS# \
|
|
VitalSetupHoldCheck (
|
|
TestSignal => WPNegIn,
|
|
TestSignalName => "WP#",
|
|
RefSignal => CSNeg_ipd,
|
|
RefSignalName => "CS#",
|
|
SetupHigh => tsetup_WPNeg_CSNeg,
|
|
CheckEnabled => true,
|
|
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 => SRWD = '1' AND WEL = '1',
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_WPNeg_CSNeg_hold,
|
|
Violation => Tviol_WPNeg_CSNeg_hold
|
|
);
|
|
|
|
-- Setup/Hold Check between HOLD# and SCK /
|
|
VitalSetupHoldCheck (
|
|
TestSignal => HOLDNegIn,
|
|
TestSignalName => "HOLD#",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupLow => tsetup_HOLDNeg_SCK,
|
|
SetupHigh => tsetup_HOLDNeg_SCK,
|
|
HoldLow => thold_HOLDNeg_SCK,
|
|
HoldHigh => thold_HOLDNeg_SCK,
|
|
CheckEnabled => QUAD = '0'
|
|
AND HOLDNegOut_zd /= HOLDNegIn,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_HOLDNeg_SCK,
|
|
Violation => Tviol_HOLDNeg_SCK
|
|
);
|
|
|
|
-- Setup/Hold Check between SI and SCK, DDR mode
|
|
VitalSetupHoldCheck (
|
|
TestSignal => SIIn,
|
|
TestSignalName => "SI",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupHigh => tsetup_SI_SCK_DDR_noedge_posedge,
|
|
SetupLow => tsetup_SI_SCK_DDR_noedge_posedge,
|
|
HoldHigh => thold_SI_SCK_DDR_noedge_posedge,
|
|
HoldLow => thold_SI_SCK_DDR_noedge_posedge,
|
|
CheckEnabled => DOUBLE AND dual = false
|
|
AND SIOut_z /= SIIn,
|
|
RefTransition => '/',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_SI_SCK_DDR_R,
|
|
Violation => Tviol_SI_SCK_DDR_R
|
|
);
|
|
|
|
-- Setup/Hold Check between SI and SCK, DDR mode
|
|
VitalSetupHoldCheck (
|
|
TestSignal => SIIn,
|
|
TestSignalName => "SI",
|
|
RefSignal => SCK_ipd,
|
|
RefSignalName => "SCK",
|
|
SetupHigh => tsetup_SI_SCK_DDR_noedge_negedge,
|
|
SetupLow => tsetup_SI_SCK_DDR_noedge_negedge,
|
|
HoldHigh => thold_SI_SCK_DDR_noedge_negedge,
|
|
HoldLow => thold_SI_SCK_DDR_noedge_negedge,
|
|
CheckEnabled => ddr AND dual = false
|
|
AND SIOut_z /= SIIn,
|
|
RefTransition => '\',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_SI_SCK_DDR_F,
|
|
Violation => Tviol_SI_SCK_DDR_F
|
|
);
|
|
|
|
-- Setup Check between RSTNeg and SCK, DDR fast mode
|
|
VitalSetupHoldCheck (
|
|
TestSignal => RSTNeg,
|
|
TestSignalName => "RSTNeg",
|
|
RefSignal => CSNeg,
|
|
RefSignalName => "CSNeg",
|
|
SetupHigh => tsetup_RSTNeg_CSNeg,
|
|
CheckEnabled => TRUE,
|
|
RefTransition => '\',
|
|
HeaderMsg => InstancePath & PartID,
|
|
TimingData => TD_RSTNeg_CSNeg,
|
|
Violation => Tviol_RSTNeg_CSNeg
|
|
);
|
|
|
|
--Pulse Width and Period Check Variables
|
|
-- Pulse Width Check SCK for READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_serial_negedge,
|
|
PulseWidthHigh => tpw_SCK_serial_posedge,
|
|
PeriodData => PD_SCK_serial,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_serial,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => rd);
|
|
|
|
-- Pulse Width Check SCK for DUAL_READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_dual_negedge,
|
|
PulseWidthHigh => tpw_SCK_dual_posedge,
|
|
PeriodData => PD_SCK_dual,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_dual,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => dual);
|
|
|
|
-- Pulse Width Check SCK for FAST_READ, serial mode
|
|
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 );
|
|
|
|
-- Pulse Width Check SCK for QPP
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_quadpg_negedge,
|
|
PulseWidthHigh => tpw_SCK_quadpg_posedge,
|
|
PeriodData => PD_SCK_quadpg,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_quadpg,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => quadpg);
|
|
|
|
-- 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 => any_read );
|
|
|
|
-- Pulse Width Check CS# for Program/Erase, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => CSNeg_ipd,
|
|
TestSignalName => "CS#",
|
|
PulseWidthHigh => tpw_CSNeg_pgers_posedge,
|
|
PeriodData => PD_CSNeg_pgers,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_CSNeg_pgers,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => NOT(any_read));
|
|
|
|
-- Pulse Width Check RSTNeg
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => RSTNeg_ipd,
|
|
TestSignalName => "RSTNeg",
|
|
PulseWidthLow => tpw_RSTNeg_negedge,
|
|
PulseWidthHigh => tpw_RSTNeg_posedge,
|
|
CheckEnabled => TRUE,
|
|
HeaderMsg => InstancePath & PartID,
|
|
PeriodData => PD_RSTNeg,
|
|
Violation => Pviol_RSTNeg
|
|
);
|
|
|
|
-- Pulse Width Check SCK for DDR READ
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
PulseWidthLow => tpw_SCK_DDR_negedge,
|
|
PulseWidthHigh => tpw_SCK_DDR_posedge,
|
|
PeriodData => PD_SCK_DDR,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_DDR,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => ddr);
|
|
|
|
-- Period Check SCK for READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_serial_rd,
|
|
PeriodData => PD_SCK_serial_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_serial_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => rd );
|
|
|
|
-- Period Check SCK for FAST READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_fast_rd,
|
|
PeriodData => PD_SCK_fast_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_fast_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => fast_rd );
|
|
|
|
-- Period Check SCK for DUAL READ, serial mode
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_dual_rd,
|
|
PeriodData => PD_SCK_dual_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_dual_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => dual );
|
|
|
|
-- Period Check SCK for QPP
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_quadpg,
|
|
PeriodData => PD_SCK_quad_pg,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_quad_pg,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => quadpg );
|
|
|
|
-- Period Check SCK for DDR READ
|
|
VitalPeriodPulseCheck (
|
|
TestSignal => SCK_ipd,
|
|
TestSignalName => "SCK",
|
|
Period => tperiod_SCK_DDR_rd,
|
|
PeriodData => PD_SCK_DDR_rd,
|
|
XOn => XOn,
|
|
MsgOn => MsgOn,
|
|
Violation => Pviol_SCK_DDR_rd,
|
|
HeaderMsg => InstancePath & PartID,
|
|
CheckEnabled => ddr );
|
|
|
|
Violation := Tviol_CSNeg_SCK_normal OR
|
|
Tviol_CSNeg_SCK_DDR OR
|
|
Tviol_CSNeg_RSTNeg OR
|
|
Tviol_SI_SCK OR
|
|
Tviol_WPNeg_CSNeg_setup OR
|
|
Tviol_WPNeg_CSNeg_hold OR
|
|
Tviol_HOLDNeg_SCK OR
|
|
Tviol_SI_SCK_DDR_R OR
|
|
Tviol_SI_SCK_DDR_F OR
|
|
Tviol_RSTNeg_CSNeg OR
|
|
Pviol_SCK_serial OR
|
|
Pviol_SCK_dual OR
|
|
Pviol_SCK_fast OR
|
|
Pviol_SCK_quadpg OR
|
|
Pviol_CSNeg_read OR
|
|
Pviol_CSNeg_pgers OR
|
|
Pviol_SCK_DDR OR
|
|
Pviol_SCK_serial_rd OR
|
|
Pviol_SCK_fast_rd OR
|
|
Pviol_SCK_dual_rd OR
|
|
Pviol_SCK_quad_pg OR
|
|
Pviol_SCK_DDR_rd;
|
|
|
|
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, RST, PoweredUp, RST_out)
|
|
|
|
BEGIN
|
|
IF PoweredUp = '1' THEN
|
|
IF RSTNeg_pullup = '1' and RST_out= '1' THEN
|
|
IF next_state'EVENT THEN
|
|
current_state <= next_state;
|
|
END IF;
|
|
ELSIF RSTNeg_pullup = '0' AND falling_edge(RST) THEN
|
|
--no state transition while RESET# low
|
|
current_state <= RESET_STATE;
|
|
RST_in <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS StateTransition;
|
|
|
|
Threset : PROCESS(RST_in)
|
|
BEGIN
|
|
IF rising_edge(RST_in) THEN
|
|
RST_out <= '0', '1' AFTER (thold_CSNeg_RSTNeg-200 ns);
|
|
END IF;
|
|
END PROCESS Threset;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Write cycle decode
|
|
---------------------------------------------------------------------------
|
|
|
|
BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RST_out,
|
|
WPNeg_pullup)
|
|
|
|
TYPE quad_data_type IS ARRAY (0 TO 1023) OF INTEGER RANGE 0 TO 15;
|
|
|
|
VARIABLE bit_cnt : NATURAL := 0;
|
|
VARIABLE Data_in : std_logic_vector(4095 downto 0)
|
|
:= (others => '0');
|
|
|
|
VARIABLE opcode : std_logic_vector(7 downto 0);
|
|
VARIABLE opcode_in : std_logic_vector(7 downto 0);
|
|
VARIABLE addr_bytes : std_logic_vector(31 downto 0);
|
|
VARIABLE hiaddr_bytes : std_logic_vector(31 downto 0);
|
|
VARIABLE Address_in : std_logic_vector(31 downto 0);
|
|
VARIABLE mode_bytes : std_logic_vector(7 downto 0);
|
|
VARIABLE mode_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);
|
|
|
|
VARIABLE CLK_PER : time;
|
|
VARIABLE LAST_CLK : time;
|
|
VARIABLE Check_freq : boolean := FALSE;
|
|
|
|
BEGIN
|
|
|
|
IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES)
|
|
AND NOT(bus_cycle_state = DUMMY_BYTES) THEN
|
|
bus_cycle_state := STAND_BY;
|
|
ELSE
|
|
CASE bus_cycle_state IS
|
|
WHEN STAND_BY =>
|
|
IF falling_edge(CSNeg_ipd) THEN
|
|
Instruct <= NONE;
|
|
write <= '1';
|
|
cfg_write <= '0';
|
|
opcode_cnt:= 0;
|
|
addr_cnt := 0;
|
|
mode_cnt := 0;
|
|
dummy_cnt := 0;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
data_cnt := 0;
|
|
DOUBLE := FALSE;
|
|
CLK_PER := 0 ns;
|
|
LAST_CLK := 0 ns;
|
|
IF current_state = AUTOBOOT THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := OPCODE_BYTE;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN OPCODE_BYTE =>
|
|
IF rising_edge(SCK_ipd) THEN
|
|
|
|
Latency_code := to_nat(LC1 & LC0);
|
|
CLK_PER := NOW - LAST_CLK;
|
|
LAST_CLK := NOW;
|
|
IF Check_freq THEN
|
|
IF (CLK_PER < 20 ns AND Latency_code = 3) OR
|
|
(CLK_PER < 12.5 ns AND Latency_code = 0) OR
|
|
(CLK_PER < 11.1 ns AND Latency_code = 1) OR
|
|
(CLK_PER < 9.6 ns AND Latency_code = 2) THEN
|
|
ASSERT FALSE
|
|
REPORT "More wait states are required for " &
|
|
"this clock frequency value"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
Check_freq := FALSE;
|
|
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN
|
|
--One-byte of instruction opcode is shifted into the
|
|
--device on the SI serial input pin with the most
|
|
--significant bit (MSB) first.Each bit input on the
|
|
--SI serial input pin is latched on the rising edge of
|
|
--the SCK serial clock signal.
|
|
opcode_in(opcode_cnt) := SIIn;
|
|
opcode_cnt := opcode_cnt + 1;
|
|
IF opcode_cnt = BYTE THEN
|
|
--MSB first
|
|
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 "00000100" => --04h
|
|
Instruct <= WRDI;
|
|
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 "00010011" => --13h
|
|
Instruct <= RD4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "01001011" => --4Bh
|
|
Instruct <= OTPR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00000101" => --05h
|
|
Instruct <= RDSR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00000111" => --07h
|
|
Instruct <= RDSR2;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00110101" => --35h
|
|
Instruct <= RDCR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10010000" => --90h
|
|
Instruct <= REMS;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "10011111" => --9Fh
|
|
Instruct <= RDID;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10101011" => --ABh
|
|
Instruct <= RES;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
WHEN "00001011" => --0Bh
|
|
Instruct <= FSTRD;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00001100" => --0Ch
|
|
Instruct <= FSTRD4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00001101" => --0Dh
|
|
Instruct <= DDRFR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00001110" => --0Eh
|
|
Instruct <= DDRFR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00111011" => --3Bh
|
|
Instruct <= DOR;
|
|
Check_freq := TRUE;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00111100" => --3Ch
|
|
Instruct <= DOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111011" => --BBh
|
|
Instruct <= DIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111100" => --BCh
|
|
Instruct <= DIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111101" => --BDh
|
|
Instruct <= DDRDIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "10111110" => --BEh
|
|
Instruct <= DDRDIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "01101011" => --6Bh
|
|
Instruct <= QOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "01101100" => --6Ch
|
|
Instruct <= QOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101011" => --EBh
|
|
Instruct <= QIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101100" => --ECh
|
|
Instruct <= QIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101101" => --EDh
|
|
Instruct <= DDRQIOR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "11101110" => --EEh
|
|
Instruct <= DDRQIOR4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
Check_freq := TRUE;
|
|
WHEN "00000010" => --02h
|
|
Instruct <= PP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00010010" => --12h
|
|
Instruct <= PP4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00110010" => --32h
|
|
Instruct <= QPP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
quadpg <= TRUE;
|
|
WHEN "00111000" => --38h
|
|
Instruct <= QPP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
quadpg <= TRUE;
|
|
WHEN "00110100" => --34h
|
|
Instruct <= QPP4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
quadpg <= TRUE;
|
|
WHEN "01000010" => --42h
|
|
Instruct <= OTPP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "10000101" => --85h
|
|
Instruct <= PGSP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10001010" => --8Ah
|
|
Instruct <= PGRS;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11000111" => --C7h
|
|
Instruct <= BE;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01100000" => --60h
|
|
Instruct <= BE;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11011000" => --D8h
|
|
Instruct <= SE;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11011100" => --DCh
|
|
Instruct <= SE4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00100000" => --20h
|
|
Instruct <= P4E;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "00100001" => --21h
|
|
Instruct <= P4E4;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "01110101" => --75h
|
|
Instruct <= ERSP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01111010" => --7Ah
|
|
Instruct <= ERRS;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010100" => --14h
|
|
Instruct <= ABRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010101" => --15h
|
|
Instruct <= ABWR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010110" => --16h
|
|
Instruct <= BRRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00010111" => --17h
|
|
Instruct <= BRWR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10111001" => --B9h
|
|
Instruct <= BRAC;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00101011" => --2Bh
|
|
Instruct <= ASPRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00101111" => --2Fh
|
|
Instruct <= ASPP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11100000" => --E0h
|
|
Instruct <= DYBRD;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100001" => --E1h
|
|
Instruct <= DYBWR;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100010" => --E2h
|
|
Instruct <= PPBRD;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100011" => --E3h
|
|
Instruct <= PPBP;
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
WHEN "11100100" => --E4h
|
|
Instruct <= PPBERS;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10100110" => --A6h
|
|
Instruct <= PLBWR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "10100111" => --A7h
|
|
Instruct <= PLBRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11100111" => --E7h
|
|
Instruct <= PASSRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11101000" => --E8h
|
|
Instruct <= PASSP;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11101001" => --E9h
|
|
Instruct <= PASSU;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11110000" => --F0h
|
|
Instruct <= RESET;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "11111111" => --FFh
|
|
Instruct <= MBR;
|
|
bus_cycle_state := MODE_BYTE;
|
|
WHEN "01000001" => -- 41h
|
|
Instruct <= DLPRD;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01000011" => -- 43h
|
|
Instruct <= PNVDLR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "01001010" => -- 4Ah
|
|
Instruct <= WVDLR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN "00110000" => --30h
|
|
Instruct <= CLSR;
|
|
bus_cycle_state := DATA_BYTES;
|
|
WHEN others =>
|
|
null;
|
|
|
|
END CASE;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ADDRESS_BYTES =>
|
|
IF Instruct= DDRFR OR Instruct= DDRFR4 OR Instruct= DDRDIOR
|
|
OR Instruct = DDRDIOR4 OR Instruct = DDRQIOR OR
|
|
Instruct = DDRQIOR4 THEN
|
|
DOUBLE := TRUE;
|
|
ELSE
|
|
DOUBLE := FALSE;
|
|
END IF;
|
|
|
|
IF (rising_edge(SCK_ipd) AND NOT(DOUBLE) AND
|
|
(CSNeg_ipd= '0')) THEN
|
|
IF (((Instruct=FSTRD AND EXTADD= '0' )
|
|
OR (Instruct=DOR AND EXTADD= '0')
|
|
OR Instruct=OTPR) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1'))
|
|
OR (Instruct=QOR AND QUAD= '1' AND EXTADD='0') THEN
|
|
--Instruction + 3 Bytes Address + Dummy Byte
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF (Instruct=FSTRD OR Instruct=DOR OR
|
|
Instruct=QOR) THEN
|
|
IF (Latency_code = 3) THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF ((((Instruct=FSTRD4) OR (Instruct=DOR4) OR
|
|
((Instruct=FSTRD) AND EXTADD= '1') OR
|
|
((Instruct=DOR) AND EXTADD= '1')) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR
|
|
((Instruct=QOR4) AND QUAD='1') OR
|
|
((Instruct=QOR) AND QUAD='1' AND EXTADD='1')) THEN
|
|
--Instruction + 4 Bytes Address + Dummy Byte
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
IF addr_cnt = 4*BYTE THEN
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF Latency_code = 3 THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF (DOUBLE AND NOT(hold_mode) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = DIOR AND EXTADD= '0' AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN
|
|
-- DUAL I/O High Performance Read (3Bytes Address)
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF ((Instruct = DIOR4 OR
|
|
(Instruct = DIOR AND EXTADD= '1')) AND
|
|
((HOLDNeg_pullup = '1' AND QUAD = '0') OR
|
|
QUAD = '1')) THEN
|
|
-- DUAL I/O High Performance Read (4Bytes Address)
|
|
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 = (4*BYTE) / 2 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF (Instruct = QIOR AND EXTADD= '0') THEN
|
|
-- QUAD I/O High Performance Read (3Bytes Address)
|
|
IF QUAD = '1' 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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := MODE_BYTE;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF (Instruct = QIOR4 OR
|
|
(Instruct = QIOR AND EXTADD= '1')) THEN
|
|
-- QUAD I/O High Performance Read (4Bytes Address)
|
|
IF QUAD = '1' 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 = (4*BYTE) / 4 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i)
|
|
:= Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := MODE_BYTE;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
ELSIF (((Instruct = RD4 OR Instruct = PP4 OR
|
|
Instruct = SE4 OR Instruct = PPBRD OR
|
|
Instruct = DYBRD OR Instruct = DYBWR OR
|
|
Instruct = PPBP OR Instruct = P4E4 OR
|
|
(Instruct = READ AND EXTADD= '1' ) OR
|
|
(Instruct = PP AND EXTADD= '1' ) OR
|
|
(Instruct = P4E AND EXTADD= '1' ) OR
|
|
(Instruct = SE AND EXTADD= '1' )) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1'))
|
|
OR (QUAD ='1' AND (Instruct=QPP4 OR
|
|
(Instruct = QPP AND EXTADD= '1' ))))THEN
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
IF addr_cnt = 4*BYTE THEN
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
hiaddr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(hiaddr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') AND EXTADD= '0') 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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (SCK_ipd'EVENT AND DOUBLE AND addr_cnt /= 0 ) OR
|
|
(rising_edge(SCK_ipd) AND DOUBLE AND addr_cnt = 0 ) THEN
|
|
IF (Instruct=DDRFR AND EXTADD= '0' ) THEN
|
|
--Fast DDR Read Mode
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = 3*BYTE THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 23 DOWNTO 0 LOOP
|
|
addr_bytes(23-i) := Address_in(i);
|
|
END LOOP;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRFR4 OR
|
|
(Instruct=DDRFR AND EXTADD= '1' )) THEN
|
|
Address_in(addr_cnt) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = 4*BYTE THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
addr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct= DDRDIOR AND EXTADD= '0' ) THEN
|
|
--Dual I/O DDR Read Mode
|
|
Address_in(2*addr_cnt) := SOIn;
|
|
Address_in(2*addr_cnt+1):= SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRDIOR4 OR
|
|
(Instruct=DDRDIOR AND EXTADD= '1' )) THEN
|
|
--Dual I/O DDR Read Mode
|
|
Address_in(2*addr_cnt) := SOIn;
|
|
Address_in(2*addr_cnt+1) := SIIn;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = (4*BYTE)/2 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
addr_bytes(31-i) := Address_in(i);
|
|
END LOOP;
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 1 ns;
|
|
IF EHP THEN
|
|
bus_cycle_state := MODE_BYTE;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRQIOR AND EXTADD= '0' ) AND
|
|
QUAD = '1' THEN
|
|
--Quad I/O DDR Read Mode
|
|
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;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
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;
|
|
addr_bytes(31 downto 26) := "000000";
|
|
addr_bytes(25 downto 24) :=
|
|
Bank_Addr_reg (1 downto 0);
|
|
Address <= to_nat(addr_bytes);
|
|
change_addr <= '1','0' AFTER 5 ns;
|
|
bus_cycle_state := MODE_BYTE;
|
|
END IF;
|
|
ELSIF QUAD = '1' AND (Instruct=DDRQIOR4 OR
|
|
(Instruct=DDRQIOR AND EXTADD= '1' )) 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;
|
|
addr_cnt := addr_cnt + 1;
|
|
read_cnt := 0;
|
|
IF addr_cnt = (4*BYTE)/4 THEN
|
|
addr_cnt := 0;
|
|
FOR I IN 31 DOWNTO 0 LOOP
|
|
addr_bytes(31-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;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN MODE_BYTE =>
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF ((Instruct=DIOR OR Instruct = DIOR4) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) 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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
IF Latency_code = 0 OR Latency_code = 3 THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
ELSE
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=QIOR OR Instruct = QIOR4)
|
|
AND QUAD = '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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
END IF;
|
|
ELSIF Instruct=DDRFR OR Instruct = DDRFR4 THEN
|
|
mode_in(2*mode_cnt) := SIIn;
|
|
ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
mode_in(4*mode_cnt) := SOIn;
|
|
mode_in(4*mode_cnt+1) := SIIn;
|
|
ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
mode_in(0) := HOLDNegIn;
|
|
mode_in(1) := WPNegIn;
|
|
mode_in(2) := SOIn;
|
|
mode_in(3) := SIIn;
|
|
END IF;
|
|
dummy_cnt := 0;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
ELSIF falling_edge(SCK_ipd) THEN
|
|
IF Instruct=DDRFR OR Instruct = DDRFR4 THEN
|
|
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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
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_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
mode_in(4) := HOLDNegIn;
|
|
mode_in(5) := WPNegIn;
|
|
mode_in(6) := SOIn;
|
|
mode_in(7) := SIIn;
|
|
FOR I IN 7 DOWNTO 0 LOOP
|
|
mode_bytes(i) := mode_in(7-i);
|
|
END LOOP;
|
|
bus_cycle_state := DUMMY_BYTES;
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN DUMMY_BYTES =>
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF ((DOUBLE AND NOT(hold_mode)) AND
|
|
VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
IF (((Instruct=FSTRD OR Instruct=FSTRD4 OR
|
|
Instruct=DOR OR Instruct=DOR4 OR
|
|
Instruct=OTPR) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR
|
|
((Instruct = QOR OR Instruct = QOR4) AND
|
|
QUAD = '1'))THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF dummy_cnt = BYTE THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF EHP THEN
|
|
IF ((Latency_code = 3 AND dummy_cnt=1) OR
|
|
(Latency_code = 0 AND dummy_cnt=2) OR
|
|
(Latency_code = 1 AND dummy_cnt=4) OR
|
|
(Latency_code = 2 AND dummy_cnt=5)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSE
|
|
IF ((Latency_code = 3 AND dummy_cnt = 4) OR
|
|
(Latency_code = 0 AND dummy_cnt = 5) OR
|
|
(Latency_code = 1 AND dummy_cnt = 6) OR
|
|
(Latency_code = 2 AND dummy_cnt = 7)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct=RES THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF dummy_cnt = 3*BYTE THEN
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (Instruct = DIOR OR Instruct = DIOR4) AND
|
|
((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF EHP THEN
|
|
IF ((Latency_code = 1 AND dummy_cnt = 1) OR
|
|
(Latency_code = 2 AND dummy_cnt = 2)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSE
|
|
IF ((Latency_code = 3 AND dummy_cnt = 4) OR
|
|
(Latency_code = 0 AND dummy_cnt = 4) OR
|
|
(Latency_code = 1 AND dummy_cnt = 5) OR
|
|
(Latency_code = 2 AND dummy_cnt = 6)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF EHP THEN
|
|
IF ((Latency_code = 3 AND dummy_cnt = 2) OR
|
|
(Latency_code = 0 AND dummy_cnt = 4) OR
|
|
(Latency_code = 1 AND dummy_cnt = 5) OR
|
|
(Latency_code = 2 AND dummy_cnt = 6)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSE
|
|
IF ((Latency_code = 3 AND dummy_cnt = 4) OR
|
|
(Latency_code = 0 AND dummy_cnt = 6) OR
|
|
(Latency_code = 1 AND dummy_cnt = 7) OR
|
|
(Latency_code = 2 AND dummy_cnt = 8)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF ((Instruct = QIOR OR Instruct = QIOR4) AND
|
|
QUAD = '1') THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF ((Latency_code = 3 AND dummy_cnt = 1) OR
|
|
(Latency_code = 0 AND dummy_cnt = 4) OR
|
|
(Latency_code = 1 AND dummy_cnt = 4) OR
|
|
(Latency_code = 2 AND dummy_cnt = 5)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
ELSIF (Instruct = DDRQIOR OR Instruct = DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
dummy_cnt := dummy_cnt + 1;
|
|
dummy_cnt_act_temp <= dummy_cnt;
|
|
IF ((Latency_code = 3 AND dummy_cnt = 3) OR
|
|
(Latency_code = 0 AND dummy_cnt = 6) OR
|
|
(Latency_code = 1 AND dummy_cnt = 7) OR
|
|
(Latency_code = 2 AND dummy_cnt = 8)) THEN
|
|
DummyBytes_act := '1';
|
|
bus_cycle_state := DATA_BYTES;
|
|
END IF;
|
|
END IF;
|
|
ELSIF falling_edge(SCK_ipd) THEN
|
|
IF NOT(hold_mode) THEN
|
|
IF (DOUBLE AND VDLR_reg /= "00000000") THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN DATA_BYTES =>
|
|
IF rising_edge(CSNeg_ipd) THEN
|
|
IF ((mode_bytes(7 downto 4) = "1010" AND
|
|
(Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QIOR OR Instruct = QIOR4)) OR
|
|
((mode_bytes(7 downto 4) =
|
|
NOT(mode_bytes(3 downto 0))) AND
|
|
(Instruct = DDRFR OR Instruct = DDRFR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct = DDRQIOR4))) THEN
|
|
bus_cycle_state := ADDRESS_BYTES;
|
|
ELSE
|
|
bus_cycle_state := STAND_BY;
|
|
END IF;
|
|
END IF;
|
|
IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' AND
|
|
NOT(DOUBLE) THEN
|
|
IF ((Instruct = READ OR Instruct=RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = RDSR OR Instruct = RDSR2 OR
|
|
Instruct = RDCR OR Instruct = OTPR OR
|
|
Instruct = DOR OR Instruct = DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = ABRD OR Instruct = BRRD OR
|
|
Instruct = ASPRD OR Instruct = DYBRD OR
|
|
Instruct = PPBRD OR
|
|
Instruct = PASSRD OR Instruct = RDID OR
|
|
Instruct = RES OR Instruct = REMS OR
|
|
Instruct = PLBRD OR Instruct = DLPRD)
|
|
AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1'))
|
|
OR (current_state = AUTOBOOT AND start_delay = 0)OR
|
|
((Instruct=QOR OR Instruct=QIOR OR Instruct=QOR4
|
|
OR Instruct= QIOR4) AND QUAD = '1') THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
ELSIF SCK_ipd'EVENT AND CSNeg_ipd = '0' AND DOUBLE THEN
|
|
read_out <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
|
|
IF rising_edge(SCK_ipd) THEN
|
|
IF QUAD = '1' AND (Instruct=QPP OR Instruct = QPP4)THEN
|
|
quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn;
|
|
IF data_cnt > (PageSize*2-1) THEN
|
|
--In case of quad mode and QPP,
|
|
--if more than 512 bytes are sent to the device
|
|
FOR I IN 0 TO (PageSize*2-2) LOOP
|
|
quad_data_in(i) := quad_data_in(i+1);
|
|
END LOOP;
|
|
quad_data_in((PageSize*2-1)) :=
|
|
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;
|
|
ELSIF ((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') THEN
|
|
IF data_cnt > (PageSize*8-1) THEN
|
|
--In case of serial mode and PP,
|
|
-- if more than 512 bytes are sent to the device
|
|
-- previously latched data are discarded and last
|
|
-- 512 data bytes are guaranteed to be programmed
|
|
-- correctly within the same page.
|
|
IF bit_cnt = 0 THEN
|
|
FOR I IN 0 TO ((PageSize-1)*BYTE - 1) LOOP
|
|
Data_in(i) := Data_in(i+8);
|
|
END LOOP;
|
|
END IF;
|
|
Data_in((PageSize-1)*BYTE + 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;
|
|
END IF;
|
|
END IF;
|
|
|
|
IF rising_edge(CSNeg_ipd) THEN
|
|
CASE Instruct IS
|
|
WHEN WREN | WRDI | BE | SE | SE4 | CLSR | RESET |
|
|
PPBP | PPBERS | PGSP | PGRS | ERSP | BRAC |
|
|
ERRS | P4E | P4E4 | PLBWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') THEN
|
|
IF data_cnt = 0 THEN
|
|
write <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN WRR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0')
|
|
OR QUAD='1') THEN
|
|
IF ((data_cnt mod 8) = 0 AND data_cnt > 0) THEN
|
|
IF data_cnt = 8 THEN
|
|
--If CS# is driven high after eight
|
|
--cycle,only the Status Register is
|
|
--written to.
|
|
write <= '0';
|
|
IF BAR_ACC = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
Status_reg1_in(i) <=
|
|
Data_in(7-i);
|
|
END LOOP;
|
|
ELSIF P_ERR = '0' AND E_ERR = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
Bank_Addr_reg_in(i) <=
|
|
Data_in(7-i);
|
|
END LOOP;
|
|
END IF;
|
|
ELSIF data_cnt = 16 THEN
|
|
--After the 16th cycle both the
|
|
--Status and Configuration Registers
|
|
--are written to.
|
|
write <= '0';
|
|
IF BAR_ACC = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
cfg_write <= '1';
|
|
FOR i IN 0 TO 7 LOOP
|
|
Status_reg1_in(i) <=
|
|
Data_in(7-i);
|
|
Config_reg1_in(i) <=
|
|
Data_in(15-i);
|
|
END LOOP;
|
|
END LOOP;
|
|
ELSIF P_ERR = '0' AND E_ERR = '0' THEN
|
|
FOR i IN 0 TO 7 LOOP
|
|
Bank_Addr_reg_in(i) <=
|
|
Data_in(7-i);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PP | PP4 | OTPP =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt > 0 THEN
|
|
IF (data_cnt mod 8) = 0 THEN
|
|
write <= '0';
|
|
FOR I IN 0 TO (PageSize-1) LOOP
|
|
FOR J IN 7 DOWNTO 0 LOOP
|
|
IF Data_in((i*8) + (7-j))
|
|
/= 'X' THEN
|
|
Byte_slv(j) :=
|
|
Data_in((i*8) + (7-j));
|
|
END IF;
|
|
END LOOP;
|
|
WByte(i) <=
|
|
to_nat(Byte_slv);
|
|
END LOOP;
|
|
IF data_cnt > PageSize*BYTE THEN
|
|
Byte_number <= PageSize-1;
|
|
ELSE
|
|
Byte_number <= data_cnt/8-1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN QPP | QPP4=>
|
|
IF data_cnt > 0 THEN
|
|
IF data_cnt mod 2 = 0 THEN
|
|
quadpg <= FALSE;
|
|
write <= '0';
|
|
FOR I IN 0 TO (PageSize-1) 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 > PageSize*2 THEN
|
|
Byte_number <= PageSize-1;
|
|
ELSE
|
|
Byte_number <= data_cnt/2-1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ABWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 32 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 31 LOOP
|
|
AutoBoot_reg_in(J) <=
|
|
Data_in(31-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN BRWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
Bank_Addr_reg_in(J) <=
|
|
Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ASPP =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 16 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 15 LOOP
|
|
ASP_reg_in(J) <=
|
|
Data_in(15-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN DYBWR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
DYBAR_in(J) <=
|
|
Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PNVDLR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
NVDLR_reg_in(J) <= Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN WVDLR =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 8 THEN
|
|
write <= '0';
|
|
FOR J IN 0 TO 7 LOOP
|
|
VDLR_reg_in(J) <= Data_in(7-J);
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PASSP =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 64 THEN
|
|
write <= '0';
|
|
FOR J IN 1 TO 8 LOOP
|
|
FOR K IN 1 TO 8 LOOP
|
|
Password_reg_in(J*8-K) <=
|
|
Data_in(8*(J-1)+K-1);
|
|
END LOOP;
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PASSU =>
|
|
IF ((HOLDNeg_pullup='1' AND QUAD='0') OR
|
|
QUAD='1') THEN
|
|
IF data_cnt = 64 THEN
|
|
write <= '0';
|
|
FOR J IN 1 TO 8 LOOP
|
|
FOR K IN 1 TO 8 LOOP
|
|
PASS_TEMP(J*8-K) <=
|
|
Data_in(8*(J-1)+K-1);
|
|
END LOOP;
|
|
END LOOP;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN others =>
|
|
null;
|
|
|
|
END CASE;
|
|
END IF;
|
|
END CASE;
|
|
END IF;
|
|
|
|
END PROCESS BusCycleDecode;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Timing control for the Page Program
|
|
---------------------------------------------------------------------------
|
|
ProgTime : PROCESS(PSTART, PGSUSP, PGRES, RST, Reseted)
|
|
VARIABLE pob : time;
|
|
VARIABLE elapsed : time;
|
|
VARIABLE start : time;
|
|
VARIABLE duration : time;
|
|
BEGIN
|
|
IF rising_edge(PSTART) AND PDONE = '1' THEN
|
|
IF Instruct = PP OR Instruct = PP4 OR Instruct = OTPP OR
|
|
Instruct = QPP OR Instruct = QPP4 THEN
|
|
pob := tdevice_PP;
|
|
ELSE
|
|
pob := tdevice_BP;
|
|
END IF;
|
|
elapsed := 0 ns;
|
|
start := NOW;
|
|
PDONE <= '0', '1' AFTER pob;
|
|
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;
|
|
|
|
IF (RST'EVENT AND RST = '0') THEN
|
|
PDONE <= '1'; -- reset done, programing terminated
|
|
ELSIF rising_edge(Reseted) THEN
|
|
PDONE <= '1'; -- reset done, programing terminated
|
|
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;
|
|
|
|
IF (RST'EVENT AND RST = '0') THEN
|
|
WDONE <= '1'; -- reset done, programing terminated
|
|
ELSIF rising_edge(Reseted) THEN
|
|
WDONE <= '1'; -- reset done, programing terminated
|
|
END IF;
|
|
|
|
END PROCESS WriteTime;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- Timing control for the Bulk Erase
|
|
---------------------------------------------------------------------------
|
|
ErsTime : PROCESS(ESTART, ESUSP, ERES, RST, Reseted)
|
|
VARIABLE seo : time;
|
|
VARIABLE beo : time;
|
|
VARIABLE elapsed : time;
|
|
VARIABLE start : time;
|
|
VARIABLE duration : time;
|
|
BEGIN
|
|
IF LongTimming THEN
|
|
seo := tdevice_SE;
|
|
beo := tdevice_BE;
|
|
ELSE
|
|
seo := tdevice_SE / 1000;
|
|
beo := tdevice_BE / 1000;
|
|
END IF;
|
|
IF rising_edge(ESTART) AND EDONE = '1' THEN
|
|
IF Instruct = BE THEN
|
|
duration := beo;
|
|
ELSE --Instruct = SE OR SE4
|
|
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;
|
|
|
|
IF (RST'EVENT AND RST = '0') THEN
|
|
EDONE <= '1'; -- reset done, eras terminated
|
|
ELSIF rising_edge(Reseted) THEN
|
|
EDONE <= '1'; -- reset done, erase terminated
|
|
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, RSTNeg_pullup, WDONE, PDONE,
|
|
ERSSUSP_out, PRGSUSP_out, EDONE, RST_out, PPBERASE_in,
|
|
PASSULCK_in)
|
|
|
|
VARIABLE sect : NATURAL RANGE 0 TO SecNum;
|
|
|
|
BEGIN
|
|
|
|
IF rising_edge(PoweredUp) THEN
|
|
IF ABE = '1' AND RPME /= '0' THEN
|
|
--Autoboot is enabled and The Read Password feature is not enabled
|
|
next_state <= AUTOBOOT;
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&"000000000");
|
|
start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
ELSE
|
|
IF RST_out= '0' then
|
|
next_state <= current_state;
|
|
ELSIF falling_edge(write) AND Instruct = RESET THEN
|
|
IF ABE = '1' AND RPME /= '0' THEN
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&
|
|
"000000000");
|
|
start_delay:= to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
next_state <= AUTOBOOT;
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
ELSE
|
|
CASE current_state IS
|
|
WHEN RESET_STATE =>
|
|
IF rising_edge(RST_out) THEN
|
|
IF ABE = '1' AND RPME /= '0'
|
|
AND RdPswdProtMode = '0' THEN
|
|
next_state <= AUTOBOOT;
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&
|
|
"000000000");
|
|
start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1));
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN IDLE =>
|
|
IF falling_edge(write) AND RdPswdProtMode = '0' THEN
|
|
IF (Instruct = WRR AND WEL = '1' AND BAR_ACC = '0') THEN
|
|
IF ((not(SRWD = '1' AND WPNeg_pullup = '0') AND
|
|
QUAD = '0') OR QUAD = '1') THEN
|
|
-- can not execute if HPM is entered
|
|
-- or if WEL bit is zero
|
|
IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR
|
|
(BPNV ='1' AND Config_reg1_in(3)='0')) AND
|
|
cfg_write = '1' THEN
|
|
ASSERT cfg_write = '0'
|
|
REPORT "Changing value of Configuration " &
|
|
"Register OTP bit from 1 to 0 is " &
|
|
"not allowed!!!"
|
|
SEVERITY WARNING;
|
|
ELSE
|
|
next_state <= WRITE_SR;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct = PP OR Instruct = QPP OR
|
|
Instruct = PP4 OR Instruct = QPP4) AND
|
|
WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
next_state <= PAGE_PG;
|
|
IF (Instruct = QPP OR Instruct = QPP4) AND
|
|
QPP_page(pgm_page) = '1' THEN
|
|
REPORT "WARNING:The same page must not be" &
|
|
" programmed more than once!!!"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct=OTPP AND WEL = '1' AND FREEZE = '0' THEN
|
|
IF ((((Address >= 16#10# AND Address <= 16#13#) OR
|
|
(Address >= 16#20# AND Address <= 16#FF#))
|
|
AND LOCK_BYTE1(Address/32) = '1') OR
|
|
((Address >= 16#100# AND Address <= 16#1FF#)
|
|
AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR
|
|
((Address >= 16#200# AND Address <= 16#2FF#)
|
|
AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR
|
|
((Address >= 16#300# AND Address <= 16#3FF#)
|
|
AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND
|
|
(Address + Byte_number <= OTPHiAddr) THEN
|
|
next_state <= OTP_PG;
|
|
END IF;
|
|
ELSIF (Instruct= SE OR Instruct= SE4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
IF Sec_Prot(sect) = '0' AND PPB_bits(sect)='1'
|
|
AND DYB_bits(sect)='1' THEN
|
|
next_state <= SECTOR_ERS;
|
|
END IF;
|
|
ELSIF (Instruct=P4E OR Instruct=P4E4) AND WEL='1' THEN
|
|
--A P4E instruction applied to a sector that
|
|
--is larger than 4 KB will not be executed
|
|
--and will not set the E_ERR status.
|
|
REPORT "Warning! Parameter 4KB-sector Erase "&
|
|
"Instruction is not allowed for "&
|
|
"512Mbit memory size!!! "&
|
|
"Instruction is ignored!!!"
|
|
SEVERITY warning;
|
|
ELSIF Instruct = BE AND WEL = '1' AND
|
|
(BP0='0' AND BP1='0' AND BP2='0') THEN
|
|
next_state <= BULK_ERS;
|
|
ELSIF Instruct = ABWR AND WEL = '1' THEN
|
|
--Autoboot Register Write Command
|
|
next_state <= AUTOBOOT_PG;
|
|
ELSIF Instruct = ASPP AND WEL = '1' THEN
|
|
--ASP Register Program Command
|
|
IF not(ASPOTPFLAG) THEN
|
|
next_state <= ASP_PG;
|
|
END IF;
|
|
ELSIF Instruct = PLBWR AND WEL = '1' AND
|
|
RdPswdProtEnable = '0' THEN
|
|
next_state <= PLB_PG;
|
|
ELSIF Instruct = PASSP AND WEL = '1' THEN
|
|
IF not(PWDMLB='0' AND PSTMLB='1') THEN
|
|
next_state <= PASS_PG;
|
|
END IF;
|
|
ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN
|
|
next_state <= PASS_UNLOCK;
|
|
ELSIF Instruct = PPBP AND WEL = '1' THEN
|
|
next_state <= PPB_PG;
|
|
ELSIF (Instruct=PPBERS AND WEL='1' AND PPBOTP='1') THEN
|
|
next_state <= PPB_ERS;
|
|
ELSIF Instruct = DYBWR AND WEL = '1' THEN
|
|
next_state <= DYB_PG;
|
|
ELSIF Instruct = PNVDLR AND WEL = '1' THEN
|
|
next_state <= NVDLR_PG;
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
END IF;
|
|
IF falling_edge(write) AND RdPswdProtMode = '1' AND
|
|
WIP = '0' THEN
|
|
IF Instruct = PASSU THEN
|
|
next_state <= PASS_UNLOCK;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT =>
|
|
IF rising_edge(CSNeg_ipd) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN WRITE_SR =>
|
|
IF rising_edge(WDONE) 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;
|
|
|
|
WHEN PG_SUSP =>
|
|
IF falling_edge(write) THEN
|
|
IF Instruct = PGRS THEN
|
|
next_state <= PAGE_PG;
|
|
ELSE
|
|
next_state <= PG_SUSP;
|
|
END IF;
|
|
ELSE
|
|
next_state <= PG_SUSP;
|
|
END IF;
|
|
|
|
WHEN OTP_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
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 falling_edge(write) THEN
|
|
IF (Instruct = PP OR Instruct = QPP OR
|
|
Instruct = PP4 OR Instruct = QPP4) AND
|
|
WEL = '1' THEN
|
|
IF SectorSuspend /= (Address/(SecSize+1)) THEN
|
|
pgm_page := Address / PageSize;
|
|
IF PPB_bits(Address/SecSize)='1' AND
|
|
DYB_bits(Address/SecSize)='1' THEN
|
|
next_state <= ERS_SUSP_PG;
|
|
IF (Instruct = QPP OR Instruct = QPP4) AND
|
|
QPP_page(pgm_page) = '1' THEN
|
|
REPORT "WARNING:The same page must " &
|
|
"not be programmed more than once!!!"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF (Instruct = DYBWR AND WEL = '1') THEN
|
|
next_state <= DYB_PG;
|
|
ELSIF Instruct = ERRS THEN
|
|
next_state <= SECTOR_ERS;
|
|
END IF;
|
|
ELSE
|
|
next_state <= ERS_SUSP;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG =>
|
|
IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN
|
|
next_state <= ERS_SUSP_PG_SUSP;
|
|
ELSIF rising_edge(PDONE) THEN
|
|
next_state <= ERS_SUSP;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG_SUSP =>
|
|
IF falling_edge(write) THEN
|
|
IF Instruct = PGRS THEN
|
|
next_state <= ERS_SUSP_PG;
|
|
ELSE
|
|
next_state <= ERS_SUSP_PG_SUSP;
|
|
END IF;
|
|
ELSE
|
|
next_state <= ERS_SUSP_PG_SUSP;
|
|
END IF;
|
|
|
|
WHEN PASS_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PASS_UNLOCK =>
|
|
IF falling_edge(PASSULCK_in) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PPB_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PPB_ERS =>
|
|
IF falling_edge(PPBERASE_in) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN PLB_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN DYB_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
IF ES = '1' THEN
|
|
next_state <= ERS_SUSP;
|
|
ELSE
|
|
next_state <= IDLE;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ASP_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
WHEN NVDLR_PG =>
|
|
IF rising_edge(PDONE) THEN
|
|
next_state <= IDLE;
|
|
END IF;
|
|
|
|
END CASE;
|
|
END IF;
|
|
END IF;
|
|
|
|
END PROCESS StateGen;
|
|
|
|
ReadEnable: PROCESS (read_out)
|
|
BEGIN
|
|
oe_z <= rising_edge(read_out) AND PoweredUp = '1';
|
|
|
|
IF read_out'EVENT AND read_out = '0' AND PoweredUp = '1' THEN
|
|
oe <= TRUE, FALSE AFTER 1 ns;
|
|
END IF;
|
|
END PROCESS ReadEnable;
|
|
|
|
---------------------------------------------------------------------------
|
|
--FSM Output generation and general funcionality
|
|
---------------------------------------------------------------------------
|
|
Functional : PROCESS(write,current_state,start_autoboot,CSNeg_ipd,
|
|
HOLDNeg_pullup, Instruct, Address, WByte,change_addr,
|
|
PoweredUp, WPNeg_pullup, WDONE, PDONE, EDONE,
|
|
PRGSUSP_out,ERSSUSP_out, PASSACC_out, oe, oe_z)
|
|
|
|
VARIABLE WData : WByteType:= (OTHERS => MaxData);
|
|
|
|
VARIABLE AddrLo : NATURAL;
|
|
VARIABLE AddrHi : NATURAL;
|
|
VARIABLE Addr : NATURAL;
|
|
VARIABLE Addr_tmp : NATURAL;
|
|
|
|
VARIABLE data_out : std_logic_vector(7 downto 0);
|
|
VARIABLE ident_out : std_logic_vector(647 downto 0);
|
|
|
|
VARIABLE ExtendedID : NATURAL;
|
|
|
|
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 old_pass : std_logic_vector(63 downto 0);
|
|
VARIABLE new_pass : std_logic_vector(63 downto 0);
|
|
VARIABLE wr_cnt : NATURAL RANGE 0 TO 511;
|
|
--Data Learning Pattern Enable
|
|
VARIABLE dlp_act : BOOLEAN := FALSE;
|
|
|
|
VARIABLE sect : NATURAL RANGE 0 TO SecNum;
|
|
VARIABLE cnt : NATURAL RANGE 0 TO 512 := 0;
|
|
|
|
BEGIN
|
|
|
|
-----------------------------------------------------------------------
|
|
-- Functionality Section
|
|
-----------------------------------------------------------------------
|
|
|
|
IF Instruct'EVENT THEN
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
fast_rd <= true;
|
|
dual <= false;
|
|
rd <= false;
|
|
any_read <= false;
|
|
END IF;
|
|
|
|
IF PASSACC_out'EVENT AND PASSACC_out = '1' THEN
|
|
WIP := '0';
|
|
PASSACC_in <= '0';
|
|
END IF;
|
|
|
|
IF rising_edge(PoweredUp) THEN
|
|
--the default condition after power-up
|
|
--The Bank Address Register is loaded to all zeroes
|
|
Bank_Addr_reg := (others => '0');
|
|
--The Configuration Register FREEZE bit is cleared.
|
|
FREEZE := '0';
|
|
--The WEL bit is cleared.
|
|
WEL := '0';
|
|
--When BPNV is set to '1'. the BP2-0 bits in Status Register are
|
|
--volatile and will be reset binary 111 after power-on reset
|
|
IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN
|
|
BP0 := '1';
|
|
BP1 := '1';
|
|
BP2 := '1';
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
--As shipped from the factory, all devices default ASP to the
|
|
--Persistent Protection mode, with all sectors unprotected,
|
|
--when power is applied. The device programmer or host system must
|
|
--then choose which sector protection method to use.
|
|
--For Persistent Protection mode, PPBLOCK defaults to "1"
|
|
PPB_LOCK := '1';
|
|
PPB_LOCK_temp <= '1';
|
|
DYB_bits := (OTHERS => '1');
|
|
END IF;
|
|
|
|
IF falling_edge(write) AND Instruct = RESET THEN
|
|
--The Configuration Register is set for Address mode
|
|
Bank_Addr_reg := (others => '0');
|
|
--P_ERR bit is cleared
|
|
P_ERR := '0';
|
|
--E_ERR bit is cleared
|
|
E_ERR := '0';
|
|
--The WEL bit is cleared.
|
|
WEL := '0';
|
|
--The WIP bit is cleared.
|
|
WIP := '0';
|
|
--The ES bit is cleared.
|
|
ES := '0';
|
|
--The PS bit is cleared.
|
|
PS := '0';
|
|
|
|
DummyBytes_act := '0';
|
|
--When BPNV is set to '1'. the BP2-0 bits in Status
|
|
--Register are volatile and will be reseted after
|
|
--reset command
|
|
IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN
|
|
BP0 := '1';
|
|
BP1 := '1';
|
|
BP2 := '1';
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
END IF;
|
|
|
|
IF change_addr'EVENT THEN
|
|
read_addr := Address;
|
|
END IF;
|
|
|
|
CASE current_state IS
|
|
WHEN IDLE =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF falling_edge(write) AND RdPswdProtMode = '1' THEN
|
|
IF Instruct = PASSU THEN
|
|
IF WIP = '0' THEN
|
|
PASSULCK_in <= '1';
|
|
ELSE
|
|
REPORT "The PASSU command cannot be accepted"&
|
|
" any faster than once every 100us"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
ELSIF Instruct = CLSR THEN
|
|
--The Clear Status Register Command resets bit SR1[5]
|
|
--(Erase Fail Flag) and bit SR1[6] (Program Fail Flag)
|
|
E_ERR := '0';
|
|
P_ERR := '0';
|
|
END IF;
|
|
END IF;
|
|
IF falling_edge(write) AND RdPswdProtMode = '0' THEN
|
|
read_cnt := 0;
|
|
byte_cnt := 1;
|
|
IF Instruct = WREN THEN
|
|
WEL := '1';
|
|
ELSIF Instruct = WRDI THEN
|
|
WEL := '0';
|
|
ELSIF Instruct = WRR AND WEL = '1' AND BAR_ACC = '0' THEN
|
|
IF (not(SRWD = '1' AND WPNeg_pullup = '0') AND
|
|
QUAD ='0') OR QUAD ='1' THEN
|
|
-- can not execute if Hardware Protection Mode
|
|
-- is entered or if WEL bit is zero
|
|
|
|
IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR
|
|
(BPNV ='1' AND Config_reg1_in(3)='0')) AND
|
|
cfg_write = '1' THEN
|
|
P_ERR := '1';
|
|
ELSE
|
|
WSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
P_ERR := '1';
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF (Sec_Prot(sect)= '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
P_ERR := '1';
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF Instruct = OTPP AND WEL = '1' THEN
|
|
-- As long as the FREEZE bit remains cleared to a logic '0'
|
|
--the OTP address space is programmable.
|
|
IF FREEZE = '0' THEN
|
|
IF ((((Address >= 16#0010# AND Address <= 16#13#)OR
|
|
(Address >= 16#0020# AND Address <= 16#FF#))
|
|
AND LOCK_BYTE1(Address/32) = '1') OR
|
|
((Address >= 16#100# AND Address <= 16#1FF#)
|
|
AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR
|
|
((Address >= 16#200# AND Address <= 16#2FF#)
|
|
AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR
|
|
((Address >= 16#300# AND Address <= 16#3FF#)
|
|
AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND
|
|
(Address + Byte_number <= OTPHiAddr) THEN
|
|
PSTART <= '1', '0' AFTER 1 ns;
|
|
WIP := '1';
|
|
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;
|
|
ELSIF (Address < 16#0010# OR (Address > 16#0013# AND
|
|
Address < 16#0020#) OR Address > 16#3FF# ) THEN
|
|
P_ERR := '1';
|
|
WEL := '0';
|
|
IF Address < 16#0020# THEN
|
|
ASSERT false
|
|
REPORT "Given address is in" &
|
|
"reserved address range"
|
|
SEVERITY warning;
|
|
ELSIF Address > 16#3FF# THEN
|
|
ASSERT false
|
|
REPORT "Given address is out of" &
|
|
"OTP address range"
|
|
SEVERITY warning;
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSIF (Instruct = SE OR Instruct = SE4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
SectorSuspend <= sect;
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
ESTART <= '1', '0' AFTER 5 ns;
|
|
ESUSP <= '0';
|
|
ERES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
Addr := Address;
|
|
ELSE
|
|
E_ERR := '1';
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF (Instruct = P4E OR Instruct = P4E4) AND WEL = '1' THEN
|
|
WEL := '0';
|
|
ELSIF Instruct = BE AND WEL = '1' THEN
|
|
IF (BP0='0' AND BP1='0' AND BP2='0') THEN
|
|
ESTART <= '1', '0' AFTER 5 ns;
|
|
ESUSP <= '0';
|
|
ERES <= '0';
|
|
INITIAL_CONFIG <= '1';
|
|
WIP := '1';
|
|
ELSE
|
|
--The Bulk Erase command will not set E_ERR if a
|
|
--protected sector is found during the command
|
|
--execution.
|
|
WEL := '0';
|
|
END IF;
|
|
ELSIF Instruct = PASSP AND WEL = '1' THEN
|
|
IF not(PWDMLB='0' AND PSTMLB='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSE
|
|
REPORT "Password programming is not allowed" &
|
|
" in Password Protection Mode."
|
|
SEVERITY warning;
|
|
END IF;
|
|
ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN
|
|
PASSULCK_in <= '1';
|
|
ELSIF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
IF (P_ERR = '0' AND E_ERR = '0') THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = ASPP AND WEL = '1' THEN
|
|
IF not(ASPOTPFLAG) THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
REPORT "Once the Protection Mode is selected," &
|
|
"no further changes to the ASP register" &
|
|
"is allowed."
|
|
SEVERITY warning;
|
|
END IF;
|
|
ELSIF Instruct = ABWR AND WEL = '1' THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = PPBP AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
Addr := Address;
|
|
pgm_page := Address/PageSize;
|
|
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = PPBERS AND WEL = '1' THEN
|
|
IF PPBOTP = '1' THEN
|
|
PPBERASE_in <= '1';
|
|
WIP := '1';
|
|
ELSE
|
|
E_ERR := '1';
|
|
END IF;
|
|
ELSIF Instruct = PLBWR AND WEL = '1' AND
|
|
RdPswdProtEnable = '0' THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = DYBWR AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = PNVDLR AND WEL = '1' THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = WVDLR AND WEL = '1' THEN
|
|
VDLR_reg := VDLR_reg_in;
|
|
WEL := '0';
|
|
ELSIF Instruct = CLSR THEN
|
|
--The Clear Status Register Command resets bit SR1[5]
|
|
--(Erase Fail Flag) and bit SR1[6] (Program Fail Flag)
|
|
E_ERR := '0';
|
|
P_ERR := '0';
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = RES OR Instruct = DLPRD THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct = DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
ELSIF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF ((bus_cycle_state = DUMMY_BYTES OR
|
|
DummyBytes_act='1') AND VDLR_reg/="00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct = DDRFR OR Instruct = DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
dlp_act := FALSE;
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
read_addr_tmp := read_addr;
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
SecAddr := ReturnSectorIDRdPswdMd(TBPROT);
|
|
read_addr := Sec_addr + SecAddr*(SecSize+1);
|
|
IF RdPswdProtMode = '0' THEN
|
|
read_addr := read_addr_tmp;
|
|
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;
|
|
END IF;
|
|
ELSIF Instruct = DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct = DDRDIOR OR Instruct = DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
read_addr_tmp := read_addr;
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
SecAddr := ReturnSectorIDRdPswdMd(TBPROT);
|
|
read_addr := Sec_addr + SecAddr*(SecSize+1);
|
|
IF RdPswdProtMode = '0' THEN
|
|
read_addr := read_addr_tmp;
|
|
END IF;
|
|
|
|
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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF ((Instruct = DDRQIOR OR Instruct = DDRQIOR4) AND
|
|
QUAD = '1') THEN
|
|
IF EHP THEN
|
|
IF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
read_addr_tmp := read_addr;
|
|
SecAddr := ReturnSectorID(read_addr);
|
|
Sec_addr := read_addr - SecAddr*(SecSize+1);
|
|
SecAddr := ReturnSectorIDRdPswdMd(TBPROT);
|
|
read_addr := Sec_addr + SecAddr*(SecSize+1);
|
|
IF RdPswdProtMode = '0' THEN
|
|
read_addr := read_addr_tmp;
|
|
END IF;
|
|
|
|
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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = OTPR THEN
|
|
IF (read_addr>=OTPLoAddr) AND
|
|
(read_addr<=OTPHiAddr) AND RdPswdProtMode = '0' THEN
|
|
--Read OTP Memory array
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
data_out := to_slv(OTPMem(read_addr),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
ELSIF (read_addr > OTPHiAddr)
|
|
OR RdPswdProtMode = '1' THEN
|
|
--OTP Read operation will not wrap to the
|
|
--starting address after the OTP address is at
|
|
--its maximum or Read Password Protection Mode
|
|
--is selected; instead, the data beyond the
|
|
--maximum OTP address will be undefined.
|
|
SOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = REMS THEN
|
|
--Read Manufacturer and Device ID
|
|
IF read_addr MOD 2 = 0 THEN
|
|
data_out := to_slv(Manuf_ID,8);
|
|
SOut_zd <= data_out(7 - read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
ELSE
|
|
data_out := to_slv(DeviceID,8);
|
|
SOut_zd <= data_out(7 - read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = RDID THEN
|
|
ident_out := CFI_array_tmp;
|
|
IF read_cnt < 648 THEN
|
|
SOut_zd <= ident_out(647-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
ELSE
|
|
--Continued shifting of output beyond the end of
|
|
--the defined ID-CFI address space will provide
|
|
--undefined data.
|
|
SOut_zd <= 'U';
|
|
END IF;
|
|
ELSIF Instruct = RES THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
data_out := to_slv(ESignature,8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = DLPRD THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= VDLR_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = ABRD THEN
|
|
--Read AutoBoot register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= AutoBoot_reg(31-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 32 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = ASPRD THEN
|
|
--Read ASP Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= ASP_reg(15-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 16 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = PASSRD THEN
|
|
--Read Password Register
|
|
IF not (PWDMLB='0' AND PSTMLB='1') THEN
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Password_reg((8*byte_cnt-1)-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
byte_cnt := byte_cnt + 1;
|
|
IF byte_cnt = 9 THEN
|
|
byte_cnt := 1;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 64 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
IF read_cnt = 0 THEN
|
|
ASSERT false
|
|
REPORT "Verification of password is not " &
|
|
" allowed in Password Protection Mode."
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
ELSIF Instruct = PLBRD THEN
|
|
--Read PPB Lock Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= PPBL(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = DYBRD THEN
|
|
--Read DYB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
DYBAR(7 downto 0) := "UUUUUUUU";
|
|
IF RdPswdProtMode = '0' THEN
|
|
IF DYB_bits(sect) = '1' THEN
|
|
DYBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
DYBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
END IF;
|
|
SOut_zd <= DYBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = PPBRD THEN
|
|
--Read PPB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
PPBAR(7 downto 0) := "UUUUUUUU";
|
|
IF RdPswdProtMode = '0' THEN
|
|
IF PPB_bits(sect) = '1' THEN
|
|
PPBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
PPBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
END IF;
|
|
SOut_zd <= PPBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT =>
|
|
IF start_autoboot = '1' THEN
|
|
IF (oe) THEN
|
|
any_read <= true;
|
|
IF QUAD = '1' THEN
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= false; --max SCK frequency is 104MHz
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
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;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
ELSE
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= true; --max SCK frequency is 133MHz
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
data_out := to_slv(Mem(read_addr),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF QUAD = '1' THEN
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= false; --max SCK frequency is 104MHz
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
ELSE
|
|
IF ABSD > 0 THEN --If ABSD > 0,
|
|
fast_rd <= true; --max SCK frequency is 133MHz
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSE -- If ABSD = 0, max SCK frequency is 50 MHz
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN WRITE_SR =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF WDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
SRWD := Status_reg1_in(7);--MSB first
|
|
|
|
IF LOCK='0' THEN
|
|
IF FREEZE='0' THEN
|
|
--The Freeze Bit, when set to 1, locks the current
|
|
--state of the BP2-0 bits in Status Register and
|
|
--the TBPROT bit in the Config Register
|
|
--As long as the FREEZE bit remains cleared to logic
|
|
--'0', the other bits of the Configuration register
|
|
--including FREEZE are writeable.
|
|
BP2 := Status_reg1_in(4);
|
|
BP1 := Status_reg1_in(3);
|
|
BP0 := Status_reg1_in(2);
|
|
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
|
|
IF TBPROT = '0' AND INITIAL_CONFIG = '0' THEN
|
|
TBPROT := Config_reg1_in(5);
|
|
END IF;
|
|
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
|
|
LC1 := Config_reg1_in(7);
|
|
LC0 := Config_reg1_in(6);
|
|
QUAD := Config_reg1_in(1);
|
|
|
|
IF FREEZE = '0' THEN
|
|
FREEZE := Config_reg1_in(0);
|
|
END IF;
|
|
|
|
IF WRLOCKENABLE AND LOCK = '0' THEN
|
|
LOCK := Config_reg1_in(4);
|
|
WRLOCKENABLE <= false;
|
|
END IF;
|
|
|
|
IF BPNV = '0' THEN
|
|
BPNV := Config_reg1_in(3);
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PAGE_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF falling_edge(PDONE) THEN
|
|
IF (Instruct = QPP OR Instruct = QPP4) THEN
|
|
QPP_page(pgm_page) := '1';
|
|
END IF;
|
|
|
|
ADDRHILO_PG(AddrLo, AddrHi, Addr);
|
|
cnt := 0;
|
|
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
new_int := WData(i);
|
|
old_int := Mem(Addr + i - cnt);
|
|
IF new_int > -1 THEN
|
|
new_bit := to_slv(new_int,8);
|
|
IF old_int > -1 THEN
|
|
old_bit := to_slv(old_int,8);
|
|
FOR j IN 0 TO 7 LOOP
|
|
IF old_bit(j) = '0' THEN
|
|
new_bit(j) := '0';
|
|
END IF;
|
|
END LOOP;
|
|
new_int := to_nat(new_bit);
|
|
END IF;
|
|
WData(i) := new_int;
|
|
ELSE
|
|
WData(i) := -1;
|
|
END IF;
|
|
|
|
Mem(Addr + i - cnt) := -1;
|
|
|
|
IF (Addr + i) = AddrHi THEN
|
|
Addr := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
cnt :=0;
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
Mem(Addr_tmp + i - cnt) := WData(i);
|
|
IF (Addr_tmp + i) = AddrHi THEN
|
|
Addr_tmp := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN
|
|
IF RES_TO_SUSP_MIN_TIME = '0' THEN
|
|
PGSUSP <= '1', '0' AFTER 1 ns;
|
|
PRGSUSP_in <= '1';
|
|
ASSERT RES_TO_SUSP_TYP_TIME = '0'
|
|
REPORT "Typical periods are needed for " &
|
|
"Program to progress to completion"
|
|
SEVERITY warning;
|
|
ELSE
|
|
ASSERT FALSE
|
|
REPORT "Minimum for tPRS is not satisfied! " &
|
|
"PGSP command is ignored"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PG_SUSP =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN
|
|
PRGSUSP_in <= '0';
|
|
--The RDY/BSY bit in the Status Register will indicate that
|
|
--the device is ready for another operation.
|
|
WIP := '0';
|
|
--The Program Suspend (PS) bit in the Status Register will
|
|
--be set to the logical “1” state to indicate that the
|
|
--program operation has been suspended.
|
|
PS := '1';
|
|
END IF;
|
|
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
--Read Array Operations
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF pgm_page /= read_addr/PageSize THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:= VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
read_cnt:=read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
data_out := to_slv(Mem(read_addr),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF pgm_page /= read_addr/PageSize THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency"&
|
|
" is set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:=VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
SIOut_zd<=data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
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;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF pgm_page /= read_addr/PageSize THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF EHP THEN
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
HOLDNegOut_zd <= 'U';
|
|
WPNegOut_zd <= 'U';
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 2 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
ELSIF falling_edge(write) THEN
|
|
IF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
-- Write to the lower address bits of the BAR
|
|
IF (P_ERR = '0' AND E_ERR = '0')THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = PGRS THEN
|
|
PGRES <= '1', '0' AFTER 5 ns;
|
|
PS := '0';
|
|
WIP := '1';
|
|
RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns;
|
|
RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us;
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND
|
|
RdPswdProtMode = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG_SUSP =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN
|
|
PRGSUSP_in <= '0';
|
|
--The RDY/BSY bit in the Status Register will indicate that
|
|
--the device is ready for another operation.
|
|
WIP := '0';
|
|
--The Program Suspend (PS) bit in the Status Register will
|
|
--be set to the logical “1” state to indicate that the
|
|
--program operation has been suspended.
|
|
PS := '1';
|
|
END IF;
|
|
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
--Read Array Operations
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF (SectorSuspend /= read_addr/(SecSize+1) AND
|
|
pgm_page /= read_addr/PageSize) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:= VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
read_cnt:=read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
data_out := to_slv(Mem(read_addr),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF (SectorSuspend /= read_addr/(SecSize+1) AND
|
|
pgm_page /= read_addr/PageSize) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency"&
|
|
" is set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:=VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
SIOut_zd<=data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
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;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF (SectorSuspend /= read_addr/(SecSize+1) AND
|
|
pgm_page /= read_addr/PageSize) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF EHP THEN
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
HOLDNegOut_zd <= 'U';
|
|
WPNegOut_zd <= 'U';
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 2 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
ELSIF falling_edge(write) THEN
|
|
IF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
-- Write to the lower address bits of the BAR
|
|
IF (P_ERR = '0' AND E_ERR = '0')THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = PGRS THEN
|
|
PGRES <= '1', '0' AFTER 5 ns;
|
|
PS := '0';
|
|
WIP := '1';
|
|
RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns;
|
|
RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us;
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND
|
|
RdPswdProtMode = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN OTP_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF Address + wr_cnt <= OTPHiAddr THEN
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
new_int := WData(i);
|
|
old_int := OTPMem(Addr + i);
|
|
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;
|
|
|
|
OTPMem(Addr + i) := -1;
|
|
END LOOP;
|
|
ELSE
|
|
ASSERT false
|
|
REPORT "Programming will reach over address limit"&
|
|
" of OTP array"
|
|
SEVERITY warning;
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
OTPMem(Addr_tmp + i) := WData(i);
|
|
END LOOP;
|
|
LOCK_BYTE1 := to_slv(OTPMem(16#10#),8);
|
|
LOCK_BYTE2 := to_slv(OTPMem(16#11#),8);
|
|
LOCK_BYTE3 := to_slv(OTPMem(16#12#),8);
|
|
LOCK_BYTE4 := to_slv(OTPMem(16#13#),8);
|
|
END IF;
|
|
|
|
WHEN SECTOR_ERS =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
ADDRHILO_SEC(AddrLo, AddrHi, Addr);
|
|
FOR i IN AddrLo TO AddrHi LOOP
|
|
Mem(i) := -1;
|
|
END LOOP;
|
|
IF EDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN AddrLo TO AddrHi LOOP
|
|
Mem(i) := MaxData;
|
|
END LOOP;
|
|
ELSIF Instruct = ERSP AND ERSSUSP_in = '0' THEN
|
|
ESUSP <= '1', '0' AFTER 10 ns;
|
|
ERSSUSP_in <= '1';
|
|
ASSERT RES_TO_SUSP_TYP_TIME = '0'
|
|
REPORT "Typical periods are needed for " &
|
|
"Program to progress to completion"
|
|
SEVERITY warning;
|
|
END IF;
|
|
|
|
WHEN BULK_ERS =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF falling_edge(EDONE) THEN
|
|
FOR i IN 0 TO AddrRANGE LOOP
|
|
sect := i/(SecSize+1);
|
|
IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN
|
|
Mem(i) := -1;
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
IF EDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN 0 TO AddrRANGE LOOP
|
|
sect := i/(SecSize+1);
|
|
IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN
|
|
Mem(i) := MaxData;
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF ERSSUSP_out = '1' THEN
|
|
ERSSUSP_in <= '0';
|
|
--The Erase Suspend (ES) bit in the Status Register will
|
|
--be set to the logical “1” state to indicate that the
|
|
--erase operation has been suspended.
|
|
ES := '1';
|
|
--The WIP bit in the Status Register will indicate that
|
|
--the device is ready for another operation.
|
|
WIP := '0';
|
|
END IF;
|
|
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = DYBRD THEN
|
|
--Read DYB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF DYB_bits(sect) = '1' THEN
|
|
DYBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
DYBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
SOut_zd <= DYBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = BRRD THEN
|
|
--Read Bank Address Register
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
SOut_zd <= Bank_Addr_reg(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = PPBRD THEN
|
|
--Read PPB Access Register
|
|
sect := Address/(SecSize+1);
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
PPBAR(7 downto 0) := "UUUUUUUU";
|
|
IF RdPswdProtMode = '0' THEN
|
|
IF PPB_bits(sect) = '1' THEN
|
|
PPBAR(7 downto 0) := "11111111";
|
|
ELSE
|
|
PPBAR(7 downto 0) := "00000000";
|
|
END IF;
|
|
END IF;
|
|
SOut_zd <= PPBAR(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
--Read Array Operations
|
|
ELSIF Instruct = READ OR Instruct = RD4 OR
|
|
Instruct = FSTRD OR Instruct = FSTRD4 OR
|
|
Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
IF SectorSuspend /= read_addr/(SecSize+1) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 1 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3 OR
|
|
Latency_code = 0) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:= VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
read_cnt:=read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is
|
|
-- enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
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 IF;
|
|
END IF;
|
|
ELSE
|
|
data_out := to_slv(Mem(read_addr),8);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF SectorSuspend /= read_addr/(SecSize+1) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN
|
|
IF EHP THEN
|
|
IF Latency_code = 0 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 1) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency"&
|
|
" is set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out:=VDLR_reg;
|
|
SOut_zd <=data_out(7-read_cnt);
|
|
SIOut_zd<=data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF Latency_code = 3 THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP)
|
|
-- is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND
|
|
dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
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;
|
|
END IF;
|
|
ELSE
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
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;
|
|
END IF;
|
|
ELSIF (Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 OR
|
|
Instruct = DDRQIOR OR Instruct= DDRQIOR4)
|
|
AND QUAD = '1' THEN
|
|
--Read Memory array
|
|
IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
END IF;
|
|
IF SectorSuspend /= read_addr/(SecSize+1) THEN
|
|
IF ((bus_cycle_state = DUMMY_BYTES
|
|
OR DummyBytes_act = '1')
|
|
AND VDLR_reg /= "00000000") THEN
|
|
DummyBytes_act := '0';
|
|
IF EHP THEN
|
|
IF (Latency_code=0
|
|
AND dummy_cnt_act>=2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
IF (Latency_code = 0 AND
|
|
dummy_cnt_act >= 2) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 1 AND
|
|
dummy_cnt_act >= 3) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 2 AND
|
|
dummy_cnt_act >= 4) THEN
|
|
dlp_act := TRUE;
|
|
ELSIF (Latency_code = 3) THEN
|
|
dlp_act := FALSE;
|
|
REPORT "Inappropriate latency is"&
|
|
" set during DPL mode"
|
|
SEVERITY WARNING;
|
|
END IF;
|
|
-- Data Learning Pattern (DLP) is enabled
|
|
-- Optional DLP
|
|
IF (VDLR_reg/="00000000" AND dlp_act) THEN
|
|
dlp_act := FALSE;
|
|
data_out := VDLR_reg;
|
|
HOLDNegOut_zd <= data_out(7-read_cnt);
|
|
WPNegOut_zd <= data_out(7-read_cnt);
|
|
SOut_zd <= data_out(7-read_cnt);
|
|
SIOut_zd <= data_out(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
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 read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
END IF;
|
|
ELSE
|
|
HOLDNegOut_zd <= 'U';
|
|
WPNegOut_zd <= 'U';
|
|
SOut_zd <= 'U';
|
|
SIOut_zd <= 'U';
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 2 THEN
|
|
read_cnt := 0;
|
|
IF read_addr = AddrRANGE THEN
|
|
read_addr := 0;
|
|
ELSE
|
|
read_addr := read_addr + 1;
|
|
END IF;
|
|
END IF;
|
|
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
IF Instruct = READ OR Instruct = RD4 THEN
|
|
fast_rd <= false;
|
|
rd <= true;
|
|
dual <= false;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= true;
|
|
ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSIF Instruct =DOR OR Instruct=DOR4 OR
|
|
Instruct = DIOR OR Instruct = DIOR4 OR
|
|
Instruct = QOR OR Instruct=QOR4 OR
|
|
Instruct = QIOR OR Instruct= QIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= false;
|
|
ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN
|
|
fast_rd <= false;
|
|
rd <= false;
|
|
dual <= true;
|
|
ddr <= true;
|
|
ELSE
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
END IF;
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF falling_edge(write) THEN
|
|
IF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF SectorSuspend /= sect THEN
|
|
IF (Sec_Prot(sect) = '0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
WIP := '1' ;
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
pgm_page := Address/PageSize;
|
|
IF SectorSuspend /= sect THEN
|
|
IF (Sec_Prot(sect)='0' AND
|
|
PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
PGSUSP <= '0';
|
|
PGRES <= '0';
|
|
WIP := '1' ;
|
|
SA <= sect;
|
|
Addr := Address;
|
|
Addr_tmp := Address;
|
|
wr_cnt := Byte_number;
|
|
FOR I IN wr_cnt DOWNTO 0 LOOP
|
|
IF Viol /= '0' THEN
|
|
WData(i) := -1;
|
|
ELSE
|
|
WData(i) := WByte(i);
|
|
END IF;
|
|
END LOOP;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSE
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
END IF;
|
|
ELSIF Instruct = WREN THEN
|
|
WEL := '1';
|
|
ELSIF Instruct = CLSR THEN
|
|
--The Clear Status Register Command resets bit SR1[5]
|
|
--(Erase Fail Flag) and bit SR1[6] (Program Fail Flag)
|
|
E_ERR := '0';
|
|
P_ERR := '0';
|
|
ELSIF Instruct = BRWR THEN
|
|
Bank_Addr_reg(7) := Bank_Addr_reg_in(7);
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
ELSIF Instruct = WRR AND BAR_ACC = '1' THEN
|
|
-- Write to the lower address bits of the BAR
|
|
IF (P_ERR = '0' AND E_ERR = '0')THEN
|
|
Bank_Addr_reg(1) := Bank_Addr_reg_in(1);
|
|
Bank_Addr_reg(0) := Bank_Addr_reg_in(0);
|
|
END IF;
|
|
ELSIF Instruct = DYBWR AND WEL = '1' THEN
|
|
sect := Address/(SecSize+1);
|
|
PSTART <= '1', '0' AFTER 5 ns;
|
|
WIP := '1';
|
|
ELSIF Instruct = ERRS THEN
|
|
ERES <= '1', '0' AFTER 5 ns;
|
|
ES := '0';
|
|
WIP := '1';
|
|
Addr := SectorSuspend*(SecSize+1);
|
|
ADDRHILO_SEC(AddrLo, AddrHi, Addr);
|
|
RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us;
|
|
END IF;
|
|
|
|
IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND
|
|
RdPswdProtMode = '0' THEN
|
|
BAR_ACC <= '1';
|
|
ELSE
|
|
BAR_ACC <= '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN ERS_SUSP_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF (Instruct = QPP OR Instruct = QPP4) THEN
|
|
QPP_page(pgm_page) := '1';
|
|
END IF;
|
|
|
|
ADDRHILO_PG(AddrLo, AddrHi, Addr);
|
|
cnt := 0;
|
|
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
new_int := WData(i);
|
|
old_int := Mem(Addr + i - cnt);
|
|
IF new_int > -1 THEN
|
|
new_bit := to_slv(new_int,8);
|
|
IF old_int > -1 THEN
|
|
old_bit := to_slv(old_int,8);
|
|
FOR j IN 0 TO 7 LOOP
|
|
IF old_bit(j) = '0' THEN
|
|
new_bit(j) := '0';
|
|
END IF;
|
|
END LOOP;
|
|
new_int := to_nat(new_bit);
|
|
END IF;
|
|
WData(i) := new_int;
|
|
ELSE
|
|
WData(i) := -1;
|
|
END IF;
|
|
|
|
IF (Addr + i) = AddrHi THEN
|
|
Addr := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
cnt :=0;
|
|
|
|
IF PDONE = '1' THEN
|
|
WIP := '0';
|
|
WEL := '0';
|
|
FOR i IN 0 TO wr_cnt LOOP
|
|
Mem(Addr_tmp + i - cnt) := WData(i);
|
|
IF (Addr_tmp + i) = AddrHi THEN
|
|
Addr_tmp := AddrLo;
|
|
cnt := i + 1;
|
|
END IF;
|
|
END LOOP;
|
|
ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN
|
|
IF RES_TO_SUSP_MIN_TIME = '0' THEN
|
|
PGSUSP <= '1', '0' AFTER 1 ns;
|
|
PRGSUSP_in <= '1';
|
|
ASSERT RES_TO_SUSP_TYP_TIME = '0'
|
|
REPORT "Typical periods are needed for " &
|
|
"Program to progress to completion"
|
|
SEVERITY warning;
|
|
ELSE
|
|
ASSERT FALSE
|
|
REPORT "Minimum for tPRS is not satisfied! " &
|
|
"PGSP command is ignored"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PASS_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
new_pass := Password_reg_in;
|
|
old_pass := Password_reg;
|
|
FOR j IN 0 TO 63 LOOP
|
|
IF old_pass(j) = '0' THEN
|
|
new_pass(j) := '0';
|
|
END IF;
|
|
END LOOP;
|
|
|
|
IF PDONE = '1' THEN
|
|
Password_reg := new_pass;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN PASS_UNLOCK =>
|
|
WIP := '1';
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PASS_TEMP = Password_reg THEN
|
|
PASS_UNLOCKED <= TRUE;
|
|
ELSE
|
|
PASS_UNLOCKED <= FALSE;
|
|
END IF;
|
|
|
|
IF PASSULCK_out = '1' THEN
|
|
IF PASS_UNLOCKED AND PWDMLB = '0' THEN
|
|
PPB_LOCK := '1';
|
|
PPB_LOCK_temp <= '1';
|
|
WIP := '0';
|
|
ELSE
|
|
P_ERR := '1';
|
|
REPORT "Incorrect Password!"
|
|
SEVERITY warning;
|
|
PASSACC_in <= '1';
|
|
END IF;
|
|
WEL := '0';
|
|
PASSULCK_in <= '0';
|
|
END IF;
|
|
|
|
WHEN PPB_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
IF PPB_LOCK /= '0' THEN
|
|
PPB_bits(sect):= '0';
|
|
WIP := '0';
|
|
WEL := '0';
|
|
ELSE
|
|
P_ERR := '0';
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN PPB_ERS =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PPBERASE_out = '1' THEN
|
|
IF PPB_LOCK /= '0' AND PPBOTP = '1' THEN
|
|
PPB_bits:= (OTHERS => '1');
|
|
ELSE
|
|
E_ERR := '1';
|
|
END IF;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
PPBERASE_in <= '0';
|
|
END IF;
|
|
|
|
WHEN AUTOBOOT_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
AutoBoot_reg := AutoBoot_reg_in;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN PLB_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
PPB_LOCK := '0';
|
|
PPB_LOCK_temp <= '0';
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN DYB_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
DYBAR := DYBAR_in;
|
|
IF DYBAR = "11111111" THEN
|
|
DYB_bits(sect):= '1';
|
|
ELSIF DYBAR = "00000000" THEN
|
|
DYB_bits(sect):= '0';
|
|
ELSE
|
|
P_ERR := '1';
|
|
END IF;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN ASP_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
|
|
IF (RPME = '0' AND ASP_reg_in(5) = '1') THEN
|
|
P_ERR := '1';
|
|
REPORT "RPME bit is allready programmed"
|
|
SEVERITY warning;
|
|
ELSE
|
|
RPME := ASP_reg_in(5);
|
|
END IF;
|
|
|
|
IF (PPBOTP = '0' AND ASP_reg_in(3) ='1') THEN
|
|
P_ERR := '1';
|
|
REPORT "PPBOTP bit is allready programmed"
|
|
SEVERITY warning;
|
|
ELSE
|
|
PPBOTP := ASP_reg_in(3);
|
|
END IF;
|
|
|
|
IF (PWDMLB = '1' AND PSTMLB = '1') THEN
|
|
IF (ASP_reg_in(2) = '0' AND ASP_reg_in(1) = '0') THEN
|
|
REPORT "ASPR[2:1] = 00 Illegal condition"
|
|
SEVERITY warning;
|
|
P_ERR := '1';
|
|
ELSE
|
|
IF (ASP_reg_in(2) /= '1' OR
|
|
ASP_reg_in(1) /= '1') THEN
|
|
ASPOTPFLAG <= TRUE;
|
|
END IF;
|
|
PWDMLB := ASP_reg_in(2);
|
|
PSTMLB := ASP_reg_in(1);
|
|
END IF;
|
|
END IF;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
END IF;
|
|
|
|
WHEN NVDLR_PG =>
|
|
fast_rd <= true;
|
|
rd <= false;
|
|
dual <= false;
|
|
ddr <= false;
|
|
IF oe THEN
|
|
any_read <= true;
|
|
IF Instruct = RDSR THEN
|
|
--Read Status Register 1
|
|
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
|
|
SOut_zd <= Status_reg2(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
ELSIF Instruct = RDCR THEN
|
|
--Read Configuration Register 1
|
|
SOut_zd <= Config_reg1(7-read_cnt);
|
|
read_cnt := read_cnt + 1;
|
|
IF read_cnt = 8 THEN
|
|
read_cnt := 0;
|
|
END IF;
|
|
END IF;
|
|
ELSIF oe_z THEN
|
|
HOLDNegOut_zd <= 'Z';
|
|
WPNegOut_zd <= 'Z';
|
|
SOut_zd <= 'Z';
|
|
SIOut_zd <= 'Z';
|
|
END IF;
|
|
|
|
IF PDONE = '1' THEN
|
|
IF NVDLR_reg = "00000000" THEN
|
|
NVDLR_reg :=NVDLR_reg_in;
|
|
VDLR_reg := NVDLR_reg_in;
|
|
WIP := '0';
|
|
WEL := '0';
|
|
ELSE
|
|
WIP := '0';
|
|
WEL := '0';
|
|
P_ERR := '1';
|
|
REPORT "NVDLR is allready programmed"
|
|
SEVERITY warning;
|
|
END IF;
|
|
END IF;
|
|
|
|
WHEN RESET_STATE =>
|
|
--the default condition hardware reset
|
|
--The Bank Address Register is loaded to all zeroes
|
|
Bank_Addr_reg := (others => '0');
|
|
IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN
|
|
BP0 := '1';
|
|
BP1 := '1';
|
|
BP2 := '1';
|
|
BP_bits := BP2 & BP1 & BP0;
|
|
change_BP <= '1', '0' AFTER 1 ns;
|
|
END IF;
|
|
--Resets the Status register 1
|
|
P_ERR := '0';
|
|
E_ERR := '0';
|
|
WEL := '0';
|
|
WIP := '0';
|
|
--Resets the Status register 2
|
|
ES := '0';
|
|
PS := '0';
|
|
--Resets the Configuration register 1
|
|
FREEZE := '0';
|
|
--On reset cycles the data pattern reverts back
|
|
--to what is in the NVDLR
|
|
VDLR_reg := NVDLR_reg;
|
|
dlp_act := FALSE;
|
|
--Loads the Program Buffer with all ones
|
|
WData := (OTHERS => MaxData);
|
|
|
|
IF PWDMLB = '0' THEN
|
|
PPB_LOCK := '0';
|
|
PPB_LOCK_temp <= '0';
|
|
ELSE
|
|
PPB_LOCK := '1';
|
|
PPB_LOCK_temp <= '1';
|
|
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;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- CFI Process
|
|
---------------------------------------------------------------------------
|
|
CFIPreload: PROCESS
|
|
|
|
BEGIN
|
|
------------------------------------------------------------------------
|
|
--CFI array data
|
|
------------------------------------------------------------------------
|
|
-- Manufacturer and Device ID
|
|
CFI_array(16#00#) := 16#01#;
|
|
CFI_array(16#01#) := 16#02#;
|
|
CFI_array(16#02#) := 16#20#;
|
|
CFI_array(16#03#) := 16#00#;
|
|
CFI_array(16#04#) := 16#00#;--Uniform 256KB sectors
|
|
CFI_array(16#05#) := 16#80#;
|
|
CFI_array(16#06#) := 16#00#;
|
|
CFI_array(16#07#) := 16#00#;
|
|
CFI_array(16#08#) := 16#00#;
|
|
CFI_array(16#09#) := 16#00#;
|
|
CFI_array(16#0A#) := 16#00#;
|
|
CFI_array(16#0B#) := 16#00#;
|
|
CFI_array(16#0C#) := 16#00#;
|
|
CFI_array(16#0D#) := 16#00#;
|
|
CFI_array(16#0E#) := 16#00#;
|
|
CFI_array(16#0F#) := 16#00#;
|
|
--CFI Query Identification String
|
|
CFI_array(16#10#) := 16#51#;
|
|
CFI_array(16#11#) := 16#52#;
|
|
CFI_array(16#12#) := 16#59#;
|
|
CFI_array(16#13#) := 16#02#;
|
|
CFI_array(16#14#) := 16#00#;
|
|
CFI_array(16#15#) := 16#40#;
|
|
CFI_array(16#16#) := 16#00#;
|
|
CFI_array(16#17#) := 16#53#;
|
|
CFI_array(16#18#) := 16#46#;
|
|
CFI_array(16#19#) := 16#51#;
|
|
CFI_array(16#1A#) := 16#00#;
|
|
--CFI system interface string
|
|
CFI_array(16#1B#) := 16#27#;
|
|
CFI_array(16#1C#) := 16#36#;
|
|
CFI_array(16#1D#) := 16#00#;
|
|
CFI_array(16#1E#) := 16#00#;
|
|
CFI_array(16#1F#) := 16#06#;
|
|
CFI_array(16#20#) := 16#09#;-- 512B page
|
|
CFI_array(16#21#) := 16#09#;-- 256KB
|
|
CFI_array(16#22#) := 16#11#;
|
|
CFI_array(16#23#) := 16#02#;
|
|
CFI_array(16#24#) := 16#02#;
|
|
CFI_array(16#25#) := 16#03#;
|
|
CFI_array(16#26#) := 16#03#;
|
|
-- Device Geometry Definition
|
|
CFI_array(16#27#) := 16#1A#;
|
|
CFI_array(16#28#) := 16#02#;
|
|
CFI_array(16#29#) := 16#01#;
|
|
CFI_array(16#2A#) := 16#09#;
|
|
CFI_array(16#2B#) := 16#00#;
|
|
CFI_array(16#2C#) := 16#01#;
|
|
CFI_array(16#2D#) := 16#FF#;
|
|
CFI_array(16#2E#) := 16#00#;
|
|
CFI_array(16#2F#) := 16#00#;
|
|
CFI_array(16#30#) := 16#04#;
|
|
CFI_array(16#31#) := 16#FF#;
|
|
CFI_array(16#32#) := 16#FF#;
|
|
CFI_array(16#33#) := 16#FF#;
|
|
CFI_array(16#34#) := 16#FF#;
|
|
CFI_array(16#35#) := 16#FF#;
|
|
CFI_array(16#36#) := 16#FF#;
|
|
CFI_array(16#37#) := 16#FF#;
|
|
CFI_array(16#38#) := 16#FF#;
|
|
CFI_array(16#39#) := 16#FF#;
|
|
CFI_array(16#3A#) := 16#FF#;
|
|
CFI_array(16#3B#) := 16#FF#;
|
|
CFI_array(16#3C#) := 16#FF#;
|
|
CFI_array(16#3D#) := 16#FF#;
|
|
CFI_array(16#3E#) := 16#FF#;
|
|
CFI_array(16#3F#) := 16#FF#;
|
|
-- CFI Primary Vendor-Specific Extended Query
|
|
CFI_array(16#40#) := 16#50#;
|
|
CFI_array(16#41#) := 16#52#;
|
|
CFI_array(16#42#) := 16#49#;
|
|
CFI_array(16#43#) := 16#31#;
|
|
CFI_array(16#44#) := 16#33#;
|
|
CFI_array(16#45#) := 16#21#;
|
|
CFI_array(16#46#) := 16#02#;
|
|
CFI_array(16#47#) := 16#01#;
|
|
CFI_array(16#48#) := 16#00#;
|
|
CFI_array(16#49#) := 16#08#;
|
|
|
|
CFI_array(16#4A#) := 16#00#;
|
|
CFI_array(16#4B#) := 16#01#;
|
|
CFI_array(16#4C#) := 16#04#;
|
|
CFI_array(16#4D#) := 16#00#;
|
|
CFI_array(16#4E#) := 16#00#;
|
|
CFI_array(16#4F#) := 16#07#;
|
|
CFI_array(16#50#) := 16#01#;
|
|
|
|
CFI_array_tmp :=to_slv(CFI_array(16#00#), 8) &
|
|
to_slv(CFI_array(16#01#), 8) &
|
|
to_slv(CFI_array(16#02#), 8) &
|
|
to_slv(CFI_array(16#03#), 8) &
|
|
to_slv(CFI_array(16#04#), 8) &
|
|
to_slv(CFI_array(16#05#), 8) &
|
|
to_slv(CFI_array(16#06#), 8) &
|
|
to_slv(CFI_array(16#07#), 8) &
|
|
to_slv(CFI_array(16#08#), 8) &
|
|
to_slv(CFI_array(16#09#), 8) &
|
|
to_slv(CFI_array(16#0A#), 8) &
|
|
to_slv(CFI_array(16#0B#), 8) &
|
|
to_slv(CFI_array(16#0C#), 8) &
|
|
to_slv(CFI_array(16#0D#), 8) &
|
|
to_slv(CFI_array(16#0E#), 8) &
|
|
to_slv(CFI_array(16#0F#), 8) &
|
|
to_slv(CFI_array(16#10#), 8) &
|
|
to_slv(CFI_array(16#11#), 8) &
|
|
to_slv(CFI_array(16#12#), 8) &
|
|
to_slv(CFI_array(16#13#), 8) &
|
|
to_slv(CFI_array(16#14#), 8) &
|
|
to_slv(CFI_array(16#15#), 8) &
|
|
to_slv(CFI_array(16#16#), 8) &
|
|
to_slv(CFI_array(16#17#), 8) &
|
|
to_slv(CFI_array(16#18#), 8) &
|
|
to_slv(CFI_array(16#19#), 8) &
|
|
to_slv(CFI_array(16#1A#), 8) &
|
|
to_slv(CFI_array(16#1B#), 8) &
|
|
to_slv(CFI_array(16#1C#), 8) &
|
|
to_slv(CFI_array(16#1D#), 8) &
|
|
to_slv(CFI_array(16#1E#), 8) &
|
|
to_slv(CFI_array(16#1F#), 8) &
|
|
to_slv(CFI_array(16#20#), 8) &
|
|
to_slv(CFI_array(16#21#), 8) &
|
|
to_slv(CFI_array(16#22#), 8) &
|
|
to_slv(CFI_array(16#23#), 8) &
|
|
to_slv(CFI_array(16#24#), 8) &
|
|
to_slv(CFI_array(16#25#), 8) &
|
|
to_slv(CFI_array(16#26#), 8) &
|
|
to_slv(CFI_array(16#27#), 8) &
|
|
to_slv(CFI_array(16#28#), 8) &
|
|
to_slv(CFI_array(16#29#), 8) &
|
|
to_slv(CFI_array(16#2A#), 8) &
|
|
to_slv(CFI_array(16#2B#), 8) &
|
|
to_slv(CFI_array(16#2C#), 8) &
|
|
to_slv(CFI_array(16#2D#), 8) &
|
|
to_slv(CFI_array(16#2E#), 8) &
|
|
to_slv(CFI_array(16#2F#), 8) &
|
|
to_slv(CFI_array(16#30#), 8) &
|
|
to_slv(CFI_array(16#31#), 8) &
|
|
to_slv(CFI_array(16#32#), 8) &
|
|
to_slv(CFI_array(16#33#), 8) &
|
|
to_slv(CFI_array(16#34#), 8) &
|
|
to_slv(CFI_array(16#35#), 8) &
|
|
to_slv(CFI_array(16#36#), 8) &
|
|
to_slv(CFI_array(16#37#), 8) &
|
|
to_slv(CFI_array(16#38#), 8) &
|
|
to_slv(CFI_array(16#39#), 8) &
|
|
to_slv(CFI_array(16#3A#), 8) &
|
|
to_slv(CFI_array(16#3B#), 8) &
|
|
to_slv(CFI_array(16#3C#), 8) &
|
|
to_slv(CFI_array(16#3D#), 8) &
|
|
to_slv(CFI_array(16#3E#), 8) &
|
|
to_slv(CFI_array(16#3F#), 8) &
|
|
to_slv(CFI_array(16#40#), 8) &
|
|
to_slv(CFI_array(16#41#), 8) &
|
|
to_slv(CFI_array(16#42#), 8) &
|
|
to_slv(CFI_array(16#43#), 8) &
|
|
to_slv(CFI_array(16#44#), 8) &
|
|
to_slv(CFI_array(16#45#), 8) &
|
|
to_slv(CFI_array(16#46#), 8) &
|
|
to_slv(CFI_array(16#47#), 8) &
|
|
to_slv(CFI_array(16#48#), 8) &
|
|
to_slv(CFI_array(16#49#), 8) &
|
|
to_slv(CFI_array(16#4A#), 8) &
|
|
to_slv(CFI_array(16#4B#), 8) &
|
|
to_slv(CFI_array(16#4C#), 8) &
|
|
to_slv(CFI_array(16#4D#), 8) &
|
|
to_slv(CFI_array(16#4E#), 8) &
|
|
to_slv(CFI_array(16#4F#), 8) &
|
|
to_slv(CFI_array(16#50#), 8);
|
|
|
|
WAIT;
|
|
|
|
END PROCESS CFIPreload;
|
|
|
|
AspRegInit: PROCESS(ASP_INIT)
|
|
BEGIN
|
|
IF ASP_INIT = 0 THEN
|
|
ASP_reg := to_slv(16#FE4F#,16);
|
|
ELSE
|
|
ASP_reg := to_slv(16#FE7F#,16);
|
|
END IF;
|
|
END PROCESS AspRegInit;
|
|
|
|
Protect : PROCESS(change_BP)
|
|
BEGIN
|
|
IF rising_edge(change_BP) THEN
|
|
|
|
CASE BP_bits IS
|
|
WHEN "000" =>
|
|
Sec_Prot := (OTHERS => '0');
|
|
WHEN "001" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*63/64)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*63/64 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/64 - 1 downto 0)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/64)
|
|
:= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "010" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*31/32)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*31/32 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/32 - 1 downto 0)
|
|
:= (others => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/32)
|
|
:= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "011" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*15/16)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*15/16 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/16 - 1 downto 0)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/16)
|
|
:= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "100" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*7/8)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*7/8 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/8 - 1 downto 0) := (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/8):= (OTHERS => '0');
|
|
END IF;
|
|
WHEN "101" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)*3/4)
|
|
:= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)*3/4 - 1 downto 0)
|
|
:= (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/4 - 1 downto 0) := (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/4):= (OTHERS => '0');
|
|
END IF;
|
|
|
|
WHEN "110" =>
|
|
IF TBPROT = '0' THEN
|
|
Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '1');
|
|
Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '0');
|
|
ELSE
|
|
Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '1');
|
|
Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '0');
|
|
END IF;
|
|
|
|
WHEN OTHERS =>
|
|
Sec_Prot := (OTHERS => '1');
|
|
END CASE;
|
|
END IF;
|
|
END PROCESS Protect;
|
|
|
|
HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup)
|
|
BEGIN
|
|
IF (HOLDNeg_pullup = '0' AND QUAD /= '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 (QUAD = '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 (QUAD = '0') THEN
|
|
IF (WPNegIn = 'Z') THEN
|
|
WPNeg_pullup <= '1';
|
|
ELSE
|
|
WPNeg_pullup <= WPNegIn;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS WP_PULL_UP;
|
|
|
|
RST_PULL_UP : PROCESS(RSTNeg)
|
|
BEGIN
|
|
IF (RSTNeg = 'Z') THEN
|
|
RSTNeg_pullup <= '1';
|
|
ELSE
|
|
RSTNeg_pullup <= RSTNeg;
|
|
END IF;
|
|
END PROCESS RST_PULL_UP;
|
|
|
|
---------------------------------------------------------------------------
|
|
---- File Read Section - Preload Control
|
|
---------------------------------------------------------------------------
|
|
MemPreload : PROCESS
|
|
|
|
-- text file input variables
|
|
FILE mem_file : text is mem_file_name;
|
|
FILE otp_file : text is otp_file_name;
|
|
VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0;
|
|
VARIABLE otp_ind : NATURAL RANGE 16#000# TO 16#3FF# := 16#000#;
|
|
VARIABLE buf : line;
|
|
|
|
BEGIN
|
|
---------------------------------------------------------------------------
|
|
--s25fl512s memory preload file format
|
|
-----------------------------------
|
|
---------------------------------------------------------------------------
|
|
-- / - comment
|
|
-- @aaaaaa - <aaaaaa> stands for address
|
|
-- dd - <dd> is byte to be written at Mem(aaaaaa++)
|
|
-- (aaaaaa is incremented at every load)
|
|
-- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!!
|
|
---------------------------------------------------------------------------
|
|
|
|
-- memory preload
|
|
IF (mem_file_name /= "none" AND UserPreload) THEN
|
|
ind := 0;
|
|
Mem := (OTHERS => MaxData);
|
|
WHILE (not ENDFILE (mem_file)) LOOP
|
|
READLINE (mem_file, buf);
|
|
IF buf(1) = '/' THEN
|
|
NEXT;
|
|
ELSIF buf(1) = '@' THEN
|
|
IF ind > AddrRANGE THEN
|
|
ASSERT false
|
|
REPORT "Given preload address is out of" &
|
|
"memory address range"
|
|
SEVERITY warning;
|
|
ELSE
|
|
ind := h(buf(2 to 8)); --address
|
|
END IF;
|
|
ELSE
|
|
Mem(ind) := h(buf(1 to 2));
|
|
IF ind < AddrRANGE THEN
|
|
ind := ind + 1;
|
|
END IF;
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
---------------------------------------------------------------------------
|
|
--s25fl512s_otp memory preload file format
|
|
---------------------------------------------------------------------------
|
|
-- / - comment
|
|
-- @aaa - <aaa> stands for address
|
|
-- dd - <dd> is byte to be written at OTPMem(aaa++)
|
|
-- (aaa is incremented at every load)
|
|
-- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!!
|
|
---------------------------------------------------------------------------
|
|
|
|
-- memory preload
|
|
IF (otp_file_name /= "none" AND UserPreload) THEN
|
|
otp_ind := 16#000#;
|
|
OTPMem := (OTHERS => MaxData);
|
|
WHILE (not ENDFILE (otp_file)) LOOP
|
|
READLINE (otp_file, buf);
|
|
IF buf(1) = '/' THEN
|
|
NEXT;
|
|
ELSIF buf(1) = '@' THEN
|
|
IF otp_ind > 16#3FF# OR otp_ind < 16#000# THEN
|
|
ASSERT false
|
|
REPORT "Given preload address is out of" &
|
|
"OTP address range"
|
|
SEVERITY warning;
|
|
ELSE
|
|
otp_ind := h(buf(2 to 4)); --address
|
|
END IF;
|
|
ELSE
|
|
OTPMem(otp_ind) := h(buf(1 to 2));
|
|
otp_ind := otp_ind + 1;
|
|
END IF;
|
|
END LOOP;
|
|
END IF;
|
|
|
|
LOCK_BYTE1 := to_slv(OTPMem(16#10#),8);
|
|
LOCK_BYTE2 := to_slv(OTPMem(16#11#),8);
|
|
LOCK_BYTE3 := to_slv(OTPMem(16#12#),8);
|
|
LOCK_BYTE4 := to_slv(OTPMem(16#13#),8);
|
|
|
|
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_normal),
|
|
PathCondition => NOT(ddr)),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => (ddr OR fast_rd)),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1'),
|
|
3 => (InputChangeTime => HOLDNegIn'LAST_EVENT,
|
|
PathDelay => tpd_HOLDNeg_SO,
|
|
PathCondition => QUAD = '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_normal),
|
|
PathCondition => dual AND NOT(ddr)),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => dual AND ddr),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1'),
|
|
3 => (InputChangeTime => HOLDNegIn'LAST_EVENT,
|
|
PathDelay => tpd_HOLDNeg_SO,
|
|
PathCondition => dual AND QUAD = '0')
|
|
)
|
|
);
|
|
END PROCESS;
|
|
|
|
HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd)
|
|
|
|
VARIABLE HOLD_GlitchData : VitalGlitchDataType;
|
|
BEGIN
|
|
VitalPathDelay01Z (
|
|
OutSignal => HOLDNegOut,
|
|
OutSignalName => "HOLDNeg",
|
|
OutTemp => HOLDNegOut_zd,
|
|
Mode => VitalTransport,
|
|
GlitchData => HOLD_GlitchData,
|
|
Paths => (
|
|
0 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal),
|
|
PathCondition => dual AND not(ddr) AND QUAD = '1'),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => ddr AND QUAD = '1'),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1' AND
|
|
HOLDNegOut_zd = 'Z' AND QUAD = '1')
|
|
)
|
|
);
|
|
END PROCESS;
|
|
|
|
WP_Out_PathDelay : PROCESS(WPNegOut_zd)
|
|
|
|
VARIABLE WP_GlitchData : VitalGlitchDataType;
|
|
BEGIN
|
|
VitalPathDelay01Z (
|
|
OutSignal => WPNegOut,
|
|
OutSignalName => "WPNeg",
|
|
OutTemp => WPNegOut_zd,
|
|
Mode => VitalTransport,
|
|
GlitchData => WP_GlitchData,
|
|
Paths => (
|
|
0 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal),
|
|
PathCondition => dual AND not(ddr) AND QUAD = '1'),
|
|
1 => (InputChangeTime => SCK_ipd'LAST_EVENT,
|
|
PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR),
|
|
PathCondition => ddr AND QUAD = '1'),
|
|
2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT,
|
|
PathDelay => tpd_CSNeg_SO,
|
|
PathCondition => CSNeg_ipd = '1' AND
|
|
WPNegOut_zd = 'Z' AND QUAD = '1')
|
|
)
|
|
);
|
|
END PROCESS;
|
|
|
|
END BLOCK behavior;
|
|
END vhdl_behavioral_static_memory_allocation; |