------------------------------------------------------------------------------- -- File Name: xc18v04.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.Stanojkovic 07 Oct 10 Inital Release -- ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: RAM -- Technology: CMOS -- Part: XC18V04 -- -- Description: 4 Mbits In-System Programmable Configuration 3.3V PROM ------------------------------------------------------------------------------- -- 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 xc18v04 IS GENERIC ( -- tipd delays: interconnect path delays tipd_CLK : VitalDelayType01 := VitalZeroDelay01; tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; tipd_TMS : VitalDelayType01 := VitalZeroDelay01; tipd_TCK : VitalDelayType01 := VitalZeroDelay01; tipd_TDI : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_RESETNeg_D0 : VitalDelayType01Z := UnitDelay01Z; -- tOE, tDF tpd_CENeg_D0 : VitalDelayType01Z := UnitDelay01Z; -- tCE, tDF tpd_CLK_D0 : VitalDelayType01 := UnitDelay01; -- tCAC tpd_RESETNeg_CEONeg : VitalDelayType01Z := UnitDelay01Z; tpd_CENeg_CEONeg : VitalDelayType01Z := UnitDelay01Z; tpd_CLK_CEONeg : VitalDelayType01 := UnitDelay01; tpd_TCK_RESETNeg : VitalDelayType01 := UnitDelay01; tpd_TCK_CFNeg : VitalDelayType01Z := UnitDelay01Z; tpd_TCK_TDO : VitalDelayType01Z := UnitDelay01Z; -- tDOV -- tsetup values: setup times tsetup_CENeg_CLK : VitalDelayType := UnitDelay; -- tSCE tsetup_TMS_TCK : VitalDelayType := UnitDelay; -- tMSS tsetup_TDI_TCK : VitalDelayType := UnitDelay; -- tDIS -- thold values: hold times thold_TMS_TCK : VitalDelayType := UnitDelay; -- tMSH thold_TDI_TCK : VitalDelayType := UnitDelay; -- tDIH -- tpw values: pulse widths tpw_CLK_posedge : VitalDelayType := UnitDelay; -- tHC tpw_CLK_negedge : VitalDelayType := UnitDelay; -- tLC tpw_CENeg_posedge : VitalDelayType := UnitDelay; -- tHCE tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; -- tHOE -- tperiod min tperiod_CLK : VitalDelayType := UnitDelay; -- tCYC tperiod_TCK_BYPSS_EQ_0 : VitalDelayType := UnitDelay; -- tCKMIN1 tperiod_TCK_BYPSS_EQ_1 : VitalDelayType := UnitDelay; -- tCKMIN2 --tdevice values: values for internal delays -- Power-up tdevice_VCC : VitalDelayType := 50 ms; --tVCC -- Power-on Reset tdevice_OER : VitalDelayType := 1 ms; --tOER -- In-System Programming tdevice_ISP : VitalDelayType := 14 ms; --tISP -- Erase all sectors tdevice_ERS : VitalDelayType := 15000 ms; --tERS -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- memory file to be loaded LongTiming : BOOLEAN := TRUE; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( -- inputs CLK : IN std_ulogic := 'U'; RESETNeg : INOUT std_ulogic := 'U'; CENeg : IN std_ulogic := 'U'; TCK : IN std_ulogic := 'U'; TMS : IN std_ulogic := 'U'; TDI : IN std_ulogic := 'U'; -- outputs D0 : OUT std_ulogic := 'U'; D1 : OUT std_ulogic := 'U'; D2 : OUT std_ulogic := 'U'; D3 : OUT std_ulogic := 'U'; D4 : OUT std_ulogic := 'U'; D5 : OUT std_ulogic := 'U'; D6 : OUT std_ulogic := 'U'; D7 : OUT std_ulogic := 'U'; CFNeg : OUT std_ulogic := 'U'; CEONeg : OUT std_ulogic := 'U'; TDO : OUT std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of xc18v04 : ENTITY IS TRUE; END xc18v04; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of xc18v04 IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT partID : STRING := "xc18v04"; CONSTANT HiAddrBit : NATURAL := 18; CONSTANT MaxData : NATURAL := 16#FF#; CONSTANT DataSize : NATURAL := 7; CONSTANT DeviceID : NATURAL := 16#05026093#; CONSTANT UserID1 : NATURAL := 16#FFFF#; CONSTANT UserID2 : NATURAL := 16#FFFF#; CONSTANT PageSize : NATURAL := 15; CONSTANT PageNum : NATURAL := 31; CONSTANT RowSize : NATURAL := (PageNum+1)*(PageSize+1)-1; CONSTANT RowNum : NATURAL := 1023; CONSTANT AddrRange : NATURAL := (RowNum+1)*(PageNum+1); --8000 CONSTANT MemSize : NATURAL := (RowNum+1)*(RowSize+1)-1; -- interconnect path delay signals SIGNAL CLK_ipd : std_ulogic := 'U'; SIGNAL RESETNeg_ipd : std_ulogic := 'U'; SIGNAL CENeg_ipd : std_ulogic := 'U'; SIGNAL TCK_ipd : std_ulogic := 'U'; SIGNAL TMS_ipd : std_ulogic := 'U'; SIGNAL TDI_ipd : std_ulogic := 'U'; -- nwv SIGNAL CLK_nwv : std_ulogic := 'U'; SIGNAL RESETNeg_nwv : std_logic := 'U'; SIGNAL CENeg_nwv : std_ulogic := 'U'; SIGNAL TCK_nwv : std_ulogic := 'U'; SIGNAL TMS_nwv : std_ulogic := 'U'; SIGNAL TDI_nwv : std_ulogic := 'U'; -- internal delays SIGNAL tVCC_in : std_ulogic := '0'; SIGNAL tVCC_out : std_ulogic := '0'; SIGNAL tOER_in : std_ulogic := '0'; SIGNAL tOER_out : std_ulogic := '0'; SIGNAL tISP_in : std_ulogic := '0'; SIGNAL tISP_out : std_ulogic := '0'; SIGNAL tERS_in : std_ulogic := '0'; SIGNAL tERS_out : std_ulogic := '0'; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays VCC :VitalBuf(tVCC_out, tVCC_in, (tdevice_VCC ,UnitDelay)); OER :VitalBuf(tOER_out, tOER_in, (tdevice_OER ,UnitDelay)); ISP :VitalBuf(tISP_out, tISP_in, (tdevice_ISP ,UnitDelay)); ERS :VitalBuf(tERS_out, tERS_in, (tdevice_ERS ,UnitDelay)); --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (CLK_ipd, CLK, tipd_CLK); w_2 : VitalWireDelay (RESETNeg_ipd, RESETNeg, tipd_RESETNeg); w_3 : VitalWireDelay (CENeg_ipd, CENeg, tipd_CENeg); w_4 : VitalWireDelay (TCK_ipd, TCK, tipd_TCK); w_5 : VitalWireDelay (TMS_ipd, TMS, tipd_TMS); w_6 : VitalWireDelay (TDI_ipd, TDI, tipd_TDI); END BLOCK; CLK_nwv <= To_UX01(CLK_ipd ); RESETNeg_nwv <= To_UX01(RESETNeg_ipd ); CENeg_nwv <= To_UX01(CENeg_ipd ); TCK_nwv <= To_UX01(TCK_ipd ); TMS_nwv <= To_UX01(TMS_ipd ); TDI_nwv <= To_UX01(TDI_ipd ); --------------------------------------------------------------------------- -- Main Behavior Block --------------------------------------------------------------------------- Behavior: BLOCK PORT ( Clock : IN std_logic; RESETIn : IN std_logic; RESETOut : OUT std_logic; CENeg : IN std_logic; TCK : IN std_logic; TMS : IN std_logic; TDI : IN std_logic; Data : OUT std_logic_vector(7 downto 0); CFNeg : OUT std_logic; CEONeg : OUT std_logic; TDO : OUT std_logic ); PORT MAP ( Clock => CLK_nwv , RESETIn => RESETNeg_nwv , CENeg => CENeg_nwv, TCK => TCK_nwv , TMS => TMS_nwv , TDI => TDI_nwv , RESETOut=> RESETNeg, Data(0) => D0 , Data(1) => D1 , Data(2) => D2 , Data(3) => D3 , Data(4) => D4 , Data(5) => D5 , Data(6) => D6 , Data(7) => D7 , CFNeg => CFNeg , CEONeg => CEONeg , TDO => TDO ); -- State Machine : State_Type TYPE state_type IS ( IDLE, ISP_MODE, ERASE, PROG_PREL, PROG ); -- JTAG Instructions TYPE Instruction IS ( bypass, sample_preload, extest, clamp, highz, idcode, usercode, config, ispen, ferase, fpgm, ispex, faddr, fdata0, fdata3 ); --zero delay signals SIGNAL Data_zd : std_logic_vector(7 DOWNTO 0) := (OTHERS => 'Z'); SIGNAL CEONeg_zd : std_logic := 'Z'; SIGNAL RESETNeg_zd : std_logic := 'Z'; SIGNAL CFNeg_zd : std_logic := 'Z'; SIGNAL TDO_zd : std_logic := 'Z'; -- timing check violation SIGNAL Viol : X01 := '0'; TYPE WByteType IS ARRAY (0 TO RowSize) OF INTEGER RANGE -1 TO MaxData; --memory definition TYPE MemArray IS ARRAY (0 TO MemSize) OF INTEGER RANGE -1 TO MaxData; SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); SHARED VARIABLE ConfMode : std_logic_vector(2 downto 0) := (OTHERS => '1'); SIGNAL WByte : WByteType := (OTHERS => 0); SIGNAL Instruct : Instruction := idcode; SIGNAL BSReg : std_logic_vector(24 downto 0) := "1101101110111011111111110"; SIGNAL ConfReg : std_logic_vector(2 downto 0) := (OTHERS => '1'); -- states SIGNAL current_state : state_type := IDLE; SIGNAL next_state : state_type := IDLE; --Command Register SIGNAL read_out : std_logic := '0'; -- ISP enable signal SIGNAL ISP : boolean := FALSE; -- BYPASS enable signal SIGNAL BYPSS : std_logic := '0'; SIGNAL change_addr : std_logic := '0'; SIGNAL Address : NATURAL RANGE 0 TO AddrRange := 0; -- powerup SIGNAL PoweredUp : std_logic := '0'; SIGNAL PoweredOn : std_logic := '0'; --FSM control signals SIGNAL PDONE : std_logic := '0'; --Programming Done SIGNAL PSTART : std_logic := '0'; --Start Programming SIGNAL EDONE : std_logic := '0'; --Erase Done SIGNAL ESTART : std_logic := '0'; --Start Erase SIGNAL ChipErased : BOOLEAN := FALSE; SIGNAL ProgStart : BOOLEAN := FALSE; SIGNAL Parallel : BOOLEAN := FALSE; SIGNAL ReadProt : BOOLEAN := FALSE; SIGNAL Configure : BOOLEAN := FALSE; PROCEDURE ADDRHILO_ROW( VARIABLE Addr : IN NATURAL RANGE 0 TO AddrRange-1; VARIABLE AddrLOW : OUT NATURAL RANGE 0 to MemSize; VARIABLE AddrHIGH : OUT NATURAL RANGE 0 to MemSize) IS VARIABLE row : NATURAL RANGE 0 TO RowNum; BEGIN row := Addr/(PageNum+1); AddrLOW := row*(PageNum+1)*(PageSize+1); AddrHIGH := (row+1)*(PageNum+1)*(PageSize+1)-1; END ADDRHILO_ROW; BEGIN --------------------------------------------------------------------------- --Power Up time --------------------------------------------------------------------------- PoweredUp <= '1' AFTER tdevice_VCC; --------------------------------------------------------------------------- --Power On time --------------------------------------------------------------------------- PowerOnReset: PROCESS (PoweredUp) BEGIN IF PoweredUp = '1' THEN PoweredOn <= '1' AFTER tdevice_OER; ELSE PoweredOn <= '0'; END IF; END PROCESS PowerOnReset; --------------------------------------------------------------------------- -- VITAL Timing Checks Procedures --------------------------------------------------------------------------- VITALTimingCheck: PROCESS(Clock, RESETIn, CENeg, TCK, TMS, TDI) -- Timing Check Variables VARIABLE TD_CENeg_CLK : VitalTimingDataType; VARIABLE Tviol_CENeg_CLK : X01 := '0'; VARIABLE TD_RESETNeg_CENeg : VitalTimingDataType; VARIABLE Tviol_RESETNeg_CENeg : X01 := '0'; VARIABLE TD_TMS_TCK : VitalTimingDataType; VARIABLE Tviol_TMS_TCK : X01 := '0'; VARIABLE TD_TDI_TCK : VitalTimingDataType; VARIABLE Tviol_TDI_TCK : X01 := '0'; VARIABLE PD_CLK : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CLK : X01 := '0'; VARIABLE PD_CENeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_CENeg : X01 := '0'; VARIABLE PD_RESETNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_RESETNeg : X01 := '0'; VARIABLE PD_TCK : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_TCK : X01 := '0'; VARIABLE PD_TCK_BYPSS : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_TCK_BYPSS : X01 := '0'; VARIABLE Violation : X01 := '0'; BEGIN --------------------------------------------------------------------------- -- Timing Check Section --------------------------------------------------------------------------- IF TimingChecksOn THEN VitalSetupHoldCheck ( TestSignal => CENeg, TestSignalName => "CENeg", RefSignal => Clock, RefSignalName => "Clock", SetupHigh => tsetup_CENeg_CLK, SetupLow => tsetup_CENeg_CLK, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_CENeg_CLK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_CENeg_CLK ); VitalSetupHoldCheck ( TestSignal => TMS, TestSignalName => "TMS", RefSignal => TCK, RefSignalName => "TCK", SetupHigh => tsetup_TMS_TCK, SetupLow => tsetup_TMS_TCK, HoldHigh => thold_TMS_TCK, HoldLow => thold_TMS_TCK, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_TMS_TCK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_TMS_TCK ); VitalSetupHoldCheck ( TestSignal => TDI, TestSignalName => "TDI", RefSignal => TCK, RefSignalName => "TCK", SetupHigh => tsetup_TDI_TCK, SetupLow => tsetup_TDI_TCK, HoldHigh => thold_TDI_TCK, HoldLow => thold_TDI_TCK, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & PartID, TimingData => TD_TDI_TCK, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_TDI_TCK ); VitalPeriodPulseCheck ( TestSignal => Clock, TestSignalName => "Clock", Period => tperiod_CLK, PulseWidthLow => tpw_CLK_negedge, PulseWidthHigh => tpw_CLK_posedge, PeriodData => PD_CLK, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CLK, HeaderMsg => InstancePath & PartID, CheckEnabled => CENeg='0' AND RESETIn = '1'); VitalPeriodPulseCheck ( TestSignal => CENeg, TestSignalName => "CENeg", PulseWidthHigh => tpw_CENeg_posedge, PeriodData => PD_CENeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_CENeg, HeaderMsg => InstancePath & PartID, CheckEnabled => true); VitalPeriodPulseCheck ( TestSignal => RESETIn, TestSignalName => "OE/RESETNeg", PulseWidthHigh => tpw_RESETNeg_negedge, PeriodData => PD_RESETNeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_RESETNeg, HeaderMsg => InstancePath & PartID, CheckEnabled => true); VitalPeriodPulseCheck ( TestSignal => TCK, TestSignalName => "JTAG Clock", Period => tperiod_TCK_BYPSS_EQ_0, PeriodData => PD_TCK, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_TCK, HeaderMsg => InstancePath & PartID, CheckEnabled => BYPSS = '0' ); VitalPeriodPulseCheck ( TestSignal => TCK, TestSignalName => "JTAG Clock", Period => tperiod_TCK_BYPSS_EQ_1, PeriodData => PD_TCK_BYPSS, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_TCK_BYPSS, HeaderMsg => InstancePath & PartID, CheckEnabled => BYPSS = '1' ); Violation := Tviol_CENeg_CLK OR Tviol_RESETNeg_CENeg OR Tviol_TMS_TCK OR Tviol_TDI_TCK OR Pviol_CLK OR Pviol_CENeg OR Pviol_RESETNeg OR Pviol_TCK OR Pviol_TCK_BYPSS; Viol <= Violation; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY WARNING; END IF; END PROCESS VITALTimingCheck; --------------------------------------------------------------------------- -- JTAG --------------------------------------------------------------------------- JTAG : PROCESS (TDI, TMS, TCK, PoweredOn) TYPE tap_state_type IS (Test_Logic_Reset, Run_Test_Idle, Select_DR_Scan, Capture_DR, Shift_DR, Exit1_DR, Pause_DR, Exit2_DR, Update_DR, Select_IR_Scan, Capture_IR, Shift_IR, Exit1_IR, Pause_IR, Exit2_IR, Update_IR ); VARIABLE TAP_state : tap_state_type; VARIABLE BYReg : std_logic := '0'; VARIABLE BYTmp : std_logic; VARIABLE IReg : std_logic_vector(7 downto 0); VARIABLE ITmp : std_logic_vector(7 downto 0); VARIABLE Data0Reg : std_logic_vector(4095 downto 0) := (OTHERS => '1'); VARIABLE Data0Tmp : std_logic_vector(4095 downto 0); VARIABLE IDReg : std_logic_vector(31 downto 0); VARIABLE IDTmp : std_logic_vector(31 downto 0); VARIABLE AddrReg : NATURAL RANGE 0 TO AddrRange := 0; VARIABLE AddrTmp : std_logic_vector(15 downto 0); VARIABLE ConfTmp : std_logic_vector(2 downto 0); VARIABLE USEReg1 : std_logic_vector(15 downto 0) := (OTHERS => '1'); VARIABLE USEReg2 : std_logic_vector(15 downto 0) := (OTHERS => '1'); VARIABLE USETmp : std_logic_vector(31 downto 0); VARIABLE BSTmp : std_logic_vector(24 downto 0) := (others => '1'); VARIABLE Byte_slv : std_logic_vector(7 downto 0); VARIABLE TDOTmp : std_logic; VARIABLE Shift : BOOLEAN := false; VARIABLE UpdateIR : BOOLEAN := false; VARIABLE UpdateDR : BOOLEAN := false; BEGIN ---------------------------------------------------------------------------- -- Functional Section ---------------------------------------------------------------------------- -- Power Up & Reset JTAG IF rising_edge(PoweredOn) THEN TAP_state := Test_Logic_Reset; Shift := false; UpdateIR := false; UpdateDR := false; Instruct <= idcode; IReg := "11111110"; IDReg := to_slv(DeviceID,32); USEReg1 := to_slv(UserID1,16); USEReg2 := to_slv(UserID2,16); END IF; -- TAP State Machine IF rising_edge(TCK) THEN CASE TAP_state IS WHEN Test_Logic_Reset => IF TMS = '1' THEN TAP_state := Test_Logic_Reset; IReg := "11111110"; IDReg := to_slv(DeviceID,32); Instruct <= idcode; ELSE TAP_state := Run_Test_Idle; END IF; WHEN Run_Test_Idle => IF TMS = '1' THEN TAP_state := Select_DR_Scan; ELSE TAP_state := Run_Test_Idle; END IF; WHEN Select_DR_Scan => IF TMS = '1' THEN TAP_state := Select_IR_Scan; ELSE TAP_state := Capture_DR; CASE Instruct IS WHEN bypass => BYTmp := BYReg; WHEN sample_preload => BSTmp := BSReg; BSTmp(20) := RESETIn; BSTmp(15) := CENeg; BSTmp(0 ) := Clock; BSReg <= BSTmp; WHEN extest => BSTmp := BSReg; BSTmp(20) := RESETIn; BSTmp(15) := CENeg; BSTmp(0 ) := Clock; BSReg <= BSTmp; WHEN clamp => BYTmp := BYReg; WHEN highz => BYTmp := BYReg; WHEN idcode => IDTmp := IDReg; WHEN usercode => USETmp(15 downto 0) := USEReg1; USETmp(31 downto 16) := USEReg2; WHEN faddr => AddrTmp := to_slv(AddrReg, 16); WHEN fdata0 => Data0Tmp := Data0Reg; WHEN fdata3 => ConfTmp := ConfReg; WHEN others => NULL; END CASE; END IF; WHEN Capture_DR => IF TMS = '1' THEN TAP_state := Exit1_DR; Shift := false; ELSE TAP_state := Shift_DR; CASE Instruct IS WHEN bypass => TDOTmp := BYTmp; BYTmp := TDI; Shift := true; WHEN sample_preload => TDOTmp := BSTmp(24); FOR I IN 24 DOWNTO 1 LOOP BSTmp(i) := BSTmp(i-1); END LOOP; BSTmp(0) := TDI; Shift := true; WHEN extest => TDOTmp := BSTmp(24); FOR I IN 24 DOWNTO 1 LOOP BSTmp(i) := BSTmp(i-1); END LOOP; BSTmp(0) := TDI; Shift := true; WHEN clamp => TDOTmp := BYTmp; BYTmp := TDI; Shift := true; WHEN highz => TDOTmp := BYTmp; BYTmp := TDI; Shift := true; WHEN idcode => TDOTmp := IDTmp(0); FOR I IN 0 TO 30 LOOP IDTmp(i) := IDTmp(i+1); END LOOP; IDTmp(31) := TDI; Shift := true; WHEN usercode => TDOTmp := USETmp(0); FOR I IN 0 TO 30 LOOP USETmp(i) := USETmp(i+1); END LOOP; USETmp(31) := TDI; Shift := true; WHEN faddr => TDOTmp := AddrTmp(0); FOR I IN 0 TO 14 LOOP AddrTmp(i) := AddrTmp(i+1); END LOOP; AddrTmp(15) := TDI; Shift := true; WHEN fdata0 => TDOTmp := Data0Tmp(0); FOR I IN 0 TO 4094 LOOP Data0Tmp(i) := Data0Tmp(i+1); END LOOP; Data0Tmp(4095) := TDI; Shift := true; WHEN fdata3 => TDOTmp := ConfTmp(0); FOR I IN 0 TO 1 LOOP ConfTmp(i) := ConfTmp(i+1); END LOOP; ConfTmp(2) := TDI; Shift := true; WHEN others => NULL; END CASE; END IF; WHEN Shift_DR => IF TMS = '1' THEN TAP_state := Exit1_DR; Shift := false; ELSE TAP_state := Shift_DR; CASE Instruct IS WHEN bypass => TDOTmp := BYTmp; BYTmp := TDI; Shift := true; WHEN sample_preload => TDOTmp := BSTmp(24); FOR I IN 24 DOWNTO 1 LOOP BSTmp(i) := BSTmp(i-1); END LOOP; BSTmp(0) := TDI; Shift := true; WHEN extest => TDOTmp := BSTmp(24); FOR I IN 24 DOWNTO 1 LOOP BSTmp(i) := BSTmp(i-1); END LOOP; BSTmp(0) := TDI; Shift := true; WHEN clamp => TDOTmp := BYTmp; BYTmp := TDI; Shift := true; WHEN highz => TDOTmp := BYTmp; BYTmp := TDI; Shift := true; WHEN idcode => TDOTmp := IDTmp(0); FOR I IN 0 TO 30 LOOP IDTmp(i) := IDTmp(i+1); END LOOP; IDTmp(31) := TDI; Shift := true; WHEN usercode => TDOTmp := USETmp(0); FOR I IN 0 TO 30 LOOP USETmp(i) := USETmp(i+1); END LOOP; USETmp(31) := TDI; Shift := true; WHEN faddr => TDOTmp := AddrTmp(0); FOR I IN 0 TO 14 LOOP AddrTmp(i) := AddrTmp(i+1); END LOOP; AddrTmp(15) := TDI; Shift := true; WHEN fdata0 => TDOTmp := Data0Tmp(0); FOR I IN 0 TO 4094 LOOP Data0Tmp(i) := Data0Tmp(i+1); END LOOP; Data0Tmp(4095) := TDI; Shift := true; WHEN fdata3 => TDOTmp := ConfTmp(0); FOR I IN 0 TO 1 LOOP ConfTmp(i) := ConfTmp(i+1); END LOOP; ConfTmp(2) := TDI; Shift := true; WHEN others => NULL; END CASE; END IF; WHEN Exit1_DR => IF TMS = '1' THEN TAP_state := Update_DR; UpdateDR := true; ELSE TAP_state := Pause_DR; END IF; WHEN Pause_DR => IF TMS = '1' THEN TAP_state := Exit2_DR; ELSE TAP_state := Pause_DR; END IF; WHEN Exit2_DR => IF TMS = '1' THEN TAP_state := Update_DR; UpdateDR := true; ELSE TAP_state := Shift_DR; Shift := false; END IF; WHEN Update_DR => IF TMS = '1' THEN TAP_state := Select_DR_Scan; ELSE TAP_state := Run_Test_Idle; END IF; WHEN Select_IR_Scan => IF TMS = '1' THEN TAP_state := Test_Logic_Reset; IReg := "11111110"; IDReg := to_slv(DeviceID,32); Instruct <= idcode; ELSE TAP_state := Capture_IR; IF ISP AND ReadProt THEN ITmp := "00011001"; ELSIF ISP AND NOT ReadProt THEN ITmp := "00010001"; ELSE ITmp := "00000001"; END IF; TDO_zd <= 'Z'; END IF; WHEN Capture_IR => IF TMS = '1' THEN TAP_state := Exit1_IR; Shift := false; ELSE TAP_state := Shift_IR; TDOTmp := ITmp(0); FOR I IN 0 TO 6 LOOP ITmp(i) := ITmp(i+1); END LOOP; ITmp(7) := TDI; Shift := true; END IF; WHEN Shift_IR => IF TMS = '1' THEN TAP_state := Exit1_IR; Shift := false; ELSE TAP_state := Shift_IR; TDOTmp := ITmp(0); FOR I IN 0 TO 6 LOOP ITmp(i) := ITmp(i+1); END LOOP; ITmp(7) := TDI; Shift := true; END IF; WHEN Exit1_IR => IF TMS = '1' THEN TAP_state := Update_IR; UpdateIR := true; ELSE TAP_state := Pause_IR; END IF; WHEN Pause_IR => IF TMS = '1' THEN TAP_state := Exit2_IR; ELSE TAP_state := Pause_IR; END IF; WHEN Exit2_IR => IF TMS = '1' THEN TAP_state := Update_IR; UpdateIR := true; ELSE TAP_state := Shift_IR; Shift := false; END IF; WHEN Update_IR => IF TMS = '1' THEN TAP_state := Select_DR_Scan; ELSE TAP_state := Run_Test_Idle; END IF; END CASE; END IF; IF falling_edge(TCK) THEN IF Shift = true THEN TDO_zd <= TDOTmp; ELSIF UpdateIR = true THEN TDO_zd <= 'Z'; IReg:= ITmp; CASE IReg IS WHEN "11111111" => Instruct <= bypass; BYPSS <= '1'; WHEN "00000001" => Instruct <= sample_preload; BYPSS <= '0'; WHEN "00000000" => Instruct <= extest; BYPSS <= '0'; WHEN "11111010" => Instruct <= clamp; BYPSS <= '0'; WHEN "11111100" => Instruct <= highz; BYPSS <= '0'; WHEN "11111110" => Instruct <= idcode; BYPSS <= '0'; IDReg := to_slv(DeviceID,32); WHEN "11111101" => Instruct <= usercode; BYPSS <= '0'; WHEN "11101110" => Instruct <= config; BSReg(21) <= '0', '1' AFTER 400 ns; BYPSS <= '0'; WHEN "11101000" => Instruct <= ispen; ISP <= TRUE; BYPSS <= '0'; WHEN "11101100" => Instruct <= ferase; ConfReg <= (OTHERS => '1'); BYPSS <= '0'; WHEN "11101010" => Instruct <= fpgm; BYPSS <= '0'; WHEN "11101001" => Instruct <= ispex; ISP <= FALSE; BYPSS <= '0'; WHEN "11101011" => Instruct <= faddr; BYPSS <= '0'; WHEN "11101101" => Instruct <= fdata0; BYPSS <= '0'; WHEN "11110011" => Instruct <= fdata3; BYPSS <= '0'; WHEN others => NULL; END CASE; UpdateIR := false; ELSIF UpdateDR = true THEN TDO_zd <= 'Z'; UpdateDR := false; CASE Instruct IS WHEN bypass => BYReg := BYTmp; WHEN sample_preload => BSReg <= BSTmp; WHEN extest => BSReg <= BSTmp; WHEN clamp => BYReg := BYTmp; WHEN highz => BYReg := BYTmp; WHEN idcode => IDReg := IDTmp; WHEN usercode => USEReg1 := USETmp(15 downto 0); USEReg2 := USETmp(31 downto 16); WHEN faddr => AddrReg := to_nat(AddrTmp); Address <= AddrReg; change_addr <= '1','0' AFTER 1 ns; WHEN fdata0 => Data0Reg := Data0Tmp; FOR I IN 0 TO RowSize LOOP FOR J IN 7 DOWNTO 0 LOOP Byte_slv(j) := Data0Reg((i*8) + (7-j)); END LOOP; WByte(i) <= to_nat(Byte_slv); END LOOP; WHEN fdata3 => ConfReg <= ConfTmp; WHEN others => NULL; END CASE; ELSE TDO_zd <= 'Z'; END IF; END IF; END PROCESS JTAG; ---------------------------------------------------------------------------- -- sequential process for FSM state transition ---------------------------------------------------------------------------- StateTransition : PROCESS(next_state) BEGIN IF RESETIn = '0' THEN current_state <= next_state; ELSE current_state <= IDLE; END IF; END PROCESS StateTransition; --------------------------------------------------------------------------- -- Timing control for Program All Addresses --------------------------------------------------------------------------- ProgTime : PROCESS(PSTART) BEGIN IF PSTART = '0' THEN PDONE <= '0'; ELSE IF LongTiming THEN PDONE <= '1' AFTER (tdevice_ISP - 1 ns); ELSE PDONE <= '1' AFTER (tdevice_ISP/1000 - 1 ns); END IF; END IF; END PROCESS ProgTime; --------------------------------------------------------------------------- -- Timing control for the Erase --------------------------------------------------------------------------- ErsTime : PROCESS(ESTART) BEGIN IF ESTART = '0' THEN EDONE <= '0'; ELSE IF LongTiming THEN EDONE <= '1' AFTER (tdevice_ERS - 1 ns); ELSE EDONE <= '1' AFTER (tdevice_ERS/10000 - 1 ns); END IF; END IF; END PROCESS ErsTime; --------------------------------------------------------------------------- -- Main Behavior Process -- combinational process for next state generation --------------------------------------------------------------------------- StateGen_ISP :PROCESS(Instruct, EDONE, PDONE) BEGIN ----------------------------------------------------------------------- -- Functionality Section ----------------------------------------------------------------------- CASE current_state IS WHEN IDLE => IF Instruct'EVENT AND Instruct = ispen THEN next_state <= ISP_MODE; ELSE next_state <= IDLE; END IF; WHEN ISP_MODE => IF Instruct'EVENT AND Instruct = ferase AND ISP THEN next_state <= ERASE; ELSIF Instruct'EVENT AND Instruct = fpgm AND ISP THEN next_state <= PROG; ELSIF Instruct'EVENT AND Instruct = fdata3 AND ISP AND Address = AddrRange THEN next_state <= PROG_PREL; ELSIF Instruct'EVENT AND Instruct = ispex THEN next_state <= IDLE; ELSE next_state <= ISP_MODE; END IF; WHEN PROG_PREL => IF Instruct'EVENT AND Instruct = fpgm AND ISP THEN next_state <= PROG; ELSIF Instruct'EVENT AND Instruct = ispex THEN next_state <= IDLE; END IF; WHEN PROG => IF rising_edge(PDONE) THEN next_state <= ISP_MODE; END IF; WHEN ERASE => IF rising_edge(EDONE) THEN next_state <= ISP_MODE; END IF; END CASE; END PROCESS StateGen_ISP; read_dc: PROCESS (Clock, CENeg, RESETIn) BEGIN IF rising_edge(Clock) AND CENeg = '0' AND RESETIn = '1' THEN read_out <= '1', '0' AFTER 1 ns; END IF; END PROCESS read_dc; --------------------------------------------------------------------------- --FSM Output generation and general funcionality --------------------------------------------------------------------------- Functional: PROCESS(TCK, TDI, Instruct, EDONE, PDONE, read_out, Clock, RESETIn, change_addr, BSReg) VARIABLE oe : boolean := FALSE; VARIABLE data_cnt : NATURAL := 0; VARIABLE addr_cnt : NATURAL := 0; VARIABLE data_out : std_logic_vector(7 downto 0); VARIABLE write_addr : NATURAL RANGE 0 TO AddrRANGE; VARIABLE AddrLo : NATURAL RANGE 0 to MemSize; VARIABLE AddrHi : NATURAL RANGE 0 to MemSize; BEGIN oe := rising_edge(read_out); IF rising_edge(change_addr) THEN write_addr := Address; END IF; IF RESETIn = '0' THEN Data_zd <= (OTHERS => 'Z'); data_cnt := 0; addr_cnt := 0; CEONeg_zd <= '1'; END IF; CASE current_state IS WHEN IDLE => ProgStart <= FALSE; IF oe THEN IF ReadProt THEN Data_zd <= (OTHERS => 'Z'); data_cnt := 0; addr_cnt := 0; CEONeg_zd <= '1'; ELSE IF addr_cnt <= MemSize THEN IF Mem(addr_cnt) > -1 THEN data_out := to_slv(Mem(addr_cnt),8); ELSE data_out := "XXXXXXXX"; END IF; IF Parallel THEN Data_zd <= data_out; addr_cnt := addr_cnt + 1; CEONeg_zd <= '1'; ELSE Data_zd(0) <= data_out(data_cnt); Data_zd(7 downto 1) <= (OTHERS => 'Z'); data_cnt := data_cnt + 1; IF data_cnt = 8 THEN data_cnt := 0; addr_cnt := addr_cnt + 1; CEONeg_zd <= '1'; END IF; END IF; ELSE addr_cnt := addr_cnt; CEONeg_zd <= '0'; END IF; END IF; END IF; WHEN ISP_MODE => IF Instruct'EVENT AND Instruct = ferase AND ISP THEN ESTART <= '0', '1' AFTER 1 ns; Mem := (OTHERS => -1); ELSIF Instruct'EVENT AND Instruct = fpgm AND ISP THEN PSTART <= '0', '1' AFTER 1 ns; ADDRHILO_ROW(write_addr, AddrLo, AddrHi); Mem(AddrLo TO AddrHi) := (OTHERS => -1); ELSIF Instruct'EVENT AND Instruct = fdata3 AND ISP AND Address = AddrRange THEN Configure <= TRUE; END IF; WHEN ERASE => IF rising_edge(EDONE) THEN Mem := (OTHERS => MaxData); ChipErased <= TRUE; ProgStart <= FALSE; END IF; WHEN PROG_PREL => IF Instruct'EVENT AND Instruct = fpgm AND ISP THEN PSTART <= '0', '1' AFTER 1 ns; ELSIF Instruct'EVENT AND Instruct = ispex THEN Configure <= FALSE; END IF; WHEN PROG => IF rising_edge (PDONE) THEN IF Configure THEN CASE ConfReg IS WHEN "111" => Parallel <= false; ReadProt <= false; WHEN "101" => Parallel <= true; ReadProt <= false; WHEN "011" => ReadProt <= true; WHEN others => NULL; END CASE; Configure <= FALSE; ELSIF ChipErased OR ProgStart THEN ADDRHILO_ROW(write_addr, AddrLo, AddrHi); FOR I IN AddrLo TO AddrHi LOOP Mem(I) := WByte(I-AddrLo); END LOOP; ChipErased <= FALSE; ProgStart <= TRUE; END IF; END IF; END CASE; IF Instruct = extest OR Instruct = clamp THEN Data_zd(4) <= BSReg(24); CFNeg_zd <= BSReg(22); Data_zd(6) <= BSReg(17); Data_zd(7) <= BSReg(14); CEONeg_zd <= BSReg(12); Data_zd(5) <= BSReg(10); Data_zd(3) <= BSReg(8 ); Data_zd(1) <= BSReg(6 ); Data_zd(0) <= BSReg(4 ); Data_zd(2) <= BSReg(2 ); END IF; IF Instruct = highz THEN Data_zd <= (others => 'Z'); CFNeg_zd <= 'Z'; END IF; END PROCESS Functional; ------------------------------------------------------------------------ -- Path Delay Section for Data Port signal ------------------------------------------------------------------------ RESETNeg_PathDelay_Gen : PROCESS(RESETNeg_zd) VARIABLE RESETNeg_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01( OutSignal => RESETOut, OutSignalName => "RESETNeg", OutTemp => RESETNeg_zd, GlitchData => RESETNeg_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => TCK'LAST_EVENT, PathDelay => tpd_TCK_RESETNeg, PathCondition => TRUE) ) ); END PROCESS; ------------------------------------------------------------------------ -- Path Delay Section for Data Port signal ------------------------------------------------------------------------ DATA_PathDelay_Gen : FOR i IN Data_zd'RANGE GENERATE PROCESS(Data_zd(i)) VARIABLE D_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z( OutSignal => Data(i), OutSignalName => "DATA", OutTemp => Data_zd(i), GlitchData => D_GlitchData, Mode => VitalTransport, Paths => ( 0 => (InputChangeTime => Clock'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_D0), PathCondition => RESETIn = '1' AND CENeg = '0'), 1 => (InputChangeTime => RESETIn'LAST_EVENT, PathDelay => tpd_RESETNeg_D0, PathCondition => CENeg ='0' ), 2 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_D0, PathCondition => true) ) ); END PROCESS; END GENERATE DATA_PathDelay_Gen; ------------------------------------------------------------------------ -- Path Delay Section for CEONeg Port signal ------------------------------------------------------------------------ CEONeg_OUT: PROCESS(CEONeg_zd) -- Output Glitch Detection Variables VARIABLE CEONeg_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => CEONeg, OutSignalName => "CEONeg", OutTemp => CEONeg_zd, GlitchData => CEONeg_GlitchData, XOn => XOn, MsgOn => MsgOn, Paths => ( 0 => (InputChangeTime => Clock'LAST_EVENT, PathDelay => VitalExtendToFillDelay(tpd_CLK_CEONeg), PathCondition => RESETIn = '1' AND CENeg = '0'), 1 => (InputChangeTime => RESETIn'LAST_EVENT, PathDelay => tpd_RESETNeg_CEONeg, PathCondition => CENeg ='0' ), 2 => (InputChangeTime => CENeg'LAST_EVENT, PathDelay => tpd_CENeg_CEONeg, PathCondition => true) ) ); END PROCESS CEONeg_OUT; ------------------------------------------------------------------------ -- Path Delay Section for CFNeg Port signal ------------------------------------------------------------------------ CFNeg_OUT: PROCESS(CFNeg_zd) -- Output Glitch Detection Variables VARIABLE CFNeg_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => CFNeg, OutSignalName => "CFNeg", OutTemp => CFNeg_zd, GlitchData => CFNeg_GlitchData, XOn => XOn, MsgOn => MsgOn, Paths => ( 0 => (InputChangeTime => TCK'LAST_EVENT, PathDelay => tpd_TCK_CFNeg, PathCondition => TRUE) ) ); END PROCESS CFNeg_OUT; ------------------------------------------------------------------------ -- JTAG Path Delay Section ------------------------------------------------------------------------ TDO_OUT: PROCESS(TDO_zd) -- Output Glitch Detection Variables VARIABLE TDO_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z ( OutSignal => TDO, OutSignalName => "TDO", OutTemp => TDO_zd, GlitchData => TDO_GlitchData, XOn => XOn, MsgOn => MsgOn, Paths => ( 0 => (InputChangeTime => TCK'LAST_EVENT, PathDelay => tpd_TCK_TDO, PathCondition => TRUE) ) ); END PROCESS TDO_OUT; END BLOCK Behavior; END vhdl_behavioral;