summaryrefslogtreecommitdiffstats
path: root/zpu/hdl/tap/tap.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'zpu/hdl/tap/tap.vhd')
-rw-r--r--zpu/hdl/tap/tap.vhd217
1 files changed, 217 insertions, 0 deletions
diff --git a/zpu/hdl/tap/tap.vhd b/zpu/hdl/tap/tap.vhd
new file mode 100644
index 0000000..41dc07b
--- /dev/null
+++ b/zpu/hdl/tap/tap.vhd
@@ -0,0 +1,217 @@
+-- Example Test Access Port (TAP) controller implementation
+-- (c) 2005-2011 Martin Strubel <hackfin@section5.ch>
+
+-- General behaviour summary:
+
+-- * JtagController entity decodes the TMS and TDI sequences
+-- * IR and DR are decoded by this TAP controller
+-- * Signals to a CPU core are generated by the TAP. See
+-- "Core emulation signals" below. These are mapped into a control register:
+-- emuctl [W]
+-- * Signals from a CPU core are mapped into a status register:
+-- emustat [R]
+
+-- Note: Fixed size IR register is clocked in LSB first,
+-- Variable size DR register is clocked in MSB first.
+
+-- The default EMUIR value on a state machine reset is set to
+-- INS_NOP, which should be defined properly by the parent module.
+-- This is necessary for the core to not run any spurious command when
+-- a breakpoint was hit and the JTAG state machine enters Run-Test-Idle.
+
+-- This TAP is supported by a generic software library as part of the
+-- ICEbear software suite.
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.jtag.all;
+-- TAP register definitions (generated):
+use work.tap_registers.all;
+
+entity tap is
+ generic (EMUDAT_SIZE : natural := 32;
+ EMUIR_SIZE : natural := 8;
+ IDCODE : std_logic_vector(32-1 downto 0) := x"deadbeef";
+ INS_NOP : std_logic_vector(8-1 downto 0) := x"00");
+ port (
+ -- JTAG signals:
+ tck, trst, tms, tdi : in std_logic;
+ tdo : out std_logic;
+ -- Core <-> TAP signals:
+ core_reset : out std_logic; -- Reset core logic
+ emuexec : out std_logic; -- Execute opcode on rising edge
+ emurequest : out std_logic; -- Emulation request to core
+ emuack : in std_logic; -- Core has acknowledged EMULATION request
+ emurdy : in std_logic; -- Core ready to execute next instruction
+ pulse : in std_logic; -- Pulse event counter
+ -- PC of possibly running core. Allows to access PC without
+ -- entering emulation.
+ dbgpc : in std_logic_vector(EMUDAT_SIZE-1 downto 0); -- PC
+
+ -- Extra status bits, core dependent
+ exstat : in std_logic_vector(7 downto 0);
+
+ emudata_i : in std_logic_vector(EMUDAT_SIZE-1 downto 0);
+ emudata_o : out std_logic_vector(EMUDAT_SIZE-1 downto 0);
+ -- Not implemented in this version
+ -- emudat_wr : in std_logic;
+ -- emudat_rd : in std_logic;
+ emuir : out std_logic_vector(EMUIR_SIZE-1 downto 0)
+ );
+end tap;
+
+architecture behaviour of tap is
+
+ -- Use generated registers from tap_pkg.vhd
+
+ -- Note: all ones is always reserved for BYPASS
+ -- all zeros is normally reserved for EXTEST
+
+ signal jtag_state : jtag_state_type;
+
+ signal exec : std_logic := '0';
+
+ -- Emulation control/status registers:
+ signal emustat : std_logic_vector(16-1 downto 0);
+ signal emuctl : std_logic_vector(16-1 downto 0) := x"0000";
+
+ -- Core emulation signals:
+
+ signal dr_in : std_logic_vector(EMUDAT_SIZE-1 downto 0);
+ signal dr_out : std_logic_vector(EMUDAT_SIZE-1 downto 0);
+
+ signal count1 : unsigned(32-1 downto 0);
+ signal count1_reset : std_logic;
+ signal count2 : unsigned(16-1 downto 0);
+
+ signal ir : std_logic_vector(4-1 downto 0);
+
+ -- Position of MSB of data register when not in BYPASS
+ -- (defines length of DR register). See also jtag_config.vhd
+ signal msbpos : bitpos_type := 31;
+
+ -- Emulation auxiliaries:
+
+ -- Emulation data register for exchange between core and JTAG:
+ signal emudat_i : std_logic_vector(EMUDAT_SIZE-1 downto 0);
+ signal emudat_o : std_logic_vector(EMUDAT_SIZE-1 downto 0);
+-- These signals are just stubs. Not implemented in this version.
+ -- signal emudat_rxf : std_logic; -- Receive full
+ -- signal emudat_txe : std_logic := '0'; -- Transmit empty
+ -- signal emudat_ovr : std_logic := '0'; -- Overrun
+ -- signal emudat_unr : std_logic := '0'; -- Underrun
+
+begin
+i_jtag : JtagController
+ port map (
+ tck => tck,
+ tms => tms,
+ tdi => tdi,
+ tdo => tdo,
+ trst => trst,
+ state => jtag_state,
+ dr_out => dr_out,
+ msbpos => msbpos,
+ dr_in => dr_in,
+ ir_out => ir
+ );
+
+-- Select DR register according to supported IRs
+-- We sample this with tck to avoid gated clock issues
+
+select_dr:
+ process (tck)
+ begin
+ if rising_edge(tck) then
+ case ir is
+ when TAP_IDCODE =>
+ dr_in <= IDCODE;
+ msbpos <= 31;
+ when TAP_EMUDATA =>
+ dr_in <= emudata_i;
+ msbpos <= emudata_i'length - 1;
+ when TAP_EMUSTAT =>
+ dr_in(emustat'length-1 downto 0) <= emustat;
+ msbpos <= emustat'length - 1;
+ when TAP_DBGPC =>
+ dr_in <= dbgpc;
+ msbpos <= dbgpc'length - 1;
+ when TAP_COUNT1 =>
+ dr_in(count1'length-1 downto 0) <= std_logic_vector(count1);
+ msbpos <= count1'length - 1;
+ when TAP_COUNT2 =>
+ dr_in(count2'length-1 downto 0) <= std_logic_vector(count2);
+ msbpos <= count2'length - 1;
+ when others =>
+ dr_in <= (others => 'X');
+ msbpos <= 31;
+ end case;
+ end if;
+ end process;
+
+
+-- NOTE: action is being taken when ENTERING the concerning state
+-- on rising edge of tck.
+
+-- exec is the signal sent to the core. It is like an IRQ event, thus
+-- it must be properly treated as an exception (edge sensitive)
+-- inside the core logic.
+
+decode_scanchain_w:
+ process (tck)
+ begin
+ if rising_edge(tck) then
+ count1_reset <= '0';
+ exec <= '0';
+ case jtag_state is
+ when UPDATE_DR =>
+ if ir = TAP_EMUCTRL then
+ emuctl <= dr_out(15 downto 0);
+ elsif ir = TAP_EMUDATA then
+ emudat_o <= dr_out;
+ elsif ir = TAP_EMUIR then
+ emuir <= dr_out(EMUIR_SIZE-1 downto 0);
+ end if;
+ when TEST_LOGIC_RESET =>
+ count1_reset <= '1';
+ count2 <= (others => '0');
+ emuctl <= (others => '0');
+ emudat_o <= (others => '0');
+-- Important to reset the EMUIR to NOP for sane JTAG operation:
+ emuir <= INS_NOP;
+ when RUN_TEST_IDLE =>
+ count2 <= count2 + 1;
+ exec <= '1';
+ when others =>
+ end case;
+ end if;
+ end process;
+
+pulse_count:
+ process (count1_reset, pulse)
+ begin
+ if count1_reset = '1' then
+ count1 <= (others => '0');
+ elsif rising_edge(pulse) then
+ count1 <= count1 + 1;
+ end if;
+ end process;
+
+emuexec <= exec;
+emurequest <= emuctl(0);
+core_reset <= emuctl(15);
+
+-- Registers:
+emudata_o <= emudat_o;
+
+-- FIXME:
+-- These mappings should probably move to glue between TAP and core
+-- to be more generic.
+
+emustat <= exstat &
+ "0000" & "00" & emurdy & emuack;
+
+end behaviour;
OpenPOWER on IntegriCloud