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 ISPORT(CLK : IN STD_LOGIC; -- external 24/25 MHz oscillatornRXF : IN STD_LOGIC; -- FT245BM nRXFnTXE : IN STD_LOGIC; -- FT245BM nTXEB_TDO : IN STD_LOGIC; -- JTAG input: TDO, AS/PS input: CONF_DONEB_ASDO : IN STD_LOGIC; -- AS input: DATAOUT, PS input: nSTATUSB_TCK : BUFFER STD_LOGIC; -- JTAG output: TCK to chain, AS/PS DCLKB_TMS : BUFFER STD_LOGIC; -- JTAG output: TMS to chain, AS/PS nCONFIGB_NCE : BUFFER STD_LOGIC; -- AS output: nCEB_NCS : BUFFER STD_LOGIC; -- AS output: nCSB_TDI : BUFFER STD_LOGIC; -- JTAG output: TDI to chain, AS: ASDI, PS: DATA0B_OE : BUFFER STD_LOGIC; -- LED output/output driver enablenRD : OUT STD_LOGIC; -- FT245BM nRDWR : OUT STD_LOGIC; -- FT245BM WRD : 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;BEGINsm: PROCESS(nRXF, nTXE, state, bitcount, ioshifter, do_output)BEGINCASE state IS-- ============================ INPUTWHEN wait_for_nRXF_low =>IF nRXF='0' THENnext_state <= set_nRD_low;ELSEnext_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") THENnext_state <= bytes_get_tdo_set_tdi;ELSIF ioshifter(7) = '1' THENnext_state <= bytes_set_bitcount;ELSEnext_state <= bits_set_pins_from_data;END IF;WHEN bytes_set_bitcount =>next_state <= wait_for_nRXF_low;-- ============================ BIT BANGINGWHEN bits_set_pins_from_data =>IF ioshifter(6) = '0' THENnext_state <= wait_for_nRXF_low; -- read next byte from hostELSEnext_state <= wait_for_nTXE_low; -- output byte to hostEND 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") THENnext_state <= bytes_get_tdo_set_tdi; -- clock next bitELSIF do_output = '1' THENnext_state <= wait_for_nTXE_low; -- output byte to hostELSEnext_state <= wait_for_nRXF_low; -- read next byte from hostEND IF;-- ============================ OUTPUT BYTE TO HOSTWHEN wait_for_nTXE_low =>IF nTXE = '0' THENnext_state <= set_WR_high;ELSEnext_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 hostWHEN OTHERS =>next_state <= wait_for_nRXF_low;END CASE;END PROCESS sm;out_sm: PROCESS(CLK)BEGINIF CLK = '1' AND CLK'event THENIF state = set_nRD_low OR state = keep_nRD_low OR state = latch_data_from_host THENnRD <= '0';ELSEnRD <= '1';END IF;IF state = latch_data_from_host THENioshifter(7 DOWNTO 0) <= D;END IF;IF state = set_WR_high OR state = output_enable THENWR <= '1';ELSEWR <= '0';END IF;IF state = output_enable OR state = set_WR_low THEND <= ioshifter(7 DOWNTO 0);ELSED <= "ZZZZZZZZ";END IF;IF state = bits_set_pins_from_data THENB_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 THENbitcount <= ioshifter(5 DOWNTO 0) & "111";do_output <= ioshifter(6);END IF;IF state = bytes_get_tdo_set_tdi THENIF B_NCS = '1' THENcarry <= B_TDO; -- JTAG mode (nCS=1)ELSEcarry <= 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 THENB_TCK <= '1';END IF;IF state = bytes_clock_high_and_shift THENioshifter <= carry & ioshifter(7 DOWNTO 1);END IF;IF state = bytes_clock_finish THENB_TCK <= '0';END IF;state <= next_state;END IF;END PROCESS out_sm;END spec;