------------------------------------------------------------------------------ -- 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 -- Functionality and specifications based on SFI-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 -- Jan 31, 1994 1.4 Fixed timing issues. --Known issues: (VHDL model differences only) -- BSRs should come OUT of reset reading block locked. -- Algorithms that fail may have different error codes. -- Next Release should be toward the end of Feb. LIBRARY ieee; USE std.textio.all; USE ieee.std_logic_1164.all; --------------------------------------------- ENTITY Intel28F016XS IS GENERIC ( LoadOnPowerUp : BOOLEAN := False; LoadFileName : STRING := ""; SaveOnPowerDown : BOOLEAN := False; SaveFileName : STRING := "" ); PORT ( dq : INOUT STD_LOGIC_VECTOR(15 DOWNTO 0); advb : IN STD_LOGIC; clk : IN STD_LOGIC; addr : IN STD_LOGIC_VECTOR(20 DOWNTO 0); byteb : IN STD_LOGIC; wpb : IN STD_LOGIC; ceb0 : IN STD_LOGIC; ceb1 : 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 Intel28F016XS; ARCHITECTURE Intel28F016XS_hdl OF Intel28F016XS 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#0A# ; 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#FFFF# ; CONSTANT PipeDepth : INTEGER := 16#08#; CONSTANT ID_ManufacturerB : INTEGER := 16#8989# ; 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 ; -- synchronous reads CONSTANT TELCH_3v : TIME := 12 ns ; CONSTANT TELCH_5v : TIME := 15 ns ; CONSTANT TVLCH_3v : TIME := 12 ns ; CONSTANT TVLCH_5v : TIME := 15 ns ; CONSTANT TAVCH_3v : TIME := 12 ns ; CONSTANT TAVCH_5v : TIME := 15 ns ; CONSTANT TGLCH_3v : TIME := 12 ns ; CONSTANT TGLCH_5v : TIME := 15 ns ; CONSTANT TCHQV_3v : TIME := 20 ns ; CONSTANT TCHQV_5v : TIME := 20 ns ; CONSTANT TPHQV_3v : TIME := 480 ns ; CONSTANT TPHQV_5v : TIME := 620 ns ; CONSTANT TCHQX_3v : TIME := 6 ns ; CONSTANT TCHQX_5v : TIME := 6 ns ; CONSTANT TEHQZ_3v : TIME := 30 ns ; CONSTANT TEHQZ_5v : TIME := 30 ns ; CONSTANT TCLCH_3v : TIME := 10 ns ; CONSTANT TCLCH_5v : TIME := 10 ns ; CONSTANT TCHCL_3v : TIME := 10 ns ; CONSTANT TCHCL_5v : TIME := 10 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(15 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); TYPE Banks_T IS ARRAY (0 TO 1) OF INTEGER; -- 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 (15 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 (15 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 Byte_T IS (By8,By16); TYPE BytePtr_T IS (By16,By8H,By8L); TYPE BytePin_T IS ARRAY (2 DOWNTO 1) OF Byte_T; 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 15; OpType : OpType_T; Count : INTEGER; CmdAdd : Add_T; CmdData : Data_T; BytePin : Byte_T; CmdByte : BytePin_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; TPHQV :TIME; TELCH :TIME; TAVCH :TIME; TCHCL :TIME; TCLCH :TIME; TGLCH :TIME; TCHQV :TIME; TCHQX :TIME; END RECORD; TYPE OutUnit_T IS RECORD AddressValid : BOOLEAN; Valid : BOOLEAN; BytePtr : BytePtr_T; Data : INTEGER; END RECORD; TYPE SFIconfig_T IS RECORD EnterPipe : INTEGER; BankHit : INTEGER; BankMiss : INTEGER; Value : INTEGER; END RECORD; TYPE OutputPipe_T IS ARRAY (0 TO 8) OF OutUnit_T; TYPE BankLat_T IS ARRAY (0 TO 1) OF INTEGER; 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 OutBytePtr : BytePtr_T ; -- Stores byte reference in x8 mode 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 ceb : STD_LOGIC ; -- Combined chip enables (active low) 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 SFIconfig : SFIconfig_T ; -- Current Latency CONFIGURATION 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; AC.TPHQV <= TPHQV_3v; AC.TELCH <= TELCH_3v; AC.TAVCH <= TAVCH_3v; AC.TCHCL <= TCHCL_3v; AC.TCLCH <= TCLCH_3v; AC.TGLCH <= TGLCH_3v; AC.TGHQZ <= TGHQZ_3v; AC.TCHQV <= TCHQV_3v; AC.TCHQX <= TCHQX_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; AC.TPHQV <= TPHQV_5v; AC.TELCH <= TELCH_5v; AC.TAVCH <= TAVCH_5v; AC.TCHCL <= TCHCL_5v; AC.TCLCH <= TCLCH_5v; AC.TGLCH <= TGLCH_5v; AC.TGHQZ <= TGHQZ_5v; AC.TCHQV <= TCHQV_5v; AC.TCHQX <= TCHQX_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 15 LOOP FOR RowPtr IN 0 TO BlockWordSize LOOP READ(ArrayInFile,MainArray(BlockPtr)(RowPtr)); END LOOP; END LOOP; FOR BlockPtr IN 0 TO 15 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 15 LOOP FOR RowPtr IN 0 TO BlockWordSize LOOP WRITE(ArrayOutFile,MainArray(BlockPtr)(RowPtr)); END LOOP; END LOOP; FOR BlockPtr IN 0 TO 15 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 ; BytePtr : IN BytePtr_T ) IS VARIABLE OldData : INTEGER ; VARIABLE NewData : INTEGER ; VARIABLE LowByte : INTEGER ; BEGIN OldData := TheArrayValue; LowByte := OldData MOD 256; CASE BytePtr IS WHEN By16 => NewData := DataIn; WHEN By8H => NewData := DataIn*256 + LowByte; WHEN By8L => NewData := DataIn + OldData - LowByte; END CASE; TheArrayValue := NewData AND OldData; 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 15 LOOP BSR(LoopCount)(6) := NVLockBit(LoopCount); END LOOP; END UploadStatus; BEGIN ------------------ -- chip selects -- ------------------ ceb <= ceb0 OR ceb1; MainCore: PROCESS (RdyBsy,ceb,byteb,Internal_OE,Internal_WE,DataPtr,Enqueue,TimerClk,StartupFlag,c lk, Q1Valid,Q2Valid,Q3Valid,CmdValid,AlgDone,vcc,Reset) VARIABLE BSR : BSRmem_T ; -- Contains current contents of BSR VARIABLE BankLat : BankLat_T ; -- Counters per bank to check and maintain bank latencies VARIABLE Bank : INTEGER ; -- Points to currently active bank VARIABLE AddressValid : BOOLEAN := False ; -- internal represention of the ADV pin gated with CE 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 OutPipe : OutputPipe_T ; -- This is the output pipeline. inserted afterread. 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 afterthe 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 afterthe 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 TheByte : Byte_T ; VARIABLE LowByte : INTEGER := 0 ; 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 15 LOOP BSR(loopcntr) := "00000000" ; NVLockBit(loopcntr) := '0' ; END LOOP; AlgTime := 0 ; ErasingBlock := -1 ; OutBytePtr <= By8L ; AddressValid := False ; BankLat(0) := 0 ; BankLat(1) := 0 ; SFIconfig.value <= 4 ; SFIconfig.BankHit <= 4 ; SFIconfig.BankMiss <= 2 ; SFIconfig.EnterPipe <= 5 ; -- Clear the output pipeline FOR loopcntr IN 0 TO PipeDepth LOOP OutPipe(loopcntr).AddressValid := False ; OutPipe(loopcntr).BytePtr := By16 ; OutPipe(loopcntr).Data := 0 ; END LOOP; 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 15 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 IF clk'event AND clk='1' THEN AddressValid:= (ceb OR advb) ='0'; IF AddressValid THEN ----------------- -- array reads -- ----------------- IF ReadMode = rdARRAY THEN -- Determine Bank, Rownum, Blocknum from address Bank := btoi(to_bit(addr(1))) ; BlockNum := bvtoi(to_bitvector(addr(20 DOWNTO 17))); RowNum := bvtoi(To_bitvector(addr(16 DOWNTO 1))); -- Determine if the latency counter has not expired for this bank. IF (BankLat(Bank) > 0) THEN ASSERT False REPORT "ERROR: BANK COLLISION" SEVERITY WARNING; END IF; -- Do the actual array read. ArrayOut := MainArray(BlockNum)(RowNum); BankLat(Bank) := SFIconfig.BankHit; BankLat(1-Bank) := SFIconfig.BankMiss; END IF; ----------------- -- other reads -- ----------------- IF (ReadMode /= rdARRAY) THEN CSROut := bvtoi(CSR); IF bvtoi(to_bitvector(addr(16 DOWNTO 3))) = 0 AND (byteb = '1' OR addr(0) = '0') THEN -- Create the correct BSR output IF addr(2 DOWNTO 1)="01" THEN BlockPtr := bvtoi(to_bitvector(addr(20 DOWNTO 17))); 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 (byteb = '0') THEN IF addr(0) = '0' THEN IDOut := ID_ManufacturerB; ELSE IDOUT := ID_DeviceCodeB; END IF; ELSE IF addr(1) = '0' THEN IDOut := ID_ManufacturerW; ELSE IDOUT := ID_DeviceCodeW; END IF; 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))); IF (byteb = '0') THEN IF addr(0) = '0' THEN PBOut := PageBuffer(PBPtr)(PBindex) MOD 256; ELSE PBOut := PageBuffer(PBPtr)(PBindex)/256; END IF; ELSE PBOut := PageBuffer(PBPtr)(PBindex); END IF; END IF; END IF; ---------------- -- output mux -- ---------------- -- Latency Manager IF ReadMode = rdARRAY THEN FOR LoopCounter IN 0 TO 1 LOOP IF (BankLat(LoopCounter)>0) THEN BankLat(LoopCounter) := BankLat(LoopCounter) -1; END IF; END LOOP; END IF; -- Output Mux OutPipe(SFIconfig.EnterPipe).AddressValid := AddressValid; OutPipe(SFIconfig.EnterPipe).Valid := True; CASE ReadMode IS WHEN rdARRAY => OutPipe(SFIconfig.EnterPipe).Data := ArrayOut; WHEN rdESR => OutPipe(SFIconfig.EnterPipe).Data := ESROut; WHEN rdCSR => OutPipe(SFIconfig.EnterPipe).Data := CSROut; WHEN rdID => OutPipe(SFIconfig.EnterPipe).Data := IDOut; WHEN rdPB => OutPipe(SFIconfig.EnterPipe).Data := PBOut; END CASE; -- Pipe Manager FOR loopcntr IN 0 TO (PipeDepth - 1) LOOP OutPipe(loopcntr) := OutPipe(loopcntr + 1); END LOOP; OutPipe(PipeDepth).Valid := False; OutPipe(PipeDepth).AddressValid := False; IF OutPipe(0).AddressValid THEN OutBytePtr <= OutPipe(0).BytePtr AFTER AC.TCHQV; InternalOutput <= OutPipe(0).Data AFTER AC.TCHQV; END IF; END IF; -- Handle BytePin IF byteb'event THEN IF byteb = '1' THEN OutBytePtr <= By16; FOR loopcntr IN 0 TO PipeDepth LOOP OutPipe(loopcntr).BytePtr := By16; END LOOP; ELSE OutBytePtr <= By8L; END IF; END IF; -------------------------- -- Handle Write to Part -- -------------------------- IF Internal_WE'event AND not Internal_WE THEN -- Rising Edge -- Record state of byte pin IF to_bit(byteb) = '0' THEN TheByte := By8; ELSE TheByte := By16; END IF; -- 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)); Cmd.BytePin := TheByte; -- CmdValid sends it to the Predecode section CmdValid <= True; DataPtr <= -1; WHEN CmdField => -- This is data used by another command Cmd.CmdData(DataPtr)(7 DOWNTO 0) := To_bitvector(dq(7 DOWNTO 0)); IF TheByte = By16 THEN Cmd.CmdData(DataPtr)(15 DOWNTO 8) := To_bitvector(dq(15 DOWNTO 8)); END IF; Cmd.CmdByte(DataPtr) := TheByte; 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 IF (byteb = '0') THEN LowByte := PageBuffer(PBPtr)(Index) MOD 256; IF to_bit(addr(0)) = '0' THEN PageBuffer(PBPtr)(Index) := PageBuffer(PBPtr)(Index) - LowByte + bvtoi(to_bitvector(dq(7 DOWNTO 0))); ELSE PageBuffer(PBPtr)(Index) := LowByte + 256 * bvtoi(to_bitvector(dq(7 DOWNTO 0))); END IF; ELSE PageBuffer(PBPtr)(Index) := bvtoi(to_bitvector(dq(15 DOWNTO 0))); END IF; 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/BYTE COMMAND -- WHEN ProgramCmd => -- Program Word/Byte 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; -- TWO BYTE PROGRAM COMMAND -- WHEN TwoByteWriteCmd => -- Two Byte Write WriteToPtr := CmdField; DataPtr <= 2; Cmd.Time := AC_TwoByteProgramTime; -- PROGRAM WORD/BYTE COMMAND -- WHEN Program2Cmd => -- Program Word/Byte 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 15 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; CmdValid <= False; ASSERT False REPORT "Illegal Command: Part is ASLEEP" SEVERITY ERROR; ELSIF (Cmd.UsesPB AND PBInUse(PBPtr)) OR QueueFull THEN CmdValid <= False; ASSERT False REPORT "Illegal Command: PageBuffer unavail OR queue is full." SEVERITY ERROR; 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 17)); -- 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 15 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 IF Cmd.BytePin= By8 THEN Tmp1 := bvtoi(Cmd.CmdData(1)(7 DOWNTO 0)); Tmp2 := bvtoi(Cmd.CmdData(2)(7 DOWNTO 0)); IF Cmd.CmdAdd(1)(0)='1' THEN write(l,STRING'("Low Count is")); Cmd.Count := ((256*Tmp2)+Tmp1); ELSE write(l,STRING'("High Count is")); Cmd.Count := ((256*Tmp1)+Tmp2); END IF; Cmd.Time := Cmd.Count/2 * AC_PBProgramTime; int2string(Tmp1,s); write(l,s); writeline(output,l); write(l,STRING'("Other Count is")); int2string(Tmp2,s); write(l,s); writeline(output,l); write(l,STRING'("Result is")); int2string(((256*Tmp2)+Tmp1),s); write(l,s); writeline(output,l); ELSE Cmd.Count := bvtoi(Cmd.CmdData(1)(15 DOWNTO 0)); Cmd.Time := AC_PBProgramTime*Cmd.Count; END IF; 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 (4*AC.TimerPeriod); 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 (4*AC.TimerPeriod); 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; Q2Valid <= True; Q3Valid <= False AFTER 1 ns; END IF; IF NOT Q1Valid AND Q2Valid THEN Queue1 := Queue2; Q1Valid <= True; 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 afterus, 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 afterus, 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 15 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; EndOfErase <= True,False AFTER 10 ns; Q1Valid <= False AFTER 1 ns; -- ERASE Terminates 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 afterone 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 15 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)(16 DOWNTO 1)); NewData := bvtoi(TheCmd.CmdData(1)(15 DOWNTO 0)); IF TheCmd.BytePin = By8 THEN IF TheCmd.CmdAdd(1)(0) = '1' THEN program(MainArray(TheCmd.OpBlock)(RowNum),NewData,By8H); ELSE program(MainArray(TheCmd.OpBlock)(RowNum),NewData,By8L); END IF; ELSE program(MainArray(TheCmd.OpBlock)(RowNum),NewData,By16); END IF; END IF; -- TWO BYTE WRITE COMMAND -- WHEN TwoByteWriteCmd => IF VppFlag THEN VppError <= True; ELSE RowNum := bvtoi(TheCmd.CmdAdd(1)(16 DOWNTO 1)); IF TheCmd.CmdAdd(1)(0) = '0' THEN NewData := 256*bvtoi(TheCmd.CmdData(1)(7 DOWNTO 0)) + bvtoi(TheCmd.CmdData(2)(7 DOWNTO 0)); ELSE NewData := bvtoi(TheCmd.CmdData(1)(7 DOWNTO 0)) + 256*bvtoi(TheCmd.CmdData(2)(7 DOWNTO 0)); END IF; program(MainArray(TheCmd.OpBlock)(RowNum),NewData,By16); 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 Tmp1 := 1; RowNum := bvtoi(TheCmd.CmdAdd(1)(16 DOWNTO 1)); PBIndex := bvtoi(TheCmd.CmdAdd(1)(7 DOWNTO 1)); IF TheCmd.BytePin = By8 THEN -- if in by eight mode, handle the possible odd byte IF TheCmd.CmdAdd(1)(0) = '1' THEN NewData := PageBuffer(TheCmd.PBPtr)(PBIndex)/256; program(MainArray(TheCmd.OpBlock)(RowNum),NewData,By8H); RowNum := RowNum + Tmp1; PBIndex := PBIndex + 1; TheCmd.Count := TheCmd.Count - 1; END IF; WordCount := TheCmd.Count/2; END IF; -- 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,By16); 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 NOT Fail AND (TheCmd.BytePin = By8) AND (TheCmd.Count MOD 2 = 1) THEN NewData := PageBuffer(TheCmd.PBPtr)(PBIndex) MOD 256; program(MainArray(TheCmd.OpBlock)(RowNum),NewData,By8L); END IF; 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)); CASE TheCmd.CmdData(1)(5 DOWNTO 3) IS WHEN "000" => SFIconfig.value <= 4; SFIconfig.EnterPipe <= 5; SFIconfig.BankHit <= 4; SFIconfig.BankMiss <= 2; WHEN "001" => SFIconfig.value <= 1; SFIconfig.EnterPipe <= 2; SFIconfig.BankHit <= 1; SFIconfig.BankMiss <= 1; WHEN "010" => SFIconfig.value <= 2; SFIconfig.EnterPipe <= 3; SFIconfig.BankHit <= 1; SFIconfig.BankMiss <= 2; WHEN "011" => SFIconfig.value <= 3; SFIconfig.EnterPipe <= 4; SFIconfig.BankHit <= 2; SFIconfig.BankMiss <= 3; WHEN "100" => SFIconfig.value <= 4; SFIconfig.EnterPipe <= 5; SFIconfig.BankHit <= 4; SFIconfig.BankMiss <= 2; WHEN others => ASSERT False REPORT "Illegal Configuration" SEVERITY FAILURE; END CASE; -- UPLOAD DEVICE STATUS COMMAND -- WHEN UpDevInfoCmd => UploadStatus(BSR,NVLockBit); WHEN others => ASSERT False; END CASE; END IF; -- See if we need to suspend afterthe 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 -- ---------------- Internal_OE<= (ceb OR oeb OR NOT rpb) = '0' ; 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 -1 ELSE "XXXXXXXX" WHEN DriveOutputs AND byteb='1' AND InternalOutput < 0 ELSE "ZZZZZZZZ"; dq(7 DOWNTO 0) <= itov(InternalOutput MOD 256 ,8) WHEN DriveOutputs AND NOT (byteb='0' AND OutBytePtr=By8H) ELSE itov (InternalOutput/256,8) WHEN DriveOutputs AND byteb='0' AND OutBytePtr=By8H ELSE "ZZZZZZZZ"; Internal_WE <= (ceb OR web OR NOT rpb) = '0'; QueueFull<= Q3Valid OR QueueCmd; PROCESS (Internal_WE,addr,dq,clk) PROCEDURE timing_chk( SIGNAL TheSig : IN STD_LOGIC; --From SIGNAL RefSig : IN BOOLEAN; --To edge : IN edge_t; spec : IN TIME; warning : IN STRING ) IS VARIABLE l : line; VARIABLE e :BOOLEAN; BEGIN e := (edge=RisingEdge OR edge=RE); IF RefSig'event AND (RefSig = e OR edge = AnyEdge OR edge = AE) THEN IF TheSig'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 Intel28F016XS_hdl; CONFIGURATION TheIntel28F016XSmodel OF Intel28F016XS IS FOR Intel28F016XS_hdl END FOR; END TheIntel28F016XSmodel;