⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tap.vhd

📁 Xilinx_usb_jtag 下载器原理图及程序
💻 VHD
字号:
--
--   Copyright (C) 2003 by J. Kearney, Bolton, Massachusetts
--
--   This program 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.
--
--   This program 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; if not, write to the Free Software Foundation, Inc.,
-- 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
--

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

library unisim;
use unisim.vcomponents.all;

entity TAP is
    port
	 	(reset : in std_logic;
		 clk96 : in std_logic;
		 clk64 : in std_logic;
		 clk_select : in unsigned(3 downto 0);
		 busy : out std_logic;

		 tristate : in boolean;
		 TCK_term : in std_logic_vector(1 downto 0);
		 TDO_term : in std_logic;

		 run_start : in std_logic;
		 run_ack : buffer std_logic;
		 run_freerun : in std_logic;
		 run_bits : in unsigned(11 downto 0);
		 run_TMS : in unsigned(11 downto 0);
		 run_TDI : in boolean;
		 run_TDO : in boolean;
		 run_pingTMS : in boolean;

		 wr_clk : out std_logic;
		 wr_addr : buffer unsigned(11 downto 0);
		 wr_store : out std_logic;
		 wr_data : out std_logic;

		 rd_clk : out std_logic;
		 rd_addr : buffer unsigned(11 downto 0);
		 rd_data : in std_logic;

		 TCK : out std_logic_vector(1 downto 0);
		 TCK_fb : in std_logic;
		 TDI : out std_logic_vector(1 downto 0);
		 TMS : out std_logic;
		 TDO : in std_logic);
end TAP;

architecture RTL of TAP is

	component ClkMux is
	    Port ( RESET : in std_logic;
	           A : in std_logic;
	           B : in std_logic;
	           sel : in std_logic;
	           O : out std_logic);
	end component;

	component Sync is
	    Port ( RESET : in std_logic;
		 		  REQ : in std_logic;
	           ACK : in std_logic;
	           STATUS : buffer std_logic);
	end component;

	signal clk_base : std_logic;
	signal clk_divider: unsigned(7 downto 0);
	signal jtag_clk : std_logic;

	type States is
		(Idle, Handshake, Starting, Run, Stopping, Freerun);

	signal state : States;

	signal max : unsigned(run_bits'range);
	signal tms_i : unsigned(run_TMS'length downto 0);
	signal tdo_1, tdo_2, tdo_3 : std_logic;
	signal running, tck_i, ack : std_logic;
	signal clocking, writing, reading, pingTMS : boolean;

begin

	--========================================================================
	-- Synthesize the JTAG clock
	-- first, select 96 or 64 MHz base

	mux: ClkMux port map (RESET => reset, A => clk96, B => clk64, sel => clk_select(0), O => clk_base);

	-- then divide it by 2, 4, .. 256

	process (reset, clk_base)
	begin
		if reset = '1' then
			clk_divider <= (others => '0');
		elsif rising_edge(clk_base) then
			clk_divider <= clk_divider + 1;
		end if;
	end process;

	-- and select a tap from that

	jtag_clk <= clk_divider(to_integer(clk_select(3 downto 1)));

	--========================================================================
	-- The actual TAP controller

	busy <= '1' when state /= Idle else '0';

	wr_clk <= TCK_fb;
	wr_store <= '1' when clocking and writing else '0';
	wr_data <= TDO;
	

	rd_clk <= jtag_clk when reading else '0';

	tdo_3 <= tdo_2 when clocking else '0';

	TDI(1) <= 'Z' when tristate or (TDO_term = '0') else '0';
	TDI(0) <= 'Z' when tristate else tdo_3;

	tck_i <= '1' when (jtag_clk = '0') and clocking else '0';

	TCK(0) <= 'Z' when tristate or (TCK_term(0) = '0') else tck_i;
	TCK(1) <= 'Z' when tristate or (TCK_term(1) = '0') else tck_i;

	TMS <= 'Z' when tristate else tms_i(0);	-- tms comes from shift register

	-- tdo is pipelined 2 cycles
	process (reset, jtag_clk)
	begin
		if reset = '1' then
			tdo_1 <= '0';
			tdo_2 <= '0';
		elsif rising_edge(jtag_clk) then	-- falling edge of tck
			tdo_2 <= tdo_1;
			tdo_1	<= rd_data;				-- latch tdo data
		end if;
	end process;

	-- maintain read and write address:
	--  init when not being used
	--	 increment on falling edge of clk to set up for rising edge read or write
	process (running, jtag_clk)
	begin
		if running = '0' then
			rd_addr <= to_unsigned(0, rd_addr'length);
		elsif falling_edge(jtag_clk) then
			rd_addr <= rd_addr + 1;
		end if;
	end process;

	process (running, jtag_clk)
	begin
		if running = '0' then
			wr_addr <= unsigned(to_signed(-2, wr_addr'length));
		elsif rising_edge(jtag_clk) then
			wr_addr <= wr_addr + 1;
		end if;
	end process;

	shaker: Sync port map
		(RESET => reset,
		 REQ => run_start,
		 ACK => not ack,
		 STATUS => run_ack);

	process (reset, jtag_clk, run_start)
	begin
		if reset = '1' then

			state <= Idle;
			tms_i(0) <= '0';
			writing <= false;
			reading <= false;
			clocking <= false;
			running <= '0';
			ack <= '0';

		elsif rising_edge(jtag_clk) then
		
			case state is

				when Idle =>	-- wait for start signal
					if run_start = '1' then
						max <= run_bits;			-- latch vector size
						tms_i <= run_TMS & "0";-- latch tms data
			 			writing <= run_tdi;
						reading <= run_tdo;
						pingTMS <= run_pingTMS;
						state <= Handshake;
						ack <= '1';
					elsif run_freerun = '1' then
						writing <= false;
						reading <= false;
						clocking <= true;
						state <= Freerun;
						ack <= '1';
					end if;

				when Freerun =>
					ack <= '0';
					if run_freerun = '0' then
						state <= Idle;
						clocking <= false;
					end if;

				when Handshake =>
					ack <= '0';
					running <= '1';
					state <= Starting;

				when Starting =>
					state <= Run;

				when Run =>

					if max = 0 then	-- done?
						state <= Stopping;
						clocking <= false;
						tms_i(0) <= '0';
					elsif pingTMS and (max = 1) then
						tms_i(0) <= '1';
						clocking <= true;
						max <= max - 1;
					else
						clocking <= true;
						max <= max - 1;
						for idx in tms_i'right to tms_i'left-1 loop
							tms_i(idx) <= tms_i(idx + 1);
						end loop;
					end if;

				when Stopping =>
					running <= '0';
					state <= Idle;

			end case;

		end if;
	end process;

end RTL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -