📄 ocdprogtck.vhd
字号:
--**********************************************************************************************
-- JTAG "Flash" programmer for AVR Core(TCK Clock Domain)
-- Version 0.4
-- Modified 20.06.2006
-- Designed by Ruslan Lepetenok
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use WORK.JTAGPack.all;
use WORK.JTAGProgrammerPack.all;
use WORK.JTAGDataPack.all;
use WORK.JTAGTAPCtrlSMPack.all;
entity OCDProgTCK is port(
-- JTAG related inputs/outputs
TRSTn : in std_logic; -- Optional
TMS : in std_logic;
TCK : in std_logic;
TDI : in std_logic;
TDO : out std_logic;
TDO_OE : out std_logic;
-- From/To cp2 clock domain("Flash" programmer)
FlEEPrgAdr : out std_logic_vector(15 downto 0);
FlPrgRdData : in std_logic_vector(15 downto 0);
EEPrgRdData : in std_logic_vector(7 downto 0);
FlEEPrgWrData : out std_logic_vector(15 downto 0);
ChipEraseStart : out std_logic;
ChipEraseDone : in std_logic;
ProgEnable : out std_logic;
FlWrMStart : out std_logic; -- Multiple
FlWrSStart : out std_logic; -- Single
FlRdMStart : out std_logic; -- Multiple
FlRdSStart : out std_logic; -- Single
EEWrStart : out std_logic;
EERdStart : out std_logic;
TAPCtrlTLR : out std_logic; -- TAP Controller is in the Test-Logic/Reset state
-- CPU reset
jtag_rst : out std_logic
);
end OCDProgTCK;
architecture RTL of OCDProgTCK is
signal CurrentTAPState : TAPCtrlState_Type;
signal NextTAPState : TAPCtrlState_Type;
-- JTAG Registers
-- Instruction registers
signal InstructionShRg : std_logic_vector(CInstrLength-1 downto 0); -- Shift
signal InstructionRg : std_logic_vector(CInstrLength-1 downto 0); -- Update
-- Bypass register
signal BypassShRg : std_logic; -- Shift(only)
-- **********************************************************************
signal IDCODEShRg : std_logic_vector(31 downto 0);
signal DataRegsOutMux : std_logic;
signal UnusedInstr : std_logic; -- Unsupported instruction
-- Reset chain (1 bit length, no updade register)
signal ResetShRg : std_logic;
-- ************************* Programmer part ********************************************
-- Program chains
signal PERSh : std_logic_vector(15 downto 0); -- Programming Enable Register (Shift part ?only?)
signal PCRSh : std_logic_vector(14 downto 0); -- Programming Command Register (Shift part)
signal PCRUd : std_logic_vector(PCRSh'range); -- Programming Command Register (Update part)
signal PCRShIn : std_logic_vector(PCRSh'range); -- Programming Command Register Input
signal VFPLSh : std_logic_vector(7 downto 0); -- Virtual Flash Page Load Register (Shift part only)
signal VFPRSh : std_logic_vector(7 downto 0); -- Virtual Flash Page Read Register (Shift part only)
signal VFPRShIn : std_logic_vector(VFPRSh'range); -- Virtual Flash Page Read Register Input
signal ProgEnable_Int : std_logic;
-- TCK counter for Virtual Flash Page Load/Read commands
signal VFPCnt : std_logic_vector(3 downto 0);
signal LdDataLow : std_logic; -- Load low byte of data
signal LdDataHigh : std_logic; -- Load high byte of data and runs "Flash" write SM(cp2 clock domain)
signal FlashAdrIncrEn : std_logic; -- Enables increment of VFPCnt (when LdDataHigh='1')
signal LatchWrData : std_logic;
-- Address(16-bit) and Instruction For Write (16-bit) registers located in TCK clock domaim
signal FlEEPrgAdr_Int : std_logic_vector(15 downto 0); -- Copy of output
-- Address counter length
constant CPageAdrCntLength : positive range 7 to 8 := 7; -- 8 for ATmega128, 7 for ATmega16,...
-- "Flash" programmer state machines (located in TCK clock domaim)
type ChipEraseSMStType is (ChipEraseSMStIdle,ChipEraseSMSt1,ChipEraseSMSt2,ChipEraseSMSt3);
signal ChipEraseSM_CurrentState : ChipEraseSMStType; -- Chip erase
signal ChipEraseSM_NextState : ChipEraseSMStType; -- Chip erase (combinatorial)
signal FlashWr_St : std_logic; -- 2
signal FlashRd_St : std_logic; -- 3
signal EEPROMWr_St : std_logic; -- 4
signal EEPROMRd_St : std_logic; -- 5
signal FuseWr_St : std_logic; -- 6
signal LockWr_St : std_logic; -- 7
signal FuseLockRd_St : std_logic; -- 8
signal SignByteRd_St : std_logic; -- 9
signal LoadNOP_St : std_logic; -- 11
-- EEPROM Write Support
signal EEWrStart_Int : std_logic;
signal EERdStart_Int : std_logic;
begin
TAPStateReg:process(TCK,TRSTn)
begin
if(TRSTn='0') then -- Reset
CurrentTAPState <= TestLogicReset;
elsif(TCK='1' and TCK'event) then -- Clock(rising edge)
CurrentTAPState <= NextTAPState;
end if;
end process;
NextTAPState <= FnTAPNextState(CurrentTAPState,TMS);
-- Instruction register
InstructionRegisterShift:process(TCK,TRSTn)
begin
if(TRSTn='0') then -- Reset
InstructionShRg <= (others => '0');
elsif(TCK='1' and TCK'event) then -- Clock(rising edge)
case CurrentTAPState is
--when CaptureIR => InstructionShRg <= InstructionRg(InstructionRg'high downto 2)&"01"; -- !!! TBD !!!
when CaptureIR => InstructionShRg <= InstructionRg; -- !!! TBD !!!
when ShiftIR => InstructionShRg <= FnJTAGRgSh(InstructionShRg,TDI);
when others => null;
end case;
end if;
end process;
InstructionRegisterUpdate:process(TCK,TRSTn)
begin
if (TRSTn='0') then -- Reset
InstructionRg <= CInitInstrRegVal;
elsif (TCK='0' and TCK'event) then -- Clock(falling edge)
if (CurrentTAPState=TestLogicReset) then
InstructionRg <= CInitInstrRegVal; -- Set to give IDCODE or BYPASS instruction
elsif CurrentTAPState=UpdateIR then
InstructionRg <= InstructionShRg;
end if;
end if;
end process;
-- Data registers
-- ID Code register
IDCodeRegisterShift:process(TCK,TRSTn)
begin
if (TRSTn='0') then -- Reset
IDCODEShRg <= (others => '0');
elsif (TCK='1' and TCK'event) then -- Clock(rising edge)
if (InstructionRg=C_IDCODE) then -- The Instruction register content enables The Data register shift
case CurrentTAPState is
when CaptureDR => IDCODEShRg <= CVersion&CPartNumber&CManufacturerId&'1';
when ShiftDR => IDCODEShRg <= FnJTAGRgSh(IDCODEShRg,TDI);
when others => null;
end case;
end if;
end if;
end process;
-- Bypass register
BypassRegisterShift:process(TCK,TRSTn)
begin
if (TRSTn='0') then -- Reset
BypassShRg <= '0';
elsif (TCK='1' and TCK'event) then -- Clock(rising edge)
if (InstructionRg=C_BYPASS) then -- !!! TBD !!!
case CurrentTAPState is
when ShiftDR => BypassShRg <= TDI;
when others => BypassShRg <= '0'; -- ??? TBD
end case;
end if;
end if;
end process;
DORegAndTDOOE:process(TCK,TRSTn)
begin
if (TRSTn='0') then -- Reset
TDO <= '0';
TDO_OE <= '0';
elsif (TCK='0' and TCK'event) then -- Clock(falling edge)
TDO <= DataRegsOutMux;
if (CurrentTAPState=ShiftIR or CurrentTAPState=ShiftDR) then
TDO_OE <= '1';
else
TDO_OE <= '0';
end if;
end if;
end process;
-- ***************************************************************************************
UnusedInstr <= '1' when (InstructionRg=C_UNUSED_3 or InstructionRg=C_UNUSED_D or
InstructionRg=C_UNUSED_E or InstructionRg=C_OCD_ACCESS or InstructionRg= C_EX_INST) else '0';
DataRegsOutMux <= InstructionShRg(InstructionShRg'low) when CurrentTAPState=ShiftIR else -- !!! TBD !!!
'0' when InstructionRg=C_SAMPLE_PRELOAD or InstructionRg=C_EXTEST else -- !!! TBD !!!
IDCODEShRg(IDCODEShRg'low) when InstructionRg=C_IDCODE else
ResetShRg when InstructionRg=C_AVR_RESET else
PERSh(PERSh'low) when InstructionRg=C_PROG_ENABLE else
PCRSh(PCRSh'low) when InstructionRg=C_PROG_COMMANDS else
VFPLSh(VFPLSh'low) when InstructionRg=C_PROG_PAGELOAD else
VFPRSh(VFPRSh'low) when InstructionRg=C_PROG_PAGEREAD else
BypassShRg;
-- ***************************************************************************************
-- Reset chain (1 bit length, no updade register)
ResetRegisterShift:process(TCK)
begin
if(TCK='1' and TCK'event) then -- Clock(rising edge)
if(InstructionRg=C_AVR_RESET and CurrentTAPState=ShiftDR) then
ResetShRg <= TDI;
end if;
end if;
end process;
jtag_rst <= ResetShRg;
-- ************************************************************************************
-- ************************* Programmer part ********************************************
-- ************************************************************************************
-- Programming Enable Register(no update circuit)
PER_Shift:process(TCK)
begin
if(TCK='1' and TCK'event) then -- Clock(rising edge)
if(InstructionRg=C_PROG_ENABLE and CurrentTAPState=ShiftDR) then
PERSh <= FnJTAGRgSh(PERSh,TDI);
end if;
end if;
end process;
-- Programming enable signal generation(!!! TBD !!!)
PE_Gen_Rg:process(TCK)
begin
if(TCK='0' and TCK'event) then -- Clock(falling edge)
if(InstructionRg=C_PROG_ENABLE and CurrentTAPState=UpdateDR) then -- ???
if(PERSh=C_ProgEnableVect) then
ProgEnable_Int <= '1';
else
ProgEnable_Int <= '0';
end if;
end if;
end if;
end process;
-- Programming Command Register
PCR_Shift:process(TCK)
begin
if(TCK='1' and TCK'event) then -- Clock(rising edge)
if(InstructionRg=C_PROG_COMMANDS) then
case CurrentTAPState is
when CaptureDR => PCRSh <= PCRShIn; -- Load data
when ShiftDR => PCRSh <= FnJTAGRgSh(PCRSh,TDI);
when others => null;
end case;
end if;
end if;
end process;
PCRShIn(14 downto 10) <= PCRSh(14 downto 10);
PCRShIn(8) <= PCRSh(8);
-- Poll response !!!TBD!!!
PCRShIn(9) <= '0' when (ChipEraseSM_CurrentState /= ChipEraseSMStIdle) else '1';
PCRReadSystem:process(TCK)
begin
if(TCK='1' and TCK'event) then -- Clock(rising edge)
if(CurrentTAPState=UpdateDR and InstructionRg=C_PROG_COMMANDS) then
if(FlashRd_St='1') then -- Flash read
if(PCRSh=C_Prg_3D_1) then
PCRShIn(7 downto 0) <= FlPrgRdData(7 downto 0); -- Read low flash byte
elsif(PCRSh=C_Prg_3D_2) then
PCRShIn(7 downto 0) <= FlPrgRdData(15 downto 8); -- Read high flash byte
end if;
elsif(EEPROMRd_St='1') then -- EEPROM read
if(PCRSh=C_Prg_5D_2) then
PCRShIn(7 downto 0) <= EEPrgRdData;
end if;
elsif(FuseLockRd_St='1') then -- Fuse/Lock bit Read Mode(8)
case PCRSh is -- !!!TBD!!! (Length)
when C_Prg_8B_1 => -- 8b(8f1) Read Extended Fuse Byte
PCRShIn(7 downto 0) <= C_ExtFuseByte;
when C_Prg_8C_1 => -- 8c(8f2) Read Fuse High Byte
PCRShIn(7 downto 0) <= C_HighFuseByte;
when C_Prg_8D_1 => -- 8d(8f3) Read Fuse Low Byte
PCRShIn(7 downto 0) <= C_LowFuseByte;
when C_Prg_8E_1 => -- 8e(8f4) Read Lock Bits
PCRShIn(7 downto 0) <= C_LockBits;
when others => null;
end case;
elsif (SignByteRd_St='1') then -- Signature Byte Read Mode(9/10)
if(PCRSh=C_Prg_9C_1) then -- Read Signature Byte(9c) -> 0110010_00000000
case FlEEPrgAdr_Int(3 downto 0) is -- !!!TBD!!! (Length)
when x"0" => PCRShIn(7 downto 0) <= C_SignByte1;
when x"1" => PCRShIn(7 downto 0) <= C_SignByte2;
when x"2" => PCRShIn(7 downto 0) <= C_SignByte3;
when others => null;
end case;
elsif(PCRSh=C_Prg_10C_1) then -- Read Calibration Byte(10c) -> 0110110_00000000
case FlEEPrgAdr_Int(3 downto 0) is -- !!!TBD!!! (Length)
when x"0" => PCRShIn(7 downto 0) <= C_CalibrByte1;
when x"1" => PCRShIn(7 downto 0) <= C_CalibrByte2;
when x"2" => PCRShIn(7 downto 0) <= C_CalibrByte3;
when x"3" => PCRShIn(7 downto 0) <= C_CalibrByte4;
when others => null;
end case;
end if;
end if;
end if;
end if;
end process;
PCR_Update:process(TCK)
begin
if(TCK='0' and TCK'event) then -- Clock(falling edge)
if (CurrentTAPState=UpdateDR and InstructionRg=C_PROG_COMMANDS) then -- Clock enable (!!!InstructionRg=C_PROG_COMMANDS!!!)
PCRUd <= PCRSh;
end if;
end if;
end process;
-- Virtual Flash Page Load Register(!!!shift only!!!)
VFPL_Shift:process(TCK)
begin
if(TCK='1' and TCK'event) then -- Clock(rising edge)
if(InstructionRg=C_PROG_PAGELOAD and CurrentTAPState=ShiftDR) then
VFPLSh <= FnJTAGRgSh(VFPLSh,TDI);
end if;
end if;
end process;
-- !!! TBD !!!
VFPRShIn <= FlPrgRdData(7 downto 0) when VFPCnt(VFPCnt'high)='0' else -- Low Byte
FlPrgRdData(15 downto 8); -- High Byte
-- Virtual Flash Page Read Register
VFPR_Shift:process(TCK)
begin
if(TCK='1' and TCK'event) then -- Clock(rising edge)
if((VFPCnt=x"7" or VFPCnt=x"F"))then -- Load Data (Low/High Byte) !!!TBD!!!
VFPRSh <= VFPRShIn; -- Load data
elsif(InstructionRg=C_PROG_PAGEREAD and CurrentTAPState=ShiftDR) then
VFPRSh <= FnJTAGRgSh(VFPRSh,TDI);
end if;
end if;
end process;
-- TCK counter for Virtual Flash Page Load/Read commands
VFPCounterReg:process(TCK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -