URL
https://opencores.org/ocsvn/or1200_soc/or1200_soc/trunk
Subversion Repositories or1200_soc
[/] [or1200_soc/] [trunk/] [boards/] [de1_board/] [sim/] [models/] [S29al032d_00/] [utilities/] [CreateSDF/] [testbench.vhd] - Rev 22
Compare with Previous | Blame | View Log
------------------------------------------------------------------------------ -- File name : testbench_640.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2003 AMD. -- -- MODIFICATION HISTORY : -- -- version: | author: | mod date: | changes made: -- V0.1 M.Marinkovic 11 July 03 Initial -- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Description: -- Generic test enviroment for verification of AMD flash memory -- VITAL models.my_mem -- ------------------------------------------------------------------------------- -- Note: VHDL code formating not done -- For High/Low sector protection selection change: -- TimingModel constant and TimingModel generic value -- ------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; --USE IEEE.VITAL_timing.ALL; --USE IEEE.VITAL_primitives.ALL; USE STD.textio.ALL; LIBRARY VITAL2000; USE VITAL2000.vital_timing.ALL; USE VITAL2000.vital_primitives.ALL; LIBRARY FMF; USE FMF.gen_utils.ALL; USE FMF.conversions.ALL; LIBRARY work; USE work.amd_tc_pkg.ALL; ------------------------------------------------------------------------------- -- ENTITY DECLARATION ------------------------------------------------------------------------------- ENTITY testbench_640 IS END testbench_640; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of testbench_640 IS COMPONENT my_mem GENERIC ( -- tipd delays: interconnect path delays tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(tCE,tCE,tDF,-,tDF,-) tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(tOE,tOE,tDF,-,tDF,-) tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; --(-,-,0,-,0,-) tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY --tsetup values tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / --thold values thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / --tpw values: pulse width tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC -- tdevice values: values for internal delays --Effective Write Buffer Program Operation tWHWH1 tdevice_WBPB : VitalDelayType := 11 us; --Program Operation tdevice_POB : VitalDelayType := 100 us; --Sector Erase Operation tWHWH2 tdevice_SEO : VitalDelayType := 500 ms; --Timing Limit Exceeded tdevice_HANG : VitalDelayType := 400 ms; --? --program/erase suspend timeout tdevice_START_T1 : VitalDelayType := 5 us; --sector erase command sequence timeout tdevice_CTMOUT : VitalDelayType := 50 us; --device ready after Hardware reset(during embeded algorithm) tdevice_READY : VitalDelayType := 20 us; --tReady -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- memory file to be loaded mem_file_name : STRING ;--:= "am29lv640m.mem"; prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; UserPreload : BOOLEAN ;--:= TRUE; LongTimming : BOOLEAN ;--:= TRUE; -- For FMF SDF technology file usage TimingModel : STRING --:= "AM29LV640MH90R" ); PORT ( A21 : IN std_logic := 'U'; -- A20 : IN std_logic := 'U'; -- A19 : IN std_logic := 'U'; -- A18 : IN std_logic := 'U'; -- A17 : IN std_logic := 'U'; -- A16 : IN std_logic := 'U'; -- A15 : IN std_logic := 'U'; -- A14 : IN std_logic := 'U'; -- A13 : IN std_logic := 'U'; --address A12 : IN std_logic := 'U'; --lines A11 : IN std_logic := 'U'; -- A10 : IN std_logic := 'U'; -- A9 : IN std_logic := 'U'; -- A8 : IN std_logic := 'U'; -- A7 : IN std_logic := 'U'; -- A6 : IN std_logic := 'U'; -- A5 : IN std_logic := 'U'; -- A4 : IN std_logic := 'U'; -- A3 : IN std_logic := 'U'; -- A2 : IN std_logic := 'U'; -- A1 : IN std_logic := 'U'; -- A0 : IN std_logic := 'U'; -- DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 DQ14 : INOUT std_logic := 'U'; -- DQ13 : INOUT std_logic := 'U'; -- DQ12 : INOUT std_logic := 'U'; -- DQ11 : INOUT std_logic := 'U'; -- DQ10 : INOUT std_logic := 'U'; -- DQ9 : INOUT std_logic := 'U'; -- data DQ8 : INOUT std_logic := 'U'; -- lines DQ7 : INOUT std_logic := 'U'; -- DQ6 : INOUT std_logic := 'U'; -- DQ5 : INOUT std_logic := 'U'; -- DQ4 : INOUT std_logic := 'U'; -- DQ3 : INOUT std_logic := 'U'; -- DQ2 : INOUT std_logic := 'U'; -- DQ1 : INOUT std_logic := 'U'; -- DQ0 : INOUT std_logic := 'U'; -- CENeg : IN std_logic := 'U'; OENeg : IN std_logic := 'U'; WENeg : IN std_logic := 'U'; RESETNeg : IN std_logic := 'U'; WPNeg : IN std_logic := 'U'; --WP#/ACC BYTENeg : IN std_logic := 'U'; RY : OUT std_logic := 'U' --RY/BY# ); END COMPONENT; FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); --------------------------------------------------------------------------- --memory configuration --------------------------------------------------------------------------- CONSTANT MaxData : NATURAL := 16#FF#; --255; CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 CONSTANT SecSiSize : NATURAL := 255; CONSTANT SecNum : NATURAL := 127; CONSTANT HiAddrBit : NATURAL := 21; --Address of the Protected Sector -- CONSTANT ProtSecNum : NATURAL := SecNum; --------------------------------------------------------------------------- --model configuration --------------------------------------------------------------------------- CONSTANT mem_file : STRING := "am29lv640m.mem"; CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; CONSTANT UserPreload : boolean := TRUE; CONSTANT DebugInfo : boolean := FALSE; CONSTANT LongTimming : boolean := TRUE; CONSTANT TimingModel : STRING := "MY_MEM"; -- "AM29LV640MH90R";--High sect prot. -- "AM29LV128ML93R";--Low sect. prot. --------------------------------------------------------------------------- SIGNAL ProtSecNum : NATURAL := SecNum ; --Flash Memory Array TYPE SecType IS ARRAY (0 TO SecSize) OF INTEGER RANGE -1 TO MaxData; TYPE MemArray IS ARRAY (0 TO SecNum) OF SecType; --Common Flash Interface Query codes TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF NATURAL RANGE 0 TO 16#FF#; --SecSi Sector TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF INTEGER RANGE -1 TO MaxData; --------------------------------------------------------------------------- -- memory declaration --------------------------------------------------------------------------- -- -- Mem(SecAddr)(Address).... SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); --command sequence SHARED VARIABLE cmd_seq : cmd_seq_type; SIGNAL status : status_type := none; SIGNAL sts_check : std_logic_vector(7 downto 0); SIGNAL check_err : std_logic := '0'; SIGNAL ErrorInTest : std_logic := '0'; -- ---------------------------------------------------------------------------- --Personality module: -- -- instanciates the DUT module and adapts generic test signals to it -- TBD: block port ---------------------------------------------------------------------------- --DUT port SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); SIGNAL T_RESETNeg : std_logic := 'U'; SIGNAL T_CENeg : std_logic := 'U'; SIGNAL T_WENeg : std_logic := 'U'; SIGNAL T_OENeg : std_logic := 'U'; SIGNAL T_WPNeg : std_logic := 'U'; SIGNAL T_BYTENeg : std_logic := 'U'; SIGNAL T_RY : std_logic := 'U'; --------------------------------------------------------------------------- -- --------------------------------------------------------------------------- --SecSi ProtectionStatus SHARED VARIABLE FactoryProt : std_logic := '1'; --Sector Protection Status SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := (OTHERS => '0'); SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; --CONSTANT --timming parameters CONSTANT RESETNeg_pw : time := 500 ns; --tRP SIGNAL pwron : std_logic := '0'; SIGNAL Tseries : NATURAL; SIGNAL Tcase : NATURAL; SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter BEGIN DUT : my_mem GENERIC MAP ( -- tipd delays: interconnect path delays tipd_A0 => VitalZeroDelay01, -- tipd_A1 => VitalZeroDelay01, -- tipd_A2 => VitalZeroDelay01, -- tipd_A3 => VitalZeroDelay01, -- tipd_A4 => VitalZeroDelay01, -- tipd_A5 => VitalZeroDelay01, -- tipd_A6 => VitalZeroDelay01, -- tipd_A7 => VitalZeroDelay01, -- tipd_A8 => VitalZeroDelay01, -- tipd_A9 => VitalZeroDelay01, --address tipd_A10 => VitalZeroDelay01, --lines tipd_A11 => VitalZeroDelay01, -- tipd_A12 => VitalZeroDelay01, -- tipd_A13 => VitalZeroDelay01, -- tipd_A14 => VitalZeroDelay01, -- tipd_A15 => VitalZeroDelay01, -- tipd_A16 => VitalZeroDelay01, -- tipd_A17 => VitalZeroDelay01, -- tipd_A18 => VitalZeroDelay01, -- tipd_A19 => VitalZeroDelay01, -- tipd_A20 => VitalZeroDelay01, -- tipd_A21 => VitalZeroDelay01, -- tipd_DQ0 => VitalZeroDelay01, -- tipd_DQ1 => VitalZeroDelay01, -- tipd_DQ2 => VitalZeroDelay01, -- tipd_DQ3 => VitalZeroDelay01, -- tipd_DQ4 => VitalZeroDelay01, -- tipd_DQ5 => VitalZeroDelay01, -- tipd_DQ6 => VitalZeroDelay01, -- data tipd_DQ7 => VitalZeroDelay01, -- lines tipd_DQ8 => VitalZeroDelay01, -- tipd_DQ9 => VitalZeroDelay01, -- tipd_DQ10 => VitalZeroDelay01, -- tipd_DQ11 => VitalZeroDelay01, -- tipd_DQ12 => VitalZeroDelay01, -- tipd_DQ13 => VitalZeroDelay01, -- tipd_DQ14 => VitalZeroDelay01, -- tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 tipd_CENeg => VitalZeroDelay01, tipd_OENeg => VitalZeroDelay01, tipd_WENeg => VitalZeroDelay01, tipd_RESETNeg => VitalZeroDelay01, tipd_WPNeg => VitalZeroDelay01,--WP#/ACC tipd_BYTENeg => VitalZeroDelay01, -- tpd delays tpd_A0_DQ0 => UnitDelay01,--tACC tpd_A0_DQ1 => UnitDelay01,--tPACC tpd_CENeg_DQ0 => UnitDelay01Z, --(tCE,tCE,tDF,-,tDF tpd_OENeg_DQ0 => UnitDelay01Z, --(tOE,tOE,tDF,-,tDF tpd_RESETNeg_DQ0 => UnitDelay01Z, --(-,-,0,-,0,-) tpd_CENeg_RY => UnitDelay01, --tBUSY tpd_WENeg_RY => UnitDelay01, --tBUSY --tsetup values tsetup_A0_CENeg => UnitDelay, --tAS edge \ tsetup_A0_OENeg => UnitDelay, --tASO edge \ tsetup_DQ0_CENeg => UnitDelay, --tDS edge / --thold values thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / thold_OENeg_WENeg => UnitDelay, --tOEH edge / thold_A0_CENeg => UnitDelay, --tAH edge \ thold_A0_OENeg => UnitDelay, --tAHT edge \ thold_DQ0_CENeg => UnitDelay, --tDH edge / thold_WENeg_OENeg => UnitDelay, --tGHVL edge / --tpw values: pulse width tpw_RESETNeg_negedge=> UnitDelay, --tRP tpw_OENeg_posedge => UnitDelay, --tOEPH tpw_WENeg_negedge => UnitDelay, --tWP tpw_WENeg_posedge => UnitDelay, --tWPH tpw_CENeg_negedge => UnitDelay, --tCP tpw_CENeg_posedge => UnitDelay, --tCEPH tpw_A0_negedge => UnitDelay, --tWC tRC -- tdevice values: values for internal delays --Effective Write Buffer Program Operation tWHWH1 tdevice_WBPB => 11 us, --Program Operation tdevice_POB => 100 us, --Sector Erase Operation tWHWH2 tdevice_SEO => 500 ms, --Timing Limit Exceeded tdevice_HANG => 400 ms, --? --program/erase suspend timeout tdevice_START_T1 => 5 us, --sector erase command sequence timeout tdevice_CTMOUT => 50 us, --device ready after Hardware reset(during embeded algorithm) tdevice_READY => 20 us, --tReady -- generic control parameters InstancePath => DefaultInstancePath, TimingChecksOn => TRUE,--DefaultTimingChecks, MsgOn => DefaultMsgOn, XOn => DefaultXon, -- memory file to be loaded mem_file_name => mem_file, prot_file_name => prot_file , secsi_file_name => secsi_file, UserPreload => UserPreload, LongTimming => LongTimming, -- For FMF SDF technology file usage TimingModel => "AM29LV640MH90R" -- TimingModel ) PORT MAP( A21 => T_A(21), -- A20 => T_A(20), -- A19 => T_A(19), -- A18 => T_A(18), -- A17 => T_A(17), -- A16 => T_A(16), -- A15 => T_A(15), -- A14 => T_A(14), -- A13 => T_A(13), --address A12 => T_A(12), --lines A11 => T_A(11), -- A10 => T_A(10), -- A9 => T_A(9), -- A8 => T_A(8), -- A7 => T_A(7), -- A6 => T_A(6), -- A5 => T_A(5),-- A4 => T_A(4),-- A3 => T_A(3), -- A2 => T_A(2), -- A1 => T_A(1), -- A0 => T_A(0), -- DQ15 => T_DQ(15), -- DQ15/A-1 DQ14 => T_DQ(14), -- DQ13 => T_DQ(13), -- DQ12 => T_DQ(12), -- DQ11 => T_DQ(11), -- DQ10 => T_DQ(10), -- DQ9 => T_DQ(9), -- data DQ8 => T_DQ(8), -- lines DQ7 => T_DQ(7), -- DQ6 => T_DQ(6), -- DQ5 => T_DQ(5), -- DQ4 => T_DQ(4), -- DQ3 => T_DQ(3), -- DQ2 => T_DQ(2), -- DQ1 => T_DQ(1), -- DQ0 => T_DQ(0), -- CENeg => T_CENeg, OENeg => T_OENeg, WENeg => T_WENeg, RESETNeg => T_RESETNeg, WPNeg => T_WPNeg, --WP#/ACC BYTENeg => T_BYTENeg, RY => T_RY --RY/BY# ); --------------------------------------------------------------------------- --protected sector --------------------------------------------------------------------------- ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE 0 ;-- WHEN TimingModel = "AM29LV128ML93R" pwron <= '0', '1' after 1 ns; --At the end of the simulation, if ErrorInTest='0' there were no errors err_ctrl : PROCESS ( check_err ) BEGIN IF check_err = '1' THEN ErrorInTest <= '1'; END IF; END PROCESS err_ctrl; tb :PROCESS -------------------------------------------------------------------------- --= PROCEDURE to select TC -- can be modified to read TC list from file, or to generate random list -------------------------------------------------------------------------- PROCEDURE Pick_TC (Model : IN STRING := "AM29LV640MH90R" ) IS BEGIN IF TC_cnt < tc(TS_cnt) THEN TC_cnt := TC_cnt+1; ELSE TC_cnt:=1; IF TS_cnt<30 THEN TS_cnt := TS_cnt+1; ELSE -- end test IF ErrorInTest='0' THEN REPORT "Test Ended without errors" SEVERITY note; ELSE REPORT "There were errors in test" SEVERITY note; END IF; WAIT; END IF; END IF; END PROCEDURE Pick_TC; --------------------------------------------------------------------------- --bus commands, device specific implementation --------------------------------------------------------------------------- TYPE bus_type IS (bus_idle, bus_standby, --CE# deasseretd, others are don't care bus_enable, --CE# asserted, others deasserted bus_output_disable, bus_reset, bus_write, bus_read); --bus drive for specific command sequence cycle PROCEDURE bus_cycle( bus_cmd :IN bus_type := bus_idle; byte :IN boolean ; data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr address :IN NATURAL RANGE 0 TO SecSize := 0; disable :IN boolean := false; violate :IN boolean := false; tm :IN TIME := 10 ns) IS VARIABLE tmp : std_logic_vector(15 downto 0); BEGIN IF data=-1 THEN -- HiZ T_DQ(7 downto 0) <= (OTHERS => 'Z'); END IF; IF (NOT byte)THEN --word access IF dataHi=-1 THEN -- HiZ T_DQ(15 downto 8) <= (OTHERS => 'Z'); END IF; T_BYTENeg <= '1'; ELSE --byte access T_BYTENeg <= '0'; T_DQ(14 downto 8) <= (OTHERS => 'Z'); END IF; IF sector > -1 THEN T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); tmp := to_slv(address, 16); IF byte THEN T_A(14 downto 0) <= tmp(15 downto 1); T_DQ(15) <= tmp(0); ELSE T_A(14 downto 0) <= tmp(14 downto 0); END IF; END IF; wait for 1 ns; CASE bus_cmd IS WHEN bus_output_disable => T_OENeg <= '1'; WAIT FOR 20 ns; WHEN bus_idle => T_RESETNeg <= '1'; T_WENeg <= '1'; T_CENeg <= '1'; T_OENeg <= '1'; IF disable THEN T_WPNeg <= '0'; ELSE T_WPNeg <= '1'; END IF; WAIT FOR 30 ns; WHEN bus_standby => T_CENeg <= '1'; WAIT FOR 30 ns; WHEN bus_reset => T_RESETNeg <= '0', '1' AFTER tm ; -- WAIT FOR 500 ns should follow this bus cmd for reset to --complete WAIT FOR 30 ns; WHEN bus_enable => T_WENeg <= '1' AFTER 50 ns; --- T_CENeg <= '0' AFTER 50 ns; --- T_OENeg <= '1' AFTER 30 ns; --- WAIT FOR tm ; WHEN bus_write => T_OENeg <= '1' ;-- AFTER 5 ns; T_CENeg <= '0' AFTER 10 ns ; T_WENeg <= '0' AFTER 20 ns; IF data>-1 THEN T_DQ(7 downto 0) <= to_slv(data,8); END IF; IF NOT byte THEN IF dataHi>-1 THEN T_DQ(15 downto 8) <= to_slv(dataHi,8); END IF; END IF; IF violate THEN T_WENeg <= '1'; WAIT FOR 50 ns; T_WENeg <= '0', '1' AFTER tm; WAIT FOR 50 ns; ELSE WAIT FOR 100 ns; END IF; WHEN bus_read => T_CENeg <= '0' ; T_WENeg <= '1'AFTER 10 ns; IF NOT disable THEN T_OENeg <= '0' AFTER 15 ns; ELSE T_OENeg <= '1'; END IF; IF NOT byte THEN T_DQ(15 downto 8) <= (OTHERS => 'Z'); END IF; T_DQ(7 downto 0) <= (OTHERS => 'Z'); WAIT FOR 100 ns; -- T_OENeg <= '1' ; ----------- END CASE; END PROCEDURE; --------------------------------------------------------------------------- --procedure to decode commands into specific bus command sequence --------------------------------------------------------------------------- PROCEDURE cmd_dc ( command : IN cmd_rec ) IS VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; VARIABLE D_lo : NATURAL RANGE 0 to MaxData; VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); VARIABLE byte : boolean; VARIABLE i : NATURAL; BEGIN CASE command.cmd IS WHEN idle => bus_cycle(bus_cmd => bus_idle, byte => command.byte, disable => command.aux=disable); WHEN h_reset => bus_cycle(bus_cmd => bus_reset, byte => command.byte, tm => command.wtime); WHEN rd => bus_cycle(bus_cmd => bus_enable, byte => command.byte, data => -1, sector => command.sect, address => command.addr, tm => 90 ns); bus_cycle(bus_cmd => bus_read, byte => command.byte, data => -1, dataHi => -1, sector => command.sect, address => command.addr, disable => command.aux=disable); bus_cycle(bus_cmd => bus_output_disable, byte => command.byte); WHEN rd_page => bus_cycle(bus_cmd => bus_enable, byte => command.byte, data => -1, sector => 0, address => 0, tm => 90 ns); Addr := command.addr; Sect := command.sect; byte := command.byte; ---- 08July---- WAIT FOR 10 ns; -------------- i := 0; WHILE i < command.d_hi LOOP IF command.wtime > 0 ns THEN bus_cycle(bus_cmd => bus_output_disable, ---- byte => byte); ---- --byte toggle mode bus_cycle(bus_cmd => bus_enable, byte => byte, data => -1, sector => -1, tm => 10 ns); byte := false; bus_cycle(bus_cmd => bus_enable, byte => byte, data => -1, sector => -1, tm => 10 ns); Addrfix := Addr /2; IF Addr < SecSize THEN Addr := Addr+1; ELSE Addr := 0; IF Sect < SecNum THEN Sect := Sect+1; ELSE REPORT "No more locations to read !!!" SEVERITY warning; END IF; END IF; --word read; bus_cycle(bus_cmd => bus_read, byte => byte, data => -1, dataHi => -1, sector => Sect, address => Addrfix); bus_cycle(bus_cmd => bus_output_disable, ---- byte => byte); ---- bus_cycle(bus_cmd => bus_enable, byte => byte, data => -1, sector => -1, tm => 10 ns); byte := true; bus_cycle(bus_cmd => bus_enable, byte => byte, data => -1, sector => -1, tm => 30 ns); --first byte read bus_cycle(bus_cmd => bus_read, byte => byte, data => -1, dataHi => -1, sector => Sect, address => Addr); bus_cycle(bus_cmd => bus_output_disable, ---- byte => byte); ---- IF Addr < SecSize THEN Addr := Addr+1; ELSE Addr := 0; IF Sect < SecNum THEN Sect := Sect+1; ELSE REPORT "No more locations to read !!!" SEVERITY warning; END IF; END IF; i := i +3; wait for 10 ns; ------- ELSE byte := command.byte; END IF; --second byte read in byte toggle mode bus_cycle(bus_cmd => bus_read, byte => byte, data => -1, dataHi => -1, sector => Sect, address => Addr); IF Addr < SecSize THEN Addr := Addr+1; ELSE Addr := 0; IF Sect < SecNum THEN Sect := Sect+1; ELSE REPORT "No more locations to read !!!" SEVERITY warning; END IF; END IF; i := i +1; WAIT FOR 10 ns; END LOOP; bus_cycle(bus_cmd => bus_output_disable, byte => command.byte); WHEN w_cycle => D_lo := 16#AA# ; --first command data Addr := 16#AAA#; --first command byte address D_hi := 16#55#; --second command data Addrfix := 16#555#; --second command byte address IF NOT command.byte THEN --if word addressing Addr := 16#555#; --first command byte address Addrfix := 16#2AA#; --second command byte address END IF; bus_cycle(bus_cmd => bus_write, byte => command.byte, data => D_lo, dataHi => 0, sector => 0, address => Addr, violate => command.aux=violate, tm => command.wtime); bus_cycle(bus_cmd => bus_standby, byte => command.byte); bus_cycle(bus_cmd => bus_write, byte => command.byte, data => D_hi, dataHi => 0, sector => 0, address => Addrfix); bus_cycle(bus_cmd => bus_standby, byte => command.byte); WHEN w_reset | w_prog | w_erase | w_unlock | w_autoselect | w_enter_sec => Addr := 16#AAA#; IF NOT command.byte THEN --if word addressing Addr := 16#555#; --first command byte address END IF; CASE command.cmd IS WHEN w_reset => d_lo := 16#F0#; WHEN w_prog => d_lo := 16#A0#; WHEN w_erase => d_lo := 16#80#; WHEN w_unlock => d_lo := 16#20#; WHEN w_autoselect => d_lo := 16#90#; WHEN w_enter_sec => d_lo := 16#88#; WHEN OTHERS => d_lo := 0; END CASE; bus_cycle(bus_cmd => bus_write, byte => command.byte, data => d_lo, dataHi => 0, sector => 0, address => Addr); bus_cycle(bus_cmd => bus_standby, byte => command.byte); WHEN w_unlock_reset => Addr := 16#AAA#; --first command byte address IF NOT command.byte THEN --if word addressing Addr := 16#555#; --first command byte address END IF; bus_cycle(bus_cmd => bus_write, byte => command.byte, data => 16#90#, dataHi => 0, sector => 0, address => Addr); bus_cycle(bus_cmd => bus_standby, byte => command.byte); bus_cycle(bus_cmd => bus_write, byte => command.byte, data => 16#F0#, dataHi => 0, sector => 0, address => Addr); bus_cycle(bus_cmd => bus_standby, byte => command.byte); WHEN w_chip_ers => Addr := 16#AAA#; --first command byte address IF NOT command.byte THEN --if word addressing Addr := 16#555#; --first command byte address END IF; bus_cycle(bus_cmd => bus_write, byte => command.byte, data => 16#10#, dataHi => 0, sector => 0, Address => Addr); FOR i IN 0 TO SecNum LOOP IF Sec_Prot(i)/='1' THEN mem(i) := (OTHERS=>16#FF#); END IF; END LOOP; bus_cycle(bus_cmd => bus_standby, byte => command.byte); WHEN w_cfi => Addr := 16#AA#; --first command byte address IF NOT command.byte THEN --if word addressing Addr := 16#55#; --first command byte address END IF; bus_cycle(bus_cmd => bus_write, byte => command.byte, data => 16#98#, dataHi => 0, sector => 0, Address => Addr); bus_cycle(bus_cmd => bus_standby, byte => command.byte); WHEN w_suspend => bus_cycle(bus_cmd => bus_write, byte => command.byte, data => 16#B0#, dataHi => 0, sector => -1); bus_cycle(bus_cmd => bus_standby, byte => command.byte); WHEN w_resume => bus_cycle(bus_cmd => bus_write, byte => command.byte, data => 16#30#, dataHi => 0, sector => -1); bus_cycle(bus_cmd => bus_standby, byte => command.byte); WHEN w_data => D_hi := command.d_hi MOD 16#100#; D_lo := command.d_lo ; Addr := command.addr; Sect := command.sect; bus_cycle(bus_cmd => bus_write, byte => command.byte, data => D_lo, dataHi => D_hi, sector => Sect, address => Addr); bus_cycle(bus_cmd => bus_standby, byte => command.byte); IF NOT command.byte THEN Addr := Addr*2; END IF; --write value(s) in default mem IF status = erase_active AND Sec_Prot(Sect)/='1'THEN --sector should be erased mem(Sect) := (OTHERS=>16#FF#); ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN --sector erase terminated = data integrity violated mem(Sect) := (OTHERS=>-1); ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN mem(Sect)(Addr) := -1; IF NOT command.byte THEN mem(Sect)(Addr+1) := -1; END IF; -- Write to Secure Silicon Sector Region ELSIF status = rd_SecSi AND FactoryProt/='1' THEN slv_1 := to_slv(d_lo,8); IF SecSi(Addr)>-1 THEN slv_2 := to_slv(SecSi(Addr),8); ELSE slv_2 := (OTHERS=>'X'); END IF; FOR i IN 0 to 7 LOOP IF slv_2(i)='0' THEN slv_1(i):='0'; END IF; END LOOP; SecSi(Addr) := to_nat(slv_1); IF NOT command.byte THEN slv_1 := to_slv(d_hi,8); IF SecSi(Addr+1)>-1 THEN slv_2 := to_slv(SecSi(Addr+1),8); ELSE slv_2 := (OTHERS=>'X'); END IF; FOR i IN 0 to 7 LOOP IF slv_2(i)='0' THEN slv_1(i):='0'; END IF; END LOOP; SecSi(Addr+1) := to_nat(slv_1); END IF; ELSIF status=buff_wr_busy THEN --Write to Buffer command cycle null; ELSIF status=erase_na THEN --sector erase command sequence violation null; -- Write to Flash Memory Array ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN slv_1 := to_slv(d_lo,8); IF mem(Sect)(Addr)>-1 THEN slv_2 := to_slv(mem(Sect)(Addr),8); ELSE slv_2 := (OTHERS=>'X'); END IF; FOR i IN 0 to 7 LOOP IF slv_2(i)='0' THEN slv_1(i):='0'; END IF; END LOOP; mem(Sect)(Addr) := to_nat(slv_1); IF NOT command.byte THEN slv_1 := to_slv(d_hi,8); IF mem(Sect)(Addr+1)>-1 THEN slv_2 := to_slv(mem(Sect)(Addr+1),8); ELSE slv_2 := (OTHERS=>'X'); END IF; FOR i IN 0 to 7 LOOP IF slv_2(i)='0' THEN slv_1(i):='0'; END IF; END LOOP; mem(Sect)(Addr+1) := to_nat(slv_1); END IF; END IF; WHEN wt => WAIT FOR command.wtime; WHEN wt_rdy => IF T_RY/='1' THEN WAIT UNTIL rising_edge(T_RY) FOR command.wtime; END IF; WHEN wt_bsy => IF T_RY='1' THEN WAIT UNTIL falling_edge(T_RY) FOR command.wtime; END IF; WHEN OTHERS => null; END CASE; END PROCEDURE; VARIABLE cmd_cnt : NATURAL; VARIABLE command : cmd_rec; -- BEGIN Pick_TC (Model => "AM29LV640MH90R" ); Tseries <= ts_cnt ; Tcase <= tc_cnt ; Generate_TC (Model => "AM29LV640MH90R" , Series => ts_cnt, TestCase => tc_cnt, command_seq => cmd_seq); cmd_cnt := 1; WHILE cmd_seq(cmd_cnt).cmd/=done LOOP command:= cmd_seq(cmd_cnt); IF command.sect = -1 THEN command.sect := ProtSecNum; END IF; status <= command.status; sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check cmd_dc(command); cmd_cnt :=cmd_cnt +1; END LOOP; END PROCESS tb; --process to monitor WP# PROCESS(T_WPNeg) VARIABLE reg : std_logic; BEGIN IF falling_edge(T_WPNeg) THEN reg := Sec_Prot(ProtSecNum); Sec_Prot(ProtSecNum) := '1'; ELSIF rising_edge(T_WPNeg) THEN Sec_Prot(ProtSecNum) := reg; END IF; END PROCESS; -------------------------------------------------------------------------------- -- Checker process, -- Bus transition extractor: when bus cycle is read samples addr and data -- Transition checker : verifies correct read data using default memory -------------------------------------------------------------------------------- checker: PROCESS VARIABLE RAddr : NATURAL; VARIABLE RSect : NATURAL; VARIABLE longread : boolean; VARIABLE shortread : boolean; VARIABLE toggle : boolean:=false; VARIABLE toggle_sts : std_logic_vector(7 downto 0); BEGIN -- Transition extractor IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN IF T_BYTENeg='1' THEN RAddr := to_nat(T_A(14 downto 0)&'0'); ELSE RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); END IF; RSect := to_nat(T_A(HiAddrBit downto 15)); shortread:= false; longread := false; --DUT specific timing IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) longread := true; CASE TimingModel IS WHEN "AM29LV640MH90R" | "AM29LV640ML90R" => WAIT FOR 95 ns; -- WHEN "AM29LV640MH101" | -- "AM29LV640ML101" => WAIT FOR 105 ns; -- WHEN "AM29LV640MH101R" | -- "AM29LV640ML101R" => WAIT FOR 105 ns; -- WHEN "AM29LV640MH112" | -- "AM29LV640ML112" => WAIT FOR 115 ns; -- WHEN "AM29LV640MH112R" | -- "AM29LV640ML112R" => WAIT FOR 115 ns; -- WHEN "AM29LV640MH120" | -- "AM29LV640ML120" => WAIT FOR 125 ns; -- WHEN "AM29LV640MH120R" | -- "AM29LV640ML120R" => WAIT FOR 125 ns; WHEN OTHERS => REPORT "Timing model NOT supported : "&TimingModel SEVERITY error; END CASE; ELSIF T_A(1 downto 0)'EVENT OR (T_DQ(15)'EVENT AND T_BYTENeg='0')OR (T_BYTENeg'EVENT) OR T_OENeg'EVENT OR (status/=read AND status/=rd_cfi AND status/=rd_secsi) THEN --AND status/=readX) shortread:=true; CASE TimingModel IS WHEN "AM29LV640MH90R" | "AM29LV640ML90R" => WAIT FOR 30 ns; -- WHEN "AM29LV640MH101" | -- "AM29LV640ML101" => WAIT FOR 40 ns; -- WHEN "AM29LV640MH101R" | -- "AM29LV640ML101R" => WAIT FOR 40 ns; -- WHEN "AM29LV640MH112" | -- "AM29LV640ML112" => WAIT FOR 45 ns; -- WHEN "AM29LV640MH112R" | -- "AM29LV640ML112R" => WAIT FOR 45 ns; -- WHEN "AM29LV640MH120" | -- "AM29LV640ML120" => WAIT FOR 45 ns; -- WHEN "AM29LV640MH120R" | -- "AM29LV640ML120R" => WAIT FOR 45 ns; WHEN OTHERS => REPORT "Timing model NOT supported : "&TimingModel SEVERITY error; END CASE; END IF; --Checker IF longread OR shortread THEN CASE status IS WHEN none => toggle := false; -- read memory array data WHEN read => toggle := false; Check_read ( DQ => T_DQ, D_lo => mem(RSect)(RAddr), D_hi => mem(RSect)(RAddr+1), Byte => T_BYTENeg, check_err=> check_err); -- read secure silicon region WHEN rd_secsi => toggle := false; Check_SecSi ( DQ => T_DQ, D_lo => SecSi(RAddr), D_hi => SecSi(RAddr+1), Byte => T_BYTENeg, check_err=>check_err); --read CFI query codes WHEN rd_cfi => RAddr := to_nat(T_A(14 downto 0)); --x16 addressing toggle := false; Check_CFI ( DQ => T_DQ, D_lo => CFI_array(RAddr) , D_hi => 0 , Byte => T_BYTENeg, check_err=>check_err); -- read Autoselect codes WHEN rd_AS => RAddr := to_nat(T_A(14 downto 0)); --x16 addressing toggle := false; Check_AS ( DQ => T_DQ, addr => RAddr, ProtSecNum=>ProtSecNum, secProt => Sec_Prot(RSect), FactoryProt=>FactoryProt , Byte => T_BYTENeg, AS_E => to_slv(16#0C#,8), AS_F => to_slv(1,8), check_err=>check_err); WHEN rd_HiZ => toggle:=false; Check_Z ( DQ => T_DQ, check_err=>check_err); WHEN readX => toggle:=false; Check_X ( DQ => T_DQ, check_err=>check_err); WHEN erase_na | erase_active => IF toggle THEN Check_Erase ( DQ => T_DQ(7 downto 0), sts => status, toggle => toggle_sts, sts_check=>sts_check, RY => T_RY, check_err=>check_err); toggle_sts := T_DQ(7 downto 0); --update toggle check END IF; WHEN ers_susp_e => IF toggle THEN Check_Ers_Susp ( DQ => T_DQ(7 downto 0), sts => status, toggle => toggle_sts, sts_check=>sts_check, RY => T_RY, check_err=>check_err); toggle_sts := T_DQ(7 downto 0); --update toggle check END IF; -- WHEN ers_susp_prog_na | ers_susp_prog => IF toggle THEN Check_Ers_Susp_Prog ( DQ => T_DQ(7 downto 0), sts => status, toggle => toggle_sts, sts_check=>sts_check, RY => T_RY, check_err=>check_err); toggle_sts := T_DQ(7 downto 0); --update toggle check END IF; -- WHEN prog_na | prog_active => IF toggle THEN Check_Progr ( DQ => T_DQ(7 downto 0), sts => status, toggle => toggle_sts, sts_check=>sts_check, RY => T_RY, check_err=>check_err); toggle_sts := T_DQ(7 downto 0); --update toggle check END IF; WHEN buff_wr_busy | buff_wr_N_busy => IF toggle THEN Check_Buff_Busy ( DQ => T_DQ(7 downto 0), sts => status, toggle => toggle_sts, sts_check=>sts_check, RY => T_RY, check_err=>check_err); toggle_sts := T_DQ(7 downto 0); --update toggle check END IF; WHEN buff_abort => IF toggle THEN Check_Abort ( DQ => T_DQ(7 downto 0), sts => status, toggle => toggle_sts, sts_check=>sts_check, RY => T_RY, check_err=>check_err); toggle_sts := T_DQ(7 downto 0); --update toggle check END IF; WHEN OTHERS => null; END CASE; -- get firs data for toggle check CASE status IS WHEN prog_active | prog_na | erase_active | erase_na | ers_susp_e | ers_susp_prog | ers_susp_prog_na | buff_wr_busy | buff_wr_N_busy | buff_abort | get_toggle => IF (NOT toggle) OR (status=get_toggle) THEN toggle:=true; toggle_sts := T_DQ(7 downto 0); END IF; WHEN OTHERS => null; END CASE; END IF; END IF; WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; END PROCESS checker; default: PROCESS -- text file input variables FILE mem_f : text is mem_file; FILE prot_f : text is prot_file; FILE secsi_f : text is secsi_file; VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; VARIABLE buf : line; BEGIN --Preload Control ----------------------------------------------------------------------- -- File Read Section ----------------------------------------------------------------------- IF UserPreload THEN --- Sector protection preload IF (prot_file /= "none" ) THEN ind := 0; FactoryProt := '0'; Sec_Prot := (OTHERS => '0'); WHILE (not ENDFILE (prot_f)) LOOP READLINE (prot_f, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 to 3)); --address ELSE IF ind > SecNum THEN --SecSi Factory protect preload IF buf(1)='1' THEN FactoryProt := '1'; END IF; ELSE -- Standard Sector prload IF buf(1)='1' THEN Sec_Prot(ind):= '1'; END IF; ind := ind + 1; END IF; END IF; END LOOP; END IF; -- Secure Silicon Sector Region preload IF (SecSi_file /= "none" ) THEN SecSi := (OTHERS => MaxData); ind := 0; WHILE (not ENDFILE (SecSi_f)) LOOP READLINE (SecSi_f, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 to 3)); --address ELSE IF ind <= SecSiSize THEN SecSi(ind) := h(buf(1 TO 2)); ind := ind + 1; END IF; END IF; END LOOP; END IF; --- Memory Preload IF (mem_file /= "none" ) THEN ind := 0; Mem := (OTHERS => (OTHERS => MaxData)); -- load sector 0 WHILE (not ENDFILE (mem_f)) LOOP READLINE (mem_f, buf); IF buf(1) = '/' THEN NEXT; ELSIF buf(1) = '@' THEN ind := h(buf(2 to 5)); --address ELSE IF ind <= SecSize THEN Mem(0)(ind) := h(buf(1 to 2)); ind := ind + 1; END IF; END IF; END LOOP; -- load other sectors FOR i IN 1 TO SecNum LOOP Mem(i) := Mem(0); END LOOP; END IF; END IF; ----------------------------------------------------------------------- --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC ----------------------------------------------------------------------- --CFI query identification string -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr --CFI query identification string CFI_array(16#10#) := 16#51#; CFI_array(16#11#) := 16#52#; CFI_array(16#12#) := 16#59#; CFI_array(16#13#) := 16#02#; CFI_array(16#14#) := 16#00#; CFI_array(16#15#) := 16#40#; CFI_array(16#16#) := 16#00#; CFI_array(16#17#) := 16#00#; CFI_array(16#18#) := 16#00#; CFI_array(16#19#) := 16#00#; CFI_array(16#1A#) := 16#00#; --system interface string CFI_array(16#1B#) := 16#27#; CFI_array(16#1C#) := 16#36#; CFI_array(16#1D#) := 16#00#; CFI_array(16#1E#) := 16#00#; CFI_array(16#1F#) := 16#07#; CFI_array(16#20#) := 16#07#; CFI_array(16#21#) := 16#0A#; CFI_array(16#22#) := 16#00#; CFI_array(16#23#) := 16#01#; CFI_array(16#24#) := 16#05#; CFI_array(16#25#) := 16#04#; CFI_array(16#26#) := 16#00#; --device geometry definition CFI_array(16#27#) := 16#17#; CFI_array(16#28#) := 16#02#; CFI_array(16#29#) := 16#00#; CFI_array(16#2A#) := 16#05#; CFI_array(16#2B#) := 16#00#; CFI_array(16#2C#) := 16#01#; CFI_array(16#2D#) := 16#7F#; CFI_array(16#2E#) := 16#00#; CFI_array(16#2F#) := 16#00#; CFI_array(16#30#) := 16#01#; CFI_array(16#31#) := 16#00#; CFI_array(16#32#) := 16#00#; CFI_array(16#33#) := 16#00#; CFI_array(16#34#) := 16#00#; CFI_array(16#35#) := 16#00#; CFI_array(16#36#) := 16#00#; CFI_array(16#37#) := 16#00#; CFI_array(16#38#) := 16#00#; CFI_array(16#39#) := 16#00#; CFI_array(16#3A#) := 16#00#; CFI_array(16#3B#) := 16#00#; CFI_array(16#3C#) := 16#00#; --primary vendor-specific extended query CFI_array(16#40#) := 16#50#; CFI_array(16#41#) := 16#52#; CFI_array(16#42#) := 16#49#; CFI_array(16#43#) := 16#31#; CFI_array(16#44#) := 16#33#; CFI_array(16#45#) := 16#08#; CFI_array(16#46#) := 16#02#; CFI_array(16#47#) := 16#01#; CFI_array(16#48#) := 16#01#; CFI_array(16#49#) := 16#04#; CFI_array(16#4A#) := 16#00#; CFI_array(16#4B#) := 16#00#; CFI_array(16#4C#) := 16#01#; CFI_array(16#4D#) := 16#B5#; CFI_array(16#4E#) := 16#C5#; IF TimingModel(11) = 'L' THEN CFI_array(16#4F#) := 16#04#; ELSE CFI_array(16#4F#) := 16#05#; --uniform sectors top protect END IF; CFI_array(16#50#) := 16#01#; WAIT; END PROCESS default; END vhdl_behavioral;