--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+library work;
+
+library nexys2_lib;
+
+
+entity nexys2_test_jtag is
+ port (
+ clk_50: in std_logic;
+ seg: out std_logic_vector(6 downto 0);
+ dp: out std_logic;
+ an: out std_logic_vector(3 downto 0);
+ Led: out std_logic_vector(7 downto 0);
+ sw: in std_logic_vector(7 downto 0)
+ );
+end nexys2_test_jtag;
+
+
+architecture behavioral of nexys2_test_jtag is
+
+ signal jtag_capture: std_logic;
+ signal jtag_drck1: std_logic;
+ signal jtag_drck2: std_logic;
+ signal jtag_reset: std_logic;
+ signal jtag_sel1: std_logic;
+ signal jtag_sel2: std_logic;
+ signal jtag_shift: std_logic;
+ signal jtag_tdi: std_logic;
+ signal jtag_update: std_logic;
+ signal jtag_tdo1: std_logic;
+ signal jtag_tdo2: std_logic;
+
+ signal clk_div_reg: std_logic_vector(15 downto 0);
+ signal seg_0: std_logic_vector(6 downto 0);
+ signal seg_1: std_logic_vector(6 downto 0);
+ signal seg_2: std_logic_vector(6 downto 0);
+ signal seg_3: std_logic_vector(6 downto 0);
+
+ signal user1: std_logic_vector(3 downto 0);
+ signal user1_reg: std_logic_vector(3 downto 0);
+ signal user1_update: std_logic;
+ signal user1_count_reg: std_logic_vector(7 downto 0);
+
+ signal user2: std_logic_vector(3 downto 0);
+ signal user2_reg: std_logic_vector(3 downto 0);
+ signal user2_update: std_logic;
+ signal user2_count_reg: std_logic_vector(7 downto 0);
+
+begin
+
+ e_bscan: bscan_spartan3
+ port map (
+ reset => jtag_reset,
+ capture => jtag_capture,
+ shift => jtag_shift,
+ update => jtag_update,
+
+ tdi => jtag_tdi,
+
+ drck1 => jtag_drck1,
+ sel1 => jtag_sel1,
+ tdo1 => jtag_tdo1,
+
+ drck2 => jtag_drck2,
+ sel2 => jtag_sel2,
+ tdo2 => jtag_tdo2
+ );
+
+
+ e_user1: entity work.jtag_reg
+ generic map (N => 4)
+ port map (
+ clk_i => clk_50,
+ upd_o => user1_update,
+ dat_i => sw(7 downto 4),
+ dat_o => user1,
+
+ reset => jtag_reset,
+ capture => jtag_capture,
+ shift => jtag_shift,
+ update => jtag_update,
+ sel => jtag_sel1,
+ drck => jtag_drck1,
+ tdi => jtag_tdi,
+ tdo => jtag_tdo1
+ );
+
+
+ e_user2: entity work.jtag_reg
+ generic map (N => 4)
+ port map (
+ clk_i => clk_50,
+ upd_o => user2_update,
+ dat_i => sw(3 downto 0),
+ dat_o => user2,
+
+ reset => jtag_reset,
+ capture => jtag_capture,
+ shift => jtag_shift,
+ update => jtag_update,
+ sel => jtag_sel2,
+ drck => jtag_drck2,
+ tdi => jtag_tdi,
+ tdo => jtag_tdo2
+ );
+
+
+ process (clk_50)
+ begin
+ if rising_edge(clk_50) then
+ clk_div_reg <= std_logic_vector(unsigned(clk_div_reg) + 1);
+
+ if user1_update = '1' then
+ user1_reg <= user1;
+ user1_count_reg <= std_logic_vector(unsigned(user1_count_reg) + 1);
+ end if;
+
+ if user2_update = '1' then
+ user2_reg <= user2;
+ user2_count_reg <= std_logic_vector(unsigned(user2_count_reg) + 1);
+ end if;
+ end if;
+ end process;
+ Led(7 downto 4) <= user1_reg;
+ Led(3 downto 0) <= user2_reg;
+
+
+ e_seven_seg_hex_0: entity nexys2_lib.seven_seg_hex
+ port map (
+ data_in => user2_count_reg(3 downto 0),
+ seg_out => seg_0
+ );
+
+
+ e_seven_seg_hex_1: entity nexys2_lib.seven_seg_hex
+ port map (
+ data_in => user2_count_reg(7 downto 4),
+ seg_out => seg_1
+ );
+
+
+ e_seven_seg_hex_2: entity nexys2_lib.seven_seg_hex
+ port map (
+ data_in => user1_count_reg(3 downto 0),
+ seg_out => seg_2
+ );
+
+
+ e_seven_seg_hex_3: entity nexys2_lib.seven_seg_hex
+ port map (
+ data_in => user1_count_reg(7 downto 4),
+ seg_out => seg_3
+ );
+
+
+ e_seven_seg_mux: entity nexys2_lib.seven_seg_mux
+ port map (
+ clk_in => clk_div_reg(15),
+ clk_en => '1',
+ seg_0_in => seg_0,
+ seg_1_in => seg_1,
+ seg_2_in => seg_2,
+ seg_3_in => seg_3,
+ dps_in => "1011",
+ seg_out => seg,
+ dp_out => dp,
+ an_out => an
+ );
+
+end behavioral;
--- /dev/null
+#include <stdbool.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+// Digilent SDK
+#include <dpcdecl.h>
+#include <djtg.h>
+#include <dmgr.h>
+
+#include "ec.h"
+
+#define MAX_ID_CODES 16
+#define MAX_REG_WIDTH 0x1000
+#define SENTINEL 0xdeadbeefcafefeed
+
+// Debug
+#include <unistd.h>
+
+
+// -----------------------------------------------------------------------------
+
+
+uint8_t tms_shift_dr[] = {0x01};
+const uint32_t tms_shift_dr_bits = 3;
+
+uint8_t tms_shift_ir[] = {0x03};
+const uint32_t tms_shift_ir_bits = 4;
+
+uint8_t tms_shift_to_idle[] = {0x03};
+const uint32_t tms_shift_to_idle_bits = 3;
+
+uint64_t window = 0;
+
+
+uint64_t field_read(size_t num_bits)
+{
+ assert(num_bits <= 64);
+ uint64_t mask = num_bits == 64 ? ~0ull : (1ull << num_bits) - 1;
+ return window & mask;
+}
+
+
+void field_write(size_t num_bits, uint64_t value)
+{
+ assert(num_bits <= 64);
+ uint64_t mask = num_bits == 64 ? ~0ull : (1ull << num_bits) - 1;
+ window = (window & ~mask) | (value & mask);
+}
+
+
+bool tap_reset(HIF hif)
+{
+ return DjtgClockTck(hif, true, false, 5, false);
+}
+
+
+bool tap_reset_to_idle(HIF hif)
+{
+ return DjtgClockTck(hif, false, false, 1, false);
+}
+
+
+bool tap_idle_to_dr(HIF hif)
+{
+ //return DjtgPutTmsBits(hif, false, tms_shift_dr, NULL, tms_shift_dr_bits, false);
+ EC_FALSE(DjtgClockTck(hif, true, false, 1, false));
+ EC_FALSE(DjtgClockTck(hif, false, false, 1, false));
+ EC_FALSE(DjtgClockTck(hif, false, false, 1, false));
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool tap_idle_to_ir(HIF hif)
+{
+ //return DjtgPutTmsBits(hif, false, tms_shift_ir, NULL, tms_shift_ir_bits, false);
+ EC_FALSE(DjtgClockTck(hif, true, false, 2, false));
+ EC_FALSE(DjtgClockTck(hif, false, false, 1, false));
+ EC_FALSE(DjtgClockTck(hif, false, false, 1, false));
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool tap_reg_to_idle(HIF hif)
+{
+ //return DjtgPutTmsBits(hif, false, tms_shift_to_idle, NULL, tms_shift_to_idle_bits, false);
+ EC_FALSE(DjtgClockTck(hif, true, false, 2, false));
+ EC_FALSE(DjtgClockTck(hif, false, false, 1, false));
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool tap_reg_shift(HIF hif, size_t num_bits, bool final)
+{
+ assert(hif != hifInvalid);
+ int tms, tdi, tdo, tck;
+
+ for (size_t i = 0; i < num_bits; i++)
+ {
+ EC_FALSE(DjtgGetTmsTdiTdoTck(hif, &tms, &tdi, &tdo, &tck));
+ tdi = window & 1;
+ if (final)
+ {
+ EC_FALSE(DjtgClockTck(hif, i == num_bits-1, tdi, 1, false));
+ }
+ else
+ {
+ EC_FALSE(DjtgClockTck(hif, false, tdi, 1, false));
+ }
+ window >>= 1;
+ if (tdo) window |= 0x8000000000000000;
+ }
+ if (final)
+ {
+ EC_FALSE(DjtgClockTck(hif, true, false, 1, false));
+ EC_FALSE(DjtgClockTck(hif, false, false, 1, false));
+ }
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool tap_reg_get_len(HIF hif, uint32_t *len_out)
+{
+ assert(hif != hifInvalid);
+ assert(len_out != NULL);
+
+ uint32_t len = 0;
+
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ for (len = 0; len < MAX_REG_WIDTH; len++)
+ {
+ if (field_read(64) == SENTINEL) break;
+ EC_FALSE(tap_reg_shift(hif, 1, false));
+ }
+ EC_NE(field_read(64), SENTINEL);
+
+ *len_out = len;
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+bool scan(HIF hif)
+{
+ assert(hif != hifInvalid);
+
+ uint32_t ir_width = 0;
+ uint32_t bypass_width = 0;
+
+ // Assume IDCODE is selected on reset and scan
+ printf("IDCODEs:\n");
+ EC_FALSE(tap_reset(hif));
+ EC_FALSE(tap_reset_to_idle(hif));
+ EC_FALSE(tap_idle_to_dr(hif));
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+ for (size_t i = 0; i < MAX_ID_CODES; i++)
+ {
+ uint32_t idcode = field_read(32);
+ printf(" 0x%08x\n", idcode);
+ EC_FALSE(tap_reg_shift(hif, 32, false));
+ if (field_read(64) == SENTINEL) break;
+ }
+ EC_NE(field_read(64), SENTINEL);
+
+ // Select IR and find length
+ EC_FALSE(tap_reset(hif));
+ EC_FALSE(tap_reset_to_idle(hif));
+ EC_FALSE(tap_idle_to_ir(hif));
+ EC_FALSE(tap_reg_get_len(hif, &ir_width));
+ printf("JTAG chain total IR width: %u\n", ir_width);
+
+ // Select BYPASS and find length
+ // TMS TDI
+ EC_FALSE(DjtgClockTck(hif, false, true, ir_width, false));
+ EC_FALSE(tap_reg_to_idle(hif));
+ EC_FALSE(tap_idle_to_dr(hif));
+ EC_FALSE(tap_reg_get_len(hif, &bypass_width));
+ printf("JTAG chain total BYPASS width: %u\n", bypass_width);
+
+ // Reset
+ EC_FALSE(tap_reset(hif));
+
+ return true;
+EC_CLEANUP_BEGIN
+ return false;
+EC_CLEANUP_END
+}
+
+
+// -----------------------------------------------------------------------------
+
+
+int main(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ // Requested settings
+ char *device = "Nexys2";
+ int32_t port = 0;
+
+ // Port handle and properties
+ HIF hif = hifInvalid;
+ char version[cchVersionMax];
+ int32_t port_count;
+ uint32_t speed;
+
+ // -------------------------------------------------------------
+
+ EC_FALSE(DjtgGetVersion(version));
+ printf("DJTG version: %s\n", version);
+
+ EC_FALSE(DmgrOpen(&hif, device));
+ printf("Opened device \"%s\"\n", device);
+
+ EC_FALSE(DjtgGetPortCount(hif, &port_count));
+ printf("Port count: %" PRIi32 "\n", port_count);
+ for (int32_t i = 0; i < port_count; i++)
+ {
+ uint32_t port_properties = 0;
+ EC_FALSE(DjtgGetPortProperties(hif, i, &port_properties));
+ printf("Port %" PRIi32 " properties: 0x%08" PRIx32 "\n", i, port_properties);
+ printf(" %c JtgSetSpeed\n", port_properties & dprpJtgSetSpeed ? 'y' : 'n');
+ printf(" %c JtgSetPinState\n", port_properties & dprpJtgSetPinState ? 'y' : 'n');
+ printf(" %c JtgWait\n", port_properties & dprpJtgWait ? 'y' : 'n');
+ printf(" %c JtgBatch\n", port_properties & dprpJtgBatch ? 'y' : 'n');
+ printf(" %c JtgSetAuxReset\n", port_properties & dprpJtgSetAuxReset ? 'y' : 'n');
+ printf(" %c JtgSetGetGpio\n", port_properties & dprpJtgSetGetGpio ? 'y' : 'n');
+
+ if (port_properties & dprpJtgBatch)
+ {
+ uint32_t batch_properties = 0;
+ EC_FALSE(DjtgGetBatchProperties(hif, i, &batch_properties));
+ printf(" Batch properties:\n");
+ printf(" %c WaitUs\n", batch_properties & djbpWaitUs ? 'y' : 'n');
+ printf(" %c SetAuxReset\n", batch_properties & djbpSetAuxReset ? 'y' : 'n');
+ printf(" %c SetGetGpio\n", batch_properties & djbpSetGetGpio ? 'y' : 'n');
+ }
+ }
+
+ if (port >= port_count)
+ {
+ fprintf(stderr, "Requested port out of range\n");
+ EC_FAIL;
+ }
+
+ EC_FALSE(DjtgEnableEx(hif, port));
+ printf("Opened JTAG port %" PRIi32 "\n", port);
+
+ EC_FALSE(DjtgGetSpeed(hif, &speed));
+ printf("Port speed: %" PRIi32 " Hz\n", speed);
+
+ // -------------------------------------------------------------
+
+ // Perform a scan to see what's on the chain
+ EC_FALSE(scan(hif));
+ printf("\n\n");
+
+ // Select IR
+ EC_FALSE(tap_reset(hif));
+ EC_FALSE(tap_reset_to_idle(hif));
+ EC_FALSE(tap_idle_to_ir(hif));
+
+ // Insert sentinel
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false));
+
+ // Write first instruction
+ field_write(8, 0xff);
+ EC_FALSE(tap_reg_shift(hif, 7, false));
+
+ // Write second instruction
+ field_write(6, 0x03);
+ EC_FALSE(tap_reg_shift(hif, 6, true));
+
+ // Select DR
+ EC_FALSE(tap_idle_to_dr(hif));
+ field_write(64, SENTINEL);
+ EC_FALSE(tap_reg_shift(hif, 64, false)); // Shift out sentinel
+ EC_FALSE(tap_reg_shift(hif, 1, false)); // Shift out ROM BYPASS
+ printf("USER1: 0x%1" PRIx64 "\n", field_read(4)); // Read USER1
+ field_write(4, 0x3); // Write USER1
+ EC_FALSE(tap_reg_shift(hif, 4, true)); // Shift out USER1
+ EC_NE(field_read(64), SENTINEL); // Verify sentinel
+
+ // -------------------------------------------------------------
+ // Close JTAG session
+
+ if (hif != hifInvalid)
+ {
+ DjtgDisable(hif);
+ DmgrClose(hif);
+ }
+ return 0;
+EC_CLEANUP_BEGIN
+ if (hif != hifInvalid)
+ {
+ DjtgDisable(hif);
+ DmgrClose(hif);
+ }
+ ec_print();
+ return 1;
+EC_CLEANUP_END
+}