📄 tag2.vhd
字号:
end loop;
-- init TAP setup registers
for tap in 0 to NUM_TAPS - 1 loop
-- CONFIG1: TCK term A, TDO term off, all extra bits as inputs
setup_reg(tap)(CONFIG1) <= "011000000000";
-- CONFIG2: rst, trst, tristate inactive, clock = 1 MHz, different buffer for each
setup_reg(tap)(CONFIG2) <= "0011" & to_unsigned(tap, 4) & to_unsigned(11, 4);
end loop;
elsif rising_edge(usb_clk) then
case cmd_state is
when Idle =>
reading_status <= false;
reading_buf <= false;
reading_ack <= false;
if sync_rd = '1' then
cmd_state <= PutCmd;
-- else
-- acking := false;
-- for cur in 0 to NUM_TAPS - 1 loop
-- if not acking then
-- if done_flagged(cur) = '1' then
-- acking := true;
-- done_ack(cur) <= '1';
-- ack_code <= "10100" & std_logic_vector(to_unsigned(cur, 3));
-- cmd_state <= GetAck_wait;
-- reading_ack <= true;
-- end if;
-- end if;
-- end loop;
-- if not acking then
-- done_ack <= (others => '0');
-- end if;
end if;
when PutCmd =>
reg_num := to_integer(unsigned(usb_d(6 downto 4)));
if usb_d(7) = '0' then
-- action command
case usb_d(6 downto 4) is
when CMD_GETSTATUS =>
reading_status <= true;
cmd_state <= GetStatus_wait;
when CMD_SETCURTAP =>
cur_tap <= to_integer(unsigned(usb_d(3 downto 0)));
cmd_state <= Idle;
when CMD_WRBUF =>
cmd_state <= PutBuf_wait;
when CMD_RDBUF =>
reading_buf <= true;
cmd_state <= GetBuf_wait;
when CMD_RUN =>
want_tdi <= usb_d(0) = '1';
want_tdo <= usb_d(1) = '1';
want_pingTMS <= usb_d(2) = '1';
cmd_state <= RunStart;
when CMD_COPY =>
reading_buf <= true;
cmd_state <= Copy1;
when CMD_DELAY =>
cmd_state <= Delay;
when others =>
cmd_state <= Idle;
end case;
else
-- Set register, either global or per-TAP-instance
case usb_d(6 downto 4) is
when "110" =>
cur_setup_reg <= 0;
setup_reg(cur_tap)(0)(11 downto 8) <= unsigned(usb_d(3 downto 0));
cmd_state <= PutLowT_wait;
when "111" =>
cur_setup_reg <= 1;
setup_reg(cur_tap)(1)(11 downto 8) <= unsigned(usb_d(3 downto 0));
cmd_state <= PutLowT_wait;
when "101" =>
cmd_state <= Idle; -- no-op
when others =>
cur_reg <= reg_num;
reg(reg_num)(11 downto 8) <= unsigned(usb_d(3 downto 0));
cmd_state <= PutLow_wait;
end case;
end if;
when PutLow_wait =>
if sync_rd = '1' then
cmd_state <= PutLow;
end if;
when PutLow =>
reg(cur_reg)(7 downto 0) <= unsigned(usb_d);
cmd_state <= Idle;
when PutLowT_wait =>
if sync_rd = '1' then
cmd_state <= PutLowT;
else
cmd_state <= PutLowT_wait;
end if;
when PutLowT =>
setup_reg(cur_tap)(cur_setup_reg)(7 downto 0) <= unsigned(usb_d);
cmd_state <= Idle;
when RunStart =>
if TAP_busy(cur_tap) = '0' then
TAP_start(cur_tap) <= '1'; -- rising edge sets TAP_ack() = '1'
cmd_state <= RunAck;
end if;
when RunAck =>
if TAP_ack(cur_tap) = '0' then
TAP_start(cur_tap) <= '0';
cmd_state <= Idle;
end if;
when Copy1 =>
if TAP_busy(cur_tap) = '0' then
if reg(COUNT) = 0 then
reading_buf <= false;
cmd_state <= Idle;
else
cmd_state <= Copy2;
end if;
end if;
when Copy2 =>
cmd_state <= Copy1;
reg(COUNT) <= reg(COUNT) - 1;
reg(ADDR) <= reg(ADDR) + 1;
when PutBuf_wait =>
if TAP_busy(cur_tap) /= '0' then
cmd_state <= PutBuf_wait;
elsif reg(COUNT) = 0 then
cmd_state <= Idle;
elsif sync_rd = '1' then
cmd_state <= PutBuf;
end if;
when PutBuf =>
cmd_state <= PutBuf_wait;
reg(COUNT) <= reg(COUNT) - 1;
reg(ADDR) <= reg(ADDR) + 1;
when GetStatus_wait =>
if usb_txe_n = '0' then
cmd_state <= GetStatus;
end if;
when GetAck =>
cmd_state <= Idle;
when GetAck_wait =>
if usb_txe_n = '0' then
cmd_state <= GetAck;
end if;
when GetStatus =>
cmd_state <= Idle;
when GetBuf_wait =>
if TAP_busy(cur_tap) /= '0' then
cmd_state <= GetBuf_wait;
elsif reg(COUNT) = 0 then
cmd_state <= Idle;
elsif usb_txe_n = '0' then
cmd_state <= GetBuf;
end if;
when GetBuf =>
cmd_state <= GetBuf_wait;
reg(COUNT) <= reg(COUNT) - 1;
reg(ADDR) <= reg(ADDR) + 1;
when Delay =>
if reg(COUNT) = 0 then
if reg(ADDR) = 0 then
-- ack_code <= "10101000";
-- cmd_state <= GetAck_wait;
cmd_state <= Idle;
else
reg(ADDR) <= reg(ADDR) + 1;
reg(COUNT) <= reg(COUNT) - 1;
end if;
else
reg(COUNT) <= reg(COUNT) - 1;
end if;
when others =>
cmd_state <= Idle;
end case;
end if;
end process;
--===========================================================================
-- Buffers
--===========================================================================
-- for each TAP there is a dedicated input buffer. Output buffers are in a
-- pool and TAPs can individually address them. Not very efficient in terms
-- of muxes, but the resources are available.
-- p.s. 'input' here means in from jtag tdi, output means out to jtag tdo.
-----------------------------------------------------------------------------
tap_in_bufs: for idx in 0 to NUM_TAPS-1 generate
signal zero : std_logic_vector(7 downto 0);
signal reading : std_logic;
attribute INIT_00 : string;
attribute INIT_00 of in_buf : label is "00000000000000000000000000000000000000302E3156204741544A20425355"; -- 'USB JTAG V1.0'
begin
zero <= (others => '0');
reading <= '1' when reading_buf else '0';
in_buf: RAMB4_S1_S8
-- synthesis translate_off
generic map
(INIT_00 => X"00000000000000000000000000000000000000302E3156204741544A20425355") -- 'USB JTAG V1.0'
-- synthesis translate_on
port map
(-- data coming from TAP tdi may be stored
DIA(0) => TAP_wr_data(idx),
ENA => TAP_wr_store(idx),
WEA => TAP_wr_store(idx),
RSTA => '0',
CLKA => TAP_wr_clk(idx),
ADDRA => std_logic_vector(TAP_wr_addr(idx)),
DOA => open,
-- USB channel may access it via ADDR & COUNT registers and command CMD_RDBUF
DIB => zero,
ENB => reading,
WEB => '0',
RSTB => '0',
CLKB => usb_clk,
ADDRB => std_logic_vector(reg(ADDR)(BFAddr'left downto BFAddr'right)),
DOB => buf_rd_data(idx));
end generate;
tap_out_bufs: for idx in 0 to NUM_BUFS-1 generate
signal rdata : std_logic;
signal wdata : std_logic;
signal raddr : BVAddr;
signal sel_buf : integer range 0 to NUM_BUFS-1;
signal rclk : std_logic;
begin
-- generate a tristate multiplexer for address, clock and data. Effectively
-- forms a crossbar with the outer loop. Potential for internal bus contention.
out_addr: for tap in 0 to NUM_TAPS-1 generate
signal sel : boolean;
begin
sel <= to_integer(setup_reg(tap)(CONFIG2)(6 downto 4)) = idx;
raddr <= TAP_rd_addr(tap) when sel else (others => 'Z');
TAP_rd_data(tap) <= rdata when sel else 'Z';
rclk <= TAP_rd_clk(tap) when sel else 'Z';
end generate;
-- write enable from USB channel - currently selected buffer and write data available
wdata <= '1' when (to_integer(setup_reg(cur_tap)(CONFIG2)(6 downto 4)) = idx) and
((cmd_state = Copy2) or (cmd_state = PutBuf)) else '0';
out_buf: RAMB4_S1_S8
port map
(-- stored bits may be output to TAP tdo
DIA(0) => '0',
ENA => '1',
WEA => '0',
RSTA => '0',
CLKA => rclk,
ADDRA => std_logic_vector(raddr),
DOA(0) => rdata,
-- bits may be written to through USB channel via COUNT & ADDR registers and
-- CMD_WRBUF command
DIB => usb_d,
ENB => wdata,
WEB => wdata,
RSTB => '0',
CLKB => usb_clk,
ADDRB => std_logic_vector(reg(ADDR)(BFAddr'left downto BFAddr'right)),
DOB => open);
end generate;
--===========================================================================
-- TAPs
--===========================================================================
-- For each set of wires, there is a TAP controller that handles the basic
-- coordination of clocks, signals and addresses. Each runs independently,
-- so operations with multiple TAPs can overlap.
-----------------------------------------------------------------------------
taps: for cur in 0 to NUM_TAPS-1 generate
component 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 component;
signal tristate : boolean;
begin
tristate <= setup_reg(cur)(CONFIG2)(7) = '1';
jtag_rst_n(cur) <= 'Z' when tristate else setup_reg(cur)(CONFIG2)(8);
jtag_trst_n(cur) <= 'Z' when tristate else setup_reg(cur)(CONFIG2)(9);
jtag_dint(cur) <= 'Z' when tristate else setup_reg(cur)(CONFIG2)(10);
extra: if not DEBUG generate
begin
-- maintain jtag_extra() outputs
extra_out: for idx in 0 to 3 generate
begin
jtag_extra(cur*4+idx) <= 'Z' when setup_reg(cur)(CONFIG1)(idx*2) = '0' else
setup_reg(cur)(CONFIG1)(idx*2+1);
end generate;
end generate;
a_TAP : TAP port map
(reset => reset,
clk96 => clk_2,
clk64 => clk_1_5,
clk_select => setup_reg(cur)(CONFIG2)(3 downto 0),
busy => TAP_busy(cur),
tristate => tristate,
TCK_term => std_logic_vector(setup_reg(cur)(CONFIG1)(11 downto 10)),
TDO_term => setup_reg(cur)(CONFIG1)(9),
run_start => TAP_start(cur),
run_ack => TAP_ack(cur),
run_freerun => setup_reg(cur)(CONFIG2)(11),
run_bits => reg(BITS),
run_TMS => reg(TMS),
run_TDI => want_tdi,
run_TDO => want_TDO,
run_pingTMS => want_pingTMS,
wr_clk => TAP_wr_clk(cur),
wr_addr => TAP_wr_addr(cur),
wr_store => TAP_wr_store(cur),
wr_data => TAP_wr_data(cur),
rd_clk => TAP_rd_clk(cur),
rd_addr => TAP_rd_addr(cur),
rd_data => TAP_rd_data(cur),
TCK(0) => jtag_tck_A(cur),
TCK(1) => jtag_tck_B(cur),
TCK_fb => jtag_tck_fb(cur),
TMS => jtag_TMS(cur),
TDO => jtag_tdo(cur),
TDI(1) => jtag_tdi_term(cur),
TDI(0) => jtag_tdi(cur));
end generate;
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -