------------------------------------------------------------------------------- -- File name : s19mn512p01.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2007 Free Model Foundry; http://www.FreeModelFoundry.com -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2 as -- published by the Free Software Foundation. -- -- MODIFICATION HISTORY: -- -- version: | author: | mod date: | changes made: -- V1.0 D.Popovic 07 Mar 09 Initial Version -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: FLASH -- Technology: FLASH MEMORY -- Part: S19MN512P01 -- -- Description: MirrorBit Quad Flash Memory 512 Megabit, bus width x16 -- ------------------------------------------------------------------------------- -- Known Bugs: -- ------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.VITAL_timing.ALL; USE IEEE.VITAL_primitives.ALL; USE STD.textio.ALL; LIBRARY FMF; USE FMF.gen_utils.ALL; USE FMF.conversions.ALL; ------------------------------------------------------------------------------- -- ENTITY DECLARATION ------------------------------------------------------------------------------- ENTITY s19mn512p01 IS GENERIC ( tipd_IO15 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO14 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO13 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO12 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO11 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO10 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO9 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO8 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO7 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO6 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO5 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO4 : VitalDelayType01 := VitalZeroDelay01; -- data tipd_IO3 : VitalDelayType01 := VitalZeroDelay01; -- inputs tipd_IO2 : VitalDelayType01 := VitalZeroDelay01; -- /outputs tipd_IO1 : VitalDelayType01 := VitalZeroDelay01; -- tipd_IO0 : VitalDelayType01 := VitalZeroDelay01; -- tipd_CLE : VitalDelayType01 := VitalZeroDelay01; -- tipd_ALE : VitalDelayType01 := VitalZeroDelay01; -- tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; -- control tipd_RENeg : VitalDelayType01 := VitalZeroDelay01; -- inputs tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; -- tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; -- tipd_PRE : VitalDelayType01 := VitalZeroDelay01; -- -- tpd delays tpd_RENeg_IO0 : VitalDelayType01Z := UnitDelay01Z;-- tREA,tRHZ tpd_CENeg_IO0 : VitalDelayType01Z := UnitDelay01Z;-- tCEA,tCHZ tpd_WENeg_RY : VitalDelayType01 := UnitDelay01 ;-- tWB -- tsetup values tsetup_CLE_WENeg : VitalDelayType := UnitDelay;-- tCLS \ tsetup_CENeg_WENeg : VitalDelayType := UnitDelay;-- tCS \ tsetup_ALE_WENeg : VitalDelayType := UnitDelay;-- tALS \ tsetup_IO0_WENeg : VitalDelayType := UnitDelay;-- tDS / tsetup_WPNeg_WENeg : VitalDelayType := UnitDelay;-- tWW \ tsetup_CLE_RENeg : VitalDelayType := UnitDelay;-- tCLR \ tsetup_ALE_RENeg : VitalDelayType := UnitDelay;-- tAR \ tsetup_CENeg_RENeg : VitalDelayType := UnitDelay;-- tCR \ tsetup_RENeg_WENeg : VitalDelayType := UnitDelay;-- tRHW \ tsetup_WENeg_CENeg : VitalDelayType := UnitDelay;-- tWHC \ tsetup_WENeg_RENeg : VitalDelayType := UnitDelay;-- tWHR \ -- thold values thold_CLE_WENeg : VitalDelayType := UnitDelay;-- tCLH / thold_CENeg_WENeg : VitalDelayType := UnitDelay;-- tCH / thold_ALE_WENeg : VitalDelayType := UnitDelay;-- tALH / thold_IO0_WENeg : VitalDelayType := UnitDelay;-- tDH / -- tpw values: pulse width tpw_WENeg_negedge : VitalDelayType := UnitDelay;-- tWP tpw_WENeg_posedge : VitalDelayType := UnitDelay;-- tWH tpw_RENeg_negedge : VitalDelayType := UnitDelay;-- tRP tpw_RENeg_posedge : VitalDelayType := UnitDelay;-- tREH --tperiod values tperiod_WENeg : VitalDelayType := UnitDelay;-- tWC tperiod_RENeg : VitalDelayType := UnitDelay;-- tRC --tdevice values: values for internal delay -- data transfer time tdevice_TR : VitalDelayType := 85 us; -- Page programing time tdevice_PROG : VitalDelayType := 6 ms; -- Block erase time tdevice_BERASE : VitalDelayType := 70 ms; -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXOn; -- memory file to be loaded mem_file_name : STRING := "none"; --"s19mn512p01.mem"; invblocks_file_name : STRING := "none"; --"s19mn512p01_inv.mem" UserPreload : BOOLEAN := FALSE; Long_Timming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( IO15 : INOUT std_ulogic := 'U'; -- IO14 : INOUT std_ulogic := 'U'; -- IO13 : INOUT std_ulogic := 'U'; -- IO12 : INOUT std_ulogic := 'U'; -- IO11 : INOUT std_ulogic := 'U'; -- IO10 : INOUT std_ulogic := 'U'; -- IO9 : INOUT std_ulogic := 'U'; -- IO8 : INOUT std_ulogic := 'U'; -- IO7 : INOUT std_ulogic := 'U'; -- IO6 : INOUT std_ulogic := 'U'; -- IO5 : INOUT std_ulogic := 'U'; -- IO4 : INOUT std_ulogic := 'U'; -- data IO3 : INOUT std_ulogic := 'U'; -- inputs/outputs IO2 : INOUT std_ulogic := 'U'; -- IO1 : INOUT std_ulogic := 'U'; -- IO0 : INOUT std_ulogic := 'U'; -- CLE : IN std_ulogic := 'U'; -- ALE : IN std_ulogic := 'U'; -- CENeg : IN std_ulogic := 'U'; -- control RENeg : IN std_ulogic := 'U'; -- inputs WENeg : IN std_ulogic := 'U'; -- WPNeg : IN std_ulogic := 'U'; -- PRE : IN std_ulogic := 'U'; -- RY : OUT std_ulogic := 'U' -- ); ATTRIBUTE VITAL_LEVEL0 of s19mn512p01 : ENTITY IS TRUE; END ENTITY s19mn512p01; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral_dynamic_memory_allocation OF s19mn512p01 IS ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral_dynamic_memory_allocation : ARCHITECTURE IS true; CONSTANT PartId : STRING := "s19mn512p01"; CONSTANT MaxData : NATURAL := 16#FFFF#; CONSTANT BlockNum : NATURAL := 511; -- number of blocks CONSTANT BlockSize : NATURAL := 63; -- size of block in pages CONSTANT PageNum : NATURAL := 16#7FFF#; -- BlockSize * BlockNum CONSTANT PageSize : NATURAL := 1055; -- with spare CONSTANT SegmentNum : NATURAL := 3;-- 4 segment pairs within page CONSTANT SegmentSize : NATURAL := 16#200#; CONSTANT SperSegSize : NATURAL := 16#10#; CONSTANT SpareSize : NATURAL := 63; CONSTANT InvalidData : INTEGER := 2; CONSTANT InvBlocksNum : NATURAL := 10; -- Interconnect path delay signals SIGNAL IO15_ipd : std_ulogic := 'U'; SIGNAL IO14_ipd : std_ulogic := 'U'; SIGNAL IO13_ipd : std_ulogic := 'U'; SIGNAL IO12_ipd : std_ulogic := 'U'; SIGNAL IO11_ipd : std_ulogic := 'U'; SIGNAL IO10_ipd : std_ulogic := 'U'; SIGNAL IO9_ipd : std_ulogic := 'U'; SIGNAL IO8_ipd : std_ulogic := 'U'; SIGNAL IO7_ipd : std_ulogic := 'U'; SIGNAL IO6_ipd : std_ulogic := 'U'; SIGNAL IO5_ipd : std_ulogic := 'U'; SIGNAL IO4_ipd : std_ulogic := 'U'; SIGNAL IO3_ipd : std_ulogic := 'U'; SIGNAL IO2_ipd : std_ulogic := 'U'; SIGNAL IO1_ipd : std_ulogic := 'U'; SIGNAL IO0_ipd : std_ulogic := 'U'; SIGNAL CLE_ipd : std_ulogic := 'U'; SIGNAL ALE_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL RENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; SIGNAL PRE_ipd : std_ulogic := 'U'; -- internal delays SIGNAL TR_in : std_ulogic := '0'; SIGNAL TR_out : std_ulogic := '0'; SIGNAL TR_tmp_in : std_ulogic := '0'; SIGNAL TR_tmp_out : std_ulogic := '0'; SIGNAL PROG_in : std_ulogic := '0'; SIGNAL PROG_out : std_ulogic := '0'; SIGNAL PROG_tmp_in : std_ulogic := '0'; SIGNAL PROG_tmp_out : std_ulogic := '0'; SIGNAL BERS_in : std_ulogic := '0'; SIGNAL BERS_out : std_ulogic := '0'; SIGNAL BERS_tmp_in : std_ulogic := '0'; SIGNAL BERS_tmp_out : std_ulogic := '0'; BEGIN -- ARCHITECTURE vhdl_behavioral --------------------------------------------------------------------------- -- Internal delays --------------------------------------------------------------------------- -- Vital primitives which incorporate internal delays PROG : VitalBUF(PROG_tmp_out, PROG_tmp_in, tpd_a_q => (tdevice_PROG + tpd_WENeg_RY(tr10), UnitDelay)); BERASE : VitalBUF(BERS_tmp_out, BERS_tmp_in, tpd_a_q => (tdevice_BERASE + tpd_WENeg_RY(tr10), UnitDelay)); TR : VitalBUF(TR_tmp_out, TR_tmp_in, tpd_a_q => (tdevice_TR, UnitDelay)); --------------------------------------------------------------------------- -- WIRE DELAYS --------------------------------------------------------------------------- WireDelay : BLOCK IS BEGIN -- BLOCK WireDelay w_1 : VitalWireDelay( IO0_ipd, IO0, tipd_IO0 ); w_2 : VitalWireDelay( IO1_ipd, IO1, tipd_IO1 ); w_3 : VitalWireDelay( IO2_ipd, IO2, tipd_IO2 ); w_4 : VitalWireDelay( IO3_ipd, IO3, tipd_IO3 ); w_5 : VitalWireDelay( IO4_ipd, IO4, tipd_IO4 ); w_6 : VitalWireDelay( IO5_ipd, IO5, tipd_IO5 ); w_7 : VitalWireDelay( IO6_ipd, IO6, tipd_IO6 ); w_8 : VitalWireDelay( IO7_ipd, IO7, tipd_IO7 ); w_9 : VitalWireDelay( IO8_ipd, IO8, tipd_IO8 ); w_10 : VitalWireDelay( IO9_ipd, IO9, tipd_IO9 ); w_11 : VitalWireDelay( IO10_ipd, IO10, tipd_IO10 ); w_12 : VitalWireDelay( IO11_ipd, IO11, tipd_IO11 ); w_13 : VitalWireDelay( IO12_ipd, IO12, tipd_IO12 ); w_14 : VitalWireDelay( IO13_ipd, IO13, tipd_IO13 ); w_15 : VitalWireDelay( IO14_ipd, IO14, tipd_IO14 ); w_16 : VitalWireDelay( IO15_ipd, IO15, tipd_IO15 ); w_17 : VitalWireDelay( CLE_ipd, CLE, tipd_CLE ); w_18 : VitalWireDelay( ALE_ipd, ALE, tipd_ALE ); w_19 : VitalWireDelay( CENeg_ipd, CENeg, tipd_CENeg ); w_20 : VitalWireDelay( RENeg_ipd, RENeg, tipd_RENeg ); w_21 : VitalWireDelay( WENeg_ipd, WENeg, tipd_WENeg ); w_22 : VitalWireDelay( WPNeg_ipd, WPNeg, tipd_WPNeg ); w_23 : VitalWireDelay( PRE_ipd, PRE, tipd_PRE); END BLOCK WireDelay; --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior : BLOCK PORT ( A : IN std_logic_vector(7 DOWNTO 0) := (OTHERS => 'U'); DIn : IN std_logic_vector(15 DOWNTO 0) := (OTHERS => 'U'); DOut : OUT std_logic_vector(15 DOWNTO 0) := (OTHERS => 'Z'); CLE : IN std_ulogic := 'U'; ALE : IN std_ulogic := 'U'; CENeg : IN std_ulogic := 'U'; RENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U'; R : OUT std_ulogic := 'U'; PRE : IN std_ulogic := 'U' ); PORT MAP ( A(7) => IO7_ipd, A(6) => IO6_ipd, A(5) => IO5_ipd, A(4) => IO4_ipd, A(3) => IO3_ipd, A(2) => IO2_ipd, A(1) => IO1_ipd, A(0) => IO0_ipd, DIn(15) => IO15_ipd, DIn(14) => IO14_ipd, DIn(13) => IO13_ipd, DIn(12) => IO12_ipd, DIn(11) => IO11_ipd, DIn(10) => IO10_ipd, DIn(9) => IO9_ipd, DIn(8) => IO8_ipd, DIn(7) => IO7_ipd, DIn(6) => IO6_ipd, DIn(5) => IO5_ipd, DIn(4) => IO4_ipd, DIn(3) => IO3_ipd, DIn(2) => IO2_ipd, DIn(1) => IO1_ipd, DIn(0) => IO0_ipd, DOut(15) => IO15, DOut(14) => IO14, DOut(13) => IO13, DOut(12) => IO12, DOut(11) => IO11, DOut(10) => IO10, DOut(9) => IO9, DOut(8) => IO8, DOut(7) => IO7, DOut(6) => IO6, DOut(5) => IO5, DOut(4) => IO4, DOut(3) => IO3, DOut(2) => IO2, DOut(1) => IO1, DOut(0) => IO0, CLE => CLE_ipd, ALE => ALE_ipd, CENeg => CENeg_ipd, RENeg => RENeg_ipd, WENeg => WENeg_ipd, WPNeg => WPNeg_ipd, R => RY, PRE => PRE_ipd ); -- State Machine : State_Type TYPE state_type IS ( IDLE, UNKNOWN, -- wrong command sequneces PREL_RD, RESET, A0_RD, A1_RD, A2_RD, RD_WCMD, -- waiting for the confirm read command BUFF_TR, RD, CAC_PREL, -- Coloumn address change A0_CAC, A1_CAC, -- Wait for confirm EO command ID_PREL, ID, PREL_PRG, PGD_PREL, A0_PRG, A1_PRG, A2_PRG, DATA_PRG, PGMS_CAC, A0_PRG_CAC, PGMS, PREL_ERS, A1_ERS, A2_ERS, BERS_EXEC, A0_PGD, A1_PGD, A2_PGD, CONF_PGD ); -- Page Array TYPE PageArr IS ARRAY (0 TO PageSize) OF Integer RANGE -1 TO MaxData; TYPE IDArr IS ARRAY (0 TO 3) OF integer RANGE -1 TO MaxData; -- Program protection TYPE SegAddrBoundary IS ARRAY (0 TO SegmentNum) OF NATURAL; TYPE SegArr IS ARRAY (0 TO SegmentNum) OF std_logic; TYPE PageSegArr IS ARRAY (0 TO BlockSize) OF SegArr; TYPE BlockPageSegArr IS ARRAY (0 TO BlockNum) OF PageSegArr; -- ------------------------------------------------------------------------- -- Memory data initial value. -- Default value may be overridden by conigure_memory procedure -- ------------------------------------------------------------------------- SHARED VARIABLE max_data : NATURAL := 16#FFFF#; SHARED VARIABLE corrupt_flag : std_logic_vector(BlockNum downto 0) :=(OTHERS=>'0'); -- ------------------------------------------------------------------------- -- Data types required to implement link list structure -- ------------------------------------------------------------------------- TYPE mem_data_t; TYPE mem_data_pointer_t IS ACCESS mem_data_t; TYPE mem_data_t IS RECORD key_address : INTEGER; val_data : INTEGER; successor : mem_data_pointer_t; END RECORD; -- ------------------------------------------------------------------------- -- Array of linked lists. -- Support memory region partitioning for faster access. -- ------------------------------------------------------------------------- TYPE mem_data_pointer_array_t IS ARRAY(NATURAL RANGE <>) OF mem_data_pointer_t; -- states SIGNAL current_state : State_Type; SIGNAL next_state : State_Type; -- control signals SIGNAL STAT_ACT : std_logic := '0'; SIGNAL ERS_ACT : std_logic := '0'; SIGNAL PRG_ACT : std_logic := '0'; SIGNAL RSTSTART : std_logic := '0'; SIGNAL RSTDONE : std_logic := '0'; -- Control signals for read operation SIGNAL PGR_ACT : std_logic := '0'; -- Page read in progress SIGNAL PGD_ACT : std_logic := '0'; -- Page Duplicate -- powerup SIGNAL PoweredUp : std_logic := '0'; SIGNAL reseted : std_logic := '0'; SIGNAL write : std_logic := '0'; SIGNAL read : std_logic := '0'; SIGNAL DOut_zd : std_logic_vector(15 DOWNTO 0) := (OTHERS => 'Z'); SIGNAL R_zd : std_logic := '0'; SIGNAL R_Pass : std_logic := '0'; -- 8 BIT ADDRESS SIGNAL AddrCom : integer; -- Address within page SIGNAL Address : integer RANGE 0 TO PageSize; -- Page number SIGNAL PageAddr : integer RANGE -1 TO PageNum := -1; -- Block number SIGNAL BlockAddr : integer RANGE -1 TO BlockNum := -1; -- Data SIGNAL Data : integer RANGE -1 TO MaxData; -- ID control signals SIGNAL IDAddr : integer RANGE 0 TO 7; -- Write Page control signals SIGNAL WrBuffData : PageArr; SIGNAL WrAddr : integer RANGE -1 TO PageSize+1; SIGNAL WrPage : integer RANGE 0 TO PageNum; -- For delayed flags SIGNAL SegForProg : SegArr := (OTHERS => '0'); SHARED VARIABLE Page_pom : integer RANGE -1 TO PageNum; SHARED VARIABLE addr_pom : integer RANGE -1 TO PageSize+1; SHARED VARIABLE cnt_addr : integer := 0; SHARED VARIABLE pom_seg : INTEGER RANGE -1 TO SegmentNum; SHARED VARIABLE segment : INTEGER RANGE -1 TO SegmentNum; SHARED VARIABLE ProgramedFlag : BlockPageSegArr; SHARED VARIABLE Blck : INTEGER RANGE 0 to BlockNum; -- Segments starting addresses of main memory SHARED VARIABLE ssam : SegAddrBoundary :=(16#000# ,16#100# ,16#200# ,16#300#); -- Segments starting addresses of spare memory SHARED VARIABLE ssas : SegAddrBoundary :=(16#400# ,16#408# ,16#410# ,16#418#); -- Segments ending addresses of main memory SHARED VARIABLE seam : SegAddrBoundary := (16#0FF# ,16#1FF# ,16#2FF# ,16#3FF#); -- Segments ending addresses of spare memory SHARED VARIABLE seas : SegAddrBoundary := (16#407# ,16#40F# ,16#417# ,16#41F#); -- ID Array SHARED VARIABLE IDArray : IDArr; -- Page duplicate buffer SHARED VARIABLE PDBuffer : PageArr := (OTHERS => 0); -- Status SHARED VARIABLE Status : std_logic_vector(7 DOWNTO 0) := "01000000"; SHARED VARIABLE BadBlockTable : std_logic_vector(BlockNum downto 0); -- timing check violation SIGNAL Viol : X01 := '0'; -- ------------------------------------------------------------------------- -- Override mechanism provided for default parameter values -- ------------------------------------------------------------------------- PROCEDURE configure_memory( max_data_c : IN INTEGER) IS BEGIN max_data := max_data_c; END PROCEDURE configure_memory; -- ------------------------------------------------------------------------- -- Create linked listed -- ------------------------------------------------------------------------- PROCEDURE create_list( key_address : IN INTEGER; val_data : IN INTEGER; root : INOUT mem_data_pointer_t) IS BEGIN root := NEW mem_data_t; root.successor := NULL; root.key_address := key_address; root.val_data := val_data; END PROCEDURE create_list; -- ------------------------------------------------------------------------- -- Iterate through linked listed comapring key values -- Stop when key value greater or equal -- ------------------------------------------------------------------------- PROCEDURE position_list( key_address : IN INTEGER; root : INOUT mem_data_pointer_t; found : INOUT mem_data_pointer_t; prev : INOUT mem_data_pointer_t) IS BEGIN found := root; prev := NULL; WHILE ((found /= NULL) AND (found.key_address < key_address)) LOOP prev := found; found := found.successor; END LOOP; END PROCEDURE position_list; -- ------------------------------------------------------------------------- -- Add new element to a linked list -- ------------------------------------------------------------------------- PROCEDURE insert_list( key_address : IN INTEGER; val_data : IN INTEGER; root : INOUT mem_data_pointer_t) IS VARIABLE new_element : mem_data_pointer_t; VARIABLE found : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; BEGIN position_list(key_address, root, found, prev); -- Insert at list tail IF (found = NULL) THEN prev.successor := NEW mem_data_t; prev.successor.key_address := key_address; prev.successor.val_data := val_data; prev.successor.successor := NULL; ELSE -- Element exists, update memory data value IF (found.key_address = key_address) THEN found.val_data := val_data; ELSE -- No element found, allocate and link new_element := NEW mem_data_t; new_element.key_address := key_address; new_element.val_data := val_data; new_element.successor := found; -- Possible root position IF (prev /= NULL) THEN prev.successor := new_element; ELSE root := new_element; END IF; END IF; END IF; END PROCEDURE insert_list; -- ------------------------------------------------------------------------- -- Remove element from a linked list -- ------------------------------------------------------------------------- PROCEDURE remove_list( key_address : IN INTEGER; root : INOUT mem_data_pointer_t) IS VARIABLE found : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; BEGIN position_list(key_address, root, found, prev); IF (found /= NULL) THEN -- Key value match IF (found.key_address = key_address) THEN -- Handle root position removal IF (prev /= NULL) THEN prev.successor := found.successor; ELSE root := found.successor; END IF; DEALLOCATE(found); END IF; END IF; END PROCEDURE remove_list; -- ------------------------------------------------------------------------- -- Remove range of elements from a linked list -- Higher performance than one-by-one removal -- ------------------------------------------------------------------------- PROCEDURE remove_list_range( address_low : IN INTEGER; address_high : IN INTEGER; root : INOUT mem_data_pointer_t) IS VARIABLE iter : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; VARIABLE link_element : mem_data_pointer_t; BEGIN iter := root; prev := NULL; -- Find first linked list element belonging to -- a specified address range [address_low, address_high] WHILE ((iter /= NULL) AND NOT ( (iter.key_address >= address_low) AND (iter.key_address <= address_high))) LOOP prev := iter; iter := iter.successor; END LOOP; -- Continue until address_high reached -- Deallocate linked list elements pointed by iterator IF (iter /= NULL) THEN WHILE ((iter /= NULL) AND (iter.key_address >= address_low) AND (iter.key_address <= address_high)) LOOP link_element := iter.successor; DEALLOCATE(iter); iter := link_element; END LOOP; -- Handle possible root value change IF prev /= NULL THEN prev.successor := link_element; ELSE root := link_element; END IF; END IF; END PROCEDURE remove_list_range; -- ------------------------------------------------------------------------- -- Address range to be erased -- ------------------------------------------------------------------------- PROCEDURE erase_mem( address_low : IN INTEGER; address_high : IN INTEGER; linked_list : INOUT mem_data_pointer_t) IS BEGIN remove_list_range( address_low, address_high, linked_list ); END PROCEDURE erase_mem; -- ------------------------------------------------------------------------- -- Memory READ operation performed above dynamically allocated space -- ------------------------------------------------------------------------- PROCEDURE read_mem( linked_list : INOUT mem_data_pointer_t; data : INOUT INTEGER; address : IN INTEGER) IS VARIABLE found : mem_data_pointer_t; VARIABLE prev : mem_data_pointer_t; VARIABLE mem_data : INTEGER; BEGIN IF (linked_list = NULL) THEN -- Not allocated, not written, initial value mem_data := max_data ; ELSE position_list(address, linked_list, found, prev); IF (found /= NULL) THEN IF found.key_address = address THEN -- Allocated, val_data stored mem_data := found.val_data; ELSE -- Not allocated, not written, initial value mem_data := max_data ; END IF; ELSE -- Not allocated, not written, initial value mem_data := max_data ; END IF; END IF; data := mem_data; END PROCEDURE read_mem; -- ------------------------------------------------------------------------- -- Memory WRITE operation performed above dynamically allocated space -- ------------------------------------------------------------------------- PROCEDURE write_mem( linked_list : INOUT mem_data_pointer_t; address : IN INTEGER; data : IN INTEGER) IS BEGIN IF (data /= max_data ) THEN -- Handle possible root value update IF (linked_list /= NULL) THEN insert_list(address, data, linked_list); ELSE create_list(address, data, linked_list); END IF; ELSE -- Deallocate if initial value written -- No linked list, NOP, initial value implicit IF (linked_list /= NULL) THEN remove_list(address, linked_list); END IF; END IF; END PROCEDURE write_mem; ------------------------------------------------------------------------- -- Handle dynamic memory allocation ------------------------------------------------------------------------- -- Partition dynamically allocated space for performance CONSTANT list_num : INTEGER := 512; CONSTANT list_size : INTEGER := 16#10800#; -- Access dynamically allocated space SHARED VARIABLE linked_list : mem_data_pointer_array_t(0 TO list_num); SHARED VARIABLE list_id_v : NATURAL; -- Asure proper initialization PROCEDURE initialize IS VARIABLE I : INTEGER; BEGIN configure_memory(16#FFFF#); FOR I IN 0 TO list_num LOOP linked_list(I) := NULL; END LOOP; END PROCEDURE initialize; -- Memory region parition map, DUT specific FUNCTION list_id( list_address : IN INTEGER) RETURN NATURAL IS BEGIN RETURN (list_address / list_size); END FUNCTION list_id; PROCEDURE getSegment ( paddress : IN integer RANGE 0 TO PageSize; j : OUT integer RANGE -1 TO SegmentNum) IS BEGIN -- PROCEDURE getSegment FOR i IN 0 TO SegmentNum LOOP IF (paddress >= ssam(i) AND paddress <= seam(i)) OR (paddress >= ssas(i) AND paddress <= seas(i)) THEN j := i; END if; END LOOP; END PROCEDURE getSegment; BEGIN --------------------------------------------------------------------------- -- Power Up time 10 us --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 10 us; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS (A,DIn,CLE,ALE,CENeg,RENeg,WENeg,WPNeg) IS -- Timing check variables VARIABLE TViol_IO0_WENeg : X01 := '0'; VARIABLE TD_IO0_WENeg : VitalTimingDataType; VARIABLE TViol_CLE_WENeg_F : X01 := '0'; VARIABLE TD_CLE_WENeg_F : VitalTimingDataType; VARIABLE TViol_ALE_WENeg_F : X01 := '0'; VARIABLE TD_ALE_WENeg_F : VitalTimingDataType; VARIABLE TViol_CENeg_WENeg_F : X01 := '0'; VARIABLE TD_CENeg_WENeg_F : VitalTimingDataType; VARIABLE TViol_WPNeg_WENeg_F : X01 := '0'; VARIABLE TD_WPNeg_WENeg_F : VitalTimingDataType; VARIABLE TViol_WENeg_CENeg_F : X01 := '0'; VARIABLE TD_WENeg_CENeg_F : VitalTimingDataType; VARIABLE TViol_CLE_RENeg : X01 := '0'; VARIABLE TD_CLE_RENeg : VitalTimingDataType; VARIABLE TViol_ALE_RENeg : X01 := '0'; VARIABLE TD_ALE_RENeg : VitalTimingDataType; VARIABLE TViol_WENeg_RENeg : X01 := '0'; VARIABLE TD_WENeg_RENeg : VitalTimingDataType; VARIABLE TViol_CENeg_RENeg_F : X01 := '0'; VARIABLE TD_CENeg_RENeg_F : VitalTimingDataType; VARIABLE TViol_RENeg_WENeg : X01 := '0'; VARIABLE TD_RENeg_WENeg : VitalTimingDataType; VARIABLE TViol_CLE_WENeg_R : X01 := '0'; VARIABLE TD_CLE_WENeg_R : VitalTimingDataType; VARIABLE TViol_ALE_WENeg_R : X01 := '0'; VARIABLE TD_ALE_WENeg_R : VitalTimingDataType; VARIABLE TViol_CENeg_WENeg_R : X01 := '0'; VARIABLE TD_CENeg_WENeg_R : VitalTimingDataType; VARIABLE PViol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE PViol_RENeg : X01 := '0'; VARIABLE PD_RENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; BEGIN -- PROCESS VITALTimingCheck IF ( TimingChecksOn ) THEN -------------------------------------------------------------------- -- Timing Check Section -------------------------------------------------------------------- -- Setup Check between CLE and WENeg VitalSetupHoldCheck ( TestSignal => CLE, TestSignalName => "CLE", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_CLE_WENeg, SetupLow => tsetup_CLE_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLE_WENeg_F, Violation => TViol_CLE_WENeg_F ); -- Setup Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_F, Violation => TViol_CENeg_WENeg_F ); -- Setup Check between ALE and WENeg VitalSetupHoldCheck ( TestSignal => ALE, TestSignalName => "ALE", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_ALE_WENeg, SetupLow => tsetup_ALE_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_ALE_WENeg_F, Violation => TViol_ALE_WENeg_F ); -- Setup/Hold Check between IO and WENeg VitalSetupHoldCheck ( TestSignal => IO0, TestSignalName => "IO", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_IO0_WENeg, SetupLow => tsetup_IO0_WENeg, HoldHigh => thold_IO0_WENeg, HoldLow => thold_IO0_WENeg, CheckEnabled => CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_IO0_WENeg, Violation => TViol_IO0_WENeg ); -- Setup Check between WPNeg and WENeg VitalSetupHoldCheck ( TestSignal => WPNeg, TestSignalName => "WP#", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_WPNeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_WENeg_F, Violation => TViol_WPNeg_WENeg_F ); -- Setup Check between CLE and RENeg VitalSetupHoldCheck ( TestSignal => CLE, TestSignalName => "CLE", RefSignal => RENeg, RefSignalName => "RE#", SetupHigh => tsetup_CLE_RENeg, SetupLow => tsetup_CLE_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLE_RENeg, Violation => TViol_CLE_RENeg ); -- Setup Check between ALE and RENeg VitalSetupHoldCheck ( TestSignal => ALE, TestSignalName => "ALE", RefSignal => RENeg, RefSignalName => "RE#", SetupLow => tsetup_ALE_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_ALE_RENeg, Violation => TViol_ALE_RENeg ); -- Setup Check between CENeg and RENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => RENeg, RefSignalName => "RE#", SetupLow => tsetup_CENeg_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RENeg_F, Violation => TViol_CENeg_RENeg_F ); -- Setup Check between RENeg and WENeg VitalSetupHoldCheck ( TestSignal => RENeg, TestSignalName => "RE#", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_RENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_RENeg_WENeg, Violation => TViol_RENeg_WENeg ); -- Setup Check between WENeg and CENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_F, Violation => TViol_WENeg_CENeg_F ); -- Setup Check between WENeg and RENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => RENeg, RefSignalName => "RE#", SetupHigh => tsetup_WENeg_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_RENeg, Violation => TViol_WENeg_RENeg ); -- Hold Check between CLE and WENeg VitalSetupHoldCheck ( TestSignal => CLE, TestSignalName => "CLE", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_CLE_WENeg, HoldLow => thold_CLE_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CLE_WENeg_R, Violation => TViol_CLE_WENeg_R ); -- Hold Check between ALE and WENeg VitalSetupHoldCheck ( TestSignal => ALE, TestSignalName => "ALE", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_ALE_WENeg, HoldLow => thold_ALE_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_ALE_WENeg_R, Violation => TViol_ALE_WENeg_R ); -- Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_R, Violation => TViol_CENeg_WENeg_R ); -- Period and Pulse Width Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WE#", Period => tperiod_WENeg, PulseWidthLow => tpw_WENeg_negedge, PulseWidthHigh => tpw_WENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => PViol_WENeg ); -- Period and Pulse Width Check for RENeg VitalPeriodPulseCheck ( TestSignal => RENeg, TestSignalName => "RE#", Period => tperiod_RENeg, PulseWidthLow => tpw_RENeg_negedge, PulseWidthHigh => tpw_RENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RENeg, Violation => PViol_RENeg ); Violation := TViol_IO0_WENeg OR TViol_CLE_WENeg_F OR TViol_ALE_WENeg_F OR TViol_CENeg_WENeg_F OR TViol_WPNeg_WENeg_F OR TViol_WENeg_CENeg_F OR TViol_CLE_RENeg OR TViol_ALE_RENeg OR TViol_WENeg_RENeg OR TViol_CENeg_RENeg_F OR TViol_RENeg_WENeg OR TViol_CLE_WENeg_R OR TViol_ALE_WENeg_R OR TViol_CENeg_WENeg_R OR PViol_RENeg OR PViol_WENeg; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; --------------------------------------------------------------------------- -- Proces for reset control and FSM state transition --------------------------------------------------------------------------- StateTransition: PROCESS (next_state, PoweredUp) IS BEGIN -- PROCESS StateTransition IF rising_edge(PoweredUp) THEN reseted <= '1'; ELSIF PoweredUp = '1' THEN current_state <= next_state; ELSE current_state <= IDLE; reseted <= '0'; END IF; END PROCESS StateTransition; --------------------------------------------------------------------------- -- Proces for generating the write and read signals --------------------------------------------------------------------------- wr_rd_gen: PROCESS (WENeg, CENeg, RENeg) IS BEGIN -- PROCESS wr_rd_gen IF WENeg = '0' AND CENeg = '0' AND RENeg = '1' THEN write <= '1'; ELSIF WENeg = '1' AND CENeg = '0' AND RENeg = '1' THEN write <= '0'; ELSE write <= '0'; END IF; IF WENeg = '1' AND CENeg = '0' AND RENeg = '0' THEN read <= '1'; ELSIF WENeg = '1' AND CENeg = '0' AND RENeg = '1' THEN read <= '0'; ELSE read <= '0'; END IF; END PROCESS wr_rd_gen; --------------------------------------------------------------------------- -- Latches 8 bit address on the rising edge of RE# -- Latches data on rising edge of WE# --------------------------------------------------------------------------- BusCycleDecode: PROCESS (A, DIn, WENeg, CENeg, RENeg) IS BEGIN -- PROCESS BusCycleDecode -- latch address IF rising_edge(WENeg) AND ALE = '1' AND CLE = '0' AND CENeg = '0' THEN AddrCom <= to_nat(A(7 DOWNTO 0)); END IF; -- latch data IF rising_edge(WENeg) AND ALE = '0' AND RENeg = '1' THEN Data <= to_nat(DIn(15 DOWNTO 0)); END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Reset Operation --------------------------------------------------------------------------- RstTime: PROCESS (RSTSTART, reseted) IS VARIABLE duration : time; BEGIN -- PROCESS RstTime IF rising_edge(reseted) THEN RSTDONE <= '1'; --reset done ELSIF reseted = '1' THEN IF rising_edge(RSTSTART) AND RSTDONE = '1' THEN IF ERS_ACT = '1' THEN IF (Long_Timming = TRUE) THEN duration := 500 us; ELSE duration := 50 us; END IF; ELSIF PRG_ACT = '1' THEN duration := 10 us; ELSE duration := 5 us; END IF; RSTDONE <= '0', '1' AFTER duration ; END IF; END IF; END PROCESS RstTime; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen: PROCESS (write, read, reseted, current_state, BERS_out, PROG_out, TR_out, RSTDONE ) IS VARIABLE oe : BOOLEAN := FALSE; BEGIN -- PROCESS StateGen oe := rising_edge(read); IF reseted /= '1' THEN next_state <= current_state; ELSIF rising_edge(reseted) THEN IF PRE = '1' THEN next_state <= BUFF_TR; ELSE next_state <= IDLE; END IF; ELSE CASE current_state IS WHEN IDLE => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#00# THEN next_state <= PREL_RD; ELSIF CLE='1' AND ALE='0' AND Data=16#90# THEN next_state <= ID_PREL; ELSIF CLE='1' AND ALE='0' AND Data=16#80# THEN next_state <= PREL_PRG; ELSIF CLE='1' AND ALE='0' AND Data=16#60# THEN next_state <= PREL_ERS; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN next_state <= IDLE; ELSIF CLE='1' THEN next_state <= IDLE; END IF; END IF; WHEN UNKNOWN => IF falling_edge(write) THEN IF CLE = '1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; END IF; END IF; WHEN RESET => IF RSTDONE = '1' THEN next_state <= IDLE; END IF; WHEN PREL_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A0_RD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; ELSIF oe THEN next_state <= IDLE; END IF; WHEN A0_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A1_RD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A2_RD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= RD_WCMD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN RD_WCMD => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#30# THEN next_state <= BUFF_TR; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#35# THEN next_state <= BUFF_TR; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN BUFF_TR => IF falling_edge(write) THEN IF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE = '1' AND STAT_ACT = '1' THEN next_state <= BUFF_TR; END IF; ELSIF TR_out='1' THEN next_state <= RD; -- buffer transfered END IF; WHEN RD => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data=16#00# THEN IF STAT_ACT ='1' AND PGR_ACT='1' THEN next_state <= RD; ELSIF PGR_ACT='1' THEN next_state <= PREL_RD; ELSE next_state <= UNKNOWN; END IF; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#80# AND PGD_ACT = '0' THEN next_state <= PREL_PRG; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#90# AND PGD_ACT = '0' THEN next_state <= ID_PREL; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#70# THEN next_state <= RD; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#60# AND PGD_ACT = '0' THEN next_state <= PREL_ERS; -- To erase ELSIF CLE = '1' AND ALE = '0' AND Data = 16#85# AND PGD_ACT = '1' THEN next_state <= PGD_PREL; -- Read next colomn address ELSIF CLE = '1' AND ALE = '0' AND Data = 16#05# AND PGD_ACT = '0' THEN next_state <= CAC_PREL; ELSIF CLE ='1' AND STAT_ACT = '1' THEN next_state <= RD; ELSE next_state <= RD; END IF; END IF; WHEN CAC_PREL => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A0_CAC; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; ELSIF CLE ='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A0_CAC => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A1_CAC; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; ELSIF CLE ='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_CAC => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#E0# THEN next_state <= RD; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; ELSIF CLE ='1' OR ALE = '1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN ID_PREL => IF falling_edge(write) THEN IF ALE = '1' AND AddrCom = 16#00# THEN next_state <= ID; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE ='1' OR ALE = '1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN ID => IF falling_edge(write) THEN IF CLE='1' AND ALE = '0' AND Data=16#00# THEN next_state <= PREL_RD; -- ELSIF CLE='1' AND ALE = '0' AND Data=16#90# THEN next_state <= ID_PREL; ELSIF CLE='1' AND ALE = '0' AND Data=16#80# THEN next_state <= PREL_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#60# THEN next_state <= PREL_ERS; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' AND ALE = '0' AND Data=16#70# THEN next_state <= IDLE; ELSIF CLE='1' THEN next_state <= IDLE; END IF; END IF; WHEN PREL_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A0_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A0_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A1_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A2_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= DATA_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN DATA_PRG => IF falling_edge(write) THEN IF (ALE='1' AND (cnt_addr < 2 OR cnt_addr >= 4)) OR (CLE='1'AND ALE='0' AND cnt_addr > 4) THEN next_state <= UNKNOWN; ELSIF CLE='1' AND ALE='0' AND Data=16#10# THEN IF PRG_ACT='0' THEN next_state <= PGMS; END IF; ELSIF CLE ='1' AND ALE='0' AND Data = 16#85# THEN next_state <= PGMS_CAC; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; ELSIF ALE='0' AND CLE='0' AND WrAddr < PageSize+1 THEN next_state <= DATA_PRG; -- write next word to buffer END IF; END IF; WHEN PGMS_CAC => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; ELSIF ALE='1' THEN next_state <= A0_PRG_CAC; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN PGMS => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE = '1' AND STAT_ACT = '1' THEN next_state <= PGMS; END IF; ELSIF rising_edge(PROG_out) THEN next_state <= IDLE; -- programming done END IF; WHEN A0_PRG_CAC => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= DATA_PRG; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN PREL_ERS => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A1_ERS; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_ERS => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A2_ERS; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_ERS => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data = 16#D0# THEN next_state <= BERS_EXEC; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' OR ALE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN BERS_EXEC => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE = '1' AND STAT_ACT = '1' THEN next_state <= BERS_EXEC; END IF; ELSIF BERS_out='1' THEN next_state <= IDLE; END IF; WHEN PGD_PREL => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A0_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A0_PGD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A1_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_PGD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A2_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_PGD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= CONF_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN CONF_PGD => IF falling_edge(write) THEN IF (ALE='1' AND cnt_addr >= 4) OR (CLE='1' AND ALE='0' AND cnt_addr > 4) THEN next_state <= UNKNOWN; ELSIF CLE = '1' AND ALE='0' AND Data = 16#10# THEN next_state <= PGMS; ELSIF CLE='1' AND ALE='0' AND Data = 16#85# THEN next_state <= PGMS_CAC; ELSIF CLE = '1' AND ALE='0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- -- FSM Output Generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS (read, write, Data, AddrCom, reseted, current_state, RENeg, CENeg, ALE, CLE, BERS_out, PROG_out, TR_out, RSTDONE, WPNeg ) IS VARIABLE oe : BOOLEAN := false; VARIABLE Page : INTEGER RANGE 0 to PageNum; VARIABLE BlockPage : integer RANGE 0 TO BlockSize; VARIABLE Pom_Address : integer RANGE 0 TO PageSize; VARIABLE CashBuffData : PageArr; -- Page chache register VARIABLE mem_data : INTEGER; PROCEDURE Read_Data ( SIGNAL Addr : INOUT integer RANGE 0 TO PageSize; SIGNAL Page : IN integer RANGE -1 TO PageNum ) IS BEGIN -- PROCEDURE read_data read_mem( linked_list(list_id(Page * (PageSize+1) + Addr)), mem_data, Page * (PageSize+1) + Addr); IF mem_data /= -1 THEN DOut_zd <= to_slv(mem_data,16); ELSE DOut_zd <= ( OTHERS => 'X'); END IF; IF (corrupt_flag(Blck)= '1') THEN DOut_zd <= ( OTHERS => 'X'); END IF; IF Addr /= PageSize THEN Addr <= Addr+1; END IF; END PROCEDURE read_data; PROCEDURE Read_Status IS BEGIN Dout_zd(7 DOWNTO 0) <= Status; Dout_zd(15 DOWNTO 8) <= (OTHERS => '0'); END PROCEDURE Read_Status; BEGIN -- PROCESS Functional ---------------------------------------------------------------------- -- Funcionality section ---------------------------------------------------------------------- oe := rising_edge(read); Status(7) := WPNeg_ipd; IF reseted /= '1' THEN R_zd <= '0'; ELSIF rising_edge(reseted) THEN IF PRE='1' THEN Address <= 0; PageAddr <= 0; Pom_Address := 0; BlockAddr <= 0; PGR_ACT <= '1'; TR_in <= '1'; ELSE PGR_ACT <= '0'; R_zd <= '1'; END IF; ELSE CASE current_state IS WHEN IDLE => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#00# THEN Status(6 DOWNTO 0) := "1000000"; STAT_ACT <= '0'; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND ALE = '0' AND (Data = 16#80# OR Data = 16#90#) THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#60# THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN UNKNOWN => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; ERS_ACT <= '0'; PGD_ACT <= '0'; PGR_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN RESET => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#70# THEN STAT_ACT <= '1'; END IF; END IF; IF RSTDONE = '1' THEN ERS_ACT <= '0'; PGD_ACT <= '0'; PGR_ACT <= '0'; R_zd <= '1'; Status(6 DOWNTO 0) := "1000000"; PGR_ACT <= '0'; ELSE Status(6 DOWNTO 0) := "0000000"; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN PREL_RD => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := AddrCom; cnt_addr := 0; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; IF oe AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; WHEN A0_RD => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := (AddrCom* 16#100#) + Pom_Address; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_RD => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_RD => IF falling_edge(write) THEN IF ALE='1' THEN Page := (AddrCom* 16#100#) + Page; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN RD_WCMD => IF falling_edge(write) THEN IF CLE = '1' AND ALE='0' AND Data = 16#30# THEN PGR_ACT <= '1'; Address <= Pom_Address; PageAddr <= Page; BlockAddr <= Page / (BlockSize + 1); Blck := Page / (BlockSize + 1); TR_in <= '1'; R_zd <= '0'; Status(6 DOWNTO 5) := "00"; ELSIF CLE = '1' AND ALE='0' AND Data = 16#35# THEN PGD_ACT <= '1'; Address <= Pom_Address; PageAddr <= Page; BlockAddr <= Page / (BlockSize + 1); Blck := Page / (BlockSize + 1); TR_in <= '1'; R_zd <= '0'; Status(6 DOWNTO 5) := "00"; PDBuffer := (OTHERS => -1); ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF ALE='1' THEN cnt_addr := cnt_addr + 1; END IF; END IF; WHEN BUFF_TR => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN TR_in <= '0'; STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE = '1' AND ALE='0' AND Data = 16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; ELSIF TR_out='1' THEN R_zd <= '1'; Status(6 downto 5) := "10"; TR_in <= '0'; IF PGD_ACT='1' THEN list_id_v := list_id(PageAddr * (PageSize + 1)); FOR I IN 0 TO PageSize LOOP read_mem( linked_list(list_id_v), mem_data, PageAddr * (PageSize + 1) + I ); PDBuffer(I) := mem_data; END LOOP; END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN RD => IF falling_edge(write) THEN IF CLE = '1' AND ALE='0' AND Data = 16#00# THEN IF STAT_ACT = '1' THEN STAT_ACT <= '0'; Address <= Pom_Address; ELSIF PGD_ACT = '0' THEN PGR_ACT <= '0'; STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; END IF; ELSIF CLE = '1' AND ALE='0' AND Data = 16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND ALE='0' AND Data = 16#90# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; PGR_ACT <= '0'; ELSIF CLE = '1' AND ALE='0' AND Data = 16#80# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; PGR_ACT <= '0'; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#60# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; PGR_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE='1' AND ALE = '0' AND Data=16#85# AND PGD_ACT='1' THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE='1' AND ALE = '0' AND Data=16#05# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF PGD_ACT='0' AND STAT_ACT='0' THEN Read_Data(Address,PageAddr ); ELSIF STAT_ACT='1' THEN Read_Status; END IF; END IF; WHEN CAC_PREL => IF falling_edge(write) THEN IF ALE = '1' THEN Pom_Address:= AddrCom; cnt_addr := 0; ELSIF CLE='1' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_CAC => IF falling_edge(write) THEN IF ALE = '1' THEN Pom_Address := Pom_Address + AddrCom * 16#100#; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_CAC => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data = 16#E0# THEN Address <= Pom_Address; ELSIF CLE='1' AND ALE='0' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF ALE='1' THEN cnt_addr := cnt_addr+1; END IF; END IF; WHEN ID_PREL => IF falling_edge(write) THEN IF ALE='1' AND AddrCom=16#00# THEN IDAddr <= 0; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# then RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; END if; END IF; WHEN ID => IF falling_edge(write) THEN IF CLE ='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN STAT_ACT <= '1'; ELSIF CLE='1' AND ALE='0' AND Data=16#00# THEN STAT_ACT <= '0'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF IDAddr < 4 THEN DOut_zd <= to_slv(IDArray(IDAddr),16); IDAddr <= IDAddr+1; ELSE DOut_zd <= (OTHERS => 'Z'); END IF; END IF; WHEN PREL_PRG => IF falling_edge(write) THEN IF ALE='1' THEN WrAddr <= AddrCom; cnt_addr := 0; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_PRG => IF falling_edge(write) THEN IF ALE='1' THEN WrAddr <= (AddrCom * 16#100#)+WrAddr; CashBuffData := (OTHERS => -1); cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_PRG => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_PRG => IF falling_edge(write) THEN IF ALE='1' THEN Page := Page +(AddrCom * 16#100#); Blck := Page / (BlockSize+1); cnt_addr := cnt_addr + 1; BlockPage := Page MOD (BlockSize + 1); Page_pom := BlockPage; SegForProg <= ProgramedFlag(Blck)(BlockPage); ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN DATA_PRG => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF ALE='0' AND CLE='0' AND WrAddr < PageSize+1 THEN getSegment(WrAddr,segment); IF ProgramedFlag(Blck)(BlockPage)(segment)='0' THEN CashBuffData(WrAddr) := Data; END IF; SegForProg(segment) <= '1'; Page_pom := BlockPage; WrAddr <= WrAddr+1; IF WrAddr = ssam(1)-1 THEN WrAddr <= ssas(0); ELSIF WrAddr = ssas(1)-1 THEN WrAddr <= ssam(1); ELSIF WrAddr = ssam(2)-1 THEN WrAddr <= ssas(1); ELSIF WrAddr = ssas(2)-1 THEN WrAddr <= ssam(2); ELSIF WrAddr = ssam(3)-1 THEN WrAddr <= ssas(2); ELSIF WrAddr = ssas(3)-1 THEN WrAddr <= ssam(3); ELSIF WrAddr = ssas(0)-1 THEN WrAddr <= ssas(3); END IF; ELSIF CLE='1' AND ALE='0' AND Data=16#10# THEN IF PRG_ACT = '0' THEN WrPage <= Page; END IF; R_zd <= '0'; Status(6) := '0'; ELSIF ALE='1' THEN cnt_addr := cnt_addr + 1; END IF; END IF; WHEN PGMS_CAC => IF falling_edge(write) THEN IF ALE='1' THEN cnt_addr := 0; WrAddr <= AddrCom; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_PRG_CAC => IF falling_edge(write) THEN IF ALE='1' THEN WrAddr <= (AddrCom * 16#100#)+WrAddr; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN PGMS => IF WPNeg /= '0' THEN WrBuffData <= CashBuffData; list_id_v := list_id(WrPage * (PageSize + 1)); FOR i IN 0 TO PageSize LOOP getSegment(i,segment); IF ProgramedFlag (WrPage/(BlockSize+1))( WrPage mod(BlockSize+1)) (segment) = '0' AND CashBuffData(i) /= -1 AND BadBlockTable(WrPage/(BlockSize+1)) = '0' THEN write_mem(linked_list(list_id_v), WrPage * (PageSize + 1) + i, -1); END IF; END LOOP; END IF; IF rising_edge(PROG_out) THEN R_zd <= '1'; PGD_ACT <= '0'; END IF; IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN STAT_ACT <= '1'; -- read status ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN PREL_ERS => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := 0; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; END IF; END IF; WHEN A1_ERS => IF falling_edge(write) THEN IF ALE='1' THEN Page := Page + (AddrCom * 16#100#); WrPage <= Page; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data = 16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_ERS => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#D0# THEN Blck := Page / (BlockSize + 1); BlockAddr <= Blck; IF WPNeg /= '0' AND BadBlockTable(Blck) = '0' THEN corrupt_flag(Blck) := '1'; ProgramedFlag(Blck) := (OTHERS =>(OTHERS => '0')); END IF; BERS_in <= '1'; ERS_ACT <= '1'; R_zd <= '0'; Status(6 DOWNTO 5) := "00"; ELSIF ALE = '1' THEN cnt_addr := cnt_addr + 1; END IF; END IF; WHEN BERS_EXEC => IF BERS_out = '1' THEN IF WPNeg /= '0' AND BadBlockTable(Blck) = '0' THEN list_id_v := list_id(Blck * (BlockSize + 1) * (PageSize + 1)); FOR i IN Blck * (BlockSize+1) TO (Blck*(BlockSize+1)) + BlockSize LOOP erase_mem( i * (PageSize + 1), i * (PageSize + 1) + PageSize, linked_list(list_id_v) ); END LOOP; corrupt_flag(Blck) := '0'; END IF; IF BadBlockTable(Blck) = '1' THEN Status(0) := '1'; ELSE Status(0) := '0'; END IF; BERS_in <= '0'; ERS_ACT <= '0'; R_zd <= '1'; Status(6) := '1'; END IF; IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN BERS_in <= '0'; RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN PGD_PREL => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := AddrCom; cnt_addr := 0; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_PGD => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := (AddrCom* 16#100#) + Pom_Address; WrAddr <= Pom_Address; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_PGD => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_PGD => IF falling_edge(write) THEN IF ALE='1' THEN Page := (AddrCom* 16#100#) + Page; Blck := Page / (BlockSize+1); BlockPage := Page MOD (BlockSize + 1); cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN CONF_PGD => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND (Data = 16#10# OR Data = 16#85#) THEN CashBuffData := PDBuffer; SegForProg <= (OTHERS => '1'); WrPage <= Page; IF CLE = '1' AND ALE = '0' AND Data = 16#10# THEN R_zd <= '0'; Status(6) := '0'; END IF; ELSIF ALE = '1' THEN cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; END CASE; END IF; IF RENeg = '1' OR CENeg='1' THEN DOut_zd <= (others => 'Z'); END IF; IF (TR_out='1' OR PROG_out='1' ) AND (read='1' AND STAT_ACT='1') THEN Read_Status; END IF; END PROCESS Functional; --------------------------------------------------------------------------- -- Flag Generation Process --------------------------------------------------------------------------- FlagGeneration: PROCESS (write, Data, current_state, PROG_out, RSTDONE, CLE, PRG_ACT ) IS BEGIN -- PROCESS FlagGeneration IF falling_edge(write) THEN IF (current_state = DATA_PRG OR current_state = CONF_PGD) AND CLE='1' AND ALE='0' AND Data = 16#10# THEN IF PRG_ACT = '0' THEN PRG_ACT <= '1'; PROG_in <= '1'; END IF; END IF; END IF; IF current_state = PGMS THEN IF rising_edge(PROG_out) THEN PRG_ACT <= '0'; Status(6) := '1'; PROG_in <= '0'; IF WPNeg/='0' AND BadBlockTable(WrPage/(BlockSize+1)) = '0' THEN list_id_v := list_id(WrPage * (PageSize + 1)); FOR j IN 0 TO PageSize LOOP getSegment(j,pom_seg); IF WrBuffData(j) /= -1 AND ProgramedFlag(WrPage/(BlockSize+1))(WrPage MOD (BlockSize+1))(pom_seg)= '0' THEN write_mem(linked_list(list_id_v), WrPage * (PageSize + 1) + j,WrBuffData(j)); END IF; END LOOP; ProgramedFlag(WrPage/(BlockSize+1)) (WrPage MOD (BlockSize+1)) := SegForProg; END IF; ELSIF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# AND PRG_ACT='1' THEN PROG_in <= '0'; END IF; END IF; ELSIF current_state = RESET THEN IF rising_edge(RSTDONE) THEN PRG_ACT <= '0'; END IF; END IF; END PROCESS FlagGeneration; Normal_Prog: PROCESS (PROG_in) IS BEGIN IF rising_edge(PROG_in) THEN IF Long_Timming THEN PROG_out <= '1' AFTER tdevice_PROG + tpd_WENeg_RY(tr10); ELSE PROG_out <= '1' AFTER (tdevice_PROG + tpd_WENeg_RY(tr10))/100; END IF; ELSIF falling_edge (PROG_in) THEN PROG_out <= '0'; END IF; END PROCESS Normal_Prog; Normal_Erase: PROCESS (BERS_in) IS BEGIN IF rising_edge(BERS_in) THEN IF Long_Timming THEN BERS_out <= '1' AFTER tdevice_BERASE + tpd_WENeg_RY(tr10); ELSE BERS_out <= '1' AFTER (tdevice_BERASE + tpd_WENeg_RY(tr10))/160; END IF; ELSIF falling_edge (BERS_in) THEN BERS_out <= '0'; END IF; END PROCESS Normal_Erase; TR: PROCESS (TR_in) IS BEGIN IF rising_edge(TR_in) THEN IF (Long_Timming = TRUE) THEN TR_out <= '0','1' AFTER tdevice_TR + tpd_WENeg_RY(tr10); ELSE TR_out <= '0','1' AFTER (tdevice_TR + tpd_WENeg_RY(tr10))/5; END IF; ELSE TR_out <= '0'; END IF; END PROCESS TR; IDPreload: PROCESS (PoweredUp) IS BEGIN -- PROCESS IDPreload IF PoweredUp='1' THEN IDArray(0) := 16#01#; IDArray(1) := 16#2C#; IDArray(2) := 16#04#; IDArray(3) := 16#D5#; END IF; END PROCESS IDPreload; InvalidBlockControl: PROCESS FILE invblocks_file : text is invblocks_file_name; VARIABLE buf : line; VARIABLE ind : natural; VARIABLE inv : natural; VARIABLE pind : natural; BEGIN initialize; ProgramedFlag := (OTHERS => (OTHERS => (OTHERS => '0'))); BadBlockTable := (OTHERS => '0'); IF invblocks_file_name /= "none" AND UserPreload THEN ind := 0; inv := 0; WHILE (NOT ENDFILE (invblocks_file)) LOOP READLINE(invblocks_file, buf); IF buf(1)='/' THEN next; ELSIF buf(1) = '@' THEN ind := h(buf(2 TO 4)); ELSE IF ind <= BlockNum AND ind > 0 THEN IF h(buf(1 TO 1)) = 1 THEN BadBlockTable(ind) := '1'; pind := (ind*(BlockSize+1)); FOR i IN 0 TO (2*(PageSize+1)-1) LOOP write_mem( linked_list(list_id(pind*(PageSize+1)+i)), pind*(PageSize+1)+i, InvalidData); END LOOP; ProgramedFlag(ind) := (OTHERS => (OTHERS => '1')); END IF; inv := inv +1; IF inv > InvBlocksNum THEN REPORT "Number of invalid blocks exceeds range"; END IF; ind := ind +1; ELSE REPORT "Invalid Block address out of range"; END IF; END IF; END LOOP; END IF; WAIT; END PROCESS InvalidBlockControl; -- purpose: Memory preload process MemPreload: PROCESS (PoweredUp) -- text file input variable FILE mem_file : text IS mem_file_name; VARIABLE buf : line; VARIABLE i : natural; VARIABLE ind : natural; VARIABLE pind : natural; VARIABLE index : natural; VARIABLE p_data : NATURAL; VARIABLE mem_data : INTEGER; VARIABLE mem_addr : INTEGER; BEGIN -- PROCESS MemPreload IF PoweredUp='1' THEN ------------------------------------------------------------------- -- Memory preload file format for s19mn-p -------------------------------------------------------------------- -- / - comment -- @aaaaaaa - stands for page address and address within -- first 1056 words of the page -- dd -
is byte to be written at Mem(Page)(offset++) -- page is div 1056 -- offset is mod 1056 -- offset is incremented on every write ------------------------------------------------------------------- IF mem_file_name /= "none" AND UserPreload THEN ind := 0; WHILE (NOT ENDFILE (mem_file)) LOOP READLINE(mem_file,buf); IF buf(1)='/' THEN next; ELSIF buf(1) = '@' THEN ind := h(buf(2 TO 8)); ELSE p_data := h(buf(1 TO 4)); IF ind = 0 THEN pind := 0; index := 0; ELSIF ind <= PageSize THEN pind := 0; index := ind; ELSE pind := natural(ind/(PageSize+1)); index := ind - pind * (PageSize+1); END IF; IF pind <= PageNum AND index <= PageSize THEN IF p_data /= 16#FFFF# AND BadBlockTable(pind/(BlockSize+1)) = '0' THEN mem_addr := pind * (PageSize+1) + index; mem_data := h(buf(1 TO 4)); write_mem( linked_list(list_id(mem_addr)), mem_addr, mem_data); getSegment(index,segment); ProgramedFlag(pind/(BlockSize+1))( pind MOD (BlockSize+1))(segment) := '1'; ind := ind + 1; END IF; ELSE REPORT "Memory address out of range"; END IF; END IF; END LOOP; END IF; END IF; END PROCESS MemPreload; RPassTrough: PROCESS (R_zd) IS BEGIN -- PROCESS RPassTrough IF R_zd = '0' THEN R_Pass <= '0'; ELSE R_Pass <= 'Z'; END IF; END PROCESS RPassTrough; ------------------------------------------------------------------------ -- Path delay section ------------------------------------------------------------------------ PROCESS (R_Pass) VARIABLE R_GlitchData : VitalGlitchDataType; BEGIN -- PROCESS VitalPathDelay01( OutSignal => R, OutSignalName => "R", OutTemp => R_Pass, GlitchData => R_GlitchData, Mode => VitalTransport, Paths => ( 0 =>(InputChangeTime => WENeg'LAST_EVENT, PathDelay => tpd_WENeg_RY, PathCondition => true) ) ); END PROCESS; D_Out_Path_Gen : FOR i IN 0 TO 15 GENERATE BEGIN -- GENERATE D_Out_Path_Gen PROCESS (DOut_zd(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN -- PROCESS VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_zd(i), GlitchData => D0_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => RENeg'LAST_EVENT, PathDelay => tpd_RENeg_IO0, PathCondition => true), 1 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_IO0, PathCondition => true) ) ); END PROCESS; END GENERATE D_Out_Path_Gen; END BLOCK Behavior; END ARCHITECTURE vhdl_behavioral_dynamic_memory_allocation; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral_static_memory_allocation OF s19mn512p01 IS ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral_static_memory_allocation : ARCHITECTURE IS true; CONSTANT PartId : STRING := "s19mn512p01"; CONSTANT MaxData : NATURAL := 16#FFFF#; CONSTANT BlockNum : NATURAL := 511; -- number of blocks CONSTANT BlockSize : NATURAL := 63; -- size of block in pages CONSTANT PageNum : NATURAL := 16#7FFF#; -- BlockSize * BlockNum CONSTANT PageSize : NATURAL := 1055; -- with spare CONSTANT SegmentNum : NATURAL := 3; -- 4 segment pairs within page CONSTANT SegmentSize : NATURAL := 16#200#; CONSTANT SperSegSize : NATURAL := 16#10#; CONSTANT SpareSize : NATURAL := 63; CONSTANT InvalidData : INTEGER := 2; CONSTANT InvBlocksNum : NATURAL := 10; -- Interconnect path delay signals SIGNAL IO15_ipd : std_ulogic := 'U'; SIGNAL IO14_ipd : std_ulogic := 'U'; SIGNAL IO13_ipd : std_ulogic := 'U'; SIGNAL IO12_ipd : std_ulogic := 'U'; SIGNAL IO11_ipd : std_ulogic := 'U'; SIGNAL IO10_ipd : std_ulogic := 'U'; SIGNAL IO9_ipd : std_ulogic := 'U'; SIGNAL IO8_ipd : std_ulogic := 'U'; SIGNAL IO7_ipd : std_ulogic := 'U'; SIGNAL IO6_ipd : std_ulogic := 'U'; SIGNAL IO5_ipd : std_ulogic := 'U'; SIGNAL IO4_ipd : std_ulogic := 'U'; SIGNAL IO3_ipd : std_ulogic := 'U'; SIGNAL IO2_ipd : std_ulogic := 'U'; SIGNAL IO1_ipd : std_ulogic := 'U'; SIGNAL IO0_ipd : std_ulogic := 'U'; SIGNAL CLE_ipd : std_ulogic := 'U'; SIGNAL ALE_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL RENeg_ipd : std_ulogic := 'U'; SIGNAL WENeg_ipd : std_ulogic := 'U'; SIGNAL WPNeg_ipd : std_ulogic := 'U'; SIGNAL PRE_ipd : std_ulogic := 'U'; -- internal delays SIGNAL TR_in : std_ulogic := '0'; SIGNAL TR_out : std_ulogic := '0'; SIGNAL TR_tmp_in : std_ulogic := '0'; SIGNAL TR_tmp_out : std_ulogic := '0'; SIGNAL PROG_in : std_ulogic := '0'; SIGNAL PROG_out : std_ulogic := '0'; SIGNAL PROG_tmp_in : std_ulogic := '0'; SIGNAL PROG_tmp_out : std_ulogic := '0'; SIGNAL BERS_in : std_ulogic := '0'; SIGNAL BERS_out : std_ulogic := '0'; SIGNAL BERS_tmp_in : std_ulogic := '0'; SIGNAL BERS_tmp_out : std_ulogic := '0'; BEGIN -- ARCHITECTURE vhdl_behavioral --------------------------------------------------------------------------- -- Internal delays --------------------------------------------------------------------------- -- Vital primitives which incorporate internal delays PROG : VitalBUF(PROG_tmp_out, PROG_tmp_in, tpd_a_q => (tdevice_PROG + tpd_WENeg_RY(tr10), UnitDelay)); BERASE : VitalBUF(BERS_tmp_out, BERS_tmp_in, tpd_a_q => (tdevice_BERASE + tpd_WENeg_RY(tr10), UnitDelay)); TR : VitalBUF(TR_tmp_out, TR_tmp_in, tpd_a_q => (tdevice_TR, UnitDelay)); --------------------------------------------------------------------------- -- WIRE DELAYS --------------------------------------------------------------------------- WireDelay : BLOCK IS BEGIN -- BLOCK WireDelay w_1 : VitalWireDelay( IO0_ipd, IO0, tipd_IO0 ); w_2 : VitalWireDelay( IO1_ipd, IO1, tipd_IO1 ); w_3 : VitalWireDelay( IO2_ipd, IO2, tipd_IO2 ); w_4 : VitalWireDelay( IO3_ipd, IO3, tipd_IO3 ); w_5 : VitalWireDelay( IO4_ipd, IO4, tipd_IO4 ); w_6 : VitalWireDelay( IO5_ipd, IO5, tipd_IO5 ); w_7 : VitalWireDelay( IO6_ipd, IO6, tipd_IO6 ); w_8 : VitalWireDelay( IO7_ipd, IO7, tipd_IO7 ); w_9 : VitalWireDelay( IO8_ipd, IO8, tipd_IO8 ); w_10 : VitalWireDelay( IO9_ipd, IO9, tipd_IO9 ); w_11 : VitalWireDelay( IO10_ipd, IO10, tipd_IO10 ); w_12 : VitalWireDelay( IO11_ipd, IO11, tipd_IO11 ); w_13 : VitalWireDelay( IO12_ipd, IO12, tipd_IO12 ); w_14 : VitalWireDelay( IO13_ipd, IO13, tipd_IO13 ); w_15 : VitalWireDelay( IO14_ipd, IO14, tipd_IO14 ); w_16 : VitalWireDelay( IO15_ipd, IO15, tipd_IO15 ); w_17 : VitalWireDelay( CLE_ipd, CLE, tipd_CLE ); w_18 : VitalWireDelay( ALE_ipd, ALE, tipd_ALE ); w_19 : VitalWireDelay( CENeg_ipd, CENeg, tipd_CENeg ); w_20 : VitalWireDelay( RENeg_ipd, RENeg, tipd_RENeg ); w_21 : VitalWireDelay( WENeg_ipd, WENeg, tipd_WENeg ); w_22 : VitalWireDelay( WPNeg_ipd, WPNeg, tipd_WPNeg ); w_23 : VitalWireDelay( PRE_ipd, PRE, tipd_PRE); END BLOCK WireDelay; --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior : BLOCK PORT ( A : IN std_logic_vector(7 DOWNTO 0) := (OTHERS => 'U'); DIn : IN std_logic_vector(15 DOWNTO 0) := (OTHERS => 'U'); DOut : OUT std_logic_vector(15 DOWNTO 0) := (OTHERS => 'Z'); CLE : IN std_ulogic := 'U'; ALE : IN std_ulogic := 'U'; CENeg : IN std_ulogic := 'U'; RENeg : IN std_ulogic := 'U'; WENeg : IN std_ulogic := 'U'; WPNeg : IN std_ulogic := 'U'; R : OUT std_ulogic := 'U'; PRE : IN std_ulogic := 'U' ); PORT MAP ( A(7) => IO7_ipd, A(6) => IO6_ipd, A(5) => IO5_ipd, A(4) => IO4_ipd, A(3) => IO3_ipd, A(2) => IO2_ipd, A(1) => IO1_ipd, A(0) => IO0_ipd, DIn(15) => IO15_ipd, DIn(14) => IO14_ipd, DIn(13) => IO13_ipd, DIn(12) => IO12_ipd, DIn(11) => IO11_ipd, DIn(10) => IO10_ipd, DIn(9) => IO9_ipd, DIn(8) => IO8_ipd, DIn(7) => IO7_ipd, DIn(6) => IO6_ipd, DIn(5) => IO5_ipd, DIn(4) => IO4_ipd, DIn(3) => IO3_ipd, DIn(2) => IO2_ipd, DIn(1) => IO1_ipd, DIn(0) => IO0_ipd, DOut(15) => IO15, DOut(14) => IO14, DOut(13) => IO13, DOut(12) => IO12, DOut(11) => IO11, DOut(10) => IO10, DOut(9) => IO9, DOut(8) => IO8, DOut(7) => IO7, DOut(6) => IO6, DOut(5) => IO5, DOut(4) => IO4, DOut(3) => IO3, DOut(2) => IO2, DOut(1) => IO1, DOut(0) => IO0, CLE => CLE_ipd, ALE => ALE_ipd, CENeg => CENeg_ipd, RENeg => RENeg_ipd, WENeg => WENeg_ipd, WPNeg => WPNeg_ipd, R => RY, PRE => PRE_ipd ); -- State Machine : State_Type TYPE state_type IS ( IDLE, UNKNOWN, -- wrong command sequneces PREL_RD, RESET, A0_RD, A1_RD, A2_RD, RD_WCMD, -- waiting for the confirm read command BUFF_TR, RD, CAC_PREL, -- Coloumn address change A0_CAC, A1_CAC, -- Wait for confirm EO command ID_PREL, ID, PREL_PRG, PGD_PREL, A0_PRG, A1_PRG, A2_PRG, DATA_PRG, PGMS_CAC, A0_PRG_CAC, PGMS, PREL_ERS, A1_ERS, A2_ERS, BERS_EXEC, A0_PGD, A1_PGD, A2_PGD, CONF_PGD ); -- Page Array TYPE PageArr IS ARRAY (0 TO PageSize) OF Integer RANGE -1 TO MaxData; -- Flash Memory Array TYPE MemArr IS ARRAY (0 TO PageNum) OF PageArr; TYPE IDArr IS ARRAY (0 TO 3) OF integer RANGE -1 TO MaxData; -- Program protection TYPE SegAddrBoundary IS ARRAY (0 TO SegmentNum) OF NATURAL; TYPE SegArr IS ARRAY (0 TO SegmentNum) OF std_logic; TYPE PageSegArr IS ARRAY (0 TO BlockSize) OF SegArr; TYPE BlockPageSegArr IS ARRAY (0 TO BlockNum) OF PageSegArr; -- states SIGNAL current_state : State_Type; SIGNAL next_state : State_Type; -- control signals SIGNAL STAT_ACT : std_logic := '0'; SIGNAL ERS_ACT : std_logic := '0'; SIGNAL PRG_ACT : std_logic := '0'; SIGNAL RSTSTART : std_logic := '0'; SIGNAL RSTDONE : std_logic := '0'; -- Control signals for read operation SIGNAL PGR_ACT : std_logic := '0'; -- Page read in progress SIGNAL PGD_ACT : std_logic := '0'; -- Page Duplicate -- powerup SIGNAL PoweredUp : std_logic := '0'; SIGNAL reseted : std_logic := '0'; SIGNAL write : std_logic := '0'; SIGNAL read : std_logic := '0'; SIGNAL DOut_zd : std_logic_vector(15 DOWNTO 0) := (OTHERS => 'Z'); SIGNAL R_zd : std_logic := '0'; SIGNAL R_Pass : std_logic := '0'; -- 8 BIT ADDRESS SIGNAL AddrCom : integer; -- Address within page SIGNAL Address : integer RANGE 0 TO PageSize; -- Page number SIGNAL PageAddr : integer RANGE -1 TO PageNum := -1; -- Block number SIGNAL BlockAddr : integer RANGE -1 TO BlockNum := -1; -- Data SIGNAL Data : integer RANGE -1 TO MaxData; -- ID control signals SIGNAL IDAddr : integer RANGE 0 TO 7; -- Write Page control signals SIGNAL WrBuffData : PageArr; SIGNAL WrAddr : integer RANGE -1 TO PageSize+1; SIGNAL WrPage : integer RANGE 0 TO PageNum; SIGNAL SegForProg : SegArr := (OTHERS => '0'); SHARED VARIABLE Page_pom : integer RANGE -1 TO PageNum; SHARED VARIABLE addr_pom : integer RANGE -1 TO PageSize+1; SHARED VARIABLE cnt_addr : integer := 0; SHARED VARIABLE pom_seg : INTEGER RANGE -1 TO SegmentNum; SHARED VARIABLE segment : INTEGER RANGE -1 TO SegmentNum; SHARED VARIABLE ProgramedFlag : BlockPageSegArr; SHARED VARIABLE Blck : INTEGER RANGE 0 to BlockNum; -- Segments starting addresses of main memory SHARED VARIABLE ssam : SegAddrBoundary :=(16#000# ,16#100# ,16#200# ,16#300#); -- Segments starting addresses of spare memory SHARED VARIABLE ssas : SegAddrBoundary :=(16#400# ,16#408# ,16#410# ,16#418#); -- Segments ending addresses of main memory SHARED VARIABLE seam : SegAddrBoundary := (16#0FF# ,16#1FF# ,16#2FF# ,16#3FF#); -- Segments ending addresses of spare memory SHARED VARIABLE seas : SegAddrBoundary := (16#407# ,16#40F# ,16#417# ,16#41F#); -- Mem(Page)(Address) SHARED VARIABLE Mem : MemArr := (OTHERS => (OTHERS => MaxData)); -- ID Array SHARED VARIABLE IDArray : IDArr; -- Page duplicate buffer SHARED VARIABLE PDBuffer : PageArr := (OTHERS => 0); -- Status SHARED VARIABLE Status : std_logic_vector(7 DOWNTO 0) := "01000000"; SHARED VARIABLE BadBlockTable : std_logic_vector(BlockNum downto 0); -- timing check violation SIGNAL Viol : X01 := '0'; PROCEDURE getSegment ( paddress : IN integer RANGE 0 TO PageSize; j : OUT integer RANGE -1 TO SegmentNum) IS BEGIN -- PROCEDURE getSegment FOR i IN 0 TO SegmentNum LOOP IF (paddress >= ssam(i) AND paddress <= seam(i)) OR (paddress >= ssas(i) AND paddress <= seas(i)) THEN j := i; END if; END LOOP; END PROCEDURE getSegment; BEGIN --------------------------------------------------------------------------- -- Power Up time 10 us --------------------------------------------------------------------------- PoweredUp <= '1' AFTER 10 us; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS (A,DIn,CLE,ALE,CENeg,RENeg,WENeg,WPNeg) IS -- Timing check variables VARIABLE TViol_IO0_WENeg : X01 := '0'; VARIABLE TD_IO0_WENeg : VitalTimingDataType; VARIABLE TViol_CLE_WENeg_F : X01 := '0'; VARIABLE TD_CLE_WENeg_F : VitalTimingDataType; VARIABLE TViol_ALE_WENeg_F : X01 := '0'; VARIABLE TD_ALE_WENeg_F : VitalTimingDataType; VARIABLE TViol_CENeg_WENeg_F : X01 := '0'; VARIABLE TD_CENeg_WENeg_F : VitalTimingDataType; VARIABLE TViol_WPNeg_WENeg_F : X01 := '0'; VARIABLE TD_WPNeg_WENeg_F : VitalTimingDataType; VARIABLE TViol_WENeg_CENeg_F : X01 := '0'; VARIABLE TD_WENeg_CENeg_F : VitalTimingDataType; VARIABLE TViol_CLE_RENeg : X01 := '0'; VARIABLE TD_CLE_RENeg : VitalTimingDataType; VARIABLE TViol_ALE_RENeg : X01 := '0'; VARIABLE TD_ALE_RENeg : VitalTimingDataType; VARIABLE TViol_WENeg_RENeg : X01 := '0'; VARIABLE TD_WENeg_RENeg : VitalTimingDataType; VARIABLE TViol_CENeg_RENeg_F : X01 := '0'; VARIABLE TD_CENeg_RENeg_F : VitalTimingDataType; VARIABLE TViol_RENeg_WENeg : X01 := '0'; VARIABLE TD_RENeg_WENeg : VitalTimingDataType; VARIABLE TViol_CLE_WENeg_R : X01 := '0'; VARIABLE TD_CLE_WENeg_R : VitalTimingDataType; VARIABLE TViol_ALE_WENeg_R : X01 := '0'; VARIABLE TD_ALE_WENeg_R : VitalTimingDataType; VARIABLE TViol_CENeg_WENeg_R : X01 := '0'; VARIABLE TD_CENeg_WENeg_R : VitalTimingDataType; VARIABLE PViol_WENeg : X01 := '0'; VARIABLE PD_WENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE PViol_RENeg : X01 := '0'; VARIABLE PD_RENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Violation : X01 := '0'; BEGIN -- PROCESS VITALTimingCheck IF ( TimingChecksOn ) THEN -------------------------------------------------------------------- -- Timing Check Section -------------------------------------------------------------------- -- Setup Check between CLE and WENeg VitalSetupHoldCheck ( TestSignal => CLE, TestSignalName => "CLE", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_CLE_WENeg, SetupLow => tsetup_CLE_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLE_WENeg_F, Violation => TViol_CLE_WENeg_F ); -- Setup Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", SetupLow => tsetup_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_F, Violation => TViol_CENeg_WENeg_F ); -- Setup Check between ALE and WENeg VitalSetupHoldCheck ( TestSignal => ALE, TestSignalName => "ALE", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_ALE_WENeg, SetupLow => tsetup_ALE_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_ALE_WENeg_F, Violation => TViol_ALE_WENeg_F ); -- Setup/Hold Check between IO and WENeg VitalSetupHoldCheck ( TestSignal => IO0, TestSignalName => "IO", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_IO0_WENeg, SetupLow => tsetup_IO0_WENeg, HoldHigh => thold_IO0_WENeg, HoldLow => thold_IO0_WENeg, CheckEnabled => CENeg = '0', RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_IO0_WENeg, Violation => TViol_IO0_WENeg ); -- Setup Check between WPNeg and WENeg VitalSetupHoldCheck ( TestSignal => WPNeg, TestSignalName => "WP#", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_WPNeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WPNeg_WENeg_F, Violation => TViol_WPNeg_WENeg_F ); -- Setup Check between CLE and RENeg VitalSetupHoldCheck ( TestSignal => CLE, TestSignalName => "CLE", RefSignal => RENeg, RefSignalName => "RE#", SetupHigh => tsetup_CLE_RENeg, SetupLow => tsetup_CLE_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CLE_RENeg, Violation => TViol_CLE_RENeg ); -- Setup Check between ALE and RENeg VitalSetupHoldCheck ( TestSignal => ALE, TestSignalName => "ALE", RefSignal => RENeg, RefSignalName => "RE#", SetupLow => tsetup_ALE_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_ALE_RENeg, Violation => TViol_ALE_RENeg ); -- Setup Check between CENeg and RENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => RENeg, RefSignalName => "RE#", SetupLow => tsetup_CENeg_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_RENeg_F, Violation => TViol_CENeg_RENeg_F ); -- Setup Check between RENeg and WENeg VitalSetupHoldCheck ( TestSignal => RENeg, TestSignalName => "RE#", RefSignal => WENeg, RefSignalName => "WE#", SetupHigh => tsetup_RENeg_WENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_RENeg_WENeg, Violation => TViol_RENeg_WENeg ); -- Setup Check between WENeg and CENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => CENeg, RefSignalName => "CE#", SetupHigh => tsetup_WENeg_CENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_CENeg_F, Violation => TViol_WENeg_CENeg_F ); -- Setup Check between WENeg and RENeg VitalSetupHoldCheck ( TestSignal => WENeg, TestSignalName => "WE#", RefSignal => RENeg, RefSignalName => "RE#", SetupHigh => tsetup_WENeg_RENeg, CheckEnabled => TRUE, RefTransition => '\', HeaderMsg => InstancePath & PartID, TimingData => TD_WENeg_RENeg, Violation => TViol_WENeg_RENeg ); -- Hold Check between CLE and WENeg VitalSetupHoldCheck ( TestSignal => CLE, TestSignalName => "CLE", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_CLE_WENeg, HoldLow => thold_CLE_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CLE_WENeg_R, Violation => TViol_CLE_WENeg_R ); -- Hold Check between ALE and WENeg VitalSetupHoldCheck ( TestSignal => ALE, TestSignalName => "ALE", RefSignal => WENeg, RefSignalName => "WE#", HoldHigh => thold_ALE_WENeg, HoldLow => thold_ALE_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_ALE_WENeg_R, Violation => TViol_ALE_WENeg_R ); -- Hold Check between CENeg and WENeg VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CE#", RefSignal => WENeg, RefSignalName => "WE#", HoldLow => thold_CENeg_WENeg, CheckEnabled => TRUE, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_WENeg_R, Violation => TViol_CENeg_WENeg_R ); -- Period and Pulse Width Check for WENeg VitalPeriodPulseCheck ( TestSignal => WENeg, TestSignalName => "WE#", Period => tperiod_WENeg, PulseWidthLow => tpw_WENeg_negedge, PulseWidthHigh => tpw_WENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_WENeg, Violation => PViol_WENeg ); -- Period and Pulse Width Check for RENeg VitalPeriodPulseCheck ( TestSignal => RENeg, TestSignalName => "RE#", Period => tperiod_RENeg, PulseWidthLow => tpw_RENeg_negedge, PulseWidthHigh => tpw_RENeg_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_RENeg, Violation => PViol_RENeg ); Violation := TViol_IO0_WENeg OR TViol_CLE_WENeg_F OR TViol_ALE_WENeg_F OR TViol_CENeg_WENeg_F OR TViol_WPNeg_WENeg_F OR TViol_WENeg_CENeg_F OR TViol_CLE_RENeg OR TViol_ALE_RENeg OR TViol_WENeg_RENeg OR TViol_CENeg_RENeg_F OR TViol_RENeg_WENeg OR TViol_CLE_WENeg_R OR TViol_ALE_WENeg_R OR TViol_CENeg_WENeg_R OR PViol_RENeg OR PViol_WENeg; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; --------------------------------------------------------------------------- -- Proces for reset control and FSM state transition --------------------------------------------------------------------------- StateTransition: PROCESS (next_state, PoweredUp) IS BEGIN -- PROCESS StateTransition IF rising_edge(PoweredUp) THEN reseted <= '1'; ELSIF PoweredUp = '1' THEN current_state <= next_state; ELSE current_state <= IDLE; reseted <= '0'; END IF; END PROCESS StateTransition; --------------------------------------------------------------------------- -- Proces for generating the write and read signals --------------------------------------------------------------------------- wr_rd_gen: PROCESS (WENeg, CENeg, RENeg) IS BEGIN -- PROCESS wr_rd_gen IF WENeg = '0' AND CENeg = '0' AND RENeg = '1' THEN write <= '1'; ELSIF WENeg = '1' AND CENeg = '0' AND RENeg = '1' THEN write <= '0'; ELSE write <= '0'; END IF; IF WENeg = '1' AND CENeg = '0' AND RENeg = '0' THEN read <= '1'; ELSIF WENeg = '1' AND CENeg = '0' AND RENeg = '1' THEN read <= '0'; ELSE read <= '0'; END IF; END PROCESS wr_rd_gen; --------------------------------------------------------------------------- -- Latches 8 bit address on the rising edge of RE# -- Latches data on rising edge of WE# --------------------------------------------------------------------------- BusCycleDecode: PROCESS (A, DIn, WENeg, CENeg, RENeg) IS BEGIN -- PROCESS BusCycleDecode -- latch address IF rising_edge(WENeg) AND ALE = '1' AND CLE = '0' AND CENeg = '0' THEN AddrCom <= to_nat(A(7 DOWNTO 0)); END IF; -- latch data IF rising_edge(WENeg) AND ALE = '0' AND RENeg = '1' THEN Data <= to_nat(DIn(15 DOWNTO 0)); END IF; END PROCESS BusCycleDecode; --------------------------------------------------------------------------- -- Timing control for the Reset Operation --------------------------------------------------------------------------- RstTime: PROCESS (RSTSTART, reseted) IS VARIABLE duration : time; BEGIN -- PROCESS RstTime IF rising_edge(reseted) THEN RSTDONE <= '1'; --reset done ELSIF reseted = '1' THEN IF rising_edge(RSTSTART) AND RSTDONE = '1' THEN IF ERS_ACT = '1' THEN IF (Long_Timming = TRUE) THEN duration := 500 us; ELSE duration := 50 us; END IF; ELSIF PRG_ACT = '1' THEN duration := 10 us; ELSE duration := 5 us; END IF; RSTDONE <= '0', '1' AFTER duration ; END IF; END IF; END PROCESS RstTime; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen: PROCESS (write, read, reseted, current_state, BERS_out, PROG_out, TR_out, RSTDONE ) IS VARIABLE oe : BOOLEAN := FALSE; BEGIN -- PROCESS StateGen oe := rising_edge(read); IF reseted /= '1' THEN next_state <= current_state; ELSIF rising_edge(reseted) THEN IF PRE = '1' THEN next_state <= BUFF_TR; ELSE next_state <= IDLE; END IF; ELSE CASE current_state IS WHEN IDLE => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#00# THEN next_state <= PREL_RD; ELSIF CLE='1' AND ALE='0' AND Data=16#90# THEN next_state <= ID_PREL; ELSIF CLE='1' AND ALE='0' AND Data=16#80# THEN next_state <= PREL_PRG; ELSIF CLE='1' AND ALE='0' AND Data=16#60# THEN next_state <= PREL_ERS; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN next_state <= IDLE; ELSIF CLE='1' THEN next_state <= IDLE; END IF; END IF; WHEN UNKNOWN => IF falling_edge(write) THEN IF CLE = '1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; END IF; END IF; WHEN RESET => IF RSTDONE = '1' THEN next_state <= IDLE; END IF; WHEN PREL_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A0_RD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; ELSIF oe THEN next_state <= IDLE; END IF; WHEN A0_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A1_RD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A2_RD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_RD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= RD_WCMD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN RD_WCMD => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#30# THEN next_state <= BUFF_TR; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#35# THEN next_state <= BUFF_TR; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN BUFF_TR => IF falling_edge(write) THEN IF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE = '1' AND STAT_ACT = '1' THEN next_state <= BUFF_TR; END IF; ELSIF TR_out='1' THEN next_state <= RD; -- buffer transfered END IF; WHEN RD => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data=16#00# THEN IF STAT_ACT ='1' AND PGR_ACT='1' THEN next_state <= RD; ELSIF PGR_ACT='1' THEN next_state <= PREL_RD; ELSE next_state <= UNKNOWN; END IF; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#80# AND PGD_ACT = '0' THEN next_state <= PREL_PRG; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#90# AND PGD_ACT = '0' THEN next_state <= ID_PREL; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#70# THEN next_state <= RD; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#60# AND PGD_ACT = '0' THEN next_state <= PREL_ERS; -- To erase ELSIF CLE = '1' AND ALE = '0' AND Data = 16#85# AND PGD_ACT = '1' THEN next_state <= PGD_PREL; -- Read next colomn address ELSIF CLE = '1' AND ALE = '0' AND Data = 16#05# AND PGD_ACT = '0' THEN next_state <= CAC_PREL; ELSIF CLE ='1' AND STAT_ACT = '1' THEN next_state <= RD; ELSE next_state <= RD; END IF; END IF; WHEN CAC_PREL => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A0_CAC; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; ELSIF CLE ='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A0_CAC => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A1_CAC; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; ELSIF CLE ='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_CAC => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#E0# THEN next_state <= RD; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; ELSIF CLE ='1' OR ALE = '1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN ID_PREL => IF falling_edge(write) THEN IF ALE = '1' AND AddrCom = 16#00# THEN next_state <= ID; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE ='1' OR ALE = '1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN ID => IF falling_edge(write) THEN IF CLE='1' AND ALE = '0' AND Data=16#00# THEN next_state <= PREL_RD; ELSIF CLE='1' AND ALE = '0' AND Data=16#90# THEN next_state <= ID_PREL; ELSIF CLE='1' AND ALE = '0' AND Data=16#80# THEN next_state <= PREL_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#60# THEN next_state <= PREL_ERS; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' AND ALE = '0' AND Data=16#70# THEN next_state <= IDLE; ELSIF CLE='1' THEN next_state <= IDLE; END IF; END IF; WHEN PREL_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A0_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A0_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A1_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A2_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_PRG => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= DATA_PRG; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN DATA_PRG => IF falling_edge(write) THEN IF (ALE='1' AND (cnt_addr < 2 OR cnt_addr >= 4)) OR (CLE='1' AND ALE='0' AND cnt_addr > 4) THEN next_state <= UNKNOWN; ELSIF CLE='1' AND ALE='0' AND Data=16#10# THEN IF PRG_ACT='0' THEN next_state <= PGMS; END IF; ELSIF CLE ='1' AND ALE='0' AND Data = 16#85# THEN next_state <= PGMS_CAC; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; ELSIF ALE='0' AND CLE='0' AND WrAddr < PageSize+1 THEN next_state <= DATA_PRG; -- write next word to buffer END IF; END IF; WHEN PGMS_CAC => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; ELSIF ALE='1' THEN next_state <= A0_PRG_CAC; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN PGMS => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE = '1' AND STAT_ACT = '1' THEN next_state <= PGMS; END IF; ELSIF rising_edge(PROG_out) THEN next_state <= IDLE; -- programming done END IF; WHEN A0_PRG_CAC => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= DATA_PRG; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN PREL_ERS => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A1_ERS; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_ERS => IF falling_edge(write) THEN IF ALE='1' THEN next_state <= A2_ERS; ELSIF CLE='1' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_ERS => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data = 16#D0# THEN next_state <= BERS_EXEC; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE='1' OR ALE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN BERS_EXEC => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN next_state <= RESET; -- reset ELSIF CLE = '1' AND STAT_ACT = '1' THEN next_state <= BERS_EXEC; END IF; ELSIF BERS_out='1' THEN next_state <= IDLE; END IF; WHEN PGD_PREL => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A0_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A0_PGD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A1_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A1_PGD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= A2_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN A2_PGD => IF falling_edge(write) THEN IF ALE = '1' THEN next_state <= CONF_PGD; ELSIF CLE = '1' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; WHEN CONF_PGD => IF falling_edge(write) THEN IF (ALE='1' AND cnt_addr >= 4) OR (CLE='1' AND ALE='0' AND cnt_addr > 4) THEN next_state <= UNKNOWN; ELSIF CLE = '1' AND ALE='0' AND Data = 16#10# THEN next_state <= PGMS; ELSIF CLE='1' AND ALE='0' AND Data = 16#85# THEN next_state <= PGMS_CAC; ELSIF CLE = '1' AND ALE='0' AND Data = 16#FF# THEN next_state <= RESET; ELSIF CLE='1' THEN next_state <= UNKNOWN; END IF; END IF; END CASE; END IF; END PROCESS StateGen; --------------------------------------------------------------------------- -- FSM Output Generation and general funcionality --------------------------------------------------------------------------- Functional : PROCESS (read, write, Data, AddrCom, reseted, current_state, RENeg, CENeg, ALE, CLE, BERS_out, PROG_out, TR_out, RSTDONE, WPNeg ) IS VARIABLE oe : BOOLEAN := false; VARIABLE Page : INTEGER RANGE 0 to PageNum; VARIABLE BlockPage : integer RANGE 0 TO BlockSize; VARIABLE Pom_Address : integer RANGE 0 TO PageSize; VARIABLE CashBuffData : PageArr; -- Page chache register PROCEDURE Read_Data ( SIGNAL Addr : INOUT integer RANGE 0 TO PageSize; SIGNAL Page : IN integer RANGE -1 TO PageNum ) IS BEGIN -- PROCEDURE read_data IF Mem(Page)(Addr) /= -1 THEN DOut_zd <= to_slv(Mem(Page)(Addr),16); ELSE DOut_zd <= ( OTHERS => 'X'); END IF; IF Addr /= PageSize THEN Addr <= Addr+1; END IF; END PROCEDURE read_data; PROCEDURE Read_Status IS BEGIN Dout_zd(7 DOWNTO 0) <= Status; Dout_zd(15 DOWNTO 8) <= (OTHERS => '0'); END PROCEDURE Read_Status; BEGIN -- PROCESS Functional ---------------------------------------------------------------------- -- Funcionality section ---------------------------------------------------------------------- oe := rising_edge(read); Status(7) := WPNeg_ipd; IF reseted /= '1' THEN R_zd <= '0'; ELSIF rising_edge(reseted) THEN IF PRE='1' THEN Address <= 0; Pom_Address := 0; PageAddr <= 0; BlockAddr <= 0; PGR_ACT <= '1'; TR_in <= '1'; ELSE PGR_ACT <= '0'; R_zd <= '1'; END IF; ELSE CASE current_state IS WHEN IDLE => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#00# THEN Status(6 DOWNTO 0) := "1000000"; STAT_ACT <= '0'; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND ALE = '0' AND (Data = 16#80# OR Data = 16#90#) THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#60# THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN UNKNOWN => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; ERS_ACT <= '0'; PGD_ACT <= '0'; PGR_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN RESET => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND Data = 16#70# THEN STAT_ACT <= '1'; END IF; END IF; IF RSTDONE = '1' THEN ERS_ACT <= '0'; PGD_ACT <= '0'; PGR_ACT <= '0'; R_zd <= '1'; Status(6 DOWNTO 0) := "1000000"; PGR_ACT <= '0'; ELSE Status(6 DOWNTO 0) := "0000000"; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN PREL_RD => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := AddrCom; cnt_addr := 0; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; IF oe AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; WHEN A0_RD => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := (AddrCom* 16#100#) + Pom_Address; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_RD => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_RD => IF falling_edge(write) THEN IF ALE='1' THEN Page := (AddrCom* 16#100#) + Page; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN RD_WCMD => IF falling_edge(write) THEN IF CLE = '1' AND ALE='0' AND Data = 16#30# THEN PGR_ACT <= '1'; Address <= Pom_Address; PageAddr <= Page; BlockAddr <= Page / (BlockSize + 1); Blck := Page / (BlockSize + 1); TR_in <= '1'; R_zd <= '0'; Status(6) := '0'; ELSIF CLE = '1' AND ALE='0' AND Data = 16#35# THEN PGD_ACT <= '1'; Address <= Pom_Address; PageAddr <= Page; BlockAddr <= Page / (BlockSize + 1); Blck := Page / (BlockSize + 1); TR_in <= '1'; R_zd <= '0'; Status(6) := '0'; PDBuffer := (OTHERS => -1); ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF ALE='1' THEN cnt_addr := cnt_addr + 1; END IF; END IF; WHEN BUFF_TR => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN TR_in <= '0'; STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE = '1' AND ALE='0' AND Data = 16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; ELSIF TR_out='1' THEN R_zd <= '1'; Status(6) := '1'; TR_in <= '0'; IF PGD_ACT='1' THEN PDBuffer := Mem(PageAddr); END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN RD => IF falling_edge(write) THEN IF CLE = '1' AND ALE='0' AND Data = 16#00# THEN IF STAT_ACT = '1' THEN STAT_ACT <= '0'; Address <= Pom_Address; ELSIF PGD_ACT = '0' THEN PGR_ACT <= '0'; STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; END IF; ELSIF CLE = '1' AND ALE='0' AND Data = 16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND ALE='0' AND Data = 16#90# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; PGR_ACT <= '0'; ELSIF CLE = '1' AND ALE='0' AND Data = 16#80# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; PGR_ACT <= '0'; ELSIF CLE = '1' AND ALE = '0' AND Data = 16#60# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; PGR_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE='1' AND ALE = '0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE='1' AND ALE = '0' AND Data=16#85# AND PGD_ACT='1' THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE='1' AND ALE = '0' AND Data=16#05# AND PGD_ACT = '0' THEN STAT_ACT <= '0'; Status(6 DOWNTO 0) := "1000000"; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF PGD_ACT='0' AND STAT_ACT='0' THEN Read_Data(Address,PageAddr); ELSIF STAT_ACT='1' THEN Read_Status; END IF; END IF; WHEN CAC_PREL => IF falling_edge(write) THEN IF ALE = '1' THEN Pom_Address:= AddrCom; cnt_addr := 0; ELSIF CLE='1' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_CAC => IF falling_edge(write) THEN IF ALE = '1' THEN Pom_Address := Pom_Address + AddrCom * 16#100#; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_CAC => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data = 16#E0# THEN Address <= Pom_Address; ELSIF CLE='1' AND ALE='0' AND Data = 16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; ELSIF ALE='1' THEN cnt_addr := cnt_addr+1; END IF; END IF; WHEN ID_PREL => IF falling_edge(write) THEN IF ALE='1' AND AddrCom=16#00# THEN IDAddr <= 0; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; END if; END IF; WHEN ID => IF falling_edge(write) THEN IF CLE ='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN STAT_ACT <= '1'; ELSIF CLE='1' AND ALE='0' AND Data=16#00# THEN STAT_ACT <= '0'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF IDAddr < 4 THEN DOut_zd <= to_slv(IDArray(IDAddr),16); IDAddr <= IDAddr+1; ELSE DOut_zd <= (OTHERS => 'Z'); END IF; END IF; WHEN PREL_PRG => IF falling_edge(write) THEN IF ALE='1' THEN WrAddr <= AddrCom; cnt_addr := 0; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_PRG => IF falling_edge(write) THEN IF ALE='1' THEN WrAddr <= (AddrCom * 16#100#)+WrAddr; CashBuffData := (OTHERS => -1); cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_PRG => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_PRG => IF falling_edge(write) THEN IF ALE='1' THEN Page := Page +(AddrCom * 16#100#); Blck := Page / (BlockSize+1); cnt_addr := cnt_addr + 1; BlockPage := Page MOD (BlockSize + 1); Page_pom := BlockPage; SegForProg <= ProgramedFlag(Blck)(BlockPage); ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN DATA_PRG => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF ALE='0' AND CLE='0' AND WrAddr < PageSize+1 THEN getSegment(WrAddr,segment); IF ProgramedFlag(Blck)(BlockPage) (segment)='0' THEN CashBuffData(WrAddr) := Data; END IF; SegForProg(segment) <= '1'; Page_pom := BlockPage; WrAddr <= WrAddr+1; IF WrAddr = ssam(1)-1 THEN WrAddr <= ssas(0); ELSIF WrAddr = ssas(1)-1 THEN WrAddr <= ssam(1); ELSIF WrAddr = ssam(2)-1 THEN WrAddr <= ssas(1); ELSIF WrAddr = ssas(2)-1 THEN WrAddr <= ssam(2); ELSIF WrAddr = ssam(3)-1 THEN WrAddr <= ssas(2); ELSIF WrAddr = ssas(3)-1 THEN WrAddr <= ssam(3); ELSIF WrAddr = ssas(0)-1 THEN WrAddr <= ssas(3); END IF; ELSIF CLE='1' AND ALE='0' AND Data=16#10# THEN IF PRG_ACT = '0' THEN WrPage <= Page; END IF; R_zd <= '0'; Status(6) := '0'; ELSIF ALE='1' THEN cnt_addr := cnt_addr + 1; END IF; END IF; WHEN PGMS_CAC => IF falling_edge(write) THEN IF ALE='1' THEN cnt_addr := 0; WrAddr <= AddrCom; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_PRG_CAC => IF falling_edge(write) THEN IF ALE='1' THEN WrAddr <= (AddrCom * 16#100#)+WrAddr; cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN PGMS => IF WPNeg /= '0' THEN WrBuffData <= CashBuffData; FOR i IN 0 TO PageSize LOOP getSegment(i,segment); IF ProgramedFlag(WrPage/(BlockSize+1))( WrPage mod(BlockSize+1))(segment) = '0' AND CashBuffData(i) /= -1 AND BadBlockTable(WrPage/(BlockSize+1)) = '0' THEN Mem(WrPage)(i):= -1; END IF; END LOOP; END IF; IF rising_edge(PROG_out) THEN R_zd <= '1'; PGD_ACT <= '0'; END IF; IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN STAT_ACT <= '1'; -- read status ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN PREL_ERS => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := 0; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; END IF; END IF; WHEN A1_ERS => IF falling_edge(write) THEN IF ALE='1' THEN Page := Page + (AddrCom * 16#100#); WrPage <= Page; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data = 16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_ERS => IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#D0# THEN Blck := Page / (BlockSize + 1); BlockAddr <= Blck; IF WPNeg /= '0' AND BadBlockTable(Blck) = '0' THEN FOR i IN Blck*(BlockSize+1) TO (Blck*(BlockSize+1)) + BlockSize LOOP Mem(i) := (OTHERS => -1); END LOOP; ProgramedFlag(Blck) := (OTHERS =>(OTHERS => '0')); END IF; BERS_in <= '1'; ERS_ACT <= '1'; R_zd <= '0'; Status(6) := '0'; ELSIF ALE = '1' THEN cnt_addr := cnt_addr + 1; END IF; END IF; WHEN BERS_EXEC => IF BERS_out = '1' THEN IF WPNeg /= '0' AND BadBlockTable(Blck) = '0' THEN FOR i IN Blck * (BlockSize+1) TO (Blck*(BlockSize+1)) + BlockSize LOOP Mem(i) := (OTHERS => MaxData); END LOOP; END IF; IF BadBlockTable(Blck) = '1' THEN Status(0) := '1'; ELSE Status(0) := '0'; END IF; BERS_in <= '0'; ERS_ACT <= '0'; R_zd <= '1'; Status(6) := '1'; END IF; IF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# THEN BERS_in <= '0'; RSTSTART <= '1','0' AFTER 1 ns; R_zd <= '0'; STAT_ACT <= '0'; ELSIF CLE='1' AND ALE='0' AND Data=16#70# THEN STAT_ACT <= '1'; ELSIF CLE = '1' AND STAT_ACT = '1' THEN STAT_ACT <= '0'; END IF; END IF; IF oe THEN IF STAT_ACT = '1' THEN Read_Status; END IF; END IF; WHEN PGD_PREL => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := AddrCom; cnt_addr := 0; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A0_PGD => IF falling_edge(write) THEN IF ALE='1' THEN Pom_Address := (AddrCom* 16#100#) + Pom_Address; WrAddr <= Pom_Address; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A1_PGD => IF falling_edge(write) THEN IF ALE='1' THEN Page := AddrCom; cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN A2_PGD => IF falling_edge(write) THEN IF ALE='1' THEN Page := (AddrCom* 16#100#) + Page; Blck := Page / (BlockSize+1); BlockPage := Page MOD (BlockSize + 1); cnt_addr := cnt_addr+1; ELSIF CLE='1' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; WHEN CONF_PGD => IF falling_edge(write) THEN IF CLE = '1' AND ALE = '0' AND (Data = 16#10# OR Data = 16#85#) THEN CashBuffData := PDBuffer; SegForProg <= (OTHERS => '1'); WrPage <= Page; IF CLE = '1' AND ALE = '0' AND Data = 16#10# THEN R_zd <= '0'; Status(6) := '0'; END IF; ELSIF ALE = '1' THEN cnt_addr := cnt_addr + 1; ELSIF CLE='1' AND ALE='0' AND Data=16#FF# THEN STAT_ACT <= '0'; RSTSTART <= '1', '0' AFTER 1 ns; R_zd <= '0'; END IF; END IF; END CASE; END IF; IF RENeg = '1' OR CENeg='1' THEN DOut_zd <= (others => 'Z'); END IF; IF (TR_out='1' OR PROG_out='1' ) AND (read='1' AND STAT_ACT='1') THEN Read_Status; END IF; END PROCESS Functional; --------------------------------------------------------------------------- -- Flag Generation Process --------------------------------------------------------------------------- FlagGeneration: PROCESS (write, PROG_out,Data, current_state, PROG_out, RSTDONE, CLE, PRG_ACT ) IS BEGIN -- PROCESS FlagGeneration IF falling_edge(write) THEN IF (current_state = DATA_PRG OR current_state = CONF_PGD) AND CLE='1' AND ALE='0' AND Data = 16#10# THEN IF PRG_ACT = '0' THEN PRG_ACT <= '1'; PROG_in <= '1'; END IF; END IF; END IF; IF current_state = PGMS THEN IF rising_edge(PROG_out) THEN PRG_ACT <= '0'; Status(6) := '1'; PROG_in <= '0'; IF WPNeg/='0' AND BadBlockTable(WrPage/(BlockSize+1)) = '0' THEN FOR j IN 0 TO PageSize LOOP getSegment(j,pom_seg); IF WrBuffData(j) /= -1 AND ProgramedFlag(WrPage/(BlockSize+1))(WrPage MOD (BlockSize+1))(pom_seg)= '0' THEN Mem(WrPage)(j):= WrBuffData(j); END IF; END LOOP; ProgramedFlag(WrPage/(BlockSize+1)) (WrPage MOD (BlockSize+1)) := SegForProg; END IF; ELSIF falling_edge(write) THEN IF CLE='1' AND ALE='0' AND Data=16#FF# AND PRG_ACT='1' THEN PROG_in <= '0'; END IF; END IF; ELSIF current_state = RESET THEN IF rising_edge(RSTDONE) THEN PRG_ACT <= '0'; END IF; END IF; END PROCESS FlagGeneration; Normal_Prog: PROCESS (PROG_in) IS BEGIN IF rising_edge(PROG_in) THEN IF Long_Timming THEN PROG_out <= '1' AFTER tdevice_PROG + tpd_WENeg_RY(tr10); ELSE PROG_out <= '1' AFTER (tdevice_PROG + tpd_WENeg_RY(tr10))/100; END IF; ELSIF falling_edge (PROG_in) THEN PROG_out <= '0'; END IF; END PROCESS Normal_Prog; Normal_Erase: PROCESS (BERS_in) IS BEGIN IF rising_edge(BERS_in) THEN IF Long_Timming THEN BERS_out <= '1' AFTER tdevice_BERASE + tpd_WENeg_RY(tr10); ELSE BERS_out <= '1' AFTER (tdevice_BERASE + tpd_WENeg_RY(tr10))/160; END IF; ELSIF falling_edge (BERS_in) THEN BERS_out <= '0'; END IF; END PROCESS Normal_Erase; TR: PROCESS (TR_in) IS BEGIN IF rising_edge(TR_in) THEN IF (Long_Timming = TRUE) THEN TR_out <= '0','1' AFTER tdevice_TR + tpd_WENeg_RY(tr10); ELSE TR_out <= '0','1' AFTER (tdevice_TR + tpd_WENeg_RY(tr10))/5; END IF; ELSE TR_out <= '0'; END IF; END PROCESS TR; IDPreload: PROCESS (PoweredUp) IS BEGIN -- PROCESS IDPreload IF PoweredUp='1' THEN IDArray(0) := 16#01#; IDArray(1) := 16#2C#; IDArray(2) := 16#04#; IDArray(3) := 16#D5#; END IF; END PROCESS IDPreload; InvalidBlockControl: PROCESS FILE invblocks_file : text is invblocks_file_name; VARIABLE buf : line; VARIABLE ind : natural; VARIABLE inv : natural; VARIABLE pind : natural; BEGIN ProgramedFlag := (OTHERS => (OTHERS => (OTHERS => '0'))); Mem := ( OTHERS => (OTHERS => MaxData)); BadBlockTable := (OTHERS => '0'); IF invblocks_file_name /= "none" AND UserPreload THEN ind := 0; inv := 0; WHILE (NOT ENDFILE (invblocks_file)) LOOP READLINE(invblocks_file, buf); IF buf(1)='/' THEN next; ELSIF buf(1) = '@' THEN ind := h(buf(2 TO 4)); ELSE IF ind <= BlockNum AND ind > 0 THEN IF h(buf(1 TO 1)) = 1 THEN BadBlockTable(ind) := '1'; pind := (ind*(BlockSize+1)); Mem(pind) := (OTHERS => InvalidData); Mem(pind+1) := (OTHERS => InvalidData); ProgramedFlag(ind) := (OTHERS => (OTHERS => '1')); END IF; inv := inv +1; IF inv > InvBlocksNum THEN REPORT "Number of invalid blocks exceeds range"; END IF; ind := ind +1; ELSE REPORT "Invalid Block address out of range"; END IF; END IF; END LOOP; END IF; WAIT; END PROCESS InvalidBlockControl; -- purpose: Memory preload process MemPreload: PROCESS (PoweredUp) -- text file input variable FILE mem_file : text IS mem_file_name; VARIABLE buf : line; VARIABLE i : natural; VARIABLE ind : natural; VARIABLE pind : natural; VARIABLE index : natural; VARIABLE p_data : NATURAL; BEGIN -- PROCESS MemPreload IF PoweredUp='1' THEN ------------------------------------------------------------------- -- Memory preload file format for s19mn-p -------------------------------------------------------------------- -- / - comment -- @aaaaaaa - stands for page address and address within -- first 1056 words of the page -- dd -
is byte to be written at Mem(Page)(offset++) -- page is div 1056 -- offset is mod 1056 -- offset is incremented on every write ------------------------------------------------------------------- IF mem_file_name /= "none" AND UserPreload THEN ind := 0; WHILE (NOT ENDFILE (mem_file)) LOOP READLINE(mem_file,buf); IF buf(1)='/' THEN next; ELSIF buf(1) = '@' THEN ind := h(buf(2 TO 8)); ELSE p_data := h(buf(1 TO 4)); IF ind = 0 THEN pind := 0; index := 0; ELSIF ind <= PageSize THEN pind := 0; index := ind; ELSE pind := natural(ind/(PageSize+1)); index := ind - pind * (PageSize+1); END IF; IF pind <= PageNum AND index <= PageSize THEN IF p_data /= 16#FFFF# AND BadBlockTable(pind/(BlockSize+1)) = '0' THEN Mem(pind)(index) := h(buf(1 TO 4)); getSegment(index,segment); ProgramedFlag(pind/(BlockSize+1))( pind MOD (BlockSize+1))(segment) := '1'; ind := ind + 1; END IF; ELSE REPORT "Memory address out of range"; END IF; END IF; END LOOP; END IF; END IF; END PROCESS MemPreload; RPassTrough: PROCESS (R_zd) IS BEGIN -- PROCESS RPassTrough IF R_zd = '0' THEN R_Pass <= '0'; ELSE R_Pass <= 'Z'; END IF; END PROCESS RPassTrough; ------------------------------------------------------------------------ -- Path delay section ------------------------------------------------------------------------ PROCESS (R_Pass) VARIABLE R_GlitchData : VitalGlitchDataType; BEGIN -- PROCESS VitalPathDelay01( OutSignal => R, OutSignalName => "R", OutTemp => R_Pass, GlitchData => R_GlitchData, Mode => VitalTransport, Paths => ( 0 =>(InputChangeTime => WENeg'LAST_EVENT, PathDelay => tpd_WENeg_RY, PathCondition => true) ) ); END PROCESS; D_Out_Path_Gen : FOR i IN 0 TO 15 GENERATE BEGIN -- GENERATE D_Out_Path_Gen PROCESS (DOut_zd(i)) VARIABLE D0_GlitchData : VitalGlitchDataType; BEGIN -- PROCESS VitalPathDelay01Z( OutSignal => DOut(i), OutSignalName => "DOut", OutTemp => DOut_zd(i), GlitchData => D0_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => RENeg'LAST_EVENT, PathDelay => tpd_RENeg_IO0, PathCondition => true), 1 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_IO0, PathCondition => true) ) ); END PROCESS; END GENERATE D_Out_Path_Gen; END BLOCK Behavior; END ARCHITECTURE vhdl_behavioral_static_memory_allocation;