forked from cores/microwatt
				
			First pass at an external JTAG port
The verilator simulation interface uses the remote_bitbang protocol from openocd. I have a simple implementation for urjtag too. Signed-off-by: Anton Blanchard <anton@linux.ibm.com>asic-3
							parent
							
								
									18503732d7
								
							
						
					
					
						commit
						fd9350c3b5
					
				@ -0,0 +1,302 @@
 | 
			
		||||
-- JTAG to DMI interface, based on the Xilinx version
 | 
			
		||||
--
 | 
			
		||||
-- DMI bus
 | 
			
		||||
--
 | 
			
		||||
--  req : ____/------------\_____
 | 
			
		||||
--  addr: xxxx<            >xxxxx, based on the Xilinx version
 | 
			
		||||
--  dout: xxxx<            >xxxxx
 | 
			
		||||
--  wr  : xxxx<            >xxxxx
 | 
			
		||||
--  din : xxxxxxxxxxxx<      >xxx
 | 
			
		||||
--  ack : ____________/------\___
 | 
			
		||||
--
 | 
			
		||||
--  * addr/dout set along with req, can be latched on same cycle by slave
 | 
			
		||||
--  * ack & din remain up until req is dropped by master, the slave must
 | 
			
		||||
--    provide a stable output on din on reads during that time.
 | 
			
		||||
--  * req remains low at until at least one sysclk after ack seen down.
 | 
			
		||||
--
 | 
			
		||||
--   JTAG (tck)                    DMI (sys_clk)
 | 
			
		||||
--
 | 
			
		||||
--   * jtag_req = 1
 | 
			
		||||
--        (jtag_req_0)             *
 | 
			
		||||
--          (jtag_req_1) ->        * dmi_req = 1 >
 | 
			
		||||
--                                 *.../...
 | 
			
		||||
--                                 * dmi_ack = 1 <
 | 
			
		||||
--   *                         (dmi_ack_0)
 | 
			
		||||
--   *                   <-  (dmi_ack_1)
 | 
			
		||||
--   * jtag_req = 0 (and latch dmi_din)
 | 
			
		||||
--        (jtag_req_0)             *
 | 
			
		||||
--          (jtag_req_1) ->        * dmi_req = 0 >
 | 
			
		||||
--                                 * dmi_ack = 0 <
 | 
			
		||||
--  *                          (dmi_ack_0)
 | 
			
		||||
--  *                    <-  (dmi_ack_1)
 | 
			
		||||
--
 | 
			
		||||
--  jtag_req can go back to 1 when jtag_rsp_1 is 0
 | 
			
		||||
--
 | 
			
		||||
--  Questions/TODO:
 | 
			
		||||
--    - I use 2 flip fops for sync, is that enough ?
 | 
			
		||||
--    - I treat the jtag_trst as an async reset, is that necessary ?
 | 
			
		||||
--    - Dbl check reset situation since we have two different resets
 | 
			
		||||
--      each only resetting part of the logic...
 | 
			
		||||
--    - Look at optionally removing the synchronizer on the ack path,
 | 
			
		||||
--      assuming JTAG is always slow enough that ack will have been
 | 
			
		||||
--      stable long enough by the time CAPTURE comes in.
 | 
			
		||||
--    - We could avoid the latched request by not shifting while a
 | 
			
		||||
--      request is in progress (and force TDO to 1 to return a busy
 | 
			
		||||
--      status).
 | 
			
		||||
--
 | 
			
		||||
--  WARNING: This isn't the real DMI JTAG protocol (at least not yet).
 | 
			
		||||
--           a command while busy will be ignored. A response of "11"
 | 
			
		||||
--           means the previous command is still going, try again.
 | 
			
		||||
--           As such We don't implement the DMI "error" status, and
 | 
			
		||||
--           we don't implement DTMCS yet... This may still all change
 | 
			
		||||
--           but for now it's easier that way as the real DMI protocol
 | 
			
		||||
--           requires for a command to work properly that enough TCK
 | 
			
		||||
--           are sent while IDLE and I'm having trouble getting that
 | 
			
		||||
--           working with UrJtag and the Xilinx BSCAN2 for now.
 | 
			
		||||
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.math_real.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.wishbone_types.all;
 | 
			
		||||
 | 
			
		||||
entity dmi_dtm_jtag is
 | 
			
		||||
    generic(ABITS : INTEGER:=8;
 | 
			
		||||
	    DBITS : INTEGER:=32);
 | 
			
		||||
 | 
			
		||||
    port(sys_clk	: in std_ulogic;
 | 
			
		||||
	 sys_reset	: in std_ulogic;
 | 
			
		||||
	 dmi_addr	: out std_ulogic_vector(ABITS - 1 downto 0);
 | 
			
		||||
	 dmi_din	: in std_ulogic_vector(DBITS - 1 downto 0);
 | 
			
		||||
	 dmi_dout	: out std_ulogic_vector(DBITS - 1 downto 0);
 | 
			
		||||
	 dmi_req	: out std_ulogic;
 | 
			
		||||
	 dmi_wr		: out std_ulogic;
 | 
			
		||||
	 dmi_ack	: in std_ulogic;
 | 
			
		||||
--	 dmi_err	: in std_ulogic TODO: Add error response
 | 
			
		||||
         jtag_tck       : in std_ulogic;
 | 
			
		||||
         jtag_tdi       : in std_ulogic;
 | 
			
		||||
         jtag_tms       : in std_ulogic;
 | 
			
		||||
	 jtag_trst      : in std_ulogic;
 | 
			
		||||
         jtag_tdo       : out std_ulogic
 | 
			
		||||
	 );
 | 
			
		||||
end entity dmi_dtm_jtag;
 | 
			
		||||
 | 
			
		||||
architecture behaviour of dmi_dtm_jtag is
 | 
			
		||||
 | 
			
		||||
    -- Signals coming out of the JTAG TAP controller
 | 
			
		||||
    signal capture		: std_ulogic;
 | 
			
		||||
    signal update		: std_ulogic;
 | 
			
		||||
    signal sel			: std_ulogic;
 | 
			
		||||
    signal shift		: std_ulogic;
 | 
			
		||||
    signal tdi			: std_ulogic;
 | 
			
		||||
    signal tdo			: std_ulogic;
 | 
			
		||||
 | 
			
		||||
    -- ** JTAG clock domain **
 | 
			
		||||
 | 
			
		||||
    -- Shift register
 | 
			
		||||
    signal shiftr	: std_ulogic_vector(ABITS + DBITS + 1 downto 0);
 | 
			
		||||
 | 
			
		||||
    -- Latched request
 | 
			
		||||
    signal request	: std_ulogic_vector(ABITS + DBITS + 1 downto 0);
 | 
			
		||||
 | 
			
		||||
    -- A request is present
 | 
			
		||||
    signal jtag_req	: std_ulogic;
 | 
			
		||||
 | 
			
		||||
    -- Synchronizer for jtag_rsp (sys clk -> jtag_tck)
 | 
			
		||||
    signal dmi_ack_0	: std_ulogic;
 | 
			
		||||
    signal dmi_ack_1	: std_ulogic;
 | 
			
		||||
 | 
			
		||||
    -- ** sys clock domain **
 | 
			
		||||
 | 
			
		||||
    -- Synchronizer for jtag_req (jtag clk -> sys clk)
 | 
			
		||||
    signal jtag_req_0	: std_ulogic;
 | 
			
		||||
    signal jtag_req_1	: std_ulogic;
 | 
			
		||||
 | 
			
		||||
    -- ** combination signals
 | 
			
		||||
    signal jtag_bsy	: std_ulogic;
 | 
			
		||||
    signal op_valid	: std_ulogic;
 | 
			
		||||
    signal rsp_op	: std_ulogic_vector(1 downto 0);
 | 
			
		||||
 | 
			
		||||
    -- ** Constants **
 | 
			
		||||
    constant DMI_REQ_NOP : std_ulogic_vector(1 downto 0) := "00";
 | 
			
		||||
    constant DMI_REQ_RD  : std_ulogic_vector(1 downto 0) := "01";
 | 
			
		||||
    constant DMI_REQ_WR  : std_ulogic_vector(1 downto 0) := "10";
 | 
			
		||||
    constant DMI_RSP_OK  : std_ulogic_vector(1 downto 0) := "00";
 | 
			
		||||
    constant DMI_RSP_BSY : std_ulogic_vector(1 downto 0) := "11";
 | 
			
		||||
 | 
			
		||||
    attribute ASYNC_REG : string;
 | 
			
		||||
    attribute ASYNC_REG of jtag_req_0: signal is "TRUE";
 | 
			
		||||
    attribute ASYNC_REG of jtag_req_1: signal is "TRUE";
 | 
			
		||||
    attribute ASYNC_REG of dmi_ack_0: signal is "TRUE";
 | 
			
		||||
    attribute ASYNC_REG of dmi_ack_1: signal is "TRUE";
 | 
			
		||||
 | 
			
		||||
    component tap_top port (
 | 
			
		||||
        -- JTAG pads
 | 
			
		||||
        tms_pad_i : in std_ulogic;
 | 
			
		||||
        tck_pad_i : in std_ulogic;
 | 
			
		||||
        trst_pad_i : in std_ulogic;
 | 
			
		||||
        tdi_pad_i : in std_ulogic;
 | 
			
		||||
        tdo_pad_o : out std_ulogic;
 | 
			
		||||
        tdo_padoe_o : out std_ulogic;
 | 
			
		||||
 | 
			
		||||
        -- TAP states
 | 
			
		||||
        shift_dr_o : out std_ulogic;
 | 
			
		||||
        pause_dr_o : out std_ulogic;
 | 
			
		||||
        update_dr_o : out std_ulogic;
 | 
			
		||||
        capture_dr_o : out std_ulogic;
 | 
			
		||||
 | 
			
		||||
        -- Select signals for boundary scan or mbist
 | 
			
		||||
        extest_select_o : out std_ulogic;
 | 
			
		||||
        sample_preload_select_o : out std_ulogic;
 | 
			
		||||
        mbist_select_o : out std_ulogic;
 | 
			
		||||
        debug_select_o : out std_ulogic;
 | 
			
		||||
 | 
			
		||||
        -- TDO signal that is connected to TDI of sub-modules.
 | 
			
		||||
        tdo_o : out std_ulogic;
 | 
			
		||||
 | 
			
		||||
        -- TDI signals from sub-modules
 | 
			
		||||
        debug_tdi_i : in std_ulogic;
 | 
			
		||||
        bs_chain_tdi_i : in std_ulogic;
 | 
			
		||||
        mbist_tdi_i : in std_ulogic
 | 
			
		||||
        );
 | 
			
		||||
    end component;
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
    tap_top0 : tap_top
 | 
			
		||||
	port map (
 | 
			
		||||
	    tms_pad_i               => jtag_tms,
 | 
			
		||||
	    tck_pad_i               => jtag_tck,
 | 
			
		||||
	    trst_pad_i              => jtag_trst,
 | 
			
		||||
	    tdi_pad_i               => jtag_tdi,
 | 
			
		||||
	    tdo_pad_o               => jtag_tdo,
 | 
			
		||||
	    tdo_padoe_o             => open,      -- what to do with this?
 | 
			
		||||
 | 
			
		||||
	    shift_dr_o              => shift,
 | 
			
		||||
	    pause_dr_o              => open,      -- what to do with this?
 | 
			
		||||
	    update_dr_o             => update,
 | 
			
		||||
	    capture_dr_o            => capture,
 | 
			
		||||
 | 
			
		||||
	    -- connect boundary scan and mbist?
 | 
			
		||||
	    extest_select_o         => open,
 | 
			
		||||
	    sample_preload_select_o => open,
 | 
			
		||||
	    mbist_select_o          => open,
 | 
			
		||||
	    debug_select_o          => sel,
 | 
			
		||||
 | 
			
		||||
	    tdo_o                   => tdi,
 | 
			
		||||
            debug_tdi_i             => tdo,
 | 
			
		||||
	    bs_chain_tdi_i          => '0',
 | 
			
		||||
            mbist_tdi_i             => '0'
 | 
			
		||||
	    );
 | 
			
		||||
 | 
			
		||||
    -- dmi_req synchronization
 | 
			
		||||
    dmi_req_sync : process(sys_clk)
 | 
			
		||||
    begin
 | 
			
		||||
	-- sys_reset is synchronous
 | 
			
		||||
	if rising_edge(sys_clk) then
 | 
			
		||||
	    if (sys_reset = '1') then
 | 
			
		||||
		jtag_req_0 <= '0';
 | 
			
		||||
		jtag_req_1 <= '0';
 | 
			
		||||
	    else
 | 
			
		||||
		jtag_req_0 <= jtag_req;
 | 
			
		||||
		jtag_req_1 <= jtag_req_0;
 | 
			
		||||
	    end if;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
    dmi_req <= jtag_req_1;
 | 
			
		||||
 | 
			
		||||
    -- dmi_ack synchronization
 | 
			
		||||
    dmi_ack_sync: process(jtag_tck, jtag_trst)
 | 
			
		||||
    begin
 | 
			
		||||
	-- jtag_trst is async (see comments)
 | 
			
		||||
	if jtag_trst = '1' then
 | 
			
		||||
	    dmi_ack_0 <= '0';
 | 
			
		||||
	    dmi_ack_1 <= '0';
 | 
			
		||||
	elsif rising_edge(jtag_tck) then
 | 
			
		||||
	    dmi_ack_0 <= dmi_ack;
 | 
			
		||||
	    dmi_ack_1 <= dmi_ack_0;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
    -- jtag_bsy indicates whether we can start a new request, we can when
 | 
			
		||||
    -- we aren't already processing one (jtag_req) and the synchronized ack
 | 
			
		||||
    -- of the previous one is 0.
 | 
			
		||||
    --
 | 
			
		||||
    jtag_bsy <= jtag_req or dmi_ack_1;
 | 
			
		||||
 | 
			
		||||
    -- decode request type in shift register
 | 
			
		||||
    with shiftr(1 downto 0) select op_valid <=
 | 
			
		||||
	'1' when DMI_REQ_RD,
 | 
			
		||||
	'1' when DMI_REQ_WR,
 | 
			
		||||
	'0' when others;
 | 
			
		||||
 | 
			
		||||
    -- encode response op
 | 
			
		||||
    rsp_op <= DMI_RSP_BSY when jtag_bsy = '1' else DMI_RSP_OK;
 | 
			
		||||
 | 
			
		||||
    -- Some DMI out signals are directly driven from the request register
 | 
			
		||||
    dmi_addr <= request(ABITS + DBITS + 1 downto DBITS + 2);
 | 
			
		||||
    dmi_dout <= request(DBITS + 1 downto 2);
 | 
			
		||||
    dmi_wr   <= '1' when request(1 downto 0) = DMI_REQ_WR else '0';
 | 
			
		||||
 | 
			
		||||
    -- TDO is wired to shift register bit 0
 | 
			
		||||
    tdo <= shiftr(0);
 | 
			
		||||
 | 
			
		||||
    -- Main state machine. Handles shift registers, request latch and
 | 
			
		||||
    -- jtag_req latch. Could be split into 3 processes but it's probably
 | 
			
		||||
    -- not worthwhile.
 | 
			
		||||
    --
 | 
			
		||||
    shifter: process(jtag_tck, jtag_trst, sys_reset)
 | 
			
		||||
    begin
 | 
			
		||||
	if jtag_trst = '1' or sys_reset = '1' then
 | 
			
		||||
	    shiftr <= (others => '0');
 | 
			
		||||
	    jtag_req <= '0';
 | 
			
		||||
	    request <= (others => '0');
 | 
			
		||||
	elsif rising_edge(jtag_tck) then
 | 
			
		||||
 | 
			
		||||
	    -- Handle jtag "commands" when sel is 1
 | 
			
		||||
	    if sel = '1' then
 | 
			
		||||
		-- Shift state, rotate the register
 | 
			
		||||
		if shift = '1' then
 | 
			
		||||
		    shiftr <= tdi & shiftr(ABITS + DBITS + 1 downto 1);
 | 
			
		||||
		end if;
 | 
			
		||||
 | 
			
		||||
		-- Update state (trigger)
 | 
			
		||||
		--
 | 
			
		||||
		-- Latch the request if we aren't already processing one and
 | 
			
		||||
		-- it has a valid command opcode.
 | 
			
		||||
		--
 | 
			
		||||
	    	if update = '1' and op_valid = '1' then
 | 
			
		||||
		    if jtag_bsy = '0' then
 | 
			
		||||
			request <= shiftr;
 | 
			
		||||
			jtag_req <= '1';
 | 
			
		||||
		    end if;
 | 
			
		||||
		    -- Set the shift register "op" to "busy". This will prevent
 | 
			
		||||
		    -- us from re-starting the command on the next update if
 | 
			
		||||
		    -- the command completes before that.
 | 
			
		||||
		    shiftr(1 downto 0) <= DMI_RSP_BSY;
 | 
			
		||||
		end if;
 | 
			
		||||
 | 
			
		||||
		-- Request completion.
 | 
			
		||||
		--
 | 
			
		||||
		-- Capture the response data for reads and clear request flag.
 | 
			
		||||
		--
 | 
			
		||||
		-- Note: We clear req (and thus dmi_req) here which relies on tck
 | 
			
		||||
		-- ticking and sel set. This means we are stuck with dmi_req up if
 | 
			
		||||
		-- the jtag interface stops. Slaves must be resilient to this.
 | 
			
		||||
		--
 | 
			
		||||
		if jtag_req = '1' and dmi_ack_1 = '1' then
 | 
			
		||||
		    jtag_req <= '0';
 | 
			
		||||
		    if request(1 downto 0) = DMI_REQ_RD then
 | 
			
		||||
			request(DBITS + 1 downto 2) <= dmi_din;
 | 
			
		||||
		    end if;
 | 
			
		||||
		end if;
 | 
			
		||||
 | 
			
		||||
		-- Capture state, grab latch content with updated status
 | 
			
		||||
		if capture = '1' then
 | 
			
		||||
		    shiftr <= request(ABITS + DBITS + 1 downto 2) & rsp_op;
 | 
			
		||||
		end if;
 | 
			
		||||
 | 
			
		||||
	    end if;
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
end architecture behaviour;
 | 
			
		||||
@ -0,0 +1,640 @@
 | 
			
		||||
//////////////////////////////////////////////////////////////////////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
////  tap_top.v                                                   ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
////  This file is part of the JTAG Test Access Port (TAP)        ////
 | 
			
		||||
////  http://www.opencores.org/projects/jtag/                     ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
////  Author(s):                                                  ////
 | 
			
		||||
////       Igor Mohor (igorm@opencores.org)                       ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
////  All additional information is avaliable in the README.txt   ////
 | 
			
		||||
////  file.                                                       ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
//////////////////////////////////////////////////////////////////////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
//// Copyright (C) 2000 - 2003 Authors                            ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
//// This source file may be used and distributed without         ////
 | 
			
		||||
//// restriction provided that this copyright statement is not    ////
 | 
			
		||||
//// removed from the file and that any derivative work contains  ////
 | 
			
		||||
//// the original copyright notice and the associated disclaimer. ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
//// This source file is free software; you can redistribute it   ////
 | 
			
		||||
//// and/or modify it under the terms of the GNU Lesser General   ////
 | 
			
		||||
//// Public License as published by the Free Software Foundation; ////
 | 
			
		||||
//// either version 2.1 of the License, or (at your option) any   ////
 | 
			
		||||
//// later version.                                               ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
//// This source 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 Lesser General Public License for more ////
 | 
			
		||||
//// details.                                                     ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
//// You should have received a copy of the GNU Lesser General    ////
 | 
			
		||||
//// Public License along with this source; if not, download it   ////
 | 
			
		||||
//// from http://www.opencores.org/lgpl.shtml                     ////
 | 
			
		||||
////                                                              ////
 | 
			
		||||
//////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// CVS Revision History
 | 
			
		||||
//
 | 
			
		||||
// $Log: not supported by cvs2svn $
 | 
			
		||||
// Revision 1.5  2004/01/18 09:27:39  simons
 | 
			
		||||
// Blocking non blocking assignmenst fixed.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.4  2004/01/17 17:37:44  mohor
 | 
			
		||||
// capture_dr_o added to ports.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.3  2004/01/14 13:50:56  mohor
 | 
			
		||||
// 5 consecutive TMS=1 causes reset of TAP.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.2  2004/01/08 10:29:44  mohor
 | 
			
		||||
// Control signals for tdo_pad_o mux are changed to negedge.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.1  2003/12/23 14:52:14  mohor
 | 
			
		||||
// Directory structure changed. New version of TAP.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.10  2003/10/23 18:08:01  mohor
 | 
			
		||||
// MBIST chain connection fixed.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.9  2003/10/23 16:17:02  mohor
 | 
			
		||||
// CRC logic changed.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.8  2003/10/21 09:48:31  simons
 | 
			
		||||
// Mbist support added.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.7  2002/11/06 14:30:10  mohor
 | 
			
		||||
// Trst active high. Inverted on higher layer.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.6  2002/04/22 12:55:56  mohor
 | 
			
		||||
// tdo_padoen_o changed to tdo_padoe_o. Signal is active high.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.5  2002/03/26 14:23:38  mohor
 | 
			
		||||
// Signal tdo_padoe_o changed back to tdo_padoen_o.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.4  2002/03/25 13:16:15  mohor
 | 
			
		||||
// tdo_padoen_o changed to tdo_padoe_o. Signal was always active high, just
 | 
			
		||||
// not named correctly.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.3  2002/03/12 14:30:05  mohor
 | 
			
		||||
// Few outputs for boundary scan chain added.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.2  2002/03/12 10:31:53  mohor
 | 
			
		||||
// tap_top and dbg_top modules are put into two separate modules. tap_top
 | 
			
		||||
// contains only tap state machine and related logic. dbg_top contains all
 | 
			
		||||
// logic necessery for debugging.
 | 
			
		||||
//
 | 
			
		||||
// Revision 1.1  2002/03/08 15:28:16  mohor
 | 
			
		||||
// Structure changed. Hooks for jtag chain added.
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// Top module
 | 
			
		||||
module tap_top #(parameter
 | 
			
		||||
                // 0001             version
 | 
			
		||||
                // 0100100101010001 part number (IQ)
 | 
			
		||||
                // 00011100001      manufacturer id (flextronics)
 | 
			
		||||
                // 1                required by standard
 | 
			
		||||
                IDCODE_VALUE = 32'h149511c3,
 | 
			
		||||
                IR_LENGTH    = 4)
 | 
			
		||||
               (
 | 
			
		||||
                // JTAG pads
 | 
			
		||||
                tms_pad_i, 
 | 
			
		||||
                tck_pad_i, 
 | 
			
		||||
                trst_pad_i, 
 | 
			
		||||
                tdi_pad_i, 
 | 
			
		||||
                tdo_pad_o, 
 | 
			
		||||
                tdo_padoe_o,
 | 
			
		||||
 | 
			
		||||
                // TAP states
 | 
			
		||||
                shift_dr_o,
 | 
			
		||||
                pause_dr_o, 
 | 
			
		||||
                update_dr_o,
 | 
			
		||||
                capture_dr_o,
 | 
			
		||||
                
 | 
			
		||||
                // Select signals for boundary scan or mbist
 | 
			
		||||
                extest_select_o, 
 | 
			
		||||
                sample_preload_select_o,
 | 
			
		||||
                mbist_select_o,
 | 
			
		||||
                debug_select_o,
 | 
			
		||||
                
 | 
			
		||||
                // TDO signal that is connected to TDI of sub-modules.
 | 
			
		||||
                tdo_o, 
 | 
			
		||||
                
 | 
			
		||||
                // TDI signals from sub-modules
 | 
			
		||||
                debug_tdi_i,    // from debug module
 | 
			
		||||
                bs_chain_tdi_i, // from Boundary Scan Chain
 | 
			
		||||
                mbist_tdi_i     // from Mbist Chain
 | 
			
		||||
              );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// JTAG pins
 | 
			
		||||
input   tms_pad_i;      // JTAG test mode select pad
 | 
			
		||||
input   tck_pad_i;      // JTAG test clock pad
 | 
			
		||||
input   trst_pad_i;     // JTAG test reset pad
 | 
			
		||||
input   tdi_pad_i;      // JTAG test data input pad
 | 
			
		||||
output  tdo_pad_o;      // JTAG test data output pad
 | 
			
		||||
output  tdo_padoe_o;    // Output enable for JTAG test data output pad 
 | 
			
		||||
 | 
			
		||||
// TAP states
 | 
			
		||||
output  shift_dr_o;
 | 
			
		||||
output  pause_dr_o;
 | 
			
		||||
output  update_dr_o;
 | 
			
		||||
output  capture_dr_o;
 | 
			
		||||
 | 
			
		||||
// Select signals for boundary scan or mbist
 | 
			
		||||
output  extest_select_o;
 | 
			
		||||
output  sample_preload_select_o;
 | 
			
		||||
output  mbist_select_o;
 | 
			
		||||
output  debug_select_o;
 | 
			
		||||
 | 
			
		||||
// TDO signal that is connected to TDI of sub-modules.
 | 
			
		||||
output  tdo_o;
 | 
			
		||||
 | 
			
		||||
// TDI signals from sub-modules
 | 
			
		||||
input   debug_tdi_i;    // from debug module
 | 
			
		||||
input   bs_chain_tdi_i; // from Boundary Scan Chain
 | 
			
		||||
input   mbist_tdi_i;    // from Mbist Chain
 | 
			
		||||
 | 
			
		||||
//Internal constants
 | 
			
		||||
localparam EXTEST         = 4'b0000;
 | 
			
		||||
localparam SAMPLE_PRELOAD = 4'b0001;
 | 
			
		||||
localparam IDCODE         = 4'b0010;
 | 
			
		||||
localparam DEBUG          = 4'b1000;
 | 
			
		||||
localparam MBIST          = 4'b1001;
 | 
			
		||||
localparam BYPASS         = 4'b1111;
 | 
			
		||||
 | 
			
		||||
// Registers
 | 
			
		||||
reg     test_logic_reset;
 | 
			
		||||
reg     run_test_idle;
 | 
			
		||||
reg     select_dr_scan;
 | 
			
		||||
reg     capture_dr;
 | 
			
		||||
reg     shift_dr;
 | 
			
		||||
reg     exit1_dr;
 | 
			
		||||
reg     pause_dr;
 | 
			
		||||
reg     exit2_dr;
 | 
			
		||||
reg     update_dr;
 | 
			
		||||
reg     select_ir_scan;
 | 
			
		||||
reg     capture_ir;
 | 
			
		||||
reg     shift_ir, shift_ir_neg;
 | 
			
		||||
reg     exit1_ir;
 | 
			
		||||
reg     pause_ir;
 | 
			
		||||
reg     exit2_ir;
 | 
			
		||||
reg     update_ir;
 | 
			
		||||
reg     extest_select;
 | 
			
		||||
reg     sample_preload_select;
 | 
			
		||||
reg     idcode_select;
 | 
			
		||||
reg     mbist_select;
 | 
			
		||||
reg     debug_select;
 | 
			
		||||
reg     bypass_select;
 | 
			
		||||
reg     tdo_pad_o;
 | 
			
		||||
reg     tdo_padoe_o;
 | 
			
		||||
reg     tms_q1, tms_q2, tms_q3, tms_q4;
 | 
			
		||||
wire    tms_reset;
 | 
			
		||||
 | 
			
		||||
assign tdo_o = tdi_pad_i;
 | 
			
		||||
assign shift_dr_o = shift_dr;
 | 
			
		||||
assign pause_dr_o = pause_dr;
 | 
			
		||||
assign update_dr_o = update_dr;
 | 
			
		||||
assign capture_dr_o = capture_dr;
 | 
			
		||||
 | 
			
		||||
assign extest_select_o = extest_select;
 | 
			
		||||
assign sample_preload_select_o = sample_preload_select;
 | 
			
		||||
assign mbist_select_o = mbist_select;
 | 
			
		||||
assign debug_select_o = debug_select;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
always @ (posedge tck_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  tms_q1 <= tms_pad_i;
 | 
			
		||||
  tms_q2 <= tms_q1;
 | 
			
		||||
  tms_q3 <= tms_q2;
 | 
			
		||||
  tms_q4 <= tms_q3;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
assign tms_reset = tms_q1 & tms_q2 & tms_q3 & tms_q4 & tms_pad_i;    // 5 consecutive TMS=1 causes reset
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   TAP State Machine: Fully JTAG compliant                                       *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
 | 
			
		||||
// test_logic_reset state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    test_logic_reset<= 1'b1;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    test_logic_reset<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    begin
 | 
			
		||||
      if(tms_pad_i & (test_logic_reset | select_ir_scan))
 | 
			
		||||
        test_logic_reset<= 1'b1;
 | 
			
		||||
      else
 | 
			
		||||
        test_logic_reset<= 1'b0;
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// run_test_idle state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    run_test_idle<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    run_test_idle<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(~tms_pad_i & (test_logic_reset | run_test_idle | update_dr | update_ir))
 | 
			
		||||
    run_test_idle<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    run_test_idle<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// select_dr_scan state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    select_dr_scan<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    select_dr_scan<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & (run_test_idle | update_dr | update_ir))
 | 
			
		||||
    select_dr_scan<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    select_dr_scan<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// capture_dr state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    capture_dr<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    capture_dr<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(~tms_pad_i & select_dr_scan)
 | 
			
		||||
    capture_dr<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    capture_dr<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// shift_dr state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    shift_dr<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    shift_dr<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(~tms_pad_i & (capture_dr | shift_dr | exit2_dr))
 | 
			
		||||
    shift_dr<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    shift_dr<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// exit1_dr state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    exit1_dr<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    exit1_dr<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & (capture_dr | shift_dr))
 | 
			
		||||
    exit1_dr<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    exit1_dr<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// pause_dr state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    pause_dr<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    pause_dr<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(~tms_pad_i & (exit1_dr | pause_dr))
 | 
			
		||||
    pause_dr<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    pause_dr<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// exit2_dr state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    exit2_dr<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    exit2_dr<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & pause_dr)
 | 
			
		||||
    exit2_dr<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    exit2_dr<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// update_dr state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    update_dr<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    update_dr<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & (exit1_dr | exit2_dr))
 | 
			
		||||
    update_dr<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    update_dr<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// select_ir_scan state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    select_ir_scan<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    select_ir_scan<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & select_dr_scan)
 | 
			
		||||
    select_ir_scan<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    select_ir_scan<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// capture_ir state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    capture_ir<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    capture_ir<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(~tms_pad_i & select_ir_scan)
 | 
			
		||||
    capture_ir<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    capture_ir<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// shift_ir state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    shift_ir<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    shift_ir<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(~tms_pad_i & (capture_ir | shift_ir | exit2_ir))
 | 
			
		||||
    shift_ir<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    shift_ir<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// exit1_ir state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    exit1_ir<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    exit1_ir<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & (capture_ir | shift_ir))
 | 
			
		||||
    exit1_ir<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    exit1_ir<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// pause_ir state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    pause_ir<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    pause_ir<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(~tms_pad_i & (exit1_ir | pause_ir))
 | 
			
		||||
    pause_ir<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    pause_ir<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// exit2_ir state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    exit2_ir<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    exit2_ir<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & pause_ir)
 | 
			
		||||
    exit2_ir<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    exit2_ir<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
// update_ir state
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    update_ir<= 1'b0;
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    update_ir<= 1'b0;
 | 
			
		||||
  else
 | 
			
		||||
  if(tms_pad_i & (exit1_ir | exit2_ir))
 | 
			
		||||
    update_ir<= 1'b1;
 | 
			
		||||
  else
 | 
			
		||||
    update_ir<= 1'b0;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   End: TAP State Machine                                                        *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   jtag_ir:  JTAG Instruction Register                                           *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
reg [IR_LENGTH-1:0]  jtag_ir;          // Instruction register
 | 
			
		||||
reg [IR_LENGTH-1:0]  latched_jtag_ir, latched_jtag_ir_neg;
 | 
			
		||||
reg                   instruction_tdo;
 | 
			
		||||
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    jtag_ir[IR_LENGTH-1:0] <= {IR_LENGTH{1'b0}};
 | 
			
		||||
  else if(capture_ir)
 | 
			
		||||
    jtag_ir <= 4'b0101;          // This value is fixed for easier fault detection
 | 
			
		||||
  else if(shift_ir)
 | 
			
		||||
    jtag_ir[IR_LENGTH-1:0] <= {tdi_pad_i, jtag_ir[IR_LENGTH-1:1]};
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
always @ (negedge tck_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  instruction_tdo <= jtag_ir[0];
 | 
			
		||||
end
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   End: jtag_ir                                                                  *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   idcode logic                                                                  *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
reg [31:0] idcode_reg;
 | 
			
		||||
reg        idcode_tdo;
 | 
			
		||||
 | 
			
		||||
always @ (posedge tck_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(idcode_select & shift_dr)
 | 
			
		||||
    idcode_reg <= {tdi_pad_i, idcode_reg[31:1]};
 | 
			
		||||
  else
 | 
			
		||||
    idcode_reg <= IDCODE_VALUE;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
always @ (negedge tck_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
    idcode_tdo <= idcode_reg[0];
 | 
			
		||||
end
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   End: idcode logic                                                             *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   Bypass logic                                                                  *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
reg  bypassed_tdo;
 | 
			
		||||
reg  bypass_reg;
 | 
			
		||||
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if (trst_pad_i)
 | 
			
		||||
    bypass_reg<= 1'b0;
 | 
			
		||||
  else if(shift_dr)
 | 
			
		||||
    bypass_reg<= tdi_pad_i;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
always @ (negedge tck_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  bypassed_tdo <= bypass_reg;
 | 
			
		||||
end
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   End: Bypass logic                                                             *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   Activating Instructions                                                       *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
// Updating jtag_ir (Instruction Register)
 | 
			
		||||
always @ (posedge tck_pad_i or posedge trst_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  if(trst_pad_i)
 | 
			
		||||
    latched_jtag_ir <= IDCODE;   // IDCODE selected after reset
 | 
			
		||||
  else if (tms_reset)
 | 
			
		||||
    latched_jtag_ir <= IDCODE;   // IDCODE selected after reset
 | 
			
		||||
  else if(update_ir)
 | 
			
		||||
    latched_jtag_ir <= jtag_ir;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   End: Activating Instructions                                                  *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Updating jtag_ir (Instruction Register)
 | 
			
		||||
always @ (latched_jtag_ir)
 | 
			
		||||
begin
 | 
			
		||||
  extest_select           = 1'b0;
 | 
			
		||||
  sample_preload_select   = 1'b0;
 | 
			
		||||
  idcode_select           = 1'b0;
 | 
			
		||||
  mbist_select            = 1'b0;
 | 
			
		||||
  debug_select            = 1'b0;
 | 
			
		||||
  bypass_select           = 1'b0;
 | 
			
		||||
 | 
			
		||||
  case(latched_jtag_ir)    /* synthesis parallel_case */ 
 | 
			
		||||
    EXTEST:            extest_select           = 1'b1;    // External test
 | 
			
		||||
    SAMPLE_PRELOAD:    sample_preload_select   = 1'b1;    // Sample preload
 | 
			
		||||
    IDCODE:            idcode_select           = 1'b1;    // ID Code
 | 
			
		||||
    MBIST:             mbist_select            = 1'b1;    // Mbist test
 | 
			
		||||
    DEBUG:             debug_select            = 1'b1;    // Debug
 | 
			
		||||
    BYPASS:            bypass_select           = 1'b1;    // BYPASS
 | 
			
		||||
    default:            bypass_select           = 1'b1;    // BYPASS
 | 
			
		||||
  endcase
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   Multiplexing TDO data                                                         *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
always @ (shift_ir_neg or exit1_ir or instruction_tdo or latched_jtag_ir_neg or idcode_tdo or
 | 
			
		||||
          debug_tdi_i or bs_chain_tdi_i or mbist_tdi_i or 
 | 
			
		||||
          bypassed_tdo)
 | 
			
		||||
begin
 | 
			
		||||
  if(shift_ir_neg)
 | 
			
		||||
    tdo_pad_o = instruction_tdo;
 | 
			
		||||
  else
 | 
			
		||||
    begin
 | 
			
		||||
      case(latched_jtag_ir_neg)    // synthesis parallel_case
 | 
			
		||||
        IDCODE:            tdo_pad_o = idcode_tdo;       // Reading ID code
 | 
			
		||||
        DEBUG:             tdo_pad_o = debug_tdi_i;      // Debug
 | 
			
		||||
        SAMPLE_PRELOAD:    tdo_pad_o = bs_chain_tdi_i;   // Sampling/Preloading
 | 
			
		||||
        EXTEST:            tdo_pad_o = bs_chain_tdi_i;   // External test
 | 
			
		||||
        MBIST:             tdo_pad_o = mbist_tdi_i;      // Mbist test
 | 
			
		||||
        default:            tdo_pad_o = bypassed_tdo;     // BYPASS instruction
 | 
			
		||||
      endcase
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Tristate control for tdo_pad_o pin
 | 
			
		||||
always @ (negedge tck_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  tdo_padoe_o <= shift_ir | shift_dr | (pause_dr & debug_select);
 | 
			
		||||
end
 | 
			
		||||
/**********************************************************************************
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
*   End: Multiplexing TDO data                                                    *
 | 
			
		||||
*                                                                                 *
 | 
			
		||||
**********************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
always @ (negedge tck_pad_i)
 | 
			
		||||
begin
 | 
			
		||||
  shift_ir_neg <= shift_ir;
 | 
			
		||||
  latched_jtag_ir_neg <= latched_jtag_ir;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
@ -0,0 +1,196 @@
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
 | 
			
		||||
#undef DEBUG
 | 
			
		||||
 | 
			
		||||
/* XXX Make that some parameter */
 | 
			
		||||
#define TCP_PORT	13245
 | 
			
		||||
 | 
			
		||||
static int fd = -1;
 | 
			
		||||
static int cfd = -1;
 | 
			
		||||
 | 
			
		||||
static void open_socket(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_in addr;
 | 
			
		||||
	int opt, rc, flags;
 | 
			
		||||
 | 
			
		||||
	if (fd >= 0 || fd < -1)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	signal(SIGPIPE, SIG_IGN);
 | 
			
		||||
	fd = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		fprintf(stderr, "Failed to open debug socket\r\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = 0;
 | 
			
		||||
	flags = fcntl(fd, F_GETFL);
 | 
			
		||||
	if (flags >= 0)
 | 
			
		||||
		rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 | 
			
		||||
	if (flags < 0 || rc < 0) {
 | 
			
		||||
		fprintf(stderr, "Failed to configure debug socket\r\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&addr, 0, sizeof(addr));
 | 
			
		||||
	addr.sin_family = AF_INET;
 | 
			
		||||
	addr.sin_port = htons(TCP_PORT);
 | 
			
		||||
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
 | 
			
		||||
	opt = 1;
 | 
			
		||||
	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 | 
			
		||||
	rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		fprintf(stderr, "Failed to bind debug socket\r\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
	rc = listen(fd,1);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		fprintf(stderr, "Failed to listen to debug socket\r\n");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
	fprintf(stdout, "Debug socket ready\r\n");
 | 
			
		||||
#endif
 | 
			
		||||
	return;
 | 
			
		||||
fail:
 | 
			
		||||
	if (fd >= 0)
 | 
			
		||||
		close(fd);
 | 
			
		||||
	fd = -2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_connection(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_in addr;
 | 
			
		||||
	socklen_t addr_len = sizeof(addr);
 | 
			
		||||
 | 
			
		||||
	cfd = accept(fd, (struct sockaddr *)&addr, &addr_len);
 | 
			
		||||
	if (cfd < 0)
 | 
			
		||||
		return;
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
	fprintf(stdout, "Debug client connected\r\n");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool read_one_byte(char *c)
 | 
			
		||||
{
 | 
			
		||||
	struct pollfd fdset[1];
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	if (fd == -1)
 | 
			
		||||
		open_socket();
 | 
			
		||||
	if (fd < 0)
 | 
			
		||||
		return false;
 | 
			
		||||
	if (cfd < 0)
 | 
			
		||||
		check_connection();
 | 
			
		||||
	if (cfd < 0)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	memset(fdset, 0, sizeof(fdset));
 | 
			
		||||
	fdset[0].fd = cfd;
 | 
			
		||||
	fdset[0].events = POLLIN;
 | 
			
		||||
	rc = poll(fdset, 1, 0);
 | 
			
		||||
	if (rc <= 0)
 | 
			
		||||
		return false;
 | 
			
		||||
	rc = read(cfd, c, 1);
 | 
			
		||||
	if (rc != 1) {
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
		fprintf(stdout, "Debug read error, assuming client disconnected !\r\n");
 | 
			
		||||
#endif
 | 
			
		||||
		close(cfd);
 | 
			
		||||
		cfd = -1;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
	fprintf(stdout, "Got message: %c\n", *c);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_one_byte(char c)
 | 
			
		||||
{
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
	fprintf(stdout, "Sending message: %c\r\n", c);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	rc = write(cfd, &c, 1);
 | 
			
		||||
	if (rc != 1) {
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
		fprintf(stdout, "JTAG write error, disconnecting\r\n");
 | 
			
		||||
#endif
 | 
			
		||||
		close(cfd);
 | 
			
		||||
		cfd = -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct jtag_in {
 | 
			
		||||
	uint8_t tck;
 | 
			
		||||
	uint8_t tms;
 | 
			
		||||
	uint8_t tdi;
 | 
			
		||||
	uint8_t trst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct jtag_in jtag_in;
 | 
			
		||||
 | 
			
		||||
struct jtag_in jtag_one_cycle(uint8_t tdo)
 | 
			
		||||
{
 | 
			
		||||
	char c;
 | 
			
		||||
 | 
			
		||||
	if (read_one_byte(&c) == false)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	// Write request
 | 
			
		||||
	if ((c >= '0') && (c <= '7')) {
 | 
			
		||||
		uint8_t val = c - '0';
 | 
			
		||||
 | 
			
		||||
		jtag_in.tck = (val >> 2) & 1;
 | 
			
		||||
		jtag_in.tms = (val >> 1) & 1;
 | 
			
		||||
		jtag_in.tdi = (val >> 0) & 1;
 | 
			
		||||
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Reset request
 | 
			
		||||
	if ((c >= 'r') && (c <= 'u')) {
 | 
			
		||||
		uint8_t val = c - 'r';
 | 
			
		||||
 | 
			
		||||
		jtag_in.trst = (val >> 1) & 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (c) {
 | 
			
		||||
		case 'B':	// Blink on
 | 
			
		||||
		case 'b':	// Blink off
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		case 'R':	// Read request
 | 
			
		||||
			write_one_byte(tdo + '0');
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		case 'Q':	// Quit request
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
			fprintf(stdout, "Disconnecting JTAG\r\n");
 | 
			
		||||
#endif
 | 
			
		||||
			close(cfd);
 | 
			
		||||
			cfd = -1;
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			fprintf(stderr, "Unknown JTAG command %c\r\n", c);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	return jtag_in;
 | 
			
		||||
}
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue