------------------------------------------------------------------------------ -- INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT -- -- BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND -- BY THE TERMS OF THIS AGREEMENT. DO NOT USE THE SOFTWARE -- UNTIL YOU HAVE CAREFULLY READ AND AGREED TO THE FOLLOWING -- TERMS AND CONDITIONS. IF YOU DO NOT AGREE TO THE TERMS -- OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE -- AND ANY ACCOMPANYING ITEMS. -- -- IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS -- OF THIS AGREEMENT. -- -- LICENSE: Intel Corporation ("Intel") grants you -- the non-exclusive right to use the enclosed software -- program ("Software"). You will not use, copy, modify, -- display, rent, sell or transfer the Software or any portion -- thereof, except as provided in this Agreement. -- -- System OEM Developers may: -- 1. copy the Software for internal support, backup -- or archival purposes; -- 2. internally install, use, display, or distribute -- Intel owned Software in object code format; -- 3. internally modify Software source code that -- Intel makes available to you for internal use -- only as an OEM Developer; -- 4. internally install, use, display, modify, distribute, -- and/or make derivatives ("Derivatives") of Intel owned -- Software ONLY if you are a System OEM Developer and -- NOT an end-user. -- -- RESTRICTIONS: -- -- YOU WILL NOT: -- 1. copy the Software, in whole or in part, except as -- provided for in this Agreement; -- 2. decompile or reverse engineer any Software provided -- in object code format; -- 3. distribute any Software or Derivative code to any -- end-users, unless approved by Intel in a prior writing. -- -- TRANSFER: You may not transfer the Software to any third -- party without Intel’s prior written consent. -- -- OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software -- and all copies thereof remain with Intel or its vendors. -- The Software is copyrighted and is protected by United States -- and international copyright laws. You will not remove the -- copyright notice from the Software. You agree to prevent -- any unauthorized copying of the Software. -- -- DERIVATIVE WORK: OEM Developers that make Derivatives will -- not be required to provide Intel with a copy of the source -- or object code. Any modification of Software shall be at -- your sole risk and expense. No Software or Derivative -- distribution to any third party is permitted under this -- Agreement. -- -- DUAL MEDIA SOFTWARE: If the Software package contains -- multiple media, you may only use the medium appropriate -- for your system. -- -- WARRANTY: Intel warrants that it has the right to license -- you to use, modify, display, or distribute the Software as -- provided in this Agreement. The Software is provided "AS IS" -- without WARRANTY of any kind. Intel makes no representations -- to upgrade, maintain, or support the Software at any time. -- -- -- THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY -- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES -- OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE -- OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER -- INTELLECTUAL PROPERTY RIGHT. -- -- LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS -- VENDORS OR AGENTS SHALL BE LIABLE FOR ANY LOSS -- OF PROFITS, LOSS OF USE, LOSS OF DATA, INTERRUPTION -- OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL -- OR CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER -- THIS AGREEMENT OR OTHERWISE, EVEN IF ADVISED OF THE -- POSSIBILITY OF SUCH DAMAGES. -- -- TERMINATION OF THIS LICENSE: Intel reserves the right -- to conduct or have conducted audits to verify your -- compliance with this Agreement. Intel may terminate -- this Agreement at any time if you are in breach of -- any of its terms and conditions. Upon termination, -- you will immediately destroy, and certify in writing -- the destruction of, the Software or return all copies -- of the Software and documentation to Intel. -- -- U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and -- documentation were developed at private expense and -- are provided with "RESTRICTED RIGHTS". Use, duplication -- or disclosure by the Government is subject to restrictions -- as set forth in FAR52.227-14 and DFAR252.227-7013 et seq. -- or its successor. -- -- EXPORT LAWS: You agree that the distribution and -- export/re-export of the Software is in compliance -- with the laws, regulations, orders or other restrictions -- of the U.S. Export Administration Regulations. -- -- APPLICABLE LAW: This Agreement is governed by the -- laws of the State of California and the United States, -- including patent and copyright laws. Any claim -- arising out of this Agreement will be brought in -- Santa Clara County, California. -- -- Copyright 1996, Intel Corporation, All Rights Reserved ------------------------------------------------------------------------------ -- Copyright 1994, Intel Corporation -- INTEL CONFIDENTIAL: 28F016XD is an unannounced product -- Functionality and specifications based on MMI-16 -- Target Architecture Specification revision 1 -- Please contact Intel or distribution sales office for -- up-to-date specifications on Intel flash memory products -- Release History -- -- Date Rev Comments -- Sept 1, 1994 1.0 Initial Release. -- Sept 21, 1994 1.1 Modified Vpp Failure Checking -- Oct 10, 1994 1.2 Correct CSR,ESR by eight problem -- Updated timing constants -- Oct 21, 1994 1.3 Fixed minor problems library ieee; use std.textio.all; use ieee.std_logic_1164.all; --------------------------------------------- entity Intel28F016XD is generic ( LoadOnPowerUp : boolean := false; LoadFileName : string := ""; SaveOnPowerDown : boolean := false; SaveFileName : string := "" ); port ( dq : inout std_logic_vector(15 downto 0); add : in std_logic_vector(9 downto 0); rasb : in std_logic; casb : in std_logic; wpb : in std_logic; rpb : in std_logic; oeb : in std_logic; web : in std_logic; ry_byb : out std_logic; vpp : in real; vcc : in real ); end Intel28F016XD; architecture Intel28F016XD_hdl of Intel28F016XD is -- These constants control how long it take an algorithm to run -- To scale all times together (for making simulation run faster -- change the constant later listed as TimerPeriod CONSTANT AC_DeviceConfigTime : INTEGER := 16#03# ; CONSTANT AC_LockBlockTime : INTEGER := 16#25# ; CONSTANT AC_ProgramTime : INTEGER := 16#21# ; ---CONSTANT AC_EraseTime : INTEGER := 16#299D69# ; -- 1.2 sec Takes too long CONSTANT AC_EraseTime : INTEGER := 16#210# ; -- Dummy for simulation purposes CONSTANT AC_StatUploadCmd : INTEGER := 16#02# ; CONSTANT AC_TwoByteProgramTime : INTEGER := 16#21# ; CONSTANT AC_UpDevInfoTime : INTEGER := 16#0F# ; CONSTANT AC_PBProgramTime : INTEGER := 16#17# ; -- These constants are the actual command codes CONSTANT AbortCmd : INTEGER := 16#80# ; CONSTANT ClearSRCmd : INTEGER := 16#50# ; CONSTANT DeviceConfigCmd : INTEGER := 16#96# ; CONSTANT EraseAllBlocksCmd : INTEGER := 16#A7# ; CONSTANT EraseCmd : INTEGER := 16#EC# ; CONSTANT EraseSingleBlockCmd : INTEGER := 16#20# ; CONSTANT LockBlockCmd : INTEGER := 16#77# ; CONSTANT PBWriteFlashCmd : INTEGER := 16#0C# ; CONSTANT ProgramCmd : INTEGER := 16#10# ; CONSTANT Program2Cmd : INTEGER := 16#40# ; CONSTANT ReadArrayCmd : INTEGER := 16#FF# ; CONSTANT ReadCSRCmd : INTEGER := 16#70# ; CONSTANT ReadESRCmd : INTEGER := 16#71# ; CONSTANT ReadIDCmd : INTEGER := 16#90# ; CONSTANT ReadPBCmd : INTEGER := 16#75# ; CONSTANT ResumeCmd : INTEGER := 16#D0# ; CONSTANT SeqPBWriteCmd : INTEGER := 16#E0# ; CONSTANT SleepCmd : INTEGER := 16#F0# ; CONSTANT StatusUploadCmd : INTEGER := 16#97# ; CONSTANT SuspendCmd : INTEGER := 16#B0# ; CONSTANT SwapPBCmd : INTEGER := 16#72# ; CONSTANT TwoByteWriteCmd : INTEGER := 16#FB# ; CONSTANT UpDevInfoCmd : INTEGER := 16#99# ; CONSTANT WritePBCmd : INTEGER := 16#74# ; CONSTANT PBWordSize : INTEGER := 16#7F# ; CONSTANT BlockWordSize : INTEGER := 16#7FFF# ; CONSTANT ID_ManufacturerW : INTEGER := 16#0089# ; CONSTANT ID_DeviceCodeB : INTEGER := 16#A8A8# ; CONSTANT ID_DeviceCodeW : INTEGER := 16#66A8# ; CONSTANT Vcc5vThres : REAL := 4.0; CONSTANT VppThres : REAL := 9.0; constant WORDLENGTH : integer := 32; constant max_string_C : integer := 80; constant TGHIL_3v : time := 0 ns ; constant TGHIL_5v : time := 0 ns ; constant TPHIL_3v : time := 500 ns ; constant TPHIL_5v : time := 300 ns ; constant TILIH_3v : time := 60 ns ; constant TILIH_5v : time := 40 ns ; constant TVPIH_3v : time := 100 ns ; constant TVPIH_5v : time := 100 ns ; constant TAVIH_3v : time := 60 ns ; constant TAVIH_5v : time := 40 ns ; constant TDVIH_3v : time := 50 ns ; constant TDVIH_5v : time := 40 ns ; constant TIHDX_3v : time := 5 ns ; constant TIHDX_5v : time := 0 ns ; constant TIHAX_3v : time := 5 ns ; constant TIHAX_5v : time := 5 ns ; constant TIHIL_3v : time := 15 ns ; constant TIHIL_5v : time := 15 ns ; constant TWHRL_3v : time := 100 ns ; constant TWHRL_5v : time := 100 ns ; constant TWHCH_3v : time := 20 ns ; constant TWHCH_5v : time := 20 ns ; constant TIHGL_3v : time := 55 ns ; constant TIHGL_5v : time := 55 ns ; constant TAVQV_3v : time := 75 ns ; constant TAVQV_5v : time := 65 ns ; constant TGHQZ_3v : time := 30 ns ; constant TGHQZ_5v : time := 25 ns ; constant TGLQX_3v : time := 40 ns ; constant TGLQX_5v : time := 30 ns ; constant TRLRZ_3v : time := 250 ns ; constant TRLRZ_5v : time := 220 ns ; constant TIHRL_3v : time := 50 ns ; constant TIHRL_5v : time := 50 ns ; constant TADRZ_3v : time := 50 ns ; constant TADRZ_5v : time := 50 ns ; constant TimerPeriod_3v : time := 250 ns ; constant TimerPeriod_5v : time := 220 ns ; type File_T is file of integer; subtype Word is bit_vector(15 downto 0); subtype Byte is bit_vector(7 downto 0); subtype Address_T is bit_vector(20 downto 0); subtype NVLockBit_T is bit_vector(31 downto 0); type ReadMode_T is (rdARRAY, rdPB, rdESR, rdCSR, rdID); type WritePtr_T is (toPB,NewCmd,CmdField); type COV_T is (Unknown,FiveVolt,ThreeVolt); type RdyBsy_T is (Rdy,Bsy); -- memory array defs subtype mem_range is natural range 16#0000# to 16#ffff#; type mem_block is array (mem_range) of mem_range; type MainArray_T is array (31 downto 0) of mem_block; subtype PBPtr_T is natural range 0 to 1; type PBInUse_T is array (PBPtr_T) of boolean; type PBplane_T is array (127 downto 0) of integer; type PageBuffer_T is array (PBPtr_T) of PBplane_T; type BSRmem_T is array (31 downto 0) of Byte; type Add_T is array (2 downto 1) of Address_T; type Data_T is array (2 downto 1) of Word; type OpType_T is (Program,Erase,Operation); type edge_T is (RisingEdge,RE,FallingEdge,FE,AnyEdge,AE); type Cmd_T is record Cmd : integer range 0 to 16#FF#; Add : Address_T; UsesPB : boolean; PBPtr : PBPtr_T; Time : integer range 0 to 16#FFFFFFF#; Confirm : boolean; OpBlock : integer range 0 to 31; OpType : OpType_T; Count : integer; CmdAdd : Add_T; CmdData : Data_T; end record; type AC_T is record TPHIL : time; TIHIL : time; TILIH : time; TAVIH : time; TDVIH : time; TIHAX : time; TIHDX : time; TGHIL : time; TIHGL : time; TAVQV : time; TGHQZ : time; TGLQX : time; TIHRL : time; TADRZ : time; TRLRZ : time; TimerPeriod : time; end record; signal AlgDone : boolean := false ; -- Flag to show the running algorithm is done. signal CmdValid : boolean := false ; -- Flag to show that a Cmd has been written -- and needs predecoding signal DataPtr : integer := 0 ; -- Number of addition writes necessary to -- supply the current command information. -- When it hits zero it goes to Decode signal DeviceOperationError : boolean := false ; -- Represents CSR bit. signal OperationError : boolean ; -- Internal representation of CSR bit signal EraseError : boolean := false ; -- Internal representation of CSR bit signal DriveOutputs : boolean := False ; -- Flag that determines if the chip is driving -- the outputs signal Enqueue : boolean := false ; -- Flag from decoding to show that the -- current command needs to be placed in -- the algorithm queue. signal InternalOutput : integer ; -- Internal value of the out data. If DriveOutputs -- is active this value will be placed on the -- outputs. -1 == Unknown or XXXX signal Internal_WE : boolean := false ; -- Master internal write enable signal Internal_OE : boolean := false ; -- Master internal output enable signal Internal_RE : boolean := false ; -- Master internal read enable signal PBavailStatus : boolean ; -- Internal representation of the ESR bit signal PBInUse : PBInUse_T ; -- Support information for the page buffers signal PBPtr : PBPtr_T ; -- Pointer to currently active page buffer signal ProgramError : boolean ; signal Q1Valid : boolean := false ; -- Flag to tell if Queue Slot 1 is valid signal Q2Valid : boolean := false ; -- Flag to tell if Queue Slot 2 is valid signal Q3Valid : boolean := false ; -- Flag to tell if Queue Slot 3 is valid signal QueueCmd : boolean := false ; -- Flag to tell if in the process of queuing -- a command. signal QueueFull : boolean := false ; -- Internal representation of ESR bit. signal RdyBsy : RdyBsy_T ; -- Internal flag to tell if an algorithm is -- running signal Sleep : boolean := false ; -- Flag for if the part is in Sleep signal Suspended : boolean := false ; -- Flag to represent if the chip is suspended signal GoTwoCmd : boolean := false ; -- Flag to tell executer to process the command -- in the second Queue position. signal TimerClk : bit := '0' ; -- Algorithm Timer signal VppLevel : boolean := false ; -- Current Vpp Range (five volt/ 12 volt) signal VppError : boolean := false ; -- Internal representation of GSR bit signal ReadMode : ReadMode_T ; signal BSR : BSRmem_T ; -- Current value of the BSR signal CSR : Byte ; -- Current value of the CSR signal GSR : Byte ; -- Current value of the GSR signal RdyBsyConfig : integer := 1 ; -- Current Ready Busy pin configuration signal StartUpFlag : boolean := true ; -- Startup Flag phase 1 signal InitTiming : boolean := false ; -- Startup Flag phase 2 signal EndOfProgramPB : boolean := false ; -- Internal flag for Rdy Bsy generation. signal EndOfErase : boolean := false ; -- Internal flag for Rdy Bsy generation. signal ClearVppFlag : boolean := false ; signal VppFlag : boolean := false ; signal addr : std_logic_vector(20 downto 0); -- Internal Address signal AC : AC_T; -- Contains all current timing values signal Reset : boolean := true ; -- Global Reset Flag ---------------- -- BlockLocked --------------------------------------------- -- Description: Determines it the current block is locked -- ------------------------------------------------------------ FUNCTION BlockLocked( TheBlock : integer ; BSR : BSRmem_T ; NVLockBit : NVLockBit_T ; signal wpb : std_logic ) RETURN boolean is begin if (BSR(TheBlock)(6) = '1' or NVLockBit(TheBlock) = '1') and wpb = '0' then return True; else return False; end if; end BlockLocked; --------------------------------------------------------------------- -- zero Extend bit vector (x) to length. -- returns bit_vector(length-1 downto 0) -- length should be positive --------------------------------------------------------------------- function Extend (X: bit_vector; LENGTH : integer) return bit_vector is constant XLEN : integer := x'length; alias X1: bit_vector(XLEN-1 downto 0) is x; begin assert length > 0 report "LENGTH PARAMETER FOR EXTEND SHOULD BE POSITIVE" severity error; if (XLEN = 0) then return (length-1 downto 0 => '0'); elsif (length <= XLEN) then return X1(length-1 downto 0); end if; return (length-1 downto XLEN => '0') & x; end; --------------------------------------------------------------------- -- Function : BVtoI -- converts unsigned bit vector to integer -- discards all bits other than rightmost WORDLENGTH-1 --------------------------------------------------------------------- function BVtoI (X: bit_vector) return integer is variable X1: bit_vector(WORDLENGTH-1 downto 0) := Extend(x, WORDLENGTH); variable RESULT: integer := 0; begin assert x'length < WORDLENGTH report "LENGTH OF bit_vector X in function BVTOI SHOULD BE " & "LESS THEN WorDLENGTH" severity error; for I in X1'range loop if X1(I) = '1' then RESULT := 2*RESULT+1; else RESULT := 2*RESULT; end if; end loop; return RESULT; end; -- convert integer to std_logic_vector; function itov (constant i: integer; l: integer) return std_logic_vector is variable j : integer := i; variable n : integer := -1; variable r : std_logic_vector(l-1 downto 0); begin if j < 0 then assert false report "itov: value must be non-negative" severity FAILURE; end if; if l < 1 then assert false report "itov: length must be positive" severity FAILURE; end if; r := (others => '0'); while (j /= 0) loop n := n + 1; exit when n >= l; if j rem 2 /= 0 then r(n) := '1'; else r(n) := '0'; end if; j := j / 2; end loop; return r; end; procedure int2string (constant v : in integer; variable t : inout string) is variable i, j, r : integer; variable buf : string (max_string_C downto 1); begin assert t'left <= t'right report "int2string: assert 1" severity FAILURE; i := 1; r := abs v; buf(i) := '0'; while r > 0 loop case (r rem 10) is when 0 => buf(i) := '0'; when 1 => buf(i) := '1'; when 2 => buf(i) := '2'; when 3 => buf(i) := '3'; when 4 => buf(i) := '4'; when 5 => buf(i) := '5'; when 6 => buf(i) := '6'; when 7 => buf(i) := '7'; when 8 => buf(i) := '8'; when 9 => buf(i) := '9'; when others => assert FALSE report "int2string: assert 4" severity FAILURE; end case; r := r / 10; i := i + 1; assert i < max_string_C report "int2string: assert 2" severity FAILURE; end loop; if i > 1 then i := i - 1; end if; assert t'length > i report "int2string: assert 3" severity FAILURE; j := t'left; while i >= 1 loop t(j) := buf(i); j := j + 1; i := i - 1; end loop; t(j) := NUL; end int2string; PROCEDURE TimingInit(OpVolts: IN COV_T; signal AC:OUT AC_T) is begin if OpVolts=ThreeVolt then AC.TPHIL <= TPHIL_3v; AC.TIHIL <= TIHIL_3v; AC.TILIH <= TILIH_3v; AC.TAVIH <= TAVIH_3v; AC.TDVIH <= TDVIH_3v; AC.TIHAX <= TIHAX_3v; AC.TIHDX <= TIHDX_3v; AC.TGHIL <= TGHIL_3v; AC.TIHGL <= TIHGL_3v; AC.TAVQV <= TAVQV_3v; AC.TGHQZ <= TGHQZ_3v; AC.TGLQX <= TGLQX_3v; AC.TIHRL <= TIHRL_3v; AC.TADRZ <= TADRZ_3v; AC.TRLRZ <= TRLRZ_3v; AC.TimerPeriod <= TimerPeriod_3v; else AC.TPHIL <= TPHIL_5v; AC.TIHIL <= TIHIL_5v; AC.TILIH <= TILIH_5v; AC.TAVIH <= TAVIH_5v; AC.TDVIH <= TDVIH_5v; AC.TIHAX <= TIHAX_5v; AC.TIHDX <= TIHDX_5v; AC.TGHIL <= TGHIL_5v; AC.TIHGL <= TIHGL_5v; AC.TAVQV <= TAVQV_5v; AC.TGHQZ <= TGHQZ_5v; AC.TGLQX <= TGLQX_5v; AC.TIHRL <= TIHRL_5v; AC.TADRZ <= TADRZ_5v; AC.TRLRZ <= TRLRZ_5v; AC.TimerPeriod <= TimerPeriod_5v; end if; end TimingInit; -------------------------------------------------------------------------------- -- LoadAll -- -- This is used when the generic flag is set so that the Main Array contains -- -- code at startup. Basically it loads the array from data in a file -- -------------------------------------------------------------------------------- PROCEDURE LoadAll( FileInName : IN string; MainArray : OUT MainArray_T; NVLockBit : OUT NVLockBit_T) is FILE ArrayInFile : File_T IS IN FileInName; VARIABLE BlockPtr : INTEGER; VARIABLE RowPtr : INTEGER; VARIABLE DataIn : INTEGER; begin for BlockPtr in 0 to 31 loop for RowPtr in 0 to BlockWordSize loop READ(ArrayInFile,MainArray(BlockPtr)(RowPtr)); end loop; end loop; for BlockPtr in 0 to 31 loop READ(ArrayInFile,DataIn); if DataIn >0 then NVLockBit(BlockPtr) := '1'; else NVLockBit(BlockPtr) := '0'; end if; end loop; end LoadAll; ------------------------------------------------------------------------------ -- StoreAll -- -- This is used when the generic flag is set so that the Main Array stores -- -- code at powerdown. Basically it stores the array into a file -- ------------------------------------------------------------------------------ PROCEDURE StoreAll( FileOutName : IN string; MainArray : IN MainArray_T; NVLockBit : IN NVLockBit_T) is FILE ArrayOutFile : File_T IS OUT FileOutName; VARIABLE BlockPtr : INTEGER; VARIABLE RowPtr : INTEGER; VARIABLE DataOut : INTEGER; begin for BlockPtr in 0 to 31 loop for RowPtr in 0 to BlockWordSize loop WRITE(ArrayOutFile,MainArray(BlockPtr)(RowPtr)); end loop; end loop; for BlockPtr in 0 to 31 loop if NVLockBit(BlockPtr) = '1' then DataOut := 1; else DataOut := 0; end if; WRITE(ArrayOutFile,DataOut); end loop; end StoreAll; ------------------------------------------------------ -- Function: and operator overload -- -- Description: Bitwise and of two integers -- ------------------------------------------------------ FUNCTION "and" (A,B:integer) return integer is variable Count : integer ; variable OutVal : integer ; variable Ain : integer ; variable Bin : integer ; variable BaseValue : integer ; begin Ain := A; Bin := B; OutVal := 0; for Count in 15 downto 0 loop BaseValue := 2**Count; if (Ain/BaseValue) = 1 and (Bin/BaseValue) = 1 then OutVal := 2*OutVal+1; else OutVal := 2*OutVal; end if; Ain := Ain mod BaseValue; Bin := Bin mod BaseValue; end loop; return OutVal; end "and"; function btoi(It:in bit) return integer is begin if It = '1' then return 1; else return 0; end if; end; ------------------------------------------------------ -- Procedure: Program -- -- Description: Programs new values in to the array -- ------------------------------------------------------ PROCEDURE Program( TheArrayValue : INOUT integer ; DataIn : IN integer ) is begin TheArrayValue := DataIn and TheArrayValue; end Program; ------------------------------------------------------------ -- Procedure: UploadStatus -- -- Description: Read nonvolitile lock bits in to the BSR -- ------------------------------------------------------------ PROCEDURE UploadStatus( BSR : OUT BSRmem_T ; NVLockBit : IN NVLockBit_T ) is variable LoopCount : integer; begin for LoopCount in 0 to 31 loop BSR(LoopCount)(6) := NVLockBit(LoopCount); end loop; end UploadStatus; begin ------------------- -- Ammi Control -- ------------------ AmmiControl: process(casb,rasb,web,oeb,add) variable RASbeforeCAS : boolean := False; variable RAS : boolean; variable CAS : boolean; begin -- Create boolean positive logic representitives of the -- Row and Column address strobes CAS := (to_bit(casb)='0'); RAS := (to_bit(rasb)='0'); -- If currently in the idle state reset Ras/Cas ordering flag if not (CAS or RAS) then RASbeforeCAS := False; end if; -- When RAS is active allow row and column address to become -- the internal address bus. if RAS and not CAS then addr(20 downto 11) <= add(9 downto 0); addr(10 downto 1) <= add(9 downto 0); -- If RAS just went active before CAS then mark proper ordering if rasb'event then RASbeforeCAS := True; end if; end if; -- While CAS is active allow current address to become the appropriate -- internal addresses if CAS then addr(10 downto 1) <= add(9 downto 0); end if; -- Generate major internal control signals from MMI control strobes Internal_WE <= RASbeforeCAS and RAS and CAS and (to_bit(web)='0'); Internal_OE <= RASbeforeCAS and CAS and (to_bit(web) = '1') and (to_bit(oeb) = '0'); Internal_RE <= RASbeforeCAS; end process; MainCore: process (addr,ReadMode,Internal_OE,Internal_WE,Internal_RE,DataPtr,Enqueue,TimerClk,StartupFlag, Q1Valid,Q2Valid,Q3Valid,CmdValid,AlgDone,vcc,Reset,RdyBsy) variable BSR : BSRmem_T ; -- Contains current contents of BSR variable AlgTime : integer ; -- Number of timer cycles remaining for the current -- algorithm variable MainArray : MainArray_T ; -- THE MEMORY BANK variable Queue1 : Cmd_T ; -- This is slot 1 (first) of the chip algorithm queue variable Queue2 : Cmd_T ; -- This is slot 2 (middle) of the chip algorithm queue variable Queue3 : Cmd_T ; -- This is slot 3 (last) of the chip algorithm queue variable ErasingBlock : integer := -1 ; -- Points to the block currently being erased -- -1 is No Block -2 is Block to be determined variable NVLockBit : NVLockBit_T ; -- Contains the NonVolatile Block lock bits variable PauseTime : integer :=0 ; -- This records where the algorithm is when the -- the chip suspends or Queue slot 1 is interrupted. variable WriteToPtr : WritePtr_T := NewCmd ; -- This points to where data written to the part will -- go. By default it is to NewCmd. -- CmdField means the chips is waiting on -- more data for the cmd (ie confirm) -- ToPB mean to the Page Buffer variable PageBuffer : PageBuffer_T ; -- This contains the contents of the page buffers variable PendingSleep : boolean := False ; -- This flag determines if after the algorithms in -- the queue finish, the chips sleeps variable AwaitingErase : integer := -2 ; -- Points to the next block to be erased if there is -- something waiting on the block, it will set this -- and execute after the erase of that block is done. variable Cmd : Cmd_T ; -- Contains the current executing command and all its -- support information. variable ArrayOut : integer := 0 ; -- Current output of the Main Array variable ESROut : integer := 0 ; -- Current output of the Extend status register variable CSROut : integer := 0 ; -- Current output of the Compatible status register variable IDOut : integer := 0 ; -- Current output of the Intelligent Identifer (tm) variable PBOut : integer := 0 ; -- Current output of the Page Buffer variable BSROut : Byte ; -- Current output of the Block Status Registers variable LoopCntr : integer := 0 ; -- Generic temporary varible variable Suspend : boolean := False ; -- Flag for if the chip is suspended variable LoopCounter : integer := 0 ; -- Generic temporary varible variable BlockNum : integer := 0 ; -- Pointer to a Block variable RowNum : integer := 0 ; -- Pointer to a Row variable BlockPtr : integer := 0 ; -- Another pointer to a Blcok variable PBindex : integer := 0 ; -- Row pointer in the PageBuffer variable Tmp1 : integer := 0 ; -- Generic temporary variable variable Tmp2 : integer := 0 ; -- Generic temporary variable variable Index : integer := 0 ; -- Generic temporary variable variable Other : boolean := False ; -- Generic variable TheCmd : Cmd_T ; -- The currently inputing command and its support -- information variable LoopCount : integer := 0 ; -- Generic variable variable NewData : integer := 0 ; -- Generic variable variable Fail : boolean := False ; -- A Generic fail flag variable WordCount : integer := 0 ; -- Number of words to go into to PageBuffer variable ToOut : time := 0 ns ; -- #ifndef variable l : line ; variable s : string(1 to 80) ; -- #endif begin ---------- -- Reset ------------------------------------ -- This section puts the chips and all its -- -- signals into a default known state. -- --------------------------------------------- if Reset or StartupFlag then ClearVppFlag <= True after 1 ns, False after 9 ns ; AlgDone <= False ; CmdValid <= False ; DataPtr <= 0 ; EraseError <= False ; Enqueue <= False ; InternalOutput <= -1 ; OperationError <= False ; PBInUse(0) <= False ; PBInUse(1) <= False ; PBPtr <= 0 ; ProgramError <= False ; Q1Valid <= False ; Q2Valid <= False ; Q3Valid <= False ; QueueCmd <= False ; Sleep <= False ; Suspended <= False ; GoTwoCmd <= False ; VppError <= False ; ReadMode <= rdArray ; RdyBsyConfig <= 1 ; EndOfProgramPB <= False ; EndOfErase <= False ; for loopcntr in 0 to 31 loop BSR(loopcntr) := "00000000" ; NVLockBit(loopcntr) := '0' ; end loop; AlgTime := 0 ; ErasingBlock := -1 ; PauseTime := 0 ; WriteToPtr := NewCmd ; PendingSleep := False ; AwaitingErase := -1 ; ArrayOut := 0 ; ESROut := 0 ; CSROut := 0 ; IDOut := 0 ; PBOut := 0 ; Suspend := False ; if StartupFlag then ---------------- -- Array Init -- ---------------- if StartUpFlag then -- Check if we are in start up phase 1 StartUpFlag <= false after 2 ns; -- Start phase 2 (Timing Init) InitTiming <= True, False after 1 ns; -- Initialize the Array if LoadOnPowerUp then LoadAll(LoadFileName,MainArray,NVLockBit); else for loopcntr in 0 to 31 loop for LoopCount in 0 to BlockWordSize loop MainArray(loopcntr)(LoopCount) := 16#FFFF#; end loop; end loop; end if; end if; -- Save the array when chip is powered off if vcc = 0.0 then StoreAll(SaveFileName,MainArray,NVLockBit); end if; end if; else ----------------- -- array reads -- ----------------- -- Determine if an array read has been initiated if (ReadMode'event or Internal_RE'event or addr'event) and Internal_RE and ReadMode = rdARRAY then -- Get Block and RowNum, then read the array BlockNum := bvtoi(to_bitvector(addr(20 downto 16))); RowNum := bvtoi(To_bitvector(addr(15 downto 1))); ArrayOut := MainArray(BlockNum)(RowNum); end if; ----------------- -- other reads -- ----------------- if (ReadMode /= rdARRAY) and Internal_OE'event then CSROut := bvtoi(CSR); if bvtoi(to_bitvector(addr(15 downto 3))) = 0 then -- Create the correct BSR output if addr(2 downto 1)="01" then BlockPtr := bvtoi(to_bitvector(addr(20 downto 16))); BSROut := BSR(BlockPtr); if Vpp < VppThres then BSROut(1) := '1'; else BSROut(1) := '0'; end if; if QueueFull then BSROut(3) := '1'; else BSROut(3) := '0'; end if; if (Q1Valid and Queue1.OpBlock = BlockPtr) or (Q2Valid and Queue2.OpBlock = BlockPtr) or (Q3Valid and Queue3.OpBlock = BlockPtr) then BSROut(7) := '0'; else BSROut(7) := '1'; end if; ESROut := bvtoi(BSROut); elsif addr(2 downto 1) = "10" then ESROut := bvtoi(GSR); else ESROut := 0; --RESERVED end if; else ESROut := 0; --RESERVED end if; if addr(1) = '0' then IDOut := ID_ManufacturerW; else IDOUT := ID_DeviceCodeW; end if; end if; if (ReadMode'event or Internal_RE'event or addr'event) and Internal_RE and ReadMode = rdPB then PBindex := bvtoi(to_bitvector(addr(7 downto 1))); PBOut := PageBuffer(PBPtr)(PBindex); end if; ---------------- -- output mux -- ---------------- -- Determine and generate the access time. if (ReadMode'event or Internal_RE'event or Internal_OE'event or addr'event) and Internal_RE then if (not Internal_OE'event) then if (ReadMode=rdARRAY or ReadMode=rdPB) then ToOut := AC.TAVQV; else ToOut := 1 ps; end if; else if (ReadMode=rdARRAY or ReadMode=rdPB) then ToOut := 1 ns; else ToOut := 40 ns; end if; if (Now > AC.TAVQV) then if (addr'last_event ToOut) then ToOut := AC.TAVQV - addr'last_event; end if; if (ReadMode'last_event ToOut) then ToOut := AC.TAVQV - ReadMode'last_event; end if; if (Internal_RE'last_event ToOut) then ToOut := AC.TAVQV - Internal_RE'last_event; end if; end if; end if; -- Output Mux with timing if not StartUpFlag then case ReadMode is when rdARRAY => InternalOutput <= -1 ,ArrayOut after ToOut; when rdESR => InternalOutput <= -1 ,ESROut after ToOut; when rdCSR => InternalOutput <= -1 ,CSROut after ToOut; when rdID => InternalOutput <= -1 ,IDOut after ToOut; when rdPB => InternalOutput <= -1 ,PBOut after ToOut; end case; end if; end if; -------------------------- -- Handle Write to Part -- -------------------------- if Internal_WE'event and not Internal_WE then -- Rising Edge -- Where are we writting to ? case WriteToPtr is when NewCmd => -- This is a new command. Cmd.Cmd := bvtoi(To_bitvector(dq(7 downto 0))); Cmd.Add := To_bitvector(addr(20 downto 0)); -- CmdValid sends it to the Predecode section CmdValid <= True; DataPtr <= -1; when CmdField => -- This is data used by another command Cmd.CmdData(DataPtr)(15 downto 0) := To_bitvector(dq(15 downto 0)); Cmd.CmdAdd(DataPtr) := To_bitvector(addr(20 downto 0)); -- When DataPtr hits zero the command goes to the Decode section DataPtr <= DataPtr - 1 after 1 ns; when ToPB => -- This is when we are writing to the page buffer Index := bvtoi(To_bitvector(addr(7 downto 1))); DataPtr <= DataPtr - 1; -- When DataPtr hits zero the write mode will be reset in the decode section PageBuffer(PBPtr)(Index) := bvtoi(to_bitvector(dq(15 downto 0))); end case; end if; ----------------------- -- Predecode Command -- ----------------------- if CmdValid'event and CmdValid then --Set Defaults Cmd.UsesPB := False; Cmd.OpType := Program; WriteToPtr := NewCmd; DataPtr <= 0; case Cmd.Cmd is -- Handle the basic read mode commands -- READ ARRAY COMMAND -- when ReadArrayCmd => -- Read Flash Array CmdValid <= False; -- Read Array take the part out of Sleep if Sleep then Sleep <= False; end if; -- Can not read array when running an algorithm if PendingSleep or RdyBsy = Bsy then ReadMode <= rdCSR; else ReadMode <= rdARRAY; end if; -- READ INTELLIGENT IDENTIFIER COMMAND -- when ReadIDCmd => -- Read Intelligent ID ReadMode <= rdID; CmdValid <= False; -- READ COMPATIBLE STATUS REGISTER COMMAND -- when ReadCSRCmd => -- Read CSR ReadMode <= rdCSR; CmdValid <= False; -- READ EXTEND STATUS REGISTER COMMAND -- when ReadESRCmd => -- Read ESR ReadMode <= rdESR; CmdValid <= False; when others => -- Other flag marks commands that are algorithms Other := True; -- Defaults Cmd.Confirm := False; Cmd.UsesPB := False; case Cmd.Cmd is -- PROGRAM WORD COMMAND -- when ProgramCmd => -- Program Word WriteToPtr := CmdField; DataPtr <= 1; Cmd.Time := AC_ProgramTime; -- ERASE BLOCK COMMAND -- when EraseSingleBlockCmd => -- Single Block Erase WriteToPtr := CmdField; DataPtr <= 1; Cmd.Time := AC_EraseTime; Cmd.OpType:=Erase; Cmd.Confirm := True; -- PROGRAM WORD COMMAND -- when Program2Cmd => -- Program Word Cmd.Cmd := ProgramCmd; WriteToPtr := CmdField; DataPtr <= 1; Cmd.Time := AC_ProgramTime; -- ERASE ALL UNLOCKED BLOCKS COMMAND -- when EraseAllBlocksCmd => -- Erase All Unlocked Blocks WriteToPtr := CmdField; Cmd.OpType:=Erase; DataPtr <= 1; Cmd.Time := 1; -- Jump to execute to find highest block Cmd.Confirm := True; -- PAGE BUFFER PROGRAM TO FLASH COMMAND -- when PBWriteFlashCmd => -- Page Buffer Write to Flash WriteToPtr := CmdField; DataPtr <= 2; Cmd.UsesPB := True; -- LOCK BLOCK COMMAND -- when LockBlockCmd => -- Lock Block WriteToPtr := CmdField; DataPtr <= 1; Cmd.Time := AC_LockBlockTime; Cmd.Confirm := True; -- UPLOAD STATUS COMMAND -- when StatusUploadCmd => -- Status Upload WriteToPtr := CmdField; DataPtr <= 1; Cmd.Time := AC_StatUploadCmd; Cmd.Confirm := True; -- DEVICE CONFIGURE COMMAND -- when DeviceConfigCmd => -- Device Config WriteToPtr := CmdField; DataPtr <= 1; Cmd.Time := AC_DeviceConfigTime; -- UPLOAD DEVICE INFORMATOIN COMMAND -- when UpDevInfoCmd => -- Upload Device Information WriteToPtr := CmdField; DataPtr <= 1; Cmd.UsesPB := True; Cmd.Time := AC_UpDevInfoTime; Cmd.Confirm := True; when others => -- The remaining commands are complex non-algorithm commands Other := False; CmdValid <= False; -- SWAP PAGE BUFFER COMMAND -- if (Cmd.Cmd = SwapPBCmd) then PBPtr <= 1-PBPtr; ReadMode <= rdESR; -- COMMANDS: SEQUENTIAL WRITE TO PAGE BUFFER, WRITE TO PAGE BUFFER, and READ PAGE BUFFER -- elsif (Cmd.Cmd = SeqPBWriteCmd or Cmd.Cmd = WritePBCmd or Cmd.Cmd = ReadPBCmd) then -- Check if Part is in sleep (legal for ReadPB) if Sleep then -- INVALID CMD if (Cmd.Cmd = ReadPBCmd) then ReadMode <= rdPB; else ReadMode <= rdCSR; end if; else -- Are we waiting to sleep, if so kill it if Cmd.Cmd /= ReadPBCmd and PendingSleep and not PBInUse(PBPtr) then PendingSleep := False; end if; -- Is the pagebuffer availible? if PBInUse(PBPtr) then if Suspend or Cmd.Cmd = ReadPBCmd then ReadMode <= rdARRAY; else ReadMode <= rdESR; end if; -- execute command elsif Cmd.Cmd = ReadPBCmd then ReadMode <= rdPB; elsif Cmd.Cmd = WritePBCmd then WriteToPtr := ToPB; DataPtr <= 1; else WriteToPtr := CmdField; CmdValid <= True; DataPtr <= 2; end if; end if; -- COMMANDS: CLEAR STATUS REGISTERS, RESUME, and SLEEP -- elsif (Cmd.Cmd = ClearSRCmd or Cmd.Cmd = ResumeCmd or Cmd.Cmd = SleepCmd) then CmdValid <= False; -- Check for illegal conditions if Sleep or PendingSleep then ReadMode <= rdCSR; elsif (Cmd.Cmd = ResumeCmd) then if Suspend or RdyBsy=Bsy then Suspend := False; Suspended <= True; ReadMode <= rdCSR; else ReadMode <= rdARRAY; end if; elsif Cmd.Cmd = SleepCmd then if not Suspend then ReadMode <= rdARRAY; elsif (RdyBsy=Bsy) then PendingSleep := True; ReadMode <= rdCSR; else Sleep <= True; ReadMode <= rdCSR; end if; elsif Cmd.Cmd = ClearSRCmd then if Suspend then ReadMode <= rdARRAY; elsif (RdyBsy = Bsy) then ReadMode <= rdCSR; else EraseError <= False; ProgramError <= False; VppError <= False; for loopcntr in 0 to 31 loop BSR(loopcntr) := "00000000"; end loop; ReadMode <= rdARRAY; end if; end if; -- SUSPEND COMMAND -- elsif Cmd.Cmd = SuspendCmd then CmdValid <= False; if PendingSleep then PendingSleep := False; end if; if Sleep then ReadMode <= rdCSR; elsif RdyBsy = Rdy then ReadMode <= rdARRAY; else ReadMode <= rdCSR; Suspend := True; end if; -- ABORT COMMAND -- elsif Cmd.Cmd = AbortCmd then CmdValid <= False; Q1Valid <= False; Q2Valid <= False; Q3Valid <= False; Sleep <= True; PendingSleep := False; Suspend := False; BSR(Queue1.OpBlock)(5 downto 4) := "11"; if Queue1.OpType = Program then ProgramError <= True; elsif Queue1.OpType = Erase then EraseError <= True; else OperationError <= True; end if; else CmdValid <= False; assert false report "Illegal Command" severity WARNING; end if; end case; -- HANDLE ALGORITHMS if Other then if PendingSleep then PendingSleep := False; end if; if Sleep then WriteToPtr := NewCmd; ReadMode <= rdCSR; elsif (Cmd.UsesPB and PBInUse(PBPtr)) or QueueFull then WriteToPtr := NewCmd; if RdyBsy = Rdy then ReadMode <= rdARRAY; else ReadMode <= rdCSR; end if; -- If this command uses a page buffer swap it out and mark it used elsif Cmd.UsesPB then PBInUse(PBPtr) <= True; PBPtr <= 1-PBPtr; end if; end if; end case; end if; -------------------- -- Command Decode -- -------------------- if DataPtr'event and DataPtr=0 then -- When DataPtr hits zero it means that all the additional data has been -- given to the current command if WriteToPtr=ToPB then -- If we were writing to the page buffer than we just finished WriteToPtr := NewCmd; elsif CmdValid and WriteToPtr = CmdField then -- Just finish a multi-cycle command. -- Determine which block the command uses Cmd.OpBlock := bvtoi(Cmd.CmdAdd(1)(20 downto 16)); -- If in erase mark block as locked if Cmd.Cmd=EraseSingleBlockCmd then Tmp1 := 2; ErasingBlock := Cmd.OpBlock; BSR(Cmd.OpBlock)(7):='1'; elsif Cmd.Cmd=EraseAllBlocksCmd then ErasingBlock := -2; for Tmp1 in 0 to 31 loop if not BlockLocked(Tmp1,BSR,NVLockBit,wpb) then BSR(Tmp1)(7):='1'; end if; end loop; -- If the is a page buffer write to flash then we must determine how long the -- algoritm will take. This depends on the number of bytes which was just given. elsif Cmd.Cmd=PBWriteFlashCmd then -- Page Buffer Write to Flash Cmd.Count := bvtoi(Cmd.CmdData(1)(15 downto 0)); Cmd.Time := AC_PBProgramTime*Cmd.Count; elsif Cmd.Cmd=SeqPBWriteCmd then Tmp1 := bvtoi(Cmd.CmdData(2)(7 downto 0)); Tmp2 := bvtoi(Cmd.CmdData(1)(7 downto 0)); DataPtr <= ((256*Tmp2) + Tmp1); WriteToPtr := ToPB; CmdValid <= False; end if; -- If this command needs a confirm (flaged at predecode) then check if -- confirm was received if Cmd.Confirm then if Cmd.CmdData(1)(7 downto 0) = "11010000" then -- If the command is still valid put it in the queue and deactivate the array Enqueue <= True after 1 ns; ReadMode <= rdCSR; else CmdValid <= False; end if; elsif Cmd.Cmd /= SeqPBWriteCmd then ReadMode <= rdCSR; Enqueue <= True after 1 ns; end if; end if; end if; --------------------- -- Operation Queue -- --------------------- -- Enqueuer if Enqueue then -- If cmd is ready for placement in the queue then reset write ptr WriteToPtr := NewCmd; Enqueue <= False; CmdValid <= False after 1 ns; -- Find open slot if not Q1Valid and not Q1Valid'event then Queue1 := Cmd; Q1Valid <= True; QueueCmd <= True,False after 2 ns; ClearVppFlag <= True after 1 ns, False after 9 ns; AlgTime := Cmd.Time; elsif not Q2Valid and not Q2Valid'event then Queue2 := Cmd; Q2Valid <= True; QueueCmd <= True,False after 2 ns; else Queue3 := Cmd; Q3Valid <= True; end if; end if; -- Dequeuer -- Check to see if any slots should be moved up if not Q2Valid and Q3Valid then Queue2 := Queue3; Q3Valid <= False after 1 ns; end if; if not Q1Valid and Q2Valid then Queue1 := Queue2; Q2Valid <= False after 1 ns; ClearVppFlag <= True after 1 ns, False after 9 ns; AlgTime := Queue2.Time; end if; ------------------- -- Program Timer -- ------------------- if RdyBsy'event and RdyBsy = Bsy then -- If the algorithm engine just started, start the clock TimerClk <= '1' after 1 ns, '0' after AC.TimerPeriod; end if; if RdyBsy = Bsy and TimerClk'event and TimerClk = '0' then -- Reschedule clock and decrement algorithm count TimerClk <= '1' after 1 ns, '0' after AC.TimerPeriod; if not Suspended and RdyBsy = Bsy and Q1Valid then AlgTime := AlgTime-1; -- Check if the algorithm is done if AlgTime <= 0 then AlgDone <= true after 1 ns,false after 10 ns; end if; end if; end if; --------------------- -- Erase Interrupt -- --------------------- -- Check if we are in an interruptable condition if Q2Valid'event and Q2Valid and Queue1.OpType = Erase then -- Is the chip pending suspend? If so do it if Suspend then Suspend := False; Suspended <= True; end if; -- If we are currently erasing (from previous if then) and another erase -- erase is waiting right after us, then mark the block to be erased after -- the current one and remove it from the queue. if Queue2.Cmd = EraseSingleBlockCmd and Q2Valid then BSR(Queue2.OpBlock)(7) := '1'; Q2Valid <= False; -- If we are currently erasing (from previous if then) and an erase all -- is waiting right after us, then mark all blocks to be erased after -- the current one and remove it from the queue. elsif Queue2.Cmd = EraseAllBlocksCmd and Q2Valid then for loopcntr in 0 to 31 loop -- Mark Block if not BlockLocked(loopcntr,BSR,NVLockBit,wpb) then BSR(loopcntr)(7) := '1'; end if; end loop; Q2Valid <= False; elsif BSR(Queue2.OpBlock)(7) = '1' then -- Check to see if the command waiting can be executed now. Is the command's -- block pointer points to a block we plan to erase ? If so mark the block -- to be erased next, else pause and do the waiting command. AwaitingErase := Queue2.OpBlock; else GoTwoCmd <= True; PauseTime := AlgTime; AlgTime := Queue2.Time; end if; end if; --------------- -- Execution -- --------------- -- When the algorithm finishes if AlgDone'event and AlgDone then -- if chips is executing during an erase interrupt -- then execute out of queue slot 2 if GoTwoCmd then TheCmd := Queue2; else TheCmd := Queue1; end if; if TheCmd.OpType=Erase then if VppFlag then VppError <= True; else -- ERASE COMMAND -- if ErasingBlock /= -2 then -- Do ERASE to OpBlock for LoopCount in 0 to BlockWordSize loop MainArray(ErasingBlock)(LoopCount) := 16#FFFF#; end loop; -- Erase Non Volatile Lock bit NVLockBit(ErasingBlock) := '0'; BSR(ErasingBlock)(6) := '0'; -- Unlock OpBlock BSR(ErasingBlock)(7) := '0'; EndOfErase <= True,False after 10 ns; end if; -- Check if the command in slot 2 is waiting on the block -- just erased if ErasingBlock = AwaitingErase then AwaitingErase := -1; GoTwoCmd <= True; AlgTime := Queue2.Time; -- When queue 2 cmd is done go back into erase after one clock and -- search for the next block to erase. ErasingBlock:=-2; PauseTime := 1; elsif AwaitingErase /= -1 then -- Check if the command in slot 2 is waiting on a block -- needing erase if so erase in now ErasingBlock := AwaitingErase; AlgTime := AC_EraseTime; else -- Search for next block to erase. Set Block Ptr to -1 to represent -- not found BlockPtr := -1; for LoopCount in 0 to 31 loop if BSR(LoopCount)(7) = '1' then BlockPtr := LoopCount; end if; end loop; -- Did we find a block if so start erase algorithm else terminate -- the erase mechanism. if BlockPtr /= -1 then AlgTime := AC_EraseTime; ErasingBlock := BlockPtr; else Q1Valid <= False after 1 ns; -- ERASE Terminates end if; end if; end if; else case TheCmd.Cmd is -- PROGRAM COMMAND -- when ProgramCmd => if VppFlag then VppError <= True; else RowNum := bvtoi(TheCmd.CmdAdd(1)(15 downto 1)); NewData := bvtoi(TheCmd.CmdData(1)(15 downto 0)); program(MainArray(TheCmd.OpBlock)(RowNum),NewData); end if; -- LOCK BLOCK COMMAND -- when LockBlockCmd => if VppFlag then VppError <= True; else NVLockBit(TheCmd.OpBlock) := '1'; end if; -- UPLOAD STATUS COMMAND -- when StatusUploadCmd => UploadStatus(BSR,NVLockBit); -- WRITE PAGE BUFFER TO FLASH COMMAND -- when PBWriteFlashCmd => if VppFlag then VppError <= True; else -- Determine start point RowNum := bvtoi(TheCmd.CmdAdd(1)(15 downto 1)); PBIndex := bvtoi(TheCmd.CmdAdd(1)(7 downto 1)); -- Program main section in a by 16 path (regardless of byte pin) Fail := False; for LoopCount in 1 to WordCount loop if not Fail then NewData := PageBuffer(TheCmd.PBPtr)(PBIndex); program(MainArray(TheCmd.OpBlock)(RowNum),NewData); PBIndex := PBIndex+1; RowNum := RowNum+Tmp1; -- Check to see if we have hit the boundry of the page buffer if so return to bottom. if PBIndex>PBWordSize then PBIndex := 0; end if; -- Check to see if we have hit the boundry of a block if so fail and quit programming. if (RowNum > BlockWordSize) then Fail := True; end if; end if; end loop; if Fail then assert false report "Hit block boundry during PB write to Flash Cmd" severity warning; end if; end if; EndOfProgramPB <= True,False after 10 ns; -- DEVICE CONFIGURATION COMMAND -- when DeviceConfigCmd => RdyBsyConfig <= bvtoi(TheCmd.CmdData(1)(2 downto 0)); -- UPLOAD DEVICE STATUS COMMAND -- when UpDevInfoCmd => UploadStatus(BSR,NVLockBit); when others => assert false; end case; end if; -- See if we need to suspend after the algorith has ended if Suspend then Suspended <= True; end if; -- If we just finished executing queue slot 2 then kill it -- and restart queue slot 1 if GoTwoCmd then --Still old value since signal Q2Valid <= False after 1 ns; AlgTime := PauseTime; GoTwoCmd <= False; -- If algorithm does not run multiple time then when we get -- here the algorithm is done. elsif Queue1.OpType /= Erase then Q1Valid <= False; end if; end if; end if; end process; VccMonitor: process (Reset,vcc,InitTiming) variable CurrOperatingVoltage : COV_T := Unknown; begin if not Reset then if CurrOperatingVoltage = ThreeVolt then assert vcc > 3.0 and vcc < 3.6 report "Vcc is out of operating range for 3 volt mode" severity FAILURE; elsif CurrOperatingVoltage = FiveVolt then assert vcc > 4.5 and vcc < 5.5 report "Vcc is out of operating range for 5 volt mode" severity FAILURE; end if; end if; if vcc > Vcc5vThres then if CurrOperatingVoltage /= FiveVolt then TimingInit(FiveVolt,AC); CurrOperatingVoltage := FiveVolt; assert Reset or StartupFlag report "Vcc Level Changed when not in powerdown/reset" severity FAILURE; end if; else if CurrOperatingVoltage /= ThreeVolt then TimingInit(ThreeVolt,AC); CurrOperatingVoltage := ThreeVolt; assert Reset or StartupFlag report "Vcc Level Changed when not in powerdown/reset" severity FAILURE; end if; end if; end process; VppMonitor: process (VppFlag,ClearVppFlag,vpp) variable VppErrFlag : boolean := false; variable CurrOperatingVoltage : COV_T := Unknown; begin if ClearVppFlag then VppErrFlag := False; else if (Vpp > 12.6) or (Vpp < 4.5) then VppErrFlag := True; else if (Vpp>5.5) and (Vpp<11.4) then VppErrFlag := True; end if; end if; end if; VppFlag <= VppErrFlag; end process; ----------------------- -- Reset Controller -- ----------------------- ResetPowerdownMonitor: process(StartupFlag,rpb,vcc) begin -- Go into reset if reset powerdown pin is active or -- the vcc is too low if rpb /= '1' or vcc < 2.5 then -- Low Vcc protection Reset <= True; assert vcc >= 2.5 or StartupFlag report "Low Vcc: Chip Reseting" severity WARNING; else -- Coming out of reset takes time Reset <= False after 250 ns; end if; end process; ---------------------------- -- Ready Busy Pin Control -- ---------------------------- -- Determine if the algorithm engine is operating RdyBsy <= Bsy when (Q1Valid or Q2Valid or Q3Valid) and not Suspended else Rdy; ReadyBusyMonitor: -- Generate Ready busy pin responses depending of the current Rdy bsy configuration -- Note output is open drain. (It needs an external pull up of drive 'H'.) process (StartupFlag,EndOfProgramPB,EndOfErase,RdyBsy,RdyBsyConfig) begin if not StartupFlag then -- wait til timing constants assigned case RdyBsyConfig is when 2 => -- Pulse On Write if EndOfProgramPB'event and EndOfProgramPB then ry_byb <= '0','Z' after AC.TRLRZ; else if not RdyBsy'event then ry_byb <= 'Z'; end if; end if; when 3 => -- Pulse on Erase if EndOfErase'event and EndOfErase then ry_byb <= '0','Z' after AC.TRLRZ; else if not RdyBsy'event then ry_byb <= 'Z'; end if; end if; when 4 => -- Disable ry_byb <= 'Z'; when 5 => -- Pulse on Erase if EndOfErase'event and EndOfErase then ry_byb <= '0','Z' after AC.TRLRZ; else if EndOfProgramPB'event and EndOfProgramPB then ry_byb <= '0','Z' after AC.TRLRZ; else if not RdyBsy'event then ry_byb <= 'Z'; end if; end if; end if; when others => -- Normal Operation if RdyBsy = Bsy then ry_byb <= '0' after AC.TIHRL; else ry_byb <= 'Z' after AC.TADRZ; end if; end case; end if; end process; -------------------------- -- register definitions -- -------------------------- -- Compatible Status Register CSR(7) <= '0' when RdyBsy=Bsy else '1'; CSR(6) <= '1' when Suspended else '0'; CSR(5) <= '1' when EraseError else '0'; CSR(4) <= '1' when ProgramError else '0'; CSR(3) <= '1' when VppError else '0'; CSR(2 downto 0) <= "000"; DeviceOperationError <= ProgramError and EraseError and OperationError; PBavailStatus <= not (PBInUse(0) and PBInUse(1)); -- Global Status Register (same as Extended Status Register) GSR(7) <= '0' when RdyBsy=Bsy else '1'; GSR(6) <= '1' when Suspended else '0'; GSR(5) <= '1' when DeviceOperationError else '0'; GSR(4) <= '1' when Sleep else '0' ; GSR(3) <= '1' when QueueFull else '0' ; GSR(2) <= '1' when PBAvailStatus else '0' ; GSR(1) <= '0' when PBInUse(PBPtr) else '1' ; GSR(0) <= '1' when PBPtr = 1 else '0' ; ---------------- -- OE control -- ---------------- OEMonitor: -- This section generated DriveOutputs which is the main signal that -- controls the state of the output drivers process(StartupFlag,Internal_OE) variable WriteRecovery:time:= 0 ns; begin if not StartupFlag then WriteRecovery:=0 ns; if not (Now < AC.TIHGL) and (Internal_WE'last_event 0 ns) then write (l, string'("[")); write (l, time'(now)); write (l, string'("] Timing Violation: ")); write (l, warning); write (l, string'(" Insufficient High Time")); writeline(output,l); end if; else if ((Now - LastTime) < LoSpec) and (LoSpec > 0 ns) then write (l, string'("[")); write (l, time'(now)); write (l, string'("] Timing Violation: ")); write (l, warning); write (l, string'(" Insufficient Low Time")); writeline(output,l); end if; end if; LastTime:= Now; else LastTime:= LastTime; end if; end; -- variable l : line; variable LastWE : time := 0 ns; begin ------------------------- -- Write Timing Checks -- ------------------------- if (Now >0 ns) then pulse_chk(Internal_WE,LastWE,AC.TIHIL,AC.TILIH,"Internal Write Enable"); timing_chk(addr,Internal_WE,FallingEdge,AC.TAVIH,"Address setup time during write"); timing_chk(dq,Internal_WE,FallingEdge,AC.TAVIH,"Data setup time during write"); if not Internal_WE then timing_chk(Internal_WE,addr,AC.TIHAX,"Address hold time after write"); timing_chk(Internal_WE,dq,AC.TIHDX,"Data hold time after write"); end if; timing_chk(rpb,Internal_WE,FallingEdge,AC.TPHIL, "writing while coming out of powerdown"); end if; end process; end Intel28F016XD_hdl; configuration TheIntel28F016XDmodel of Intel28F016XD is for Intel28F016XD_hdl end for; end TheIntel28F016XDmodel;