jtag_logic.vhd

kawk氏のUSB Blaster互換回路

kawk氏のUSB Blaster互換回路

  • タグ:
  • タグはありません
-------------------------------------------------------------------------------
-- Serial/Parallel converter, interfacing JTAG chain with FTDI FT245BM
-------------------------------------------------------------------------------
-- Copyright (C) 2005-2007 Kolja Waschk, ixo.de
-------------------------------------------------------------------------------
-- This code is part of usbjtag. usbjtag is free software; you can redistribute
-- it and/or modify it under the terms of the GNU General Public License as
-- published by the Free Software Foundation; either version 2 of the License,
-- or (at your option) any later version. usbjtag is distributed in the hope
-- that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details. You should have received a
-- copy of the GNU General Public License along with this program in the file
-- COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin
-- St, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY jtag_logic IS
PORT
(
CLK : IN STD_LOGIC; -- external 24/25 MHz oscillator
nRXF : IN STD_LOGIC; -- FT245BM nRXF
nTXE : IN STD_LOGIC; -- FT245BM nTXE
B_TDO : IN STD_LOGIC; -- JTAG input: TDO, AS/PS input: CONF_DONE
B_ASDO : IN STD_LOGIC; -- AS input: DATAOUT, PS input: nSTATUS
B_TCK : BUFFER STD_LOGIC; -- JTAG output: TCK to chain, AS/PS DCLK
B_TMS : BUFFER STD_LOGIC; -- JTAG output: TMS to chain, AS/PS nCONFIG
B_NCE : BUFFER STD_LOGIC; -- AS output: nCE
B_NCS : BUFFER STD_LOGIC; -- AS output: nCS
B_TDI : BUFFER STD_LOGIC; -- JTAG output: TDI to chain, AS: ASDI, PS: DATA0
B_OE : BUFFER STD_LOGIC; -- LED output/output driver enable
nRD : OUT STD_LOGIC; -- FT245BM nRD
WR : OUT STD_LOGIC; -- FT245BM WR
D : INOUT STD_LOGIC_VECTOR(7 downto 0) -- FT245BM D[7..0]
);
END jtag_logic;
ARCHITECTURE spec OF jtag_logic IS
-- There are exactly 16 states. If this is encoded using 4 bits, there will
-- be no unknown/undefined state. The host will send us 64 times "0" to move
-- the state machine to a known state. We don't need a power-on reset.
TYPE states IS
(
wait_for_nRXF_low,
set_nRD_low,
keep_nRD_low,
latch_data_from_host,
set_nRD_high,
bits_set_pins_from_data,
bytes_set_bitcount,
bytes_get_tdo_set_tdi,
bytes_clock_high_and_shift,
bytes_keep_clock_high,
bytes_clock_finish,
wait_for_nTXE_low,
set_WR_high,
output_enable,
set_WR_low,
output_disable
);
ATTRIBUTE ENUM_ENCODING: STRING;
ATTRIBUTE ENUM_ENCODING OF states: TYPE IS
"0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111";
SIGNAL carry: STD_LOGIC;
SIGNAL do_output: STD_LOGIC;
SIGNAL ioshifter: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL bitcount: STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL state, next_state: states;
BEGIN
sm: PROCESS(nRXF, nTXE, state, bitcount, ioshifter, do_output)
BEGIN
CASE state IS
-- ============================ INPUT
WHEN wait_for_nRXF_low =>
IF nRXF='0' THEN
next_state <= set_nRD_low;
ELSE
next_state <= wait_for_nRXF_low;
END IF;
WHEN set_nRD_low =>
next_state <= keep_nRD_low;
WHEN keep_nRD_low =>
next_state <= latch_data_from_host;
WHEN latch_data_from_host =>
next_state <= set_nRD_high;
WHEN set_nRD_high =>
IF NOT (bitcount(8 DOWNTO 3) = "000000") THEN
next_state <= bytes_get_tdo_set_tdi;
ELSIF ioshifter(7) = '1' THEN
next_state <= bytes_set_bitcount;
ELSE
next_state <= bits_set_pins_from_data;
END IF;
WHEN bytes_set_bitcount =>
next_state <= wait_for_nRXF_low;
-- ============================ BIT BANGING
WHEN bits_set_pins_from_data =>
IF ioshifter(6) = '0' THEN
next_state <= wait_for_nRXF_low; -- read next byte from host
ELSE
next_state <= wait_for_nTXE_low; -- output byte to host
END IF;
-- ============================ BYTE OUTPUT (SHIFT OUT 8 BITS)
WHEN bytes_get_tdo_set_tdi =>
next_state <= bytes_clock_high_and_shift;
WHEN bytes_clock_high_and_shift =>
next_state <= bytes_keep_clock_high;
WHEN bytes_keep_clock_high =>
next_state <= bytes_clock_finish;
WHEN bytes_clock_finish =>
IF NOT (bitcount(2 DOWNTO 0) = "111") THEN
next_state <= bytes_get_tdo_set_tdi; -- clock next bit
ELSIF do_output = '1' THEN
next_state <= wait_for_nTXE_low; -- output byte to host
ELSE
next_state <= wait_for_nRXF_low; -- read next byte from host
END IF;
-- ============================ OUTPUT BYTE TO HOST
WHEN wait_for_nTXE_low =>
IF nTXE = '0' THEN
next_state <= set_WR_high;
ELSE
next_state <= wait_for_nTXE_low;
END IF;
WHEN set_WR_high =>
next_state <= output_enable;
WHEN output_enable =>
next_state <= set_WR_low;
WHEN set_WR_low =>
next_state <= output_disable;
WHEN output_disable =>
next_state <= wait_for_nRXF_low; -- read next byte from host
WHEN OTHERS =>
next_state <= wait_for_nRXF_low;
END CASE;
END PROCESS sm;
out_sm: PROCESS(CLK)
BEGIN
IF CLK = '1' AND CLK'event THEN
IF state = set_nRD_low OR state = keep_nRD_low OR state = latch_data_from_host THEN
nRD <= '0';
ELSE
nRD <= '1';
END IF;
IF state = latch_data_from_host THEN
ioshifter(7 DOWNTO 0) <= D;
END IF;
IF state = set_WR_high OR state = output_enable THEN
WR <= '1';
ELSE
WR <= '0';
END IF;
IF state = output_enable OR state = set_WR_low THEN
D <= ioshifter(7 DOWNTO 0);
ELSE
D <= "ZZZZZZZZ";
END IF;
IF state = bits_set_pins_from_data THEN
B_TCK <= ioshifter(0);
B_TMS <= ioshifter(1);
B_NCE <= ioshifter(2);
B_NCS <= ioshifter(3);
B_TDI <= ioshifter(4);
B_OE <= ioshifter(5);
ioshifter <= "000000" & B_ASDO & B_TDO;
END IF;
IF state = bytes_set_bitcount THEN
bitcount <= ioshifter(5 DOWNTO 0) & "111";
do_output <= ioshifter(6);
END IF;
IF state = bytes_get_tdo_set_tdi THEN
IF B_NCS = '1' THEN
carry <= B_TDO; -- JTAG mode (nCS=1)
ELSE
carry <= B_ASDO; -- Active Serial mode (nCS=0)
END IF;
B_TDI <= ioshifter(0);
bitcount <= bitcount - 1;
END IF;
IF state = bytes_clock_high_and_shift OR state = bytes_keep_clock_high THEN
B_TCK <= '1';
END IF;
IF state = bytes_clock_high_and_shift THEN
ioshifter <= carry & ioshifter(7 DOWNTO 1);
END IF;
IF state = bytes_clock_finish THEN
B_TCK <= '0';
END IF;
state <= next_state;
END IF;
END PROCESS out_sm;
END spec;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX