1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-01-11 23:43:15 +00:00
antonblanchard.microwatt/sim_jtag.vhdl
Benjamin Herrenschmidt 554b753172 Add jtag support in simulation via a socket
This adds a local socket that can be used to communicate with
the debug tool (which will be committed separately) and generates
the JTAG signals.

We generate the low level JTAG signals, thus directly driving the
simulated BSCANE2, and the Xilinx DTM

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
2019-09-20 15:07:49 +10:00

106 lines
2.6 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.sim_jtag_socket.all;
library unisim;
use unisim.vcomponents.all;
entity sim_jtag is
end sim_jtag;
architecture behaviour of sim_jtag is
begin
jtag: process
-- Global JTAG signals (used by BSCANE2 inside dmi_dtm
alias j : glob_jtag_t is glob_jtag;
-- Super fast JTAG clock for sim. For debugging the JTAG module,
-- change this to something much larger, for example 60ns, to reflect
-- more realistic conditions.
constant jclk_period : time := 1 ns;
-- Polling the socket... this could be made slower when nothing
-- is connected once we have that indication from the C code.
constant poll_period : time := 100 ns;
-- Number of dummy JTAG clocks to inject after a command. (I haven't
-- got that working with UrJtag but at least with sim, having the
-- right number here allows the synchronizers time to complete a
-- command on the first message exchange, thus avoiding the need
-- for two full shifts for a response.
constant dummy_clocks : integer := 80;
procedure clock(count: in INTEGER) is
begin
for i in 1 to count loop
j.tck <= '0';
wait for jclk_period/2;
j.tck <= '1';
wait for jclk_period/2;
end loop;
end procedure clock;
procedure clock_command(cmd: in std_ulogic_vector;
rsp: out std_ulogic_vector) is
begin
j.capture <= '1';
clock(1);
j.capture <= '0';
clock(1);
j.shift <= '1';
for i in 0 to cmd'length-1 loop
j.tdi <= cmd(i);
rsp := rsp(1 to rsp'length-1) & j.tdo;
clock(1);
end loop;
j.shift <= '0';
j.update <= '1';
clock(1);
j.update <= '0';
clock(1);
end procedure clock_command;
variable cmd : std_ulogic_vector(0 to 247);
variable rsp : std_ulogic_vector(0 to 247);
variable msize : std_ulogic_vector(7 downto 0);
variable size : integer;
begin
-- init & reset
j.reset <= '1';
j.sel <= "0000";
j.capture <= '0';
j.update <= '0';
j.shift <= '0';
j.tdi <= '0';
j.tms <= '0';
j.runtest <= '0';
clock(5);
j.reset <= '0';
clock(5);
-- select chain USER2
-- XXX TODO: Send that via protocol instead
-- XXX TODO: Also maybe have the C code tell us if connected or not
-- and clock when connected.
j.sel <= "0010";
clock(1);
rsp := (others => '0');
while true loop
wait for poll_period;
sim_jtag_read_msg(cmd, msize);
size := to_integer(unsigned(msize));
if size /= 0 and size < 248 then
clock_command(cmd(0 to size-1),
rsp(0 to size-1));
sim_jtag_write_msg(rsp, msize);
clock(dummy_clocks);
end if;
end loop;
end process;
end;