[broken]Move code
authorStaf Verhaegen <staf@stafverhaegen.be>
Fri, 6 Dec 2019 18:07:41 +0000 (19:07 +0100)
committerStaf Verhaegen <staf@stafverhaegen.be>
Fri, 6 Dec 2019 18:24:57 +0000 (19:24 +0100)
Moved files without any changes to easily track later changes.

42 files changed:
bench/vhdl/idcode.vhdl [deleted file]
bench/vhdl/sampleshift.vhdl [deleted file]
c4m/cocotb/jtag/c4m_jtag.py [new file with mode: 0644]
c4m/cocotb/jtag/c4m_jtag_svfcocotb.py [new file with mode: 0755]
c4m/cocotb/jtag/c4m_jtag_svfgrammar.py [new file with mode: 0644]
c4m/nmigen/jtag/jtag.py [new file with mode: 0755]
c4m/vhdl/jtag/c4m_jtag_idblock.vhdl [new file with mode: 0644]
c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl [new file with mode: 0644]
c4m/vhdl/jtag/c4m_jtag_iocell.vhdl [new file with mode: 0644]
c4m/vhdl/jtag/c4m_jtag_irblock.vhdl [new file with mode: 0644]
c4m/vhdl/jtag/c4m_jtag_pkg.vhdl [new file with mode: 0644]
c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl [new file with mode: 0644]
c4m/vhdl/jtag/c4m_jtag_tap_fsm.vhdl [new file with mode: 0644]
rtl/nmigen/jtag.py [deleted file]
rtl/vhdl/c4m_jtag_idblock.vhdl [deleted file]
rtl/vhdl/c4m_jtag_ioblock.vhdl [deleted file]
rtl/vhdl/c4m_jtag_iocell.vhdl [deleted file]
rtl/vhdl/c4m_jtag_irblock.vhdl [deleted file]
rtl/vhdl/c4m_jtag_pkg.vhdl [deleted file]
rtl/vhdl/c4m_jtag_tap_controller.vhdl [deleted file]
rtl/vhdl/c4m_jtag_tap_fsm.vhdl [deleted file]
sim/cocotb/c4m_jtag.py [deleted file]
sim/cocotb/c4m_jtag_svfcocotb.py [deleted file]
sim/cocotb/c4m_jtag_svfgrammar.py [deleted file]
sim/cocotb/controller/Makefile [deleted file]
sim/cocotb/controller/c4m_jtag.py [deleted symlink]
sim/cocotb/controller/test.py [deleted file]
sim/cocotb/dual_parallel/Makefile [deleted file]
sim/cocotb/dual_parallel/c4m_jtag.py [deleted symlink]
sim/cocotb/dual_parallel/dual_parallel.vhdl [deleted file]
sim/cocotb/dual_parallel/test.py [deleted file]
sim/ghdl/bench_idcode.sh [deleted file]
test/cocotb/controller/Makefile [new file with mode: 0644]
test/cocotb/controller/c4m_jtag.py [new symlink]
test/cocotb/controller/test.py [new file with mode: 0644]
test/cocotb/dual_parallel/Makefile [new file with mode: 0644]
test/cocotb/dual_parallel/c4m_jtag.py [new symlink]
test/cocotb/dual_parallel/dual_parallel.vhdl [new file with mode: 0644]
test/cocotb/dual_parallel/test.py [new file with mode: 0644]
test/ghdl/idcode/bench_idcode.sh [new file with mode: 0755]
test/rtl/vhdl/idcode.vhdl [new file with mode: 0644]
test/rtl/vhdl/sampleshift.vhdl [new file with mode: 0644]

diff --git a/bench/vhdl/idcode.vhdl b/bench/vhdl/idcode.vhdl
deleted file mode 100644 (file)
index 550df98..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
--- reset JTAG interface and then IDCODE should be shifted out
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity bench_idcode is
-end bench_idcode;
-
-architecture rtl of bench_idcode is
-  signal TCK:   std_logic;
-  signal TMS:   std_logic;
-  signal TDI:   std_logic;
-  signal TDO:   std_logic;
-  signal TRST_N: std_logic;
-
-  constant CLK_PERIOD:  time := 10 ns;
-
-  procedure ClkCycle(
-    signal CLK: out std_logic;
-    CLK_PERIOD: time
-  ) is
-  begin
-    CLK <= '0';
-    wait for CLK_PERIOD/4;
-    CLK <= '1';
-    wait for CLK_PERIOD/2;
-    CLK <= '0';
-    wait for CLK_PERIOD/4;
-  end ClkCycle;
-
-  procedure ClkCycles(
-    N:  integer;
-    signal CLK: out std_logic;
-    CLK_PERIOD: time
-  ) is
-  begin
-    for i in 1 to N loop
-      ClkCycle(CLK, CLK_PERIOD);
-    end loop;
-  end ClkCycles;
-begin
-  JTAG_BLOCK: c4m_jtag_tap_controller
-    -- Use default values
-    port map (
-      TCK => TCK,
-      TMS => TMS,
-      TDI => TDI,
-      TDO => TDO,
-      TRST_N => TRST_N,
-      RESET => open,
-      DRCAPTURE => open,
-      DRSHIFT => open,
-      DRUPDATE => open,
-      IR => open,
-      CORE_OUT => "0",
-      CORE_IN => open,
-      CORE_EN => "0",
-      PAD_OUT => open,
-      PAD_IN => "0",
-      PAD_EN => open
-    );
-
-  SIM: process
-  begin
-    -- Reset
-    TCK <= '0';
-    TMS <= '1';
-    TDI <= '0';
-    TRST_N <= '0';
-    wait for 10*CLK_PERIOD;
-
-    TRST_N <= '1';
-    wait for CLK_PERIOD;
-
-    -- Enter RunTestIdle
-    TMS <= '0';
-    ClkCycle(TCK, CLK_PERIOD);
-    -- Enter SelectDRScan
-    TMS <= '1';
-    ClkCycle(TCK, CLK_PERIOD);
-    -- Enter Capture
-    TMS <= '0';
-    ClkCycle(TCK, CLK_PERIOD);
-    -- Enter Shift, run for 35 CLK cycles
-    TMS <= '0';
-    ClkCycles(35, TCK, CLK_PERIOD);
-    -- Enter Exit1
-    TMS <= '1';
-    ClkCycle(TCK, CLK_PERIOD);
-    -- Enter Update
-    TMS <= '1';
-    ClkCycle(TCK, CLK_PERIOD);
-    -- To TestLogicReset
-    TMS <= '1';
-    ClkCycles(4, TCK, CLK_PERIOD);
-
-    -- end simulation
-    wait;
-  end process;
-end rtl;
diff --git a/bench/vhdl/sampleshift.vhdl b/bench/vhdl/sampleshift.vhdl
deleted file mode 100644 (file)
index 62ec28b..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
--- Test JTAG in the following way:
---  * reset JTAG interface
---  * load samplepreload command
---  * shift in/out sampled inputs + wanted outputs
---  * load extest command
---  * execute
-
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity bench_sampleshift is
-end bench_sampleshift;
-
-architecture rtl of bench_sampleshift is
-  signal TCK:   std_logic;
-  signal TMS:   std_logic;
-  signal TDI:   std_logic;
-  signal TDO:   std_logic;
-  signal TRST_N: std_logic;
-  
-  constant CLK_PERIOD:  time := 10 ns;
-
-  procedure ClkCycle(
-    signal CLK: out std_logic;
-    CLK_PERIOD: time
-  ) is
-  begin
-    CLK <= '0';
-    wait for CLK_PERIOD/4;
-    CLK <= '1';
-    wait for CLK_PERIOD/2;
-    CLK <= '0';
-    wait for CLK_PERIOD/4;
-  end ClkCycle;
-
-  procedure ClkCycles(
-    N:  integer;
-    signal CLK: out std_logic;
-    CLK_PERIOD: time
-  ) is
-  begin
-    for i in 1 to N loop
-      ClkCycle(CLK, CLK_PERIOD);
-    end loop;
-  end ClkCycles;
-  
-  procedure LoadIR(
diff --git a/c4m/cocotb/jtag/c4m_jtag.py b/c4m/cocotb/jtag/c4m_jtag.py
new file mode 100644 (file)
index 0000000..1dd13b1
--- /dev/null
@@ -0,0 +1,210 @@
+import cocotb
+from cocotb.triggers import Timer
+from cocotb.binary import BinaryValue
+
+class JTAGException(Exception):
+    pass
+
+class JTAG_Clock(object):
+    """
+    Class for the JTAG clock, run cycle by cycle
+    """
+    def __init__(self, signal, period):
+        self.signal = signal
+        self.t = Timer(period/4)
+
+    @cocotb.coroutine
+    def Cycle(self, cycles=1):
+        """
+        Do one or more cycles
+        Cycle start in middle of 0 pulse of the clock
+        """
+        for i in range(cycles):
+            self.signal <= 0
+            yield self.t
+            self.signal <= 1
+            yield self.t
+            yield self.t
+            self.signal <= 0
+            yield self.t
+
+class JTAG_Master(object):
+    """
+    Class that will run JTAG commands, shift in and out data
+    """
+    #TODO: Handle a JTAG chain with more than one device
+
+    def __init__(self, tck, tms, tdi, tdo, trst_n=None, clk_period=1000):
+        self.tck = tck
+        self.clkgen = JTAG_Clock(tck, clk_period)
+        tck <= 0
+        self.tms = tms
+        tms <= 1
+        self.tdi = tdi
+        tdi <= 0
+        self.tdo = tdo
+        self.trst_n = trst_n
+        if trst_n is not None:
+            trst_n <= 1
+        self.period = Timer(clk_period)
+
+        # Standard commands
+        # TODO: make IR length configurable; now 2 is assumed
+        self.BYPASS = [1, 1]
+        self.IDCODE = [0, 1]
+        self.SAMPLEPRELOAD = [1, 0]
+        self.EXTEST = [0, 0]
+
+        # After command we always leave the controller in reset or runidle state
+        # If value is None we will always reset the interface
+        self.state = None
+
+        # The methods of this class are coroutines. The results will be stored
+        # in the result field
+        self.result = None
+
+    @cocotb.coroutine
+    def cycle_clock(self, cycles=1):
+        if self.state == "Run" and self.tms == 1:
+            self.state = "Scan"
+        yield self.clkgen.Cycle(cycles)
+
+    @cocotb.coroutine
+    def reset(self):
+        if not self.trst_n is None:
+            # Enable reset signal for one clock period
+            self.trst_n <= 0
+            yield self.period
+            self.trst_n <= 1
+        else:
+            # 5 cycles with tms on 1 should reset the JTAG TAP controller
+            self.tms <= 1
+            yield self.cycle_clock(5)
+
+        self.state = "Reset"
+
+        self.result = None
+
+    @cocotb.coroutine
+    def change_state(self, tms_list):
+        """
+        Put TAP in other state by giving a TMS sequence
+        This function does not detect if one ends up in reset or run
+        state afterwards, self.state has to be updated by caller
+        if that is the case.
+        """
+        tms_copy = list(tms_list)
+        while tms_copy:
+            self.tms <= tms_copy.pop()
+            yield self.cycle_clock()
+        self.result = None
+
+    @cocotb.coroutine
+    def change_to_run(self):
+        """
+        Put TAP in RunTestIdle state
+        self.result is bool and true if TAP went through reset state
+        """
+        isreset = False
+        if self.state is None:
+            yield self.reset()
+        if self.state is "Reset":
+            isreset = True
+            self.tms <= 0
+            yield self.cycle_clock()
+            self.state = "Run"
+        assert(self.state == "Run")
+        self.result = isreset
+
+    @cocotb.coroutine
+    def load_ir(self, cmd):
+        cmd_copy = list(cmd)
+        result = BinaryValue(bits=len(cmd_copy))
+        l_result = list()
+
+        yield self.change_to_run()
+        # Go to Capture/IR
+        yield self.change_state([0, 1, 1])
+
+        # Shift the two
+        self.tms <= 0
+        while cmd_copy:
+            # In first iteration we enter SHIFT state and tdo is made active
+            yield self.cycle_clock()
+            # For the last iteration tdi will be shifted when entering next state
+            self.tdi <= cmd_copy.pop()
+            l_result.insert(0, str(self.tdo))
+
+        # Go to RunTestIdle
+        yield self.change_state([0, 1, 1])
+        self.state = "Run"
+
+    @cocotb.coroutine
+    def idcode(self):
+        """
+        Get the IDCODE from the device
+        result will contain the 32 bit IDCODE of the device
+        """
+
+        result = BinaryValue(bits=32)
+        l_result = list()
+
+        # Keep tdi 0 for the whole run
+        self.tdi <= 0
+
+        yield self.change_to_run()
+        if not self.result:
+            # If TAP was not reset we have to load IDCODE command
+            yield self.load_ir(self.IDCODE)
+
+        # Should be again in RUN state
+        assert(self.state == "Run")
+
+        # Go to Shift/DR
+        yield self.change_state([0, 0, 1])
+
+        # Enter Shift; run for 32 cycles
+        self.tms <= 0
+        for i in range(32):
+            l_result.insert(0, str(self.tdo))
+            yield self.cycle_clock()
+        result.binstr = "".join(l_result)
+
+        # Go to RunTestIdle
+        yield self.change_state([0, 1, 1])
+        self.state = "Run"
+
+        self.result = result
+
+    @cocotb.coroutine
+    def shift_data(self, data_in):
+        """
+        Shift data in through the JTAG and capture the output
+        Input can be of type BinaryValue or an iterable value of 0 and 1s.
+        Last bit will be shifted in first.
+        result will contain the sample TDO with the same number of bits as the input
+        """
+        if isinstance(data_in, BinaryValue):
+            data_copy = [int(c) for c in data_in.binstr]
+        else:
+            data_copy = list(data_in)
+        result = BinaryValue()
+        l_result = list()
+
+        yield self.change_to_run()
+        # Go to Capture/DR
+        yield self.change_state([0, 1])
+
+        # Shift data through
+        self.tms <= 0
+        while data_copy:
+            yield self.cycle_clock()
+            self.tdi <= data_copy.pop()
+            l_result.insert(0, str(self.tdo))
+        result.binstr = "".join(l_result)
+
+        # Go to RunTestIdle
+        yield self.change_state([0, 1, 1])
+        self.state = "Run"
+
+        self.result = result
diff --git a/c4m/cocotb/jtag/c4m_jtag_svfcocotb.py b/c4m/cocotb/jtag/c4m_jtag_svfcocotb.py
new file mode 100755 (executable)
index 0000000..177b7a1
--- /dev/null
@@ -0,0 +1,226 @@
+import c4m_jtag_svfgrammar
+import cocotb
+from cocotb.binary import BinaryValue
+from functools import singledispatch
+
+def decodescanspec(node):
+    length = int(str(node[2]))
+    fstr = "{:0"+str(node[2])+"b}"
+
+    g_tdi = node[4]
+    g_tdo = node[5]
+    g_mask = node[6]
+    g_smask = node[7]
+
+    if g_tdi is None:
+        tdi = None
+    else:
+        tdi = BinaryValue(fstr.format(int(str(g_tdi[2]),16)), length)
+
+    if g_tdo is None:
+        tdo = None
+    else:
+        tdo = BinaryValue(fstr.format(int(str(g_tdo[3]),16)), length)
+
+    if g_mask is None:
+        mask = None
+    else:
+        mask = BinaryValue(fstr.format(int(str(g_mask[3]),16)), length)
+
+    if g_smask is None:
+        smask = None
+    else:
+        smask = BinaryValue(fstr.format(int(str(g_smask[3]),16)), length)
+
+    return (length, tdi, tdo, mask, smask)
+
+
+class SVF_Executor(object):
+    @cocotb.coroutine
+    def execute(self, node):
+        """This is the generic method"""
+        self._p("generic")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_NOP(self, node):
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_EndDR(self, node):
+        self._p("EndDR ignored")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_EndIR(self, node):
+        self._p("EndIR ignored")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_Frequency(self, node):
+        self._p("Frequency ignored")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_HDR(self, node):
+        self._p("HDR ignored")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_HIR(self, node):
+        self._p("HIR ignored")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_SDR(self, node):
+        self._p("Executing SDR")
+        (length, tdi, tdo, mask, smask) = decodescanspec(node)
+
+        samelength = length == self._d_length
+        self._d_length = length
+
+        if tdi is None:
+            if not samelength:
+                raise(JTAGException("TDI needs to be specified when length of data changes"))
+        else:
+            self._d_tdi = tdi
+
+        if mask is not None:
+            self._d_mask = mask
+        elif not samelength:
+            self._d_mask = None
+
+        if smask is not None:
+            self._d_smask = smask
+        elif not samelength:
+            self._d_smask = None
+
+        yield self.master.shift_data(self._d_tdi)
+        if tdo is not None:
+            if self._d_mask is not None:
+                raise(JTAGException("MASK not supported for SDR"))
+            assert(self.result == tdo)
+
+    @cocotb.coroutine
+    def _execute_SIR(self, node):
+        (length, tdi, tdo, mask, smask) = decodescanspec(node)
+
+        samelength = length == self._i_length
+        self._i_length = length
+
+        if tdi is None:
+            if not samelength:
+                raise(JTAGException("TDI needs to be specified when length of data changes"))
+        else:
+            self._i_tdi = tdi
+
+        if mask is not None:
+            self._i_mask = mask
+        elif not samelength:
+            self._i_mask = None
+
+        if smask is not None:
+            self._i_smask = smask
+        elif not samelength:
+            self._i_smask = None
+
+        self._p("Executing SIR ({})".format(self._i_tdi.integer))
+
+        yield self.master.load_ir(self._i_tdi)
+        if tdo is not None:
+            if self._i_mask is not None:
+                raise(JTAGException("MASK not supported for SIR"))
+            assert(self.result == tdo)
+        
+
+    @cocotb.coroutine
+    def _execute_State(self, node):
+        self._p("State")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_TDR(self, node):
+        self._p("TDR")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_TIR(self, node):
+        self._p("TIR")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_Trst(self, node):
+        self._p("TRST ignored")
+        if False: # Make coroutine work
+            yield PythonTrigger()
+
+    @cocotb.coroutine
+    def _execute_Runtest(self, node):
+        if node[1] is not None:
+            raise(JTAGException("State specification for RUNTEST not supported"))
+        # TODO: cycle the right number of clocks or wait the right time
+        yield(self.master.change_state([0]))
+
+    @cocotb.coroutine
+    def _execute_SVFFile(self, node):
+        self._p("Executing SVFFile")
+        for statement in node.elements[0]:
+            yield self.execute(statement)
+
+    def __init__(self, master):
+        # master is assumed to be a JTAG_Master class
+        # it needs to support methods load_ir() and shift_data()
+        self.master = master
+
+        # Due to bug in Grammar definition all possible classes have to have
+        # a dispatch entry otherwise an error will be raised.
+        self.execute = singledispatch(self.execute)
+        self.execute.register(c4m_jtag_svfgrammar.EmptyLine, self._execute_NOP)
+        self.execute.register(c4m_jtag_svfgrammar.Comment, self._execute_NOP)
+        self.execute.register(c4m_jtag_svfgrammar.EndDR, self._execute_EndDR)
+        self.execute.register(c4m_jtag_svfgrammar.EndIR, self._execute_EndIR)
+        self.execute.register(c4m_jtag_svfgrammar.Frequency, self._execute_Frequency)
+        self.execute.register(c4m_jtag_svfgrammar.HDR, self._execute_HDR)
+        self.execute.register(c4m_jtag_svfgrammar.HIR, self._execute_HIR)
+        self.execute.register(c4m_jtag_svfgrammar.Runtest, self._execute_Runtest)
+        self.execute.register(c4m_jtag_svfgrammar.SDR, self._execute_SDR)
+        self.execute.register(c4m_jtag_svfgrammar.SIR, self._execute_SIR)
+        self.execute.register(c4m_jtag_svfgrammar.State, self._execute_State)
+        self.execute.register(c4m_jtag_svfgrammar.TDR, self._execute_TDR)
+        self.execute.register(c4m_jtag_svfgrammar.TIR, self._execute_TIR)
+        self.execute.register(c4m_jtag_svfgrammar.Trst, self._execute_Trst)
+        self.execute.register(c4m_jtag_svfgrammar.SVFFile, self._execute_SVFFile)
+
+        # Store the head and tail for the scan
+        self._d_tdi = self._d_tdi_h = self._d_tdi_t = None
+        self._d_tdo_h = self._d_tdo_t = None
+        self._i_tdi = self._i_tdi_h = self._i_tdi_t = None
+        self._i_tdo_h = self._i_tdo_t = None
+
+        # Remember the masks; smasks are ignored and bits always considered as care, e.g right
+        # value applied
+        self._d_length = self._d_length_h = self._d_length_t = None
+        self._d_mask = self._d_mask_h = self._d_mask_t = None
+        self._d_smask = self._d_smask_h = self._d_smask_t = None
+        self._i_length = self._i_length_h = self._i_length_t = None
+        self._i_mask = self._i_mask_h = self._i_mask_t = None
+        self._i_smask = self._i_smask_h = self._i_smask_t = None
+
+    @cocotb.coroutine
+    def run(self, cmds, p=print):
+        self._p = p
+        if isinstance(cmds, c4m_jtag_svfgrammar.SVFFile):
+            yield self.execute(cmds)
+        else:
+            p = c4m_jtag_svfgrammar.SVFFile.parser()
+            yield self.execute(p.parse_string(cmds))
diff --git a/c4m/cocotb/jtag/c4m_jtag_svfgrammar.py b/c4m/cocotb/jtag/c4m_jtag_svfgrammar.py
new file mode 100644 (file)
index 0000000..faf3aeb
--- /dev/null
@@ -0,0 +1,96 @@
+from modgrammar import *
+
+grammar_whitespace_mode = 'explicit'
+grammar_whitespace = WS_NOEOL
+
+class SVFEol(Grammar):
+    grammar = (OPTIONAL(SPACE), EOL)
+    grammar_collapse = True
+
+class SemicolonEol(Grammar):
+    grammar = (OPTIONAL(SPACE), L(";"), SVFEol)
+    grammar_collapse = True
+
+class Integer(Grammar):
+    grammar = WORD("0-9")
+    grammar_collapse = True
+
+class Float(Grammar):
+    grammar = (Integer, (L("."), OPTIONAL(Integer)), OPTIONAL(L("E"), Integer))
+
+class Hexadecimal(Grammar):
+    grammar = (L("("), WORD("0-9A-F"), L(")"))
+    grammar_collapse = True
+
+class StableState(Grammar):
+    grammar = (L("IRPAUSE") | L("DRPAUSE") | L("RESET") | L("IDLE"))
+    grammar_collapse = True
+
+
+class ScanSpec(Grammar):
+    """The specification of Scan In/Scan out data"""
+    grammar = (SPACE, Integer, SPACE,
+               OPTIONAL(L("TDI"), OPTIONAL(SPACE), Hexadecimal),
+               OPTIONAL(OPTIONAL(SPACE), L("TDO"), OPTIONAL(SPACE), Hexadecimal),
+               OPTIONAL(OPTIONAL(SPACE), L("MASK"), OPTIONAL(SPACE), Hexadecimal),
+               OPTIONAL(OPTIONAL(SPACE), L("SMASK"), OPTIONAL(SPACE), Hexadecimal)
+              )
+    grammar_collapse = True
+
+
+class EmptyLine(Grammar):
+    grammar = SVFEol
+
+class Comment(Grammar):
+    grammar = (L("!"), REST_OF_LINE, SVFEol)
+
+class EndDR(Grammar):
+    grammar = (L("ENDDR"), SPACE, StableState, SemicolonEol)
+
+class EndIR(Grammar):
+    grammar = (L("ENDIR"), SPACE, StableState, SemicolonEol)
+
+class Frequency(Grammar):
+    grammar = (L("FREQUENCY"), OPTIONAL(SPACE, Float, OPTIONAL(SPACE), L("HZ")), OPTIONAL(SPACE), SemicolonEol)
+
+class HDR(Grammar):
+    grammar = (L("HDR"), ScanSpec, SemicolonEol)
+
+class HIR(Grammar):
+    grammar = (L("HIR"), ScanSpec, SemicolonEol)
+
+#TODO: PIO, PIOMAP
+
+class Runtest(Grammar):
+    grammar = (
+        L("RUNTEST"),
+        OPTIONAL(SPACE, StableState),
+        OPTIONAL(SPACE, Integer, OPTIONAL(SPACE), (L("TCK") | L("SCK"))),
+        OPTIONAL(SPACE, Float, OPTIONAL(SPACE), L("SEC")),
+        OPTIONAL(SPACE, L("MAXIMUM"), SPACE, Float, OPTIONAL(SPACE), L("SEC")),
+        OPTIONAL(SPACE, L("ENDSTATE"), SPACE, StableState),
+        SemicolonEol
+    )
+
+class SDR(Grammar):
+    grammar = (L("SDR"), ScanSpec, SemicolonEol)
+
+class SIR(Grammar):
+    grammar = (L("SIR"), ScanSpec, SemicolonEol)
+
+class State(Grammar):
+    # TODO: Path to reach state
+    grammar = (L("STATE"), SPACE, StableState, SemicolonEol)
+
+class TDR(Grammar):
+    grammar = (L("TDR"), ScanSpec, SemicolonEol)
+
+class TIR(Grammar):
+    grammar = (L("TIR"), ScanSpec, SemicolonEol)
+
+class Trst(Grammar):
+    grammar = (L("TRST"), SPACE, (L("ON") | L("OFF") | L("Z") | L("ABSENT")), SemicolonEol)
+
+
+class SVFFile(Grammar):
+    grammar = ONE_OR_MORE(EmptyLine | Comment | Trst | EndDR | EndIR | SIR | SDR | Runtest | State)
diff --git a/c4m/nmigen/jtag/jtag.py b/c4m/nmigen/jtag/jtag.py
new file mode 100755 (executable)
index 0000000..3baaa95
--- /dev/null
@@ -0,0 +1,399 @@
+#!/bin/env python3
+import os
+
+from nmigen import *
+from nmigen.build import *
+from nmigen.lib.io import *
+
+from wishbone import Wishbone
+
+__all__ = [
+    "PmodJTAGMasterResource",
+    "PmodJTAGMasterAResource",
+    "PmodJTAGSlaveResource",
+    "PmodJTAGSlaveAResource",
+    "JTAG",
+]
+
+#TODO: Provide more documentation
+
+def PmodJTAGMasterResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
+    return Resource(name, number,
+        Subsignal("TCK", Pins("1", dir="o", conn=("pmod", pmod))),
+        Subsignal("TMS", Pins("2", dir="o", conn=("pmod", pmod))),
+        Subsignal("TDO", Pins("3", dir="o", conn=("pmod", pmod))),
+        Subsignal("TDI", Pins("4", dir="i", conn=("pmod", pmod))),
+        attrs,
+    )
+
+def PmodJTAGMasterAResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
+    return Resource(name, number,
+        Subsignal("TCK", Pins("1", dir="o", conn=("pmod", pmod))),
+        Subsignal("TMS", Pins("2", dir="o", conn=("pmod", pmod))),
+        Subsignal("TDO", Pins("3", dir="o", conn=("pmod", pmod))),
+        Subsignal("TDI", Pins("4", dir="i", conn=("pmod", pmod))),
+        Subsignal("TRST", PinsN("7", dir="o", conn=("pmod", pmod))),
+        attrs,
+    )
+
+def PmodJTAGSlaveResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
+    return Resource(name, number,
+        Subsignal("TCK", Pins("1", dir="i", conn=("pmod", pmod))),
+        Subsignal("TMS", Pins("2", dir="i", conn=("pmod", pmod))),
+        Subsignal("TDI", Pins("3", dir="i", conn=("pmod", pmod))),
+        Subsignal("TDO", Pins("4", dir="o", conn=("pmod", pmod))),
+        attrs,
+    )
+
+def PmodJTAGSlaveAResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
+    return Resource(name, number,
+        Subsignal("TCK", Pins("1", dir="i", conn=("pmod", pmod))),
+        Subsignal("TMS", Pins("2", dir="i", conn=("pmod", pmod))),
+        Subsignal("TDI", Pins("3", dir="i", conn=("pmod", pmod))),
+        Subsignal("TDO", Pins("4", dir="o", conn=("pmod", pmod))),
+        Subsignal("TRST", PinsN("7", dir="i", conn=("pmod", pmod))),
+        attrs,
+    )
+
+
+class ShiftReg(Elaboratable):
+    def __init__(self, ircodes, length, domain):
+        # The sr record will be returned to user code
+        self.sr = Record([("i", length), ("o", length), ("oe", len(ircodes)), ("ack", 1)])
+        # The next attributes are for JTAG class usage only
+        self.ir = None # made None as width is not known yet
+        self.tdi = Signal()
+        self.tdo = Signal()
+        self.tdo_en = Signal()
+        self.capture = Signal()
+        self.shift = Signal()
+        self.update = Signal()
+        self.jtag_cd = None # The JTAG clock domain
+
+        ##
+
+        self._ircodes = ircodes
+        self._domain = domain
+
+    def elaborate(self, platform):
+        length = len(self.sr.o)
+        domain = self._domain
+
+        m = Module()
+
+        m.domains.jtag = self.jtag_cd
+
+        sr_jtag = Signal(length)
+
+        assert isinstance(self.ir, Signal)
+        isir = Signal(len(self._ircodes))
+        capture = Signal()
+        shift = Signal()
+        update = Signal()
+        m.d.comb += [
+            isir.eq(Cat(self.ir == ircode for ircode in self._ircodes)),
+            capture.eq((isir != 0) & self.capture),
+            shift.eq((isir != 0) & self.shift),
+            update.eq((isir != 0) & self.update),
+        ]
+
+        # On update set o, oe and wait for ack
+        # update signal is on JTAG clockdomain, latch it
+        update_core = Signal()
+        m.d[domain] += update_core.eq(update) # This is CDC from JTAG domain to given domain
+        with m.FSM(domain=domain):
+            with m.State("IDLE"):
+                m.d.comb += self.sr.oe.eq(0)
+                with m.If(update_core):
+                    # Latch sr_jtag cross domain but it should be stable due to latching of update_core
+                    m.d[domain] += self.sr.o.eq(sr_jtag)
+                    # Wait one cycle to raise oe so sr.o has one more cycle to stabilize
+                    m.next = "WAIT4ACK"
+            with m.State("WAIT4ACK"):
+                m.d.comb += self.sr.oe.eq(isir)
+                with m.If(self.sr.ack):
+                    m.next = "WAIT4END"
+            with m.State("WAIT4END"):
+                m.d.comb += self.sr.oe.eq(0)
+                with m.If(~update_core):
+                    m.next = "IDLE"
+
+        m.d.comb += [
+            self.tdo.eq(sr_jtag[0]),
+            self.tdo_en.eq(shift),
+        ]
+
+        with m.If(shift):
+            m.d.jtag += sr_jtag.eq(Cat(sr_jtag[1:], self.tdi))
+        with m.If(capture):
+            m.d.jtag += sr_jtag.eq(self.sr.i)
+
+        return m
+
+class JTAGWishbone(Elaboratable):
+    def __init__(self, sr_addr, sr_data, wb, domain):
+        self._sr_addr = sr_addr
+        self._sr_data = sr_data
+        self._wb = wb
+        self._domain = domain
+
+        # To be set by JTAG
+        self._ir = None
+
+    def elaborate(self, platform):
+        sr_addr = self._sr_addr
+        sr_data = self._sr_data
+        wb = self._wb
+        domain = self._domain
+        ir = self._ir
+
+        m = Module()
+
+        if hasattr(wb, "sel"):
+            # Always selected
+            m.d.comb += [s.eq(1) for s in wb.sel]
+
+        # Immediately ack oe
+        m.d[domain] += [
+            sr_addr.ack.eq(sr_addr.oe),
+            sr_data.ack.eq(sr_data.oe != 0),
+        ]
+
+        with m.FSM(domain=domain) as fsm:
+            with m.State("IDLE"):
+                m.d.comb += [
+                    wb.cyc.eq(0),
+                    wb.stb.eq(0),
+                    wb.we.eq(0),
+                ]
+                with m.If(sr_addr.oe): # WBADDR code
+                    m.d[domain] += wb.addr.eq(sr_addr.o)
+                    m.next = "READ"
+                with m.If(sr_data.oe[0]): # WBREAD code
+                    m.d[domain] += wb.addr.eq(wb.addr + 1)
+                    m.next = "READ"
+                with m.If(sr_data.oe[1]): # WBWRITE code
+                    m.d[domain] += wb.dat_w.eq(sr_data.o)
+                    m.next = "WRITEREAD"
+            with m.State("READ"):
+                m.d.comb += [
+                    wb.cyc.eq(1),
+                    wb.stb.eq(1),
+                    wb.we.eq(0),
+                ]
+                with m.If(~wb.stall):
+                    m.next = "READACK"
+            with m.State("READACK"):
+                m.d.comb += [
+                    wb.cyc.eq(1),
+                    wb.stb.eq(0),
+                    wb.we.eq(0),
+                ]
+                with m.If(wb.ack):
+                    m.d[domain] += sr_data.i.eq(wb.dat_r)
+                    m.next = "IDLE"
+            with m.State("WRITEREAD"):
+                m.d.comb += [
+                    wb.cyc.eq(1),
+                    wb.stb.eq(1),
+                    wb.we.eq(1),
+                ]
+                with m.If(~wb.stall):
+                    m.next = "WRITEREADACK"
+            with m.State("WRITEREADACK"):
+                m.d.comb += [
+                    wb.cyc.eq(1),
+                    wb.stb.eq(0),
+                    wb.we.eq(0),
+                ]
+                with m.If(wb.ack):
+                    m.d[domain] += wb.addr.eq(wb.addr + 1)
+                    m.next = "READ"
+
+        return m
+
+
+class JTAG(Elaboratable):
+    @staticmethod
+    def _add_files(platform, prefix):
+        d = os.path.realpath("{0}{1}{2}{1}vhdl".format(
+            os.path.dirname(__file__), os.path.sep, os.path.pardir
+        )) + os.path.sep
+        for fname in [
+            "c4m_jtag_pkg.vhdl",
+            "c4m_jtag_idblock.vhdl",
+            "c4m_jtag_iocell.vhdl",
+            "c4m_jtag_ioblock.vhdl",
+            "c4m_jtag_irblock.vhdl",
+            "c4m_jtag_tap_fsm.vhdl",
+            "c4m_jtag_tap_controller.vhdl",
+        ]:
+            f = open(d + fname, "r")
+            platform.add_file(prefix + fname, f)
+            f.close()
+
+
+    def __init__(self, io_count, *, ir_width=None, manufacturer_id=Const(0b10001111111, 11),
+                 part_number=Const(1, 16), version=Const(0, 4)
+    ):
+        assert(isinstance(io_count, int) and io_count > 0)
+        assert((ir_width is None) or (isinstance(ir_width, int) and ir_width >= 2))
+        assert(len(version) == 4)
+
+        # TODO: Handle IOs with different directions
+        self.tck  = Signal()
+        self.tms  = Signal()
+        self.tdo  = Signal()
+        self.tdi  = Signal()
+        self.core = Array(Pin(1, "io") for _ in range(io_count)) # Signals to use for core
+        self.pad  = Array(Pin(1, "io") for _ in range(io_count)) # Signals going to IO pads
+
+        self.jtag_cd = ClockDomain(name="jtag", local=True) # Own clock domain using TCK as clock signal
+
+        ##
+
+        self._io_count = io_count
+        self._ir_width = ir_width
+        self._manufacturer_id = manufacturer_id
+        self._part_number = part_number
+        self._version = version
+
+        self._ircodes = [0, 1, 2] # Already taken codes, all ones added at the end
+        self._srs = []
+
+        self._wbs = []
+
+    def elaborate(self, platform):
+        JTAG._add_files(platform, "jtag" + os.path.sep)
+
+        m = Module()
+
+        tdo_jtag = Signal()
+        reset = Signal()
+        capture = Signal()
+        shift = Signal()
+        update = Signal()
+
+
+        ir_max = max(self._ircodes) + 1 # One extra code needed with all ones
+        ir_width = len("{:b}".format(ir_max))
+        if self._ir_width is not None:
+            assert self._ir_width >= ir_width, "Specified JTAG IR width not big enough for allocated shiift registers"
+            ir_width = self._ir_width
+        ir = Signal(ir_width)
+
+        core_i = Cat(pin.i for pin in self.core)
+        core_o = Cat(pin.o for pin in self.core)
+        core_oe = Cat(pin.oe for pin in self.core)
+        pad_i = Cat(pin.i for pin in self.pad)
+        pad_o = Cat(pin.o for pin in self.pad)
+        pad_oe = Cat(pin.oe for pin in self.pad)
+
+        params = {
+            "p_IOS": self._io_count,
+            "p_IR_WIDTH": ir_width,
+            "p_MANUFACTURER": self._manufacturer_id,
+            "p_PART_NUMBER": self._part_number,
+            "p_VERSION": self._version,
+            "i_TCK": self.tck,
+            "i_TMS": self.tms,
+            "i_TDI": self.tdi,
+            "o_TDO": tdo_jtag,
+            "i_TRST_N": Const(1),
+            "o_RESET": reset,
+            "o_DRCAPTURE": capture,
+            "o_DRSHIFT": shift,
+            "o_DRUPDATE": update,
+            "o_IR": ir,
+            "o_CORE_IN": core_i,
+            "i_CORE_OUT": core_o,
+            "i_CORE_EN": core_oe,
+            "i_PAD_IN": pad_i,
+            "o_PAD_OUT": pad_o,
+            "o_PAD_EN": pad_oe,
+        }
+        m.submodules.tap = Instance("c4m_jtag_tap_controller", **params)
+
+        m.d.comb += [
+            self.jtag_cd.clk.eq(self.tck),
+            self.jtag_cd.rst.eq(reset),
+        ]
+
+        for i, sr in enumerate(self._srs):
+            m.submodules["sr{}".format(i)] = sr
+            sr.ir = ir
+            m.d.comb += [
+                sr.tdi.eq(self.tdi),
+                sr.capture.eq(capture),
+                sr.shift.eq(shift),
+                sr.update.eq(update),
+            ]
+
+        if len(self._srs) > 0:
+            first = True
+            for sr in self._srs:
+                if first:
+                    first = False
+                    with m.If(sr.tdo_en):
+                        m.d.comb += self.tdo.eq(sr.tdo)
+                else:
+                    with m.Elif(sr.tdo_en):
+                        m.d.comb += self.tdo.eq(sr.tdo)
+            with m.Else():
+                m.d.comb += self.tdo.eq(tdo_jtag)
+        else:
+            m.d.comb += self.tdo.eq(tdo_jtag)
+
+        for i, wb in enumerate(self._wbs):
+            m.submodules["wb{}".format(i)] = wb
+            wb._ir = ir
+
+        return m
+
+
+    def add_shiftreg(self, ircode, length, domain="sync"):
+        """Add a shift register to the JTAG interface
+
+        Parameters:
+        - ircode: code(s) for the IR; int or sequence of ints. In the latter case this
+          shiftreg is shared between different IR codes.
+        - length: the length of the shift register
+        - domain: the domain on which the signal will be used"""
+
+        try:
+            ir_it = iter(ircode)
+            ircodes = ircode
+        except TypeError:
+            ir_it = ircodes = (ircode,)
+        for _ircode in ir_it:
+            assert(isinstance(_ircode, int) and _ircode > 0 and _ircode not in self._ircodes)
+
+        sr = ShiftReg(ircodes, length, domain)
+        sr.jtag_cd = self.jtag_cd
+        self._ircodes.extend(ircodes)
+        self._srs.append(sr)
+
+        return sr.sr
+
+
+    def add_wishbone(self, ircodes, address_width, data_width, sel_width=None, domain="sync"):
+        """Add a wishbone interface
+
+        Parameters:
+        - ircodes: sequence of three integer for the JTAG IR codes;
+          they represent resp. WBADDR, WBREAD and WBREADWRITE. First code
+          has a shift register of length 'address_width', the two other codes
+          share a shift register of length data_width.
+        - address_width: width of the address
+        - data_width: width of the data"""
+
+        assert len(ircodes) == 3
+
+        sr_addr = self.add_shiftreg(ircodes[0], address_width, domain=domain)
+        sr_data = self.add_shiftreg(ircodes[1:], data_width, domain=domain)
+
+        wb = Wishbone(data_width=data_width, address_width=address_width, sel_width=sel_width, master=True)
+
+        self._wbs.append(JTAGWishbone(sr_addr, sr_data, wb, domain))
+
+        return wb
diff --git a/c4m/vhdl/jtag/c4m_jtag_idblock.vhdl b/c4m/vhdl/jtag/c4m_jtag_idblock.vhdl
new file mode 100644 (file)
index 0000000..303959a
--- /dev/null
@@ -0,0 +1,72 @@
+-- The JTAG id and bypass handling block
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity c4m_jtag_idblock is
+  generic (
+    IR_WIDTH:           integer := 2;
+    
+    MANUFACTURER:       std_logic_vector(10 downto 0) := "10001111111";
+    PART_NUMBER:        std_logic_vector(15 downto 0) := "0000000000000001";
+    VERSION:            std_logic_vector(3 downto 0) := "0000"
+  );
+  port (
+    -- needed TAP signals
+    TCK:        in std_logic;
+    TDI:        in std_logic;
+    TDO:        out std_logic;
+    TDO_EN:     out std_logic := '0';
+
+    -- JTAG state
+    STATE:      in TAPSTATE_TYPE;
+    NEXT_STATE: in TAPSTATE_TYPE;
+    DRSTATE:    in std_logic;
+
+    -- The instruction
+    IR:         in std_logic_vector(IR_WIDTH-1 downto 0)
+  );
+end c4m_jtag_idblock;
+
+architecture rtl of c4m_jtag_idblock is
+  constant IDCODE:      std_logic_vector(31 downto 0) := VERSION & PART_NUMBER & MANUFACTURER & "1";
+
+  signal SR_ID:         std_logic_vector(31 downto 0);
+  signal EN_TDO:        boolean;
+  
+  constant CMD_IDCODE:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_idcode(IR_WIDTH);
+  constant CMD_BYPASS:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_bypass(IR_WIDTH);
+begin
+  process (TCK)
+  begin
+    if rising_edge(TCK) then
+      if DRSTATE = '1' then
+        case STATE is
+          when Capture =>
+            SR_ID <= IDCODE;
+
+          when Shift =>
+            if IR = CMD_IDCODE then
+              SR_ID(30 downto 0) <= SR_ID(31 downto 1);
+              SR_ID(31) <= TDI;
+            elsif IR = CMD_BYPASS then
+              SR_ID(0) <= TDI;
+            else
+              null;
+            end if;
+
+          when others =>
+            null;
+        end case;
+      end if;
+    end if;
+  end process;
+
+  EN_TDO <= STATE = Shift and DRSTATE = '1' and (IR = CMD_IDCODE or IR = CMD_BYPASS);
+  TDO <= SR_ID(0) when EN_TDO else
+         '0';
+  TDO_EN <= '1' when EN_TDO else
+            '0';
+end rtl;
diff --git a/c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl b/c4m/vhdl/jtag/c4m_jtag_ioblock.vhdl
new file mode 100644 (file)
index 0000000..c70be6f
--- /dev/null
@@ -0,0 +1,91 @@
+-- The block of io cells with JTAG boundary scan support
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity c4m_jtag_ioblock is
+  generic (
+    IR_WIDTH:   integer := 2;
+    IOS:        integer := 1
+  );
+  port (
+    -- needed TAP signals
+    TCK:        in std_logic;
+    TDI:        in std_logic;
+    TDO:        out std_logic;
+    TDO_EN:     out std_logic := '0';
+
+    -- JTAG state
+    STATE:      in TAPSTATE_TYPE;
+    NEXT_STATE: in TAPSTATE_TYPE;
+    DRSTATE:    in std_logic;
+
+    -- The instruction
+    IR:         in std_logic_vector(IR_WIDTH-1 downto 0);
+
+    -- The I/O access ports
+    CORE_OUT:   in std_logic_vector(IOS-1 downto 0);
+    CORE_IN:    out std_logic_vector(IOS-1 downto 0);
+    CORE_EN:    in std_logic_vector(IOS-1 downto 0);
+
+    -- The pad connections
+    PAD_OUT:    out std_logic_vector(IOS-1 downto 0);
+    PAD_IN:     in std_logic_vector(IOS-1 downto 0);
+    PAD_EN:     out std_logic_vector(IOS-1 downto 0)
+  );
+end c4m_jtag_ioblock;
+
+architecture rtl of c4m_jtag_ioblock is
+  signal IOMODE:        SRIOMODE_TYPE;
+  signal SAMPLEMODE:    SRSAMPLEMODE_TYPE;
+  signal ISSAMPLECMD:   boolean;
+  
+  signal BDSR_IN:       std_logic_vector(IOS-1 downto 0);
+  signal BDSR_OUT:      std_logic_vector(IOS-1 downto 0);
+  
+  constant CMD_SAMPLEPRELOAD: std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_samplepreload(IR_WIDTH);
+  constant CMD_EXTEST:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_extest(IR_WIDTH);
+begin
+  -- JTAG baundary scan IO cells
+  IOGEN: for i in 0 to IOS-1 generate
+  begin
+    IOCELL: c4m_jtag_iocell
+      port map (
+        CORE_IN => CORE_IN(i),
+        CORE_OUT => CORE_OUT(i),
+        CORE_EN => CORE_EN(i),
+        PAD_IN => PAD_IN(i),
+        PAD_OUT => PAD_OUT(i),
+        PAD_EN => PAD_EN(i),
+        BDSR_IN => BDSR_IN(i),
+        BDSR_OUT => BDSR_OUT(i),
+        IOMODE => IOMODE,
+        SAMPLEMODE => SAMPLEMODE,
+        TCK => TCK
+      );
+  end generate;
+  BDSRCONN: for i in 0 to IOS-2 generate
+  begin
+    BDSR_IN(i) <= BDSR_OUT(i+1);
+  end generate;
+  BDSR_IN(IOS-1) <= TDI;
+
+  -- Set IOMODE
+  -- Currently SR_2Core or SR_Z are not used
+  IOMODE <= SR_2Pad when IR = CMD_EXTEST else
+            SR_Through;
+
+  -- Set SAMPLEMODE
+  ISSAMPLECMD <= (IR = CMD_SAMPLEPRELOAD or IR = CMD_EXTEST) and DRSTATE = '1';
+  SAMPLEMODE <= SR_Sample when ISSAMPLECMD and STATE = Capture else
+                SR_Update when ISSAMPLECMD and STATE = Update else
+                SR_Shift when ISSAMPLECMD and STATE = Shift else
+                SR_Normal;
+
+  TDO <= BDSR_OUT(0) when ISSAMPLECMD and STATE = Shift else
+         '0';
+  TDO_EN <= '1' when ISSAMPLECMD and STATE = Shift else
+            '0';
+end rtl;
diff --git a/c4m/vhdl/jtag/c4m_jtag_iocell.vhdl b/c4m/vhdl/jtag/c4m_jtag_iocell.vhdl
new file mode 100644 (file)
index 0000000..6a218a6
--- /dev/null
@@ -0,0 +1,101 @@
+-- An JTAG boundary scan for bidirectional I/O
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity c4m_jtag_iocell is
+  generic (
+    IR_WIDTH:   integer := 2
+  );
+  port (
+    -- core connections
+    CORE_IN:    out std_logic;
+    CORE_OUT:   in std_logic;
+    CORE_EN:    in std_logic;
+
+    -- pad connections
+    PAD_IN:     in std_logic;
+    PAD_OUT:    out std_logic;
+    PAD_EN:     out std_logic;
+
+    -- BD shift register
+    BDSR_IN:    in std_logic;
+    BDSR_OUT:   out std_logic;
+
+      -- Mode of I/O cell
+    IOMODE:     in SRIOMODE_TYPE;
+    SAMPLEMODE: in SRSAMPLEMODE_TYPE;
+    TCK:        in std_logic
+  );
+end c4m_jtag_iocell;
+
+architecture rtl of c4m_jtag_iocell is
+  signal SR_IOIN: std_logic;
+  signal SR_IOOUT: std_logic;
+  signal SR_IOEN: std_logic;
+
+  signal CORE_IN_BD: std_logic;
+  signal PAD_OUT_BD: std_logic;
+  signal PAD_EN_BD: std_logic;
+begin
+  with IOMODE select
+  CORE_IN <=
+    PAD_IN when SR_Through | SR_Z,
+    PAD_IN when SR_2Pad,
+    CORE_IN_BD when SR_2Core,
+    'X' when others;
+
+  with IOMODE select
+  PAD_OUT <=
+    CORE_OUT when SR_Through,
+    PAD_OUT_BD when SR_2Pad,
+    '0' when SR_2Core | SR_Z,  
+    'X' when others;
+
+  with IOMODE select
+  PAD_EN <=
+    CORE_EN when SR_Through,
+    PAD_EN_BD when SR_2Pad,
+    '0' when SR_2Core | SR_Z,
+    'X' when others;
+
+  process (TCK)
+  begin
+    -- Sampling of inputs and shifting of boundary scan SR needs to be done on
+    -- rising edge of TCK
+    if rising_edge(TCK) then
+      case SAMPLEMODE is
+        when SR_Sample =>
+          SR_IOIN <= PAD_IN;
+          SR_IOOUT <= CORE_OUT;
+          SR_IOEN <= CORE_EN;
+
+        when SR_Shift =>
+          SR_IOIN <= BDSR_IN;
+          SR_IOOUT <= SR_IOIN;
+          SR_IOEN <= SR_IOOUT;
+
+        when others =>
+          null;
+      end case;
+    end if;
+    
+    -- Update of output from boundary scan SR needs to be done on falling edge
+    -- of TCK
+    if falling_edge(TCK) then
+      case SAMPLEMODE is
+        when SR_Update =>
+          CORE_IN_BD <= SR_IOIN;
+          PAD_OUT_BD <= SR_IOOUT;
+          PAD_EN_BD <= SR_IOEN;
+          
+        when others =>
+          null;
+      end case;
+    end if;
+  end process;
+
+  BDSR_OUT <= SR_IOEN;
+end rtl;
diff --git a/c4m/vhdl/jtag/c4m_jtag_irblock.vhdl b/c4m/vhdl/jtag/c4m_jtag_irblock.vhdl
new file mode 100644 (file)
index 0000000..8be483a
--- /dev/null
@@ -0,0 +1,64 @@
+-- Handle the instruction register for the JTAG controller
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity c4m_jtag_irblock is
+  generic (
+    IR_WIDTH:   integer := 2
+  );
+  port (
+    -- needed TAP signals
+    TCK:        in std_logic;
+    TDI:        in std_logic;
+    TDO:        out std_logic;
+    TDO_EN:     out std_logic := '0';
+    
+    -- JTAG state
+    STATE:      in TAPSTATE_TYPE;
+    NEXT_STATE: in TAPSTATE_TYPE;
+    IRSTATE:    in std_logic;
+
+    -- instruction register
+    IR:         out std_logic_vector(IR_WIDTH-1 downto 0)
+  );
+end c4m_jtag_irblock;
+
+architecture rtl of c4m_jtag_irblock is
+  signal SHIFT_IR:      std_logic_vector(IR_WIDTH-1 downto 0);
+
+  constant CMD_IDCODE:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_idcode(IR_WIDTH);
+begin
+  process (TCK, STATE)
+  begin
+    if STATE = TestLogicReset then
+        SHIFT_IR <= (others => '0');
+        IR <= CMD_IDCODE;
+    elsif rising_edge(TCK) then
+      if IRSTATE = '1' then
+        case STATE is
+          when Capture =>
+            SHIFT_IR(1) <= '0';
+            SHIFT_IR(0) <= '1';
+
+          when Shift =>
+            SHIFT_IR(IR_WIDTH-2 downto 0) <= SHIFT_IR(IR_WIDTH-1 downto 1);
+            SHIFT_IR(IR_WIDTH-1) <= TDI;
+
+          when Update =>
+            IR <= SHIFT_IR;
+
+          when others =>
+            null;
+        end case;
+      end if;
+    end if;
+  end process;
+
+  TDO <= SHIFT_IR(0) when STATE = Shift and IRSTATE = '1' else
+         '0';
+  TDO_EN <= '1' when STATE = Shift and IRSTATE = '1' else
+            '0';
+end rtl;
diff --git a/c4m/vhdl/jtag/c4m_jtag_pkg.vhdl b/c4m/vhdl/jtag/c4m_jtag_pkg.vhdl
new file mode 100644 (file)
index 0000000..0fc0749
--- /dev/null
@@ -0,0 +1,225 @@
+-- Package of jtag support code from the Chips4Makers project
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+package c4m_jtag is
+  type TAPSTATE_TYPE is (
+    TestLogicReset,
+    RunTestIdle,
+    SelectDRScan,
+    SelectIRScan,
+    Capture,
+    Shift,
+    Exit1,
+    Pause,
+    Exit2,
+    Update
+  );
+  type SRIOMODE_TYPE is (
+    SR_Through, -- Connect core signal to pad signals
+    SR_2Pad,    -- Connect BD to pad
+    SR_2Core,   -- Connect BD to core
+    SR_Z        -- pad is high impedance
+  );
+  type SRSAMPLEMODE_TYPE is (
+    SR_Normal,  -- No sampling or shifting
+    SR_Sample,  -- Sample IO state in BD SR on rising edge of TCK
+    SR_Update,  -- Update BD from SR on falling edge of TCK
+    SR_Shift    -- Shift the BD SR
+  );
+
+  component c4m_jtag_tap_fsm is
+    port (
+      -- The TAP signals
+      TCK:      in std_logic;
+      TMS:      in std_logic;
+      TRST_N:   in std_logic;
+
+      -- The state outputs
+      STATE:    out TAPSTATE_TYPE;
+      NEXT_STATE: out TAPSTATE_TYPE;
+      DRSTATE:  out std_logic;
+      IRSTATE:  out std_logic
+    );
+  end component c4m_jtag_tap_fsm;
+
+  component c4m_jtag_irblock is
+    generic (
+      IR_WIDTH: integer := 2
+    );
+    port (
+      -- needed TAP signals
+      TCK:      in std_logic;
+      TDI:      in std_logic;
+      TDO:      out std_logic;
+      TDO_EN:   out std_logic;
+    
+      -- JTAG state
+      STATE:    in TAPSTATE_TYPE;
+      NEXT_STATE: in TAPSTATE_TYPE;
+      IRSTATE:  in std_logic;
+
+      -- instruction register
+      IR:       out std_logic_vector(IR_WIDTH-1 downto 0)
+    );
+  end component c4m_jtag_irblock;
+  
+  component c4m_jtag_idblock is
+    generic (
+      IR_WIDTH:         integer := 2;
+    
+      -- The default MANUFACTURING ID is not representing a valid
+      -- manufacturer according to the JTAG standard
+      MANUFACTURER:     std_logic_vector(10 downto 0) := "10001111111";
+      PART_NUMBER:      std_logic_vector(15 downto 0) := "0000000000000001";
+      VERSION:          std_logic_vector(3 downto 0) := "0000"
+    );
+    port (
+      -- needed TAP signals
+      TCK:      in std_logic;
+      TDI:      in std_logic;
+      TDO:      out std_logic;
+      TDO_EN:   out std_logic;
+
+      -- JTAG state
+      STATE:    in TAPSTATE_TYPE;
+      NEXT_STATE: in TAPSTATE_TYPE;
+      DRSTATE:  in std_logic;
+
+      -- The instruction
+      IR:       in std_logic_vector(IR_WIDTH-1 downto 0)
+    );
+  end component c4m_jtag_idblock;
+
+  component c4m_jtag_iocell is
+    port (
+      -- core connections
+      CORE_IN:  out std_logic;
+      CORE_OUT: in std_logic;
+      CORE_EN:  in std_logic;
+
+      -- pad connections
+      PAD_IN:   in std_logic;
+      PAD_OUT:  out std_logic;
+      PAD_EN:   out std_logic;
+
+      -- BD shift register
+      BDSR_IN:  in std_logic;
+      BDSR_OUT: out std_logic;
+
+      -- Mode of I/O cell
+      IOMODE:   in SRIOMODE_TYPE;
+      SAMPLEMODE: in SRSAMPLEMODE_TYPE;
+      TCK:      in std_logic
+    );
+  end component c4m_jtag_iocell;
+  
+  component c4m_jtag_ioblock is
+    generic (
+      IR_WIDTH: integer := 2;
+      IOS:      integer := 1
+    );
+    port (
+      -- needed TAP signals
+      TCK:      in std_logic;
+      TDI:      in std_logic;
+      TDO:      out std_logic;
+      TDO_EN:   out std_logic;
+
+      -- JTAG state
+      STATE:    in TAPSTATE_TYPE;
+      NEXT_STATE: in TAPSTATE_TYPE;
+      DRSTATE:  in std_logic;
+
+      -- The instruction
+      IR:       in std_logic_vector(IR_WIDTH-1 downto 0);
+
+      -- The I/O access ports
+      CORE_OUT: in std_logic_vector(IOS-1 downto 0);
+      CORE_IN:  out std_logic_vector(IOS-1 downto 0);
+      CORE_EN:  in std_logic_vector(IOS-1 downto 0);
+
+      -- The pad connections
+      PAD_OUT:  out std_logic_vector(IOS-1 downto 0);
+      PAD_IN:   in std_logic_vector(IOS-1 downto 0);
+      PAD_EN:   out std_logic_vector(IOS-1 downto 0)
+    );
+  end component c4m_jtag_ioblock;
+
+  component c4m_jtag_tap_controller is
+    generic (
+      DEBUG:            boolean := false;
+
+      IR_WIDTH:         integer := 2;
+      IOS:              integer := 1;
+
+      -- The default MANUFACTURING ID is not representing a valid
+      -- manufacturer according to the JTAG standard
+      MANUFACTURER:     std_logic_vector(10 downto 0) := "10001111111";
+      PART_NUMBER:      std_logic_vector(15 downto 0) := "0000000000000001";
+      VERSION:          std_logic_vector(3 downto 0) := "0000"
+    );
+    port (
+      -- The TAP signals
+      TCK:      in std_logic;
+      TMS:      in std_logic;
+      TDI:      in std_logic;
+      TDO:      out std_logic;
+      TRST_N:   in std_logic;
+
+      -- The FSM state indicators
+      RESET:    out std_logic; -- In reset state
+      DRCAPTURE: out std_logic; -- In DR_Capture state
+      DRSHIFT:  out std_logic; -- In DR_Shift state
+      DRUPDATE: out std_logic; -- In DR_Update state
+
+      -- The Instruction Register
+      IR:       out std_logic_vector(IR_WIDTH-1 downto 0);
+
+      -- The I/O access ports
+      CORE_IN:  out std_logic_vector(IOS-1 downto 0);
+      CORE_EN:  in std_logic_vector(IOS-1 downto 0);
+      CORE_OUT: in std_logic_vector(IOS-1 downto 0);
+
+      -- The pad connections
+      PAD_IN:   in std_logic_vector(IOS-1 downto 0);
+      PAD_EN:   out std_logic_vector(IOS-1 downto 0);
+      PAD_OUT:  out std_logic_vector(IOS-1 downto 0)
+    );
+  end component c4m_jtag_tap_controller;
+
+  function c4m_jtag_cmd_idcode(width: integer) return std_logic_vector;
+  function c4m_jtag_cmd_bypass(width: integer) return std_logic_vector;
+  function c4m_jtag_cmd_samplepreload(width: integer) return std_logic_vector;
+  function c4m_jtag_cmd_extest(width: integer) return std_logic_vector;
+end c4m_jtag;
+
+package body c4m_jtag is
+  function c4m_jtag_cmd_bypass(width: integer) return std_logic_vector is
+    variable return_vector: std_logic_vector(width-1 downto 0);
+  begin
+    return_vector := (others => '1');
+    return return_vector;
+  end;
+
+  function c4m_jtag_cmd_idcode(width: integer) return std_logic_vector is
+    variable return_vector: std_logic_vector(width-1 downto 0);
+  begin
+    return_vector := (0 => '1', others => '0');
+    return return_vector;
+  end;
+
+  function c4m_jtag_cmd_samplepreload(width: integer) return std_logic_vector is
+    variable return_vector: std_logic_vector(width-1 downto 0);
+  begin
+    return_vector := (1 => '1', others => '0');
+    return return_vector;
+  end;
+
+  function c4m_jtag_cmd_extest(width: integer) return std_logic_vector is
+    variable return_vector: std_logic_vector(width-1 downto 0);
+  begin
+    return_vector := (others => '0');
+    return return_vector;
+  end;
+end package body;
diff --git a/c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl b/c4m/vhdl/jtag/c4m_jtag_tap_controller.vhdl
new file mode 100644 (file)
index 0000000..217982e
--- /dev/null
@@ -0,0 +1,154 @@
+-- A JTAG complient tap controller implementation
+-- This is implemented based on the IEEE 1149.1 standard
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity c4m_jtag_tap_controller is
+  generic (
+    DEBUG:              boolean := false;
+
+    IR_WIDTH:           integer := 2;
+    IOS:                integer := 1;
+
+    MANUFACTURER:       std_logic_vector(10 downto 0) := "10001111111";
+    PART_NUMBER:        std_logic_vector(15 downto 0) := "0000000000000001";
+    VERSION:            std_logic_vector(3 downto 0) := "0000"
+  );
+  port (
+    -- The TAP signals
+    TCK:        in std_logic;
+    TMS:        in std_logic;
+    TDI:        in std_logic;
+    TDO:        out std_logic;
+    TRST_N:     in std_logic;
+
+    -- The FSM state indicators
+    RESET:      out std_logic;
+    DRCAPTURE:  out std_logic;
+    DRSHIFT:    out std_logic;
+    DRUPDATE:   out std_logic;
+
+    -- The Instruction Register
+    IR:         out std_logic_vector(IR_WIDTH-1 downto 0);
+
+    -- The I/O access ports
+    CORE_IN:    out std_logic_vector(IOS-1 downto 0);
+    CORE_EN:    in std_logic_vector(IOS-1 downto 0);
+    CORE_OUT:   in std_logic_vector(IOS-1 downto 0);
+
+    -- The pad connections
+    PAD_IN:     in std_logic_vector(IOS-1 downto 0);
+    PAD_EN:     out std_logic_vector(IOS-1 downto 0);
+    PAD_OUT:    out std_logic_vector(IOS-1 downto 0)
+  );
+end c4m_jtag_tap_controller;
+
+architecture rtl of c4m_jtag_tap_controller is
+  signal S_STATE:       TAPSTATE_TYPE;
+  signal S_NEXT_STATE:  TAPSTATE_TYPE;
+  signal S_IRSTATE:     std_logic;
+  signal S_DRSTATE:     std_logic;
+  signal S_IR:          std_logic_vector(IR_WIDTH-1 downto 0);
+
+  signal IR_TDO:        std_logic;
+  signal IR_TDO_EN:     std_logic;
+  signal ID_TDO:        std_logic;
+  signal ID_TDO_EN:     std_logic;
+  signal IO_TDO:        std_logic;
+  signal IO_TDO_EN:     std_logic;
+begin
+  IR <= S_IR;
+
+  RESET     <= '1' when S_STATE = TestLogicReset              else '0';
+  DRCAPTURE <= '1' when S_STATE = Capture and S_DRSTATE = '1' else '0';
+  DRSHIFT   <= '1' when S_STATE = Shift   and S_DRSTATE = '1' else '0';
+  DRUPDATE  <= '1' when S_STATE = Update  and S_DRSTATE = '1' else '0';
+
+  -- JTAG state machine
+  FSM:  c4m_jtag_tap_fsm
+    port map (
+      TCK => TCK,
+      TMS => TMS,
+      TRST_N => TRST_N,
+      STATE => S_STATE,
+      NEXT_STATE => S_NEXT_STATE,
+      DRSTATE => S_DRSTATE,
+      IRSTATE => S_IRSTATE
+    );
+
+  -- The instruction register
+  IRBLOCK: c4m_jtag_irblock
+    generic map (
+      IR_WIDTH => IR_WIDTH
+    )
+    port map (
+      TCK => TCK,
+      TDI => TDI,
+      TDO => IR_TDO,
+      TDO_EN => IR_TDO_EN,
+      STATE => S_STATE,
+      NEXT_STATE => S_NEXT_STATE,
+      IRSTATE => S_IRSTATE,
+      IR => S_IR
+    );
+
+  -- The ID
+  IDBLOCK: c4m_jtag_idblock
+    generic map (
+      IR_WIDTH => IR_WIDTH,
+      PART_NUMBER => PART_NUMBER,
+      MANUFACTURER => MANUFACTURER
+    )
+    port map (
+      TCK => TCK,
+      TDI => TDI,
+      TDO => ID_TDO,
+      TDO_EN => ID_TDO_EN,
+      STATE => S_STATE,
+      NEXT_STATE => S_NEXT_STATE,
+      DRSTATE => S_DRSTATE,
+      IR => S_IR
+    );
+  
+  -- The IOS
+  IOBLOCK: c4m_jtag_ioblock
+    generic map (
+      IR_WIDTH => IR_WIDTH,
+      IOS => IOS
+    )
+    port map (
+      TCK => TCK,
+      TDI => TDI,
+      TDO => IO_TDO,
+      TDO_EN => IO_TDO_EN,
+      STATE => S_STATE,
+      NEXT_STATE => S_NEXT_STATE,
+      DRSTATE => S_DRSTATE,
+      IR => S_IR,
+      CORE_OUT => CORE_OUT,
+      CORE_IN => CORE_IN,
+      CORE_EN => CORE_EN,
+      PAD_OUT => PAD_OUT,
+      PAD_IN => PAD_IN,
+      PAD_EN => PAD_EN
+    );
+
+  TDO <= IR_TDO when IR_TDO_EN = '1' else
+         ID_TDO when ID_TDO_EN = '1' else
+         IO_TDO when IO_TDO_EN = '1' else
+         '0';
+
+  CHECK_EN: if DEBUG generate
+    signal EN:  std_logic_vector(2 downto 0) := "000";
+  begin
+    EN <= IR_TDO_EN & ID_TDO_EN & IO_TDO_EN;
+    assert EN = "000" or EN = "100" or EN = "010" or EN = "001"
+      report "TDO conflict in c4m_jtag_tap_controller"
+      severity ERROR;
+  end generate CHECK_EN;
+end rtl;
+
+
diff --git a/c4m/vhdl/jtag/c4m_jtag_tap_fsm.vhdl b/c4m/vhdl/jtag/c4m_jtag_tap_fsm.vhdl
new file mode 100644 (file)
index 0000000..005eccb
--- /dev/null
@@ -0,0 +1,140 @@
+-- The JTAG state machine
+-- This is implemented based on the IEEE 1149.1 standard
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity c4m_jtag_tap_fsm is
+  port (
+    -- The TAP signals
+    TCK:        in std_logic;
+    TMS:        in std_logic;
+    TRST_N:     in std_logic;
+
+    -- The state outputs
+    STATE:      out TAPSTATE_TYPE;
+    NEXT_STATE: out TAPSTATE_TYPE;
+    DRSTATE:    out std_logic;
+    IRSTATE:    out std_logic
+  );
+end c4m_jtag_tap_fsm;
+
+architecture rtl of c4m_jtag_tap_fsm is
+  signal S_STATE:         TAPSTATE_TYPE;
+  signal S_NEXT_STATE:    TAPSTATE_TYPE;
+  signal S_DRSTATE:       std_logic;
+  signal S_IRSTATE:       std_logic;
+  signal NEXT_DRSTATE:    std_logic;
+  signal NEXT_IRSTATE:    std_logic;
+begin
+  STATE <= S_STATE;
+  NEXT_STATE <= S_NEXT_STATE;
+  DRSTATE <= S_DRSTATE;
+  IRSTATE <= S_IRSTATE;
+  
+  process (TCK, TRST_N)
+  begin
+    if TRST_N = '0' then
+      S_DRSTATE <= '0';
+      S_IRSTATE <= '0';
+      S_STATE <= TestLogicReset;
+    elsif rising_edge(TCK) then
+      S_STATE <= S_NEXT_STATE;
+      S_DRSTATE <= NEXT_DRSTATE;
+      S_IRSTATE <= NEXT_IRSTATE;
+    end if;
+  end process;
+
+  NEXT_DRSTATE <=
+    '0' when S_NEXT_STATE = TestLogicReset else
+    '0' when S_NEXT_STATE = RunTestIdle else
+    '1' when S_NEXT_STATE = SelectDRScan else
+    '0' when S_NEXT_STATE = SelectIRScan else
+    S_DRSTATE;
+  NEXT_IRSTATE <=
+    '0' when S_NEXT_STATE = TestLogicReset else
+    '0' when S_NEXT_STATE = RunTestIdle else
+    '0' when S_NEXT_STATE = SelectDRScan else
+    '1' when S_NEXT_STATE = SelectIRScan else
+    S_IRSTATE;
+
+  process (S_STATE, TMS)
+  begin
+    case S_STATE is
+      when TestLogicReset =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= RunTestIdle;
+        else
+          S_NEXT_STATE <= TestLogicReset;
+        end if;
+
+      when RunTestIdle =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= RunTestIdle;
+        else
+          S_NEXT_STATE <= SelectDRScan;
+        end if;
+
+      when SelectDRScan =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= Capture;
+        else
+          S_NEXT_STATE <= SelectIRScan;
+        end if;
+
+      when SelectIRScan =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= Capture;
+        else
+          S_NEXT_STATE <= TestLogicReset;
+        end if;
+
+      when Capture =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= Shift;
+        else
+          S_NEXT_STATE <= Exit1;
+        end if;
+
+      when Shift =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= Shift;
+        else
+          S_NEXT_STATE <= Exit1;
+        end if;
+
+      when Exit1 =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= Pause;
+        else
+          S_NEXT_STATE <= Update;
+        end if;
+
+      when Pause =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= Pause;
+        else
+          S_NEXT_STATE <= Exit2;
+        end if;
+
+      when Exit2 =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= Shift;
+        else
+          S_NEXT_STATE <= Update;
+        end if;
+
+      when Update =>
+        if (TMS = '0') then
+          S_NEXT_STATE <= RunTestIdle;
+        else
+          S_NEXT_STATE <= SelectDRScan;
+        end if;
+
+      when others =>
+        S_NEXT_STATE <= TestLogicReset;
+    end case;
+  end process;
+end rtl;
diff --git a/rtl/nmigen/jtag.py b/rtl/nmigen/jtag.py
deleted file mode 100755 (executable)
index 3baaa95..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-#!/bin/env python3
-import os
-
-from nmigen import *
-from nmigen.build import *
-from nmigen.lib.io import *
-
-from wishbone import Wishbone
-
-__all__ = [
-    "PmodJTAGMasterResource",
-    "PmodJTAGMasterAResource",
-    "PmodJTAGSlaveResource",
-    "PmodJTAGSlaveAResource",
-    "JTAG",
-]
-
-#TODO: Provide more documentation
-
-def PmodJTAGMasterResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
-    return Resource(name, number,
-        Subsignal("TCK", Pins("1", dir="o", conn=("pmod", pmod))),
-        Subsignal("TMS", Pins("2", dir="o", conn=("pmod", pmod))),
-        Subsignal("TDO", Pins("3", dir="o", conn=("pmod", pmod))),
-        Subsignal("TDI", Pins("4", dir="i", conn=("pmod", pmod))),
-        attrs,
-    )
-
-def PmodJTAGMasterAResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
-    return Resource(name, number,
-        Subsignal("TCK", Pins("1", dir="o", conn=("pmod", pmod))),
-        Subsignal("TMS", Pins("2", dir="o", conn=("pmod", pmod))),
-        Subsignal("TDO", Pins("3", dir="o", conn=("pmod", pmod))),
-        Subsignal("TDI", Pins("4", dir="i", conn=("pmod", pmod))),
-        Subsignal("TRST", PinsN("7", dir="o", conn=("pmod", pmod))),
-        attrs,
-    )
-
-def PmodJTAGSlaveResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
-    return Resource(name, number,
-        Subsignal("TCK", Pins("1", dir="i", conn=("pmod", pmod))),
-        Subsignal("TMS", Pins("2", dir="i", conn=("pmod", pmod))),
-        Subsignal("TDI", Pins("3", dir="i", conn=("pmod", pmod))),
-        Subsignal("TDO", Pins("4", dir="o", conn=("pmod", pmod))),
-        attrs,
-    )
-
-def PmodJTAGSlaveAResource(name, number, *, pmod, attrs=Attrs(IOSTANDARD="LVCMOS33")):
-    return Resource(name, number,
-        Subsignal("TCK", Pins("1", dir="i", conn=("pmod", pmod))),
-        Subsignal("TMS", Pins("2", dir="i", conn=("pmod", pmod))),
-        Subsignal("TDI", Pins("3", dir="i", conn=("pmod", pmod))),
-        Subsignal("TDO", Pins("4", dir="o", conn=("pmod", pmod))),
-        Subsignal("TRST", PinsN("7", dir="i", conn=("pmod", pmod))),
-        attrs,
-    )
-
-
-class ShiftReg(Elaboratable):
-    def __init__(self, ircodes, length, domain):
-        # The sr record will be returned to user code
-        self.sr = Record([("i", length), ("o", length), ("oe", len(ircodes)), ("ack", 1)])
-        # The next attributes are for JTAG class usage only
-        self.ir = None # made None as width is not known yet
-        self.tdi = Signal()
-        self.tdo = Signal()
-        self.tdo_en = Signal()
-        self.capture = Signal()
-        self.shift = Signal()
-        self.update = Signal()
-        self.jtag_cd = None # The JTAG clock domain
-
-        ##
-
-        self._ircodes = ircodes
-        self._domain = domain
-
-    def elaborate(self, platform):
-        length = len(self.sr.o)
-        domain = self._domain
-
-        m = Module()
-
-        m.domains.jtag = self.jtag_cd
-
-        sr_jtag = Signal(length)
-
-        assert isinstance(self.ir, Signal)
-        isir = Signal(len(self._ircodes))
-        capture = Signal()
-        shift = Signal()
-        update = Signal()
-        m.d.comb += [
-            isir.eq(Cat(self.ir == ircode for ircode in self._ircodes)),
-            capture.eq((isir != 0) & self.capture),
-            shift.eq((isir != 0) & self.shift),
-            update.eq((isir != 0) & self.update),
-        ]
-
-        # On update set o, oe and wait for ack
-        # update signal is on JTAG clockdomain, latch it
-        update_core = Signal()
-        m.d[domain] += update_core.eq(update) # This is CDC from JTAG domain to given domain
-        with m.FSM(domain=domain):
-            with m.State("IDLE"):
-                m.d.comb += self.sr.oe.eq(0)
-                with m.If(update_core):
-                    # Latch sr_jtag cross domain but it should be stable due to latching of update_core
-                    m.d[domain] += self.sr.o.eq(sr_jtag)
-                    # Wait one cycle to raise oe so sr.o has one more cycle to stabilize
-                    m.next = "WAIT4ACK"
-            with m.State("WAIT4ACK"):
-                m.d.comb += self.sr.oe.eq(isir)
-                with m.If(self.sr.ack):
-                    m.next = "WAIT4END"
-            with m.State("WAIT4END"):
-                m.d.comb += self.sr.oe.eq(0)
-                with m.If(~update_core):
-                    m.next = "IDLE"
-
-        m.d.comb += [
-            self.tdo.eq(sr_jtag[0]),
-            self.tdo_en.eq(shift),
-        ]
-
-        with m.If(shift):
-            m.d.jtag += sr_jtag.eq(Cat(sr_jtag[1:], self.tdi))
-        with m.If(capture):
-            m.d.jtag += sr_jtag.eq(self.sr.i)
-
-        return m
-
-class JTAGWishbone(Elaboratable):
-    def __init__(self, sr_addr, sr_data, wb, domain):
-        self._sr_addr = sr_addr
-        self._sr_data = sr_data
-        self._wb = wb
-        self._domain = domain
-
-        # To be set by JTAG
-        self._ir = None
-
-    def elaborate(self, platform):
-        sr_addr = self._sr_addr
-        sr_data = self._sr_data
-        wb = self._wb
-        domain = self._domain
-        ir = self._ir
-
-        m = Module()
-
-        if hasattr(wb, "sel"):
-            # Always selected
-            m.d.comb += [s.eq(1) for s in wb.sel]
-
-        # Immediately ack oe
-        m.d[domain] += [
-            sr_addr.ack.eq(sr_addr.oe),
-            sr_data.ack.eq(sr_data.oe != 0),
-        ]
-
-        with m.FSM(domain=domain) as fsm:
-            with m.State("IDLE"):
-                m.d.comb += [
-                    wb.cyc.eq(0),
-                    wb.stb.eq(0),
-                    wb.we.eq(0),
-                ]
-                with m.If(sr_addr.oe): # WBADDR code
-                    m.d[domain] += wb.addr.eq(sr_addr.o)
-                    m.next = "READ"
-                with m.If(sr_data.oe[0]): # WBREAD code
-                    m.d[domain] += wb.addr.eq(wb.addr + 1)
-                    m.next = "READ"
-                with m.If(sr_data.oe[1]): # WBWRITE code
-                    m.d[domain] += wb.dat_w.eq(sr_data.o)
-                    m.next = "WRITEREAD"
-            with m.State("READ"):
-                m.d.comb += [
-                    wb.cyc.eq(1),
-                    wb.stb.eq(1),
-                    wb.we.eq(0),
-                ]
-                with m.If(~wb.stall):
-                    m.next = "READACK"
-            with m.State("READACK"):
-                m.d.comb += [
-                    wb.cyc.eq(1),
-                    wb.stb.eq(0),
-                    wb.we.eq(0),
-                ]
-                with m.If(wb.ack):
-                    m.d[domain] += sr_data.i.eq(wb.dat_r)
-                    m.next = "IDLE"
-            with m.State("WRITEREAD"):
-                m.d.comb += [
-                    wb.cyc.eq(1),
-                    wb.stb.eq(1),
-                    wb.we.eq(1),
-                ]
-                with m.If(~wb.stall):
-                    m.next = "WRITEREADACK"
-            with m.State("WRITEREADACK"):
-                m.d.comb += [
-                    wb.cyc.eq(1),
-                    wb.stb.eq(0),
-                    wb.we.eq(0),
-                ]
-                with m.If(wb.ack):
-                    m.d[domain] += wb.addr.eq(wb.addr + 1)
-                    m.next = "READ"
-
-        return m
-
-
-class JTAG(Elaboratable):
-    @staticmethod
-    def _add_files(platform, prefix):
-        d = os.path.realpath("{0}{1}{2}{1}vhdl".format(
-            os.path.dirname(__file__), os.path.sep, os.path.pardir
-        )) + os.path.sep
-        for fname in [
-            "c4m_jtag_pkg.vhdl",
-            "c4m_jtag_idblock.vhdl",
-            "c4m_jtag_iocell.vhdl",
-            "c4m_jtag_ioblock.vhdl",
-            "c4m_jtag_irblock.vhdl",
-            "c4m_jtag_tap_fsm.vhdl",
-            "c4m_jtag_tap_controller.vhdl",
-        ]:
-            f = open(d + fname, "r")
-            platform.add_file(prefix + fname, f)
-            f.close()
-
-
-    def __init__(self, io_count, *, ir_width=None, manufacturer_id=Const(0b10001111111, 11),
-                 part_number=Const(1, 16), version=Const(0, 4)
-    ):
-        assert(isinstance(io_count, int) and io_count > 0)
-        assert((ir_width is None) or (isinstance(ir_width, int) and ir_width >= 2))
-        assert(len(version) == 4)
-
-        # TODO: Handle IOs with different directions
-        self.tck  = Signal()
-        self.tms  = Signal()
-        self.tdo  = Signal()
-        self.tdi  = Signal()
-        self.core = Array(Pin(1, "io") for _ in range(io_count)) # Signals to use for core
-        self.pad  = Array(Pin(1, "io") for _ in range(io_count)) # Signals going to IO pads
-
-        self.jtag_cd = ClockDomain(name="jtag", local=True) # Own clock domain using TCK as clock signal
-
-        ##
-
-        self._io_count = io_count
-        self._ir_width = ir_width
-        self._manufacturer_id = manufacturer_id
-        self._part_number = part_number
-        self._version = version
-
-        self._ircodes = [0, 1, 2] # Already taken codes, all ones added at the end
-        self._srs = []
-
-        self._wbs = []
-
-    def elaborate(self, platform):
-        JTAG._add_files(platform, "jtag" + os.path.sep)
-
-        m = Module()
-
-        tdo_jtag = Signal()
-        reset = Signal()
-        capture = Signal()
-        shift = Signal()
-        update = Signal()
-
-
-        ir_max = max(self._ircodes) + 1 # One extra code needed with all ones
-        ir_width = len("{:b}".format(ir_max))
-        if self._ir_width is not None:
-            assert self._ir_width >= ir_width, "Specified JTAG IR width not big enough for allocated shiift registers"
-            ir_width = self._ir_width
-        ir = Signal(ir_width)
-
-        core_i = Cat(pin.i for pin in self.core)
-        core_o = Cat(pin.o for pin in self.core)
-        core_oe = Cat(pin.oe for pin in self.core)
-        pad_i = Cat(pin.i for pin in self.pad)
-        pad_o = Cat(pin.o for pin in self.pad)
-        pad_oe = Cat(pin.oe for pin in self.pad)
-
-        params = {
-            "p_IOS": self._io_count,
-            "p_IR_WIDTH": ir_width,
-            "p_MANUFACTURER": self._manufacturer_id,
-            "p_PART_NUMBER": self._part_number,
-            "p_VERSION": self._version,
-            "i_TCK": self.tck,
-            "i_TMS": self.tms,
-            "i_TDI": self.tdi,
-            "o_TDO": tdo_jtag,
-            "i_TRST_N": Const(1),
-            "o_RESET": reset,
-            "o_DRCAPTURE": capture,
-            "o_DRSHIFT": shift,
-            "o_DRUPDATE": update,
-            "o_IR": ir,
-            "o_CORE_IN": core_i,
-            "i_CORE_OUT": core_o,
-            "i_CORE_EN": core_oe,
-            "i_PAD_IN": pad_i,
-            "o_PAD_OUT": pad_o,
-            "o_PAD_EN": pad_oe,
-        }
-        m.submodules.tap = Instance("c4m_jtag_tap_controller", **params)
-
-        m.d.comb += [
-            self.jtag_cd.clk.eq(self.tck),
-            self.jtag_cd.rst.eq(reset),
-        ]
-
-        for i, sr in enumerate(self._srs):
-            m.submodules["sr{}".format(i)] = sr
-            sr.ir = ir
-            m.d.comb += [
-                sr.tdi.eq(self.tdi),
-                sr.capture.eq(capture),
-                sr.shift.eq(shift),
-                sr.update.eq(update),
-            ]
-
-        if len(self._srs) > 0:
-            first = True
-            for sr in self._srs:
-                if first:
-                    first = False
-                    with m.If(sr.tdo_en):
-                        m.d.comb += self.tdo.eq(sr.tdo)
-                else:
-                    with m.Elif(sr.tdo_en):
-                        m.d.comb += self.tdo.eq(sr.tdo)
-            with m.Else():
-                m.d.comb += self.tdo.eq(tdo_jtag)
-        else:
-            m.d.comb += self.tdo.eq(tdo_jtag)
-
-        for i, wb in enumerate(self._wbs):
-            m.submodules["wb{}".format(i)] = wb
-            wb._ir = ir
-
-        return m
-
-
-    def add_shiftreg(self, ircode, length, domain="sync"):
-        """Add a shift register to the JTAG interface
-
-        Parameters:
-        - ircode: code(s) for the IR; int or sequence of ints. In the latter case this
-          shiftreg is shared between different IR codes.
-        - length: the length of the shift register
-        - domain: the domain on which the signal will be used"""
-
-        try:
-            ir_it = iter(ircode)
-            ircodes = ircode
-        except TypeError:
-            ir_it = ircodes = (ircode,)
-        for _ircode in ir_it:
-            assert(isinstance(_ircode, int) and _ircode > 0 and _ircode not in self._ircodes)
-
-        sr = ShiftReg(ircodes, length, domain)
-        sr.jtag_cd = self.jtag_cd
-        self._ircodes.extend(ircodes)
-        self._srs.append(sr)
-
-        return sr.sr
-
-
-    def add_wishbone(self, ircodes, address_width, data_width, sel_width=None, domain="sync"):
-        """Add a wishbone interface
-
-        Parameters:
-        - ircodes: sequence of three integer for the JTAG IR codes;
-          they represent resp. WBADDR, WBREAD and WBREADWRITE. First code
-          has a shift register of length 'address_width', the two other codes
-          share a shift register of length data_width.
-        - address_width: width of the address
-        - data_width: width of the data"""
-
-        assert len(ircodes) == 3
-
-        sr_addr = self.add_shiftreg(ircodes[0], address_width, domain=domain)
-        sr_data = self.add_shiftreg(ircodes[1:], data_width, domain=domain)
-
-        wb = Wishbone(data_width=data_width, address_width=address_width, sel_width=sel_width, master=True)
-
-        self._wbs.append(JTAGWishbone(sr_addr, sr_data, wb, domain))
-
-        return wb
diff --git a/rtl/vhdl/c4m_jtag_idblock.vhdl b/rtl/vhdl/c4m_jtag_idblock.vhdl
deleted file mode 100644 (file)
index 303959a..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
--- The JTAG id and bypass handling block
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity c4m_jtag_idblock is
-  generic (
-    IR_WIDTH:           integer := 2;
-    
-    MANUFACTURER:       std_logic_vector(10 downto 0) := "10001111111";
-    PART_NUMBER:        std_logic_vector(15 downto 0) := "0000000000000001";
-    VERSION:            std_logic_vector(3 downto 0) := "0000"
-  );
-  port (
-    -- needed TAP signals
-    TCK:        in std_logic;
-    TDI:        in std_logic;
-    TDO:        out std_logic;
-    TDO_EN:     out std_logic := '0';
-
-    -- JTAG state
-    STATE:      in TAPSTATE_TYPE;
-    NEXT_STATE: in TAPSTATE_TYPE;
-    DRSTATE:    in std_logic;
-
-    -- The instruction
-    IR:         in std_logic_vector(IR_WIDTH-1 downto 0)
-  );
-end c4m_jtag_idblock;
-
-architecture rtl of c4m_jtag_idblock is
-  constant IDCODE:      std_logic_vector(31 downto 0) := VERSION & PART_NUMBER & MANUFACTURER & "1";
-
-  signal SR_ID:         std_logic_vector(31 downto 0);
-  signal EN_TDO:        boolean;
-  
-  constant CMD_IDCODE:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_idcode(IR_WIDTH);
-  constant CMD_BYPASS:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_bypass(IR_WIDTH);
-begin
-  process (TCK)
-  begin
-    if rising_edge(TCK) then
-      if DRSTATE = '1' then
-        case STATE is
-          when Capture =>
-            SR_ID <= IDCODE;
-
-          when Shift =>
-            if IR = CMD_IDCODE then
-              SR_ID(30 downto 0) <= SR_ID(31 downto 1);
-              SR_ID(31) <= TDI;
-            elsif IR = CMD_BYPASS then
-              SR_ID(0) <= TDI;
-            else
-              null;
-            end if;
-
-          when others =>
-            null;
-        end case;
-      end if;
-    end if;
-  end process;
-
-  EN_TDO <= STATE = Shift and DRSTATE = '1' and (IR = CMD_IDCODE or IR = CMD_BYPASS);
-  TDO <= SR_ID(0) when EN_TDO else
-         '0';
-  TDO_EN <= '1' when EN_TDO else
-            '0';
-end rtl;
diff --git a/rtl/vhdl/c4m_jtag_ioblock.vhdl b/rtl/vhdl/c4m_jtag_ioblock.vhdl
deleted file mode 100644 (file)
index c70be6f..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
--- The block of io cells with JTAG boundary scan support
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity c4m_jtag_ioblock is
-  generic (
-    IR_WIDTH:   integer := 2;
-    IOS:        integer := 1
-  );
-  port (
-    -- needed TAP signals
-    TCK:        in std_logic;
-    TDI:        in std_logic;
-    TDO:        out std_logic;
-    TDO_EN:     out std_logic := '0';
-
-    -- JTAG state
-    STATE:      in TAPSTATE_TYPE;
-    NEXT_STATE: in TAPSTATE_TYPE;
-    DRSTATE:    in std_logic;
-
-    -- The instruction
-    IR:         in std_logic_vector(IR_WIDTH-1 downto 0);
-
-    -- The I/O access ports
-    CORE_OUT:   in std_logic_vector(IOS-1 downto 0);
-    CORE_IN:    out std_logic_vector(IOS-1 downto 0);
-    CORE_EN:    in std_logic_vector(IOS-1 downto 0);
-
-    -- The pad connections
-    PAD_OUT:    out std_logic_vector(IOS-1 downto 0);
-    PAD_IN:     in std_logic_vector(IOS-1 downto 0);
-    PAD_EN:     out std_logic_vector(IOS-1 downto 0)
-  );
-end c4m_jtag_ioblock;
-
-architecture rtl of c4m_jtag_ioblock is
-  signal IOMODE:        SRIOMODE_TYPE;
-  signal SAMPLEMODE:    SRSAMPLEMODE_TYPE;
-  signal ISSAMPLECMD:   boolean;
-  
-  signal BDSR_IN:       std_logic_vector(IOS-1 downto 0);
-  signal BDSR_OUT:      std_logic_vector(IOS-1 downto 0);
-  
-  constant CMD_SAMPLEPRELOAD: std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_samplepreload(IR_WIDTH);
-  constant CMD_EXTEST:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_extest(IR_WIDTH);
-begin
-  -- JTAG baundary scan IO cells
-  IOGEN: for i in 0 to IOS-1 generate
-  begin
-    IOCELL: c4m_jtag_iocell
-      port map (
-        CORE_IN => CORE_IN(i),
-        CORE_OUT => CORE_OUT(i),
-        CORE_EN => CORE_EN(i),
-        PAD_IN => PAD_IN(i),
-        PAD_OUT => PAD_OUT(i),
-        PAD_EN => PAD_EN(i),
-        BDSR_IN => BDSR_IN(i),
-        BDSR_OUT => BDSR_OUT(i),
-        IOMODE => IOMODE,
-        SAMPLEMODE => SAMPLEMODE,
-        TCK => TCK
-      );
-  end generate;
-  BDSRCONN: for i in 0 to IOS-2 generate
-  begin
-    BDSR_IN(i) <= BDSR_OUT(i+1);
-  end generate;
-  BDSR_IN(IOS-1) <= TDI;
-
-  -- Set IOMODE
-  -- Currently SR_2Core or SR_Z are not used
-  IOMODE <= SR_2Pad when IR = CMD_EXTEST else
-            SR_Through;
-
-  -- Set SAMPLEMODE
-  ISSAMPLECMD <= (IR = CMD_SAMPLEPRELOAD or IR = CMD_EXTEST) and DRSTATE = '1';
-  SAMPLEMODE <= SR_Sample when ISSAMPLECMD and STATE = Capture else
-                SR_Update when ISSAMPLECMD and STATE = Update else
-                SR_Shift when ISSAMPLECMD and STATE = Shift else
-                SR_Normal;
-
-  TDO <= BDSR_OUT(0) when ISSAMPLECMD and STATE = Shift else
-         '0';
-  TDO_EN <= '1' when ISSAMPLECMD and STATE = Shift else
-            '0';
-end rtl;
diff --git a/rtl/vhdl/c4m_jtag_iocell.vhdl b/rtl/vhdl/c4m_jtag_iocell.vhdl
deleted file mode 100644 (file)
index 6a218a6..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
--- An JTAG boundary scan for bidirectional I/O
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity c4m_jtag_iocell is
-  generic (
-    IR_WIDTH:   integer := 2
-  );
-  port (
-    -- core connections
-    CORE_IN:    out std_logic;
-    CORE_OUT:   in std_logic;
-    CORE_EN:    in std_logic;
-
-    -- pad connections
-    PAD_IN:     in std_logic;
-    PAD_OUT:    out std_logic;
-    PAD_EN:     out std_logic;
-
-    -- BD shift register
-    BDSR_IN:    in std_logic;
-    BDSR_OUT:   out std_logic;
-
-      -- Mode of I/O cell
-    IOMODE:     in SRIOMODE_TYPE;
-    SAMPLEMODE: in SRSAMPLEMODE_TYPE;
-    TCK:        in std_logic
-  );
-end c4m_jtag_iocell;
-
-architecture rtl of c4m_jtag_iocell is
-  signal SR_IOIN: std_logic;
-  signal SR_IOOUT: std_logic;
-  signal SR_IOEN: std_logic;
-
-  signal CORE_IN_BD: std_logic;
-  signal PAD_OUT_BD: std_logic;
-  signal PAD_EN_BD: std_logic;
-begin
-  with IOMODE select
-  CORE_IN <=
-    PAD_IN when SR_Through | SR_Z,
-    PAD_IN when SR_2Pad,
-    CORE_IN_BD when SR_2Core,
-    'X' when others;
-
-  with IOMODE select
-  PAD_OUT <=
-    CORE_OUT when SR_Through,
-    PAD_OUT_BD when SR_2Pad,
-    '0' when SR_2Core | SR_Z,  
-    'X' when others;
-
-  with IOMODE select
-  PAD_EN <=
-    CORE_EN when SR_Through,
-    PAD_EN_BD when SR_2Pad,
-    '0' when SR_2Core | SR_Z,
-    'X' when others;
-
-  process (TCK)
-  begin
-    -- Sampling of inputs and shifting of boundary scan SR needs to be done on
-    -- rising edge of TCK
-    if rising_edge(TCK) then
-      case SAMPLEMODE is
-        when SR_Sample =>
-          SR_IOIN <= PAD_IN;
-          SR_IOOUT <= CORE_OUT;
-          SR_IOEN <= CORE_EN;
-
-        when SR_Shift =>
-          SR_IOIN <= BDSR_IN;
-          SR_IOOUT <= SR_IOIN;
-          SR_IOEN <= SR_IOOUT;
-
-        when others =>
-          null;
-      end case;
-    end if;
-    
-    -- Update of output from boundary scan SR needs to be done on falling edge
-    -- of TCK
-    if falling_edge(TCK) then
-      case SAMPLEMODE is
-        when SR_Update =>
-          CORE_IN_BD <= SR_IOIN;
-          PAD_OUT_BD <= SR_IOOUT;
-          PAD_EN_BD <= SR_IOEN;
-          
-        when others =>
-          null;
-      end case;
-    end if;
-  end process;
-
-  BDSR_OUT <= SR_IOEN;
-end rtl;
diff --git a/rtl/vhdl/c4m_jtag_irblock.vhdl b/rtl/vhdl/c4m_jtag_irblock.vhdl
deleted file mode 100644 (file)
index 8be483a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
--- Handle the instruction register for the JTAG controller
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity c4m_jtag_irblock is
-  generic (
-    IR_WIDTH:   integer := 2
-  );
-  port (
-    -- needed TAP signals
-    TCK:        in std_logic;
-    TDI:        in std_logic;
-    TDO:        out std_logic;
-    TDO_EN:     out std_logic := '0';
-    
-    -- JTAG state
-    STATE:      in TAPSTATE_TYPE;
-    NEXT_STATE: in TAPSTATE_TYPE;
-    IRSTATE:    in std_logic;
-
-    -- instruction register
-    IR:         out std_logic_vector(IR_WIDTH-1 downto 0)
-  );
-end c4m_jtag_irblock;
-
-architecture rtl of c4m_jtag_irblock is
-  signal SHIFT_IR:      std_logic_vector(IR_WIDTH-1 downto 0);
-
-  constant CMD_IDCODE:  std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_idcode(IR_WIDTH);
-begin
-  process (TCK, STATE)
-  begin
-    if STATE = TestLogicReset then
-        SHIFT_IR <= (others => '0');
-        IR <= CMD_IDCODE;
-    elsif rising_edge(TCK) then
-      if IRSTATE = '1' then
-        case STATE is
-          when Capture =>
-            SHIFT_IR(1) <= '0';
-            SHIFT_IR(0) <= '1';
-
-          when Shift =>
-            SHIFT_IR(IR_WIDTH-2 downto 0) <= SHIFT_IR(IR_WIDTH-1 downto 1);
-            SHIFT_IR(IR_WIDTH-1) <= TDI;
-
-          when Update =>
-            IR <= SHIFT_IR;
-
-          when others =>
-            null;
-        end case;
-      end if;
-    end if;
-  end process;
-
-  TDO <= SHIFT_IR(0) when STATE = Shift and IRSTATE = '1' else
-         '0';
-  TDO_EN <= '1' when STATE = Shift and IRSTATE = '1' else
-            '0';
-end rtl;
diff --git a/rtl/vhdl/c4m_jtag_pkg.vhdl b/rtl/vhdl/c4m_jtag_pkg.vhdl
deleted file mode 100644 (file)
index 0fc0749..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
--- Package of jtag support code from the Chips4Makers project
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-package c4m_jtag is
-  type TAPSTATE_TYPE is (
-    TestLogicReset,
-    RunTestIdle,
-    SelectDRScan,
-    SelectIRScan,
-    Capture,
-    Shift,
-    Exit1,
-    Pause,
-    Exit2,
-    Update
-  );
-  type SRIOMODE_TYPE is (
-    SR_Through, -- Connect core signal to pad signals
-    SR_2Pad,    -- Connect BD to pad
-    SR_2Core,   -- Connect BD to core
-    SR_Z        -- pad is high impedance
-  );
-  type SRSAMPLEMODE_TYPE is (
-    SR_Normal,  -- No sampling or shifting
-    SR_Sample,  -- Sample IO state in BD SR on rising edge of TCK
-    SR_Update,  -- Update BD from SR on falling edge of TCK
-    SR_Shift    -- Shift the BD SR
-  );
-
-  component c4m_jtag_tap_fsm is
-    port (
-      -- The TAP signals
-      TCK:      in std_logic;
-      TMS:      in std_logic;
-      TRST_N:   in std_logic;
-
-      -- The state outputs
-      STATE:    out TAPSTATE_TYPE;
-      NEXT_STATE: out TAPSTATE_TYPE;
-      DRSTATE:  out std_logic;
-      IRSTATE:  out std_logic
-    );
-  end component c4m_jtag_tap_fsm;
-
-  component c4m_jtag_irblock is
-    generic (
-      IR_WIDTH: integer := 2
-    );
-    port (
-      -- needed TAP signals
-      TCK:      in std_logic;
-      TDI:      in std_logic;
-      TDO:      out std_logic;
-      TDO_EN:   out std_logic;
-    
-      -- JTAG state
-      STATE:    in TAPSTATE_TYPE;
-      NEXT_STATE: in TAPSTATE_TYPE;
-      IRSTATE:  in std_logic;
-
-      -- instruction register
-      IR:       out std_logic_vector(IR_WIDTH-1 downto 0)
-    );
-  end component c4m_jtag_irblock;
-  
-  component c4m_jtag_idblock is
-    generic (
-      IR_WIDTH:         integer := 2;
-    
-      -- The default MANUFACTURING ID is not representing a valid
-      -- manufacturer according to the JTAG standard
-      MANUFACTURER:     std_logic_vector(10 downto 0) := "10001111111";
-      PART_NUMBER:      std_logic_vector(15 downto 0) := "0000000000000001";
-      VERSION:          std_logic_vector(3 downto 0) := "0000"
-    );
-    port (
-      -- needed TAP signals
-      TCK:      in std_logic;
-      TDI:      in std_logic;
-      TDO:      out std_logic;
-      TDO_EN:   out std_logic;
-
-      -- JTAG state
-      STATE:    in TAPSTATE_TYPE;
-      NEXT_STATE: in TAPSTATE_TYPE;
-      DRSTATE:  in std_logic;
-
-      -- The instruction
-      IR:       in std_logic_vector(IR_WIDTH-1 downto 0)
-    );
-  end component c4m_jtag_idblock;
-
-  component c4m_jtag_iocell is
-    port (
-      -- core connections
-      CORE_IN:  out std_logic;
-      CORE_OUT: in std_logic;
-      CORE_EN:  in std_logic;
-
-      -- pad connections
-      PAD_IN:   in std_logic;
-      PAD_OUT:  out std_logic;
-      PAD_EN:   out std_logic;
-
-      -- BD shift register
-      BDSR_IN:  in std_logic;
-      BDSR_OUT: out std_logic;
-
-      -- Mode of I/O cell
-      IOMODE:   in SRIOMODE_TYPE;
-      SAMPLEMODE: in SRSAMPLEMODE_TYPE;
-      TCK:      in std_logic
-    );
-  end component c4m_jtag_iocell;
-  
-  component c4m_jtag_ioblock is
-    generic (
-      IR_WIDTH: integer := 2;
-      IOS:      integer := 1
-    );
-    port (
-      -- needed TAP signals
-      TCK:      in std_logic;
-      TDI:      in std_logic;
-      TDO:      out std_logic;
-      TDO_EN:   out std_logic;
-
-      -- JTAG state
-      STATE:    in TAPSTATE_TYPE;
-      NEXT_STATE: in TAPSTATE_TYPE;
-      DRSTATE:  in std_logic;
-
-      -- The instruction
-      IR:       in std_logic_vector(IR_WIDTH-1 downto 0);
-
-      -- The I/O access ports
-      CORE_OUT: in std_logic_vector(IOS-1 downto 0);
-      CORE_IN:  out std_logic_vector(IOS-1 downto 0);
-      CORE_EN:  in std_logic_vector(IOS-1 downto 0);
-
-      -- The pad connections
-      PAD_OUT:  out std_logic_vector(IOS-1 downto 0);
-      PAD_IN:   in std_logic_vector(IOS-1 downto 0);
-      PAD_EN:   out std_logic_vector(IOS-1 downto 0)
-    );
-  end component c4m_jtag_ioblock;
-
-  component c4m_jtag_tap_controller is
-    generic (
-      DEBUG:            boolean := false;
-
-      IR_WIDTH:         integer := 2;
-      IOS:              integer := 1;
-
-      -- The default MANUFACTURING ID is not representing a valid
-      -- manufacturer according to the JTAG standard
-      MANUFACTURER:     std_logic_vector(10 downto 0) := "10001111111";
-      PART_NUMBER:      std_logic_vector(15 downto 0) := "0000000000000001";
-      VERSION:          std_logic_vector(3 downto 0) := "0000"
-    );
-    port (
-      -- The TAP signals
-      TCK:      in std_logic;
-      TMS:      in std_logic;
-      TDI:      in std_logic;
-      TDO:      out std_logic;
-      TRST_N:   in std_logic;
-
-      -- The FSM state indicators
-      RESET:    out std_logic; -- In reset state
-      DRCAPTURE: out std_logic; -- In DR_Capture state
-      DRSHIFT:  out std_logic; -- In DR_Shift state
-      DRUPDATE: out std_logic; -- In DR_Update state
-
-      -- The Instruction Register
-      IR:       out std_logic_vector(IR_WIDTH-1 downto 0);
-
-      -- The I/O access ports
-      CORE_IN:  out std_logic_vector(IOS-1 downto 0);
-      CORE_EN:  in std_logic_vector(IOS-1 downto 0);
-      CORE_OUT: in std_logic_vector(IOS-1 downto 0);
-
-      -- The pad connections
-      PAD_IN:   in std_logic_vector(IOS-1 downto 0);
-      PAD_EN:   out std_logic_vector(IOS-1 downto 0);
-      PAD_OUT:  out std_logic_vector(IOS-1 downto 0)
-    );
-  end component c4m_jtag_tap_controller;
-
-  function c4m_jtag_cmd_idcode(width: integer) return std_logic_vector;
-  function c4m_jtag_cmd_bypass(width: integer) return std_logic_vector;
-  function c4m_jtag_cmd_samplepreload(width: integer) return std_logic_vector;
-  function c4m_jtag_cmd_extest(width: integer) return std_logic_vector;
-end c4m_jtag;
-
-package body c4m_jtag is
-  function c4m_jtag_cmd_bypass(width: integer) return std_logic_vector is
-    variable return_vector: std_logic_vector(width-1 downto 0);
-  begin
-    return_vector := (others => '1');
-    return return_vector;
-  end;
-
-  function c4m_jtag_cmd_idcode(width: integer) return std_logic_vector is
-    variable return_vector: std_logic_vector(width-1 downto 0);
-  begin
-    return_vector := (0 => '1', others => '0');
-    return return_vector;
-  end;
-
-  function c4m_jtag_cmd_samplepreload(width: integer) return std_logic_vector is
-    variable return_vector: std_logic_vector(width-1 downto 0);
-  begin
-    return_vector := (1 => '1', others => '0');
-    return return_vector;
-  end;
-
-  function c4m_jtag_cmd_extest(width: integer) return std_logic_vector is
-    variable return_vector: std_logic_vector(width-1 downto 0);
-  begin
-    return_vector := (others => '0');
-    return return_vector;
-  end;
-end package body;
diff --git a/rtl/vhdl/c4m_jtag_tap_controller.vhdl b/rtl/vhdl/c4m_jtag_tap_controller.vhdl
deleted file mode 100644 (file)
index 217982e..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
--- A JTAG complient tap controller implementation
--- This is implemented based on the IEEE 1149.1 standard
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity c4m_jtag_tap_controller is
-  generic (
-    DEBUG:              boolean := false;
-
-    IR_WIDTH:           integer := 2;
-    IOS:                integer := 1;
-
-    MANUFACTURER:       std_logic_vector(10 downto 0) := "10001111111";
-    PART_NUMBER:        std_logic_vector(15 downto 0) := "0000000000000001";
-    VERSION:            std_logic_vector(3 downto 0) := "0000"
-  );
-  port (
-    -- The TAP signals
-    TCK:        in std_logic;
-    TMS:        in std_logic;
-    TDI:        in std_logic;
-    TDO:        out std_logic;
-    TRST_N:     in std_logic;
-
-    -- The FSM state indicators
-    RESET:      out std_logic;
-    DRCAPTURE:  out std_logic;
-    DRSHIFT:    out std_logic;
-    DRUPDATE:   out std_logic;
-
-    -- The Instruction Register
-    IR:         out std_logic_vector(IR_WIDTH-1 downto 0);
-
-    -- The I/O access ports
-    CORE_IN:    out std_logic_vector(IOS-1 downto 0);
-    CORE_EN:    in std_logic_vector(IOS-1 downto 0);
-    CORE_OUT:   in std_logic_vector(IOS-1 downto 0);
-
-    -- The pad connections
-    PAD_IN:     in std_logic_vector(IOS-1 downto 0);
-    PAD_EN:     out std_logic_vector(IOS-1 downto 0);
-    PAD_OUT:    out std_logic_vector(IOS-1 downto 0)
-  );
-end c4m_jtag_tap_controller;
-
-architecture rtl of c4m_jtag_tap_controller is
-  signal S_STATE:       TAPSTATE_TYPE;
-  signal S_NEXT_STATE:  TAPSTATE_TYPE;
-  signal S_IRSTATE:     std_logic;
-  signal S_DRSTATE:     std_logic;
-  signal S_IR:          std_logic_vector(IR_WIDTH-1 downto 0);
-
-  signal IR_TDO:        std_logic;
-  signal IR_TDO_EN:     std_logic;
-  signal ID_TDO:        std_logic;
-  signal ID_TDO_EN:     std_logic;
-  signal IO_TDO:        std_logic;
-  signal IO_TDO_EN:     std_logic;
-begin
-  IR <= S_IR;
-
-  RESET     <= '1' when S_STATE = TestLogicReset              else '0';
-  DRCAPTURE <= '1' when S_STATE = Capture and S_DRSTATE = '1' else '0';
-  DRSHIFT   <= '1' when S_STATE = Shift   and S_DRSTATE = '1' else '0';
-  DRUPDATE  <= '1' when S_STATE = Update  and S_DRSTATE = '1' else '0';
-
-  -- JTAG state machine
-  FSM:  c4m_jtag_tap_fsm
-    port map (
-      TCK => TCK,
-      TMS => TMS,
-      TRST_N => TRST_N,
-      STATE => S_STATE,
-      NEXT_STATE => S_NEXT_STATE,
-      DRSTATE => S_DRSTATE,
-      IRSTATE => S_IRSTATE
-    );
-
-  -- The instruction register
-  IRBLOCK: c4m_jtag_irblock
-    generic map (
-      IR_WIDTH => IR_WIDTH
-    )
-    port map (
-      TCK => TCK,
-      TDI => TDI,
-      TDO => IR_TDO,
-      TDO_EN => IR_TDO_EN,
-      STATE => S_STATE,
-      NEXT_STATE => S_NEXT_STATE,
-      IRSTATE => S_IRSTATE,
-      IR => S_IR
-    );
-
-  -- The ID
-  IDBLOCK: c4m_jtag_idblock
-    generic map (
-      IR_WIDTH => IR_WIDTH,
-      PART_NUMBER => PART_NUMBER,
-      MANUFACTURER => MANUFACTURER
-    )
-    port map (
-      TCK => TCK,
-      TDI => TDI,
-      TDO => ID_TDO,
-      TDO_EN => ID_TDO_EN,
-      STATE => S_STATE,
-      NEXT_STATE => S_NEXT_STATE,
-      DRSTATE => S_DRSTATE,
-      IR => S_IR
-    );
-  
-  -- The IOS
-  IOBLOCK: c4m_jtag_ioblock
-    generic map (
-      IR_WIDTH => IR_WIDTH,
-      IOS => IOS
-    )
-    port map (
-      TCK => TCK,
-      TDI => TDI,
-      TDO => IO_TDO,
-      TDO_EN => IO_TDO_EN,
-      STATE => S_STATE,
-      NEXT_STATE => S_NEXT_STATE,
-      DRSTATE => S_DRSTATE,
-      IR => S_IR,
-      CORE_OUT => CORE_OUT,
-      CORE_IN => CORE_IN,
-      CORE_EN => CORE_EN,
-      PAD_OUT => PAD_OUT,
-      PAD_IN => PAD_IN,
-      PAD_EN => PAD_EN
-    );
-
-  TDO <= IR_TDO when IR_TDO_EN = '1' else
-         ID_TDO when ID_TDO_EN = '1' else
-         IO_TDO when IO_TDO_EN = '1' else
-         '0';
-
-  CHECK_EN: if DEBUG generate
-    signal EN:  std_logic_vector(2 downto 0) := "000";
-  begin
-    EN <= IR_TDO_EN & ID_TDO_EN & IO_TDO_EN;
-    assert EN = "000" or EN = "100" or EN = "010" or EN = "001"
-      report "TDO conflict in c4m_jtag_tap_controller"
-      severity ERROR;
-  end generate CHECK_EN;
-end rtl;
-
-
diff --git a/rtl/vhdl/c4m_jtag_tap_fsm.vhdl b/rtl/vhdl/c4m_jtag_tap_fsm.vhdl
deleted file mode 100644 (file)
index 005eccb..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
--- The JTAG state machine
--- This is implemented based on the IEEE 1149.1 standard
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity c4m_jtag_tap_fsm is
-  port (
-    -- The TAP signals
-    TCK:        in std_logic;
-    TMS:        in std_logic;
-    TRST_N:     in std_logic;
-
-    -- The state outputs
-    STATE:      out TAPSTATE_TYPE;
-    NEXT_STATE: out TAPSTATE_TYPE;
-    DRSTATE:    out std_logic;
-    IRSTATE:    out std_logic
-  );
-end c4m_jtag_tap_fsm;
-
-architecture rtl of c4m_jtag_tap_fsm is
-  signal S_STATE:         TAPSTATE_TYPE;
-  signal S_NEXT_STATE:    TAPSTATE_TYPE;
-  signal S_DRSTATE:       std_logic;
-  signal S_IRSTATE:       std_logic;
-  signal NEXT_DRSTATE:    std_logic;
-  signal NEXT_IRSTATE:    std_logic;
-begin
-  STATE <= S_STATE;
-  NEXT_STATE <= S_NEXT_STATE;
-  DRSTATE <= S_DRSTATE;
-  IRSTATE <= S_IRSTATE;
-  
-  process (TCK, TRST_N)
-  begin
-    if TRST_N = '0' then
-      S_DRSTATE <= '0';
-      S_IRSTATE <= '0';
-      S_STATE <= TestLogicReset;
-    elsif rising_edge(TCK) then
-      S_STATE <= S_NEXT_STATE;
-      S_DRSTATE <= NEXT_DRSTATE;
-      S_IRSTATE <= NEXT_IRSTATE;
-    end if;
-  end process;
-
-  NEXT_DRSTATE <=
-    '0' when S_NEXT_STATE = TestLogicReset else
-    '0' when S_NEXT_STATE = RunTestIdle else
-    '1' when S_NEXT_STATE = SelectDRScan else
-    '0' when S_NEXT_STATE = SelectIRScan else
-    S_DRSTATE;
-  NEXT_IRSTATE <=
-    '0' when S_NEXT_STATE = TestLogicReset else
-    '0' when S_NEXT_STATE = RunTestIdle else
-    '0' when S_NEXT_STATE = SelectDRScan else
-    '1' when S_NEXT_STATE = SelectIRScan else
-    S_IRSTATE;
-
-  process (S_STATE, TMS)
-  begin
-    case S_STATE is
-      when TestLogicReset =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= RunTestIdle;
-        else
-          S_NEXT_STATE <= TestLogicReset;
-        end if;
-
-      when RunTestIdle =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= RunTestIdle;
-        else
-          S_NEXT_STATE <= SelectDRScan;
-        end if;
-
-      when SelectDRScan =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= Capture;
-        else
-          S_NEXT_STATE <= SelectIRScan;
-        end if;
-
-      when SelectIRScan =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= Capture;
-        else
-          S_NEXT_STATE <= TestLogicReset;
-        end if;
-
-      when Capture =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= Shift;
-        else
-          S_NEXT_STATE <= Exit1;
-        end if;
-
-      when Shift =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= Shift;
-        else
-          S_NEXT_STATE <= Exit1;
-        end if;
-
-      when Exit1 =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= Pause;
-        else
-          S_NEXT_STATE <= Update;
-        end if;
-
-      when Pause =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= Pause;
-        else
-          S_NEXT_STATE <= Exit2;
-        end if;
-
-      when Exit2 =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= Shift;
-        else
-          S_NEXT_STATE <= Update;
-        end if;
-
-      when Update =>
-        if (TMS = '0') then
-          S_NEXT_STATE <= RunTestIdle;
-        else
-          S_NEXT_STATE <= SelectDRScan;
-        end if;
-
-      when others =>
-        S_NEXT_STATE <= TestLogicReset;
-    end case;
-  end process;
-end rtl;
diff --git a/sim/cocotb/c4m_jtag.py b/sim/cocotb/c4m_jtag.py
deleted file mode 100644 (file)
index 1dd13b1..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-import cocotb
-from cocotb.triggers import Timer
-from cocotb.binary import BinaryValue
-
-class JTAGException(Exception):
-    pass
-
-class JTAG_Clock(object):
-    """
-    Class for the JTAG clock, run cycle by cycle
-    """
-    def __init__(self, signal, period):
-        self.signal = signal
-        self.t = Timer(period/4)
-
-    @cocotb.coroutine
-    def Cycle(self, cycles=1):
-        """
-        Do one or more cycles
-        Cycle start in middle of 0 pulse of the clock
-        """
-        for i in range(cycles):
-            self.signal <= 0
-            yield self.t
-            self.signal <= 1
-            yield self.t
-            yield self.t
-            self.signal <= 0
-            yield self.t
-
-class JTAG_Master(object):
-    """
-    Class that will run JTAG commands, shift in and out data
-    """
-    #TODO: Handle a JTAG chain with more than one device
-
-    def __init__(self, tck, tms, tdi, tdo, trst_n=None, clk_period=1000):
-        self.tck = tck
-        self.clkgen = JTAG_Clock(tck, clk_period)
-        tck <= 0
-        self.tms = tms
-        tms <= 1
-        self.tdi = tdi
-        tdi <= 0
-        self.tdo = tdo
-        self.trst_n = trst_n
-        if trst_n is not None:
-            trst_n <= 1
-        self.period = Timer(clk_period)
-
-        # Standard commands
-        # TODO: make IR length configurable; now 2 is assumed
-        self.BYPASS = [1, 1]
-        self.IDCODE = [0, 1]
-        self.SAMPLEPRELOAD = [1, 0]
-        self.EXTEST = [0, 0]
-
-        # After command we always leave the controller in reset or runidle state
-        # If value is None we will always reset the interface
-        self.state = None
-
-        # The methods of this class are coroutines. The results will be stored
-        # in the result field
-        self.result = None
-
-    @cocotb.coroutine
-    def cycle_clock(self, cycles=1):
-        if self.state == "Run" and self.tms == 1:
-            self.state = "Scan"
-        yield self.clkgen.Cycle(cycles)
-
-    @cocotb.coroutine
-    def reset(self):
-        if not self.trst_n is None:
-            # Enable reset signal for one clock period
-            self.trst_n <= 0
-            yield self.period
-            self.trst_n <= 1
-        else:
-            # 5 cycles with tms on 1 should reset the JTAG TAP controller
-            self.tms <= 1
-            yield self.cycle_clock(5)
-
-        self.state = "Reset"
-
-        self.result = None
-
-    @cocotb.coroutine
-    def change_state(self, tms_list):
-        """
-        Put TAP in other state by giving a TMS sequence
-        This function does not detect if one ends up in reset or run
-        state afterwards, self.state has to be updated by caller
-        if that is the case.
-        """
-        tms_copy = list(tms_list)
-        while tms_copy:
-            self.tms <= tms_copy.pop()
-            yield self.cycle_clock()
-        self.result = None
-
-    @cocotb.coroutine
-    def change_to_run(self):
-        """
-        Put TAP in RunTestIdle state
-        self.result is bool and true if TAP went through reset state
-        """
-        isreset = False
-        if self.state is None:
-            yield self.reset()
-        if self.state is "Reset":
-            isreset = True
-            self.tms <= 0
-            yield self.cycle_clock()
-            self.state = "Run"
-        assert(self.state == "Run")
-        self.result = isreset
-
-    @cocotb.coroutine
-    def load_ir(self, cmd):
-        cmd_copy = list(cmd)
-        result = BinaryValue(bits=len(cmd_copy))
-        l_result = list()
-
-        yield self.change_to_run()
-        # Go to Capture/IR
-        yield self.change_state([0, 1, 1])
-
-        # Shift the two
-        self.tms <= 0
-        while cmd_copy:
-            # In first iteration we enter SHIFT state and tdo is made active
-            yield self.cycle_clock()
-            # For the last iteration tdi will be shifted when entering next state
-            self.tdi <= cmd_copy.pop()
-            l_result.insert(0, str(self.tdo))
-
-        # Go to RunTestIdle
-        yield self.change_state([0, 1, 1])
-        self.state = "Run"
-
-    @cocotb.coroutine
-    def idcode(self):
-        """
-        Get the IDCODE from the device
-        result will contain the 32 bit IDCODE of the device
-        """
-
-        result = BinaryValue(bits=32)
-        l_result = list()
-
-        # Keep tdi 0 for the whole run
-        self.tdi <= 0
-
-        yield self.change_to_run()
-        if not self.result:
-            # If TAP was not reset we have to load IDCODE command
-            yield self.load_ir(self.IDCODE)
-
-        # Should be again in RUN state
-        assert(self.state == "Run")
-
-        # Go to Shift/DR
-        yield self.change_state([0, 0, 1])
-
-        # Enter Shift; run for 32 cycles
-        self.tms <= 0
-        for i in range(32):
-            l_result.insert(0, str(self.tdo))
-            yield self.cycle_clock()
-        result.binstr = "".join(l_result)
-
-        # Go to RunTestIdle
-        yield self.change_state([0, 1, 1])
-        self.state = "Run"
-
-        self.result = result
-
-    @cocotb.coroutine
-    def shift_data(self, data_in):
-        """
-        Shift data in through the JTAG and capture the output
-        Input can be of type BinaryValue or an iterable value of 0 and 1s.
-        Last bit will be shifted in first.
-        result will contain the sample TDO with the same number of bits as the input
-        """
-        if isinstance(data_in, BinaryValue):
-            data_copy = [int(c) for c in data_in.binstr]
-        else:
-            data_copy = list(data_in)
-        result = BinaryValue()
-        l_result = list()
-
-        yield self.change_to_run()
-        # Go to Capture/DR
-        yield self.change_state([0, 1])
-
-        # Shift data through
-        self.tms <= 0
-        while data_copy:
-            yield self.cycle_clock()
-            self.tdi <= data_copy.pop()
-            l_result.insert(0, str(self.tdo))
-        result.binstr = "".join(l_result)
-
-        # Go to RunTestIdle
-        yield self.change_state([0, 1, 1])
-        self.state = "Run"
-
-        self.result = result
diff --git a/sim/cocotb/c4m_jtag_svfcocotb.py b/sim/cocotb/c4m_jtag_svfcocotb.py
deleted file mode 100755 (executable)
index 177b7a1..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-import c4m_jtag_svfgrammar
-import cocotb
-from cocotb.binary import BinaryValue
-from functools import singledispatch
-
-def decodescanspec(node):
-    length = int(str(node[2]))
-    fstr = "{:0"+str(node[2])+"b}"
-
-    g_tdi = node[4]
-    g_tdo = node[5]
-    g_mask = node[6]
-    g_smask = node[7]
-
-    if g_tdi is None:
-        tdi = None
-    else:
-        tdi = BinaryValue(fstr.format(int(str(g_tdi[2]),16)), length)
-
-    if g_tdo is None:
-        tdo = None
-    else:
-        tdo = BinaryValue(fstr.format(int(str(g_tdo[3]),16)), length)
-
-    if g_mask is None:
-        mask = None
-    else:
-        mask = BinaryValue(fstr.format(int(str(g_mask[3]),16)), length)
-
-    if g_smask is None:
-        smask = None
-    else:
-        smask = BinaryValue(fstr.format(int(str(g_smask[3]),16)), length)
-
-    return (length, tdi, tdo, mask, smask)
-
-
-class SVF_Executor(object):
-    @cocotb.coroutine
-    def execute(self, node):
-        """This is the generic method"""
-        self._p("generic")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_NOP(self, node):
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_EndDR(self, node):
-        self._p("EndDR ignored")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_EndIR(self, node):
-        self._p("EndIR ignored")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_Frequency(self, node):
-        self._p("Frequency ignored")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_HDR(self, node):
-        self._p("HDR ignored")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_HIR(self, node):
-        self._p("HIR ignored")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_SDR(self, node):
-        self._p("Executing SDR")
-        (length, tdi, tdo, mask, smask) = decodescanspec(node)
-
-        samelength = length == self._d_length
-        self._d_length = length
-
-        if tdi is None:
-            if not samelength:
-                raise(JTAGException("TDI needs to be specified when length of data changes"))
-        else:
-            self._d_tdi = tdi
-
-        if mask is not None:
-            self._d_mask = mask
-        elif not samelength:
-            self._d_mask = None
-
-        if smask is not None:
-            self._d_smask = smask
-        elif not samelength:
-            self._d_smask = None
-
-        yield self.master.shift_data(self._d_tdi)
-        if tdo is not None:
-            if self._d_mask is not None:
-                raise(JTAGException("MASK not supported for SDR"))
-            assert(self.result == tdo)
-
-    @cocotb.coroutine
-    def _execute_SIR(self, node):
-        (length, tdi, tdo, mask, smask) = decodescanspec(node)
-
-        samelength = length == self._i_length
-        self._i_length = length
-
-        if tdi is None:
-            if not samelength:
-                raise(JTAGException("TDI needs to be specified when length of data changes"))
-        else:
-            self._i_tdi = tdi
-
-        if mask is not None:
-            self._i_mask = mask
-        elif not samelength:
-            self._i_mask = None
-
-        if smask is not None:
-            self._i_smask = smask
-        elif not samelength:
-            self._i_smask = None
-
-        self._p("Executing SIR ({})".format(self._i_tdi.integer))
-
-        yield self.master.load_ir(self._i_tdi)
-        if tdo is not None:
-            if self._i_mask is not None:
-                raise(JTAGException("MASK not supported for SIR"))
-            assert(self.result == tdo)
-        
-
-    @cocotb.coroutine
-    def _execute_State(self, node):
-        self._p("State")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_TDR(self, node):
-        self._p("TDR")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_TIR(self, node):
-        self._p("TIR")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_Trst(self, node):
-        self._p("TRST ignored")
-        if False: # Make coroutine work
-            yield PythonTrigger()
-
-    @cocotb.coroutine
-    def _execute_Runtest(self, node):
-        if node[1] is not None:
-            raise(JTAGException("State specification for RUNTEST not supported"))
-        # TODO: cycle the right number of clocks or wait the right time
-        yield(self.master.change_state([0]))
-
-    @cocotb.coroutine
-    def _execute_SVFFile(self, node):
-        self._p("Executing SVFFile")
-        for statement in node.elements[0]:
-            yield self.execute(statement)
-
-    def __init__(self, master):
-        # master is assumed to be a JTAG_Master class
-        # it needs to support methods load_ir() and shift_data()
-        self.master = master
-
-        # Due to bug in Grammar definition all possible classes have to have
-        # a dispatch entry otherwise an error will be raised.
-        self.execute = singledispatch(self.execute)
-        self.execute.register(c4m_jtag_svfgrammar.EmptyLine, self._execute_NOP)
-        self.execute.register(c4m_jtag_svfgrammar.Comment, self._execute_NOP)
-        self.execute.register(c4m_jtag_svfgrammar.EndDR, self._execute_EndDR)
-        self.execute.register(c4m_jtag_svfgrammar.EndIR, self._execute_EndIR)
-        self.execute.register(c4m_jtag_svfgrammar.Frequency, self._execute_Frequency)
-        self.execute.register(c4m_jtag_svfgrammar.HDR, self._execute_HDR)
-        self.execute.register(c4m_jtag_svfgrammar.HIR, self._execute_HIR)
-        self.execute.register(c4m_jtag_svfgrammar.Runtest, self._execute_Runtest)
-        self.execute.register(c4m_jtag_svfgrammar.SDR, self._execute_SDR)
-        self.execute.register(c4m_jtag_svfgrammar.SIR, self._execute_SIR)
-        self.execute.register(c4m_jtag_svfgrammar.State, self._execute_State)
-        self.execute.register(c4m_jtag_svfgrammar.TDR, self._execute_TDR)
-        self.execute.register(c4m_jtag_svfgrammar.TIR, self._execute_TIR)
-        self.execute.register(c4m_jtag_svfgrammar.Trst, self._execute_Trst)
-        self.execute.register(c4m_jtag_svfgrammar.SVFFile, self._execute_SVFFile)
-
-        # Store the head and tail for the scan
-        self._d_tdi = self._d_tdi_h = self._d_tdi_t = None
-        self._d_tdo_h = self._d_tdo_t = None
-        self._i_tdi = self._i_tdi_h = self._i_tdi_t = None
-        self._i_tdo_h = self._i_tdo_t = None
-
-        # Remember the masks; smasks are ignored and bits always considered as care, e.g right
-        # value applied
-        self._d_length = self._d_length_h = self._d_length_t = None
-        self._d_mask = self._d_mask_h = self._d_mask_t = None
-        self._d_smask = self._d_smask_h = self._d_smask_t = None
-        self._i_length = self._i_length_h = self._i_length_t = None
-        self._i_mask = self._i_mask_h = self._i_mask_t = None
-        self._i_smask = self._i_smask_h = self._i_smask_t = None
-
-    @cocotb.coroutine
-    def run(self, cmds, p=print):
-        self._p = p
-        if isinstance(cmds, c4m_jtag_svfgrammar.SVFFile):
-            yield self.execute(cmds)
-        else:
-            p = c4m_jtag_svfgrammar.SVFFile.parser()
-            yield self.execute(p.parse_string(cmds))
diff --git a/sim/cocotb/c4m_jtag_svfgrammar.py b/sim/cocotb/c4m_jtag_svfgrammar.py
deleted file mode 100644 (file)
index faf3aeb..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-from modgrammar import *
-
-grammar_whitespace_mode = 'explicit'
-grammar_whitespace = WS_NOEOL
-
-class SVFEol(Grammar):
-    grammar = (OPTIONAL(SPACE), EOL)
-    grammar_collapse = True
-
-class SemicolonEol(Grammar):
-    grammar = (OPTIONAL(SPACE), L(";"), SVFEol)
-    grammar_collapse = True
-
-class Integer(Grammar):
-    grammar = WORD("0-9")
-    grammar_collapse = True
-
-class Float(Grammar):
-    grammar = (Integer, (L("."), OPTIONAL(Integer)), OPTIONAL(L("E"), Integer))
-
-class Hexadecimal(Grammar):
-    grammar = (L("("), WORD("0-9A-F"), L(")"))
-    grammar_collapse = True
-
-class StableState(Grammar):
-    grammar = (L("IRPAUSE") | L("DRPAUSE") | L("RESET") | L("IDLE"))
-    grammar_collapse = True
-
-
-class ScanSpec(Grammar):
-    """The specification of Scan In/Scan out data"""
-    grammar = (SPACE, Integer, SPACE,
-               OPTIONAL(L("TDI"), OPTIONAL(SPACE), Hexadecimal),
-               OPTIONAL(OPTIONAL(SPACE), L("TDO"), OPTIONAL(SPACE), Hexadecimal),
-               OPTIONAL(OPTIONAL(SPACE), L("MASK"), OPTIONAL(SPACE), Hexadecimal),
-               OPTIONAL(OPTIONAL(SPACE), L("SMASK"), OPTIONAL(SPACE), Hexadecimal)
-              )
-    grammar_collapse = True
-
-
-class EmptyLine(Grammar):
-    grammar = SVFEol
-
-class Comment(Grammar):
-    grammar = (L("!"), REST_OF_LINE, SVFEol)
-
-class EndDR(Grammar):
-    grammar = (L("ENDDR"), SPACE, StableState, SemicolonEol)
-
-class EndIR(Grammar):
-    grammar = (L("ENDIR"), SPACE, StableState, SemicolonEol)
-
-class Frequency(Grammar):
-    grammar = (L("FREQUENCY"), OPTIONAL(SPACE, Float, OPTIONAL(SPACE), L("HZ")), OPTIONAL(SPACE), SemicolonEol)
-
-class HDR(Grammar):
-    grammar = (L("HDR"), ScanSpec, SemicolonEol)
-
-class HIR(Grammar):
-    grammar = (L("HIR"), ScanSpec, SemicolonEol)
-
-#TODO: PIO, PIOMAP
-
-class Runtest(Grammar):
-    grammar = (
-        L("RUNTEST"),
-        OPTIONAL(SPACE, StableState),
-        OPTIONAL(SPACE, Integer, OPTIONAL(SPACE), (L("TCK") | L("SCK"))),
-        OPTIONAL(SPACE, Float, OPTIONAL(SPACE), L("SEC")),
-        OPTIONAL(SPACE, L("MAXIMUM"), SPACE, Float, OPTIONAL(SPACE), L("SEC")),
-        OPTIONAL(SPACE, L("ENDSTATE"), SPACE, StableState),
-        SemicolonEol
-    )
-
-class SDR(Grammar):
-    grammar = (L("SDR"), ScanSpec, SemicolonEol)
-
-class SIR(Grammar):
-    grammar = (L("SIR"), ScanSpec, SemicolonEol)
-
-class State(Grammar):
-    # TODO: Path to reach state
-    grammar = (L("STATE"), SPACE, StableState, SemicolonEol)
-
-class TDR(Grammar):
-    grammar = (L("TDR"), ScanSpec, SemicolonEol)
-
-class TIR(Grammar):
-    grammar = (L("TIR"), ScanSpec, SemicolonEol)
-
-class Trst(Grammar):
-    grammar = (L("TRST"), SPACE, (L("ON") | L("OFF") | L("Z") | L("ABSENT")), SemicolonEol)
-
-
-class SVFFile(Grammar):
-    grammar = ONE_OR_MORE(EmptyLine | Comment | Trst | EndDR | EndIR | SIR | SDR | Runtest | State)
diff --git a/sim/cocotb/controller/Makefile b/sim/cocotb/controller/Makefile
deleted file mode 100644 (file)
index 708e50d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-PWD=$(realpath .)
-TOPDIR=$(realpath ../../..)
-VHDLDIR=$(TOPDIR)/rtl/vhdl
-VHDL_SOURCES = \
-  $(VHDLDIR)/c4m_jtag_pkg.vhdl \
-  $(VHDLDIR)/c4m_jtag_tap_fsm.vhdl \
-  $(VHDLDIR)/c4m_jtag_irblock.vhdl \
-  $(VHDLDIR)/c4m_jtag_iocell.vhdl \
-  $(VHDLDIR)/c4m_jtag_ioblock.vhdl \
-  $(VHDLDIR)/c4m_jtag_idblock.vhdl \
-  $(VHDLDIR)/c4m_jtag_tap_controller.vhdl
-TOPLEVEL=c4m_jtag_tap_controller
-TOPLEVEL_LANG=vhdl
-MODULE=test
-SIM=ghdl
-GPI_IMPL=vhpi
-SIM_ARGS=--wave=test.ghw
-
-COCOTBDIR=$(shell cocotb-path)
-
-include $(COCOTBDIR)/makefiles/Makefile.inc
-include $(COCOTBDIR)/makefiles/Makefile.sim
diff --git a/sim/cocotb/controller/c4m_jtag.py b/sim/cocotb/controller/c4m_jtag.py
deleted file mode 120000 (symlink)
index f409baa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../c4m_jtag.py
\ No newline at end of file
diff --git a/sim/cocotb/controller/test.py b/sim/cocotb/controller/test.py
deleted file mode 100644 (file)
index 9d66ea8..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-import cocotb
-from cocotb.utils import get_sim_steps
-from cocotb.binary import BinaryValue
-
-from c4m_jtag import JTAG_Master
-
-@cocotb.test()
-def test01_idcode(dut):
-    """
-    Test the IDCODE command
-    """
-
-    # Run @ 1MHz
-    clk_period = get_sim_steps(1, "us")
-    master = JTAG_Master(dut.tck, dut.tms, dut.tdi, dut.tdo, dut.trst_n, clk_period)
-
-    dut._log.info("Trying to get IDCODE...")
-
-    yield master.idcode()
-    result1 = master.result
-    dut._log.info("IDCODE1: {}".format(result1))
-
-    yield master.idcode()
-    result2 = master.result
-    dut._log.info("IDCODE2: {}".format(result2))
-
-    assert(result1 == result2)
-    
-@cocotb.test()
-def test02_bypass(dut):
-    """
-    Test of BYPASS mode
-    """
-
-    # Run @ 1MHz
-    clk_period = get_sim_steps(1, "us")
-    master = JTAG_Master(dut.tck, dut.tms, dut.tdi, dut.tdo, dut.trst_n, clk_period)
-
-    dut._log.info("Loading BYPASS command")
-    yield master.load_ir(master.BYPASS)
-
-    dut._log.info("Sending data")
-
-    data_in = BinaryValue()
-    data_in.binstr = "01001101"
-    yield master.shift_data(data_in)
-
-    dut._log.info("bypass out: {}".format(master.result.binstr))
-    assert(master.result.binstr[:-1] == data_in.binstr[1:])
-
-@cocotb.test()
-def test03_sample(dut):
-    """
-    Test of SAMPLEPRELOAD and EXTEST
-    """
-    data_in = BinaryValue()
-
-    # Run @ 1MHz
-    clk_period = get_sim_steps(1, "us")
-    master = JTAG_Master(dut.tck, dut.tms, dut.tdi, dut.tdo, dut.trst_n, clk_period)
-
-
-    dut._log.info("Load SAMPLEPRELOAD command")
-    yield master.load_ir(master.SAMPLEPRELOAD)
-
-    data_in.binstr = "011"
-    dut._log.info("  preloading data {}".format(data_in.binstr))
-
-    # Set the ios pins
-    dut.core_out = 0
-    dut.core_en = 0
-    dut.pad_in = 1
-    yield master.shift_data(data_in)
-    dut._log.info("  output: {}".format(master.result.binstr))
-    assert(master.result.binstr == "100")
-
-
-    dut._log.info("Load EXTEST command")
-    yield master.load_ir(master.EXTEST)
-
-    data_in.binstr = "100"
-    dut._log.info("  input data {}".format(data_in.binstr))
-    
-    # Set the ios pins
-    dut.core_out = 1
-    dut.core_en = 1
-    dut.pad_in = 0
-    yield master.shift_data(data_in)
-    dut._log.info("  output: {}".format(master.result.binstr))
-    assert(master.result.binstr == "011")
-
-    dut._log.info("Do a capture of the last loaded data")
-    yield master.shift_data([])
-
diff --git a/sim/cocotb/dual_parallel/Makefile b/sim/cocotb/dual_parallel/Makefile
deleted file mode 100644 (file)
index e7da7cd..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-PWD=$(realpath .)
-TOPDIR=$(realpath ../../..)
-VHDLDIR=$(TOPDIR)/rtl/vhdl
-VHDL_SOURCES = \
-  $(VHDLDIR)/c4m_jtag_pkg.vhdl \
-  $(VHDLDIR)/c4m_jtag_tap_fsm.vhdl \
-  $(VHDLDIR)/c4m_jtag_irblock.vhdl \
-  $(VHDLDIR)/c4m_jtag_iocell.vhdl \
-  $(VHDLDIR)/c4m_jtag_ioblock.vhdl \
-  $(VHDLDIR)/c4m_jtag_idblock.vhdl \
-  $(VHDLDIR)/c4m_jtag_tap_controller.vhdl \
-  $(PWD)/dual_parallel.vhdl
-TOPLEVEL=dual_parallel
-TOPLEVEL_LANG=vhdl
-MODULE=test
-SIM=ghdl
-GPI_IMPL=vhpi
-SIM_ARGS=--wave=test.ghw
-
-COCOTBDIR=$(shell cocotb-path)
-
-include $(COCOTBDIR)/makefiles/Makefile.inc
-include $(COCOTBDIR)/makefiles/Makefile.sim
diff --git a/sim/cocotb/dual_parallel/c4m_jtag.py b/sim/cocotb/dual_parallel/c4m_jtag.py
deleted file mode 120000 (symlink)
index f409baa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../c4m_jtag.py
\ No newline at end of file
diff --git a/sim/cocotb/dual_parallel/dual_parallel.vhdl b/sim/cocotb/dual_parallel/dual_parallel.vhdl
deleted file mode 100644 (file)
index 989d15a..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
--- Top cell with two instantiations of the tap_controller with parallel scan chains
-
-library ieee;
-use ieee.std_logic_1164.ALL;
-
-use work.c4m_jtag.ALL;
-
-entity dual_parallel is
-  port (
-    -- Instance 1
-    -- ==========
-    -- JTAG
-    I1_TCK:     in std_logic;
-    I1_TMS:     in std_logic;
-    I1_TDI:     in std_logic;
-    I1_TDO:     out std_logic;
-    I1_TRST_N:  in std_logic;
-
-    -- Instance 2
-    -- ==========
-    -- JTAG
-    I2_TCK:     in std_logic;
-    I2_TMS:     in std_logic;
-    I2_TDI:     in std_logic;
-    I2_TDO:     out std_logic;
-    I2_TRST_N:  in std_logic
-  );
-end dual_parallel;
-
-architecture rtl of dual_parallel is
-  signal I1_PAD_IN:     std_logic;
-  signal I1_PAD_EN:     std_logic;
-  signal I1_PAD_OUT:    std_logic;
-  signal I2_PAD_IN:     std_logic;
-  signal I2_PAD_EN:     std_logic;
-  signal I2_PAD_OUT:    std_logic;
-begin
-  CTRL1: c4m_jtag_tap_controller
-    port map (
-      TCK => I1_TCK,
-      TMS => I1_TMS,
-      TDI => I1_TDI,
-      TDO => I1_TDO,
-      TRST_N => I1_TRST_N,
-      RESET => open,
-      DRCAPTURE => open,
-      DRSHIFT => open,
-      DRUPDATE => open,
-      IR => open,
-      CORE_IN => open,
-      CORE_EN => "1",
-      CORE_OUT => "1",
-      PAD_IN(0) => I1_PAD_IN,
-      PAD_EN(0) => I1_PAD_EN,
-      PAD_OUT(0) => I1_PAD_OUT
-    );
-
-  CTRL2: c4m_jtag_tap_controller
-    port map (
-      TCK => I2_TCK,
-      TMS => I2_TMS,
-      TDI => I2_TDI,
-      TDO => I2_TDO,
-      TRST_N => I2_TRST_N,
-      RESET => open,
-      DRCAPTURE => open,
-      DRSHIFT => open,
-      DRUPDATE => open,
-      IR => open,
-      CORE_IN => open,
-      CORE_EN => "1",
-      CORE_OUT => "0",
-      PAD_IN(0) => I2_PAD_IN,
-      PAD_EN(0) => I2_PAD_EN,
-      PAD_OUT(0) => I2_PAD_OUT
-    );
-
-  I1_PAD_IN <= I2_PAD_OUT when I2_PAD_EN = '1' else
-               'Z';
-  I2_PAD_IN <= I1_PAD_OUT when I1_PAD_EN = '1' else
-               'Z';
-end rtl;
diff --git a/sim/cocotb/dual_parallel/test.py b/sim/cocotb/dual_parallel/test.py
deleted file mode 100644 (file)
index 47cf306..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-import cocotb
-from cocotb.utils import get_sim_steps
-
-from c4m_jtag import JTAG_Master
-
-@cocotb.test()
-def test01_dual(dut):
-    """
-    Test the IDCODE command
-    """
-
-    # TODO: Allow parallel operation of the JTAG chains
-
-    # Run @ 1MHz
-    clk_period = get_sim_steps(1, "us")
-    master1 = JTAG_Master(dut.i1_tck, dut.i1_tms, dut.i1_tdi, dut.i1_tdo, dut.i1_trst_n, clk_period)
-    master2 = JTAG_Master(dut.i2_tck, dut.i2_tms, dut.i2_tdi, dut.i2_tdo, dut.i2_trst_n, clk_period)
-
-    dut._log.info("Set command to SAMPLEPRELOAD")
-    yield master1.load_ir(master1.SAMPLEPRELOAD)
-    yield master2.load_ir(master2.SAMPLEPRELOAD)
-    
-    dut._log.info("Load data, scan out first sample")
-    yield master1.shift_data([0, 0, 0])
-    dut._log.info("  master1 scan_out: {}".format(master1.result.binstr))
-    assert(master1.result.binstr == "011")
-    yield master2.shift_data([1, 1, 1])
-    dut._log.info("  master2 scan_out: {}".format(master2.result.binstr))
-    assert(master2.result.binstr == "101")
-    
-    dut._log.info("Set command to EXTEST")
-    yield master1.load_ir(master1.EXTEST)
-    yield master2.load_ir(master2.EXTEST)
-
-    dut._log.info("Second scan")
-    yield master1.shift_data([0, 0, 0])
-    dut._log.info("  master1 scan_out: {}".format(master1.result.binstr))
-    assert(master1.result.binstr == "111")
-    yield master2.shift_data([1, 1, 1])
-    dut._log.info("  master2 scan_out: {}".format(master2.result.binstr))
-    assert(master2.result.binstr == "Z01")
diff --git a/sim/ghdl/bench_idcode.sh b/sim/ghdl/bench_idcode.sh
deleted file mode 100755 (executable)
index e17b656..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_pkg.vhdl
-ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_tap_fsm.vhdl
-ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_irblock.vhdl
-ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_idblock.vhdl
-ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_iocell.vhdl
-ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_ioblock.vhdl
-ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_tap_controller.vhdl
-ghdl -a --std=08 ../../bench/vhdl/idcode.vhdl
-ghdl -r --std=08 bench_idcode --wave=bench_idcode.ghw
diff --git a/test/cocotb/controller/Makefile b/test/cocotb/controller/Makefile
new file mode 100644 (file)
index 0000000..708e50d
--- /dev/null
@@ -0,0 +1,22 @@
+PWD=$(realpath .)
+TOPDIR=$(realpath ../../..)
+VHDLDIR=$(TOPDIR)/rtl/vhdl
+VHDL_SOURCES = \
+  $(VHDLDIR)/c4m_jtag_pkg.vhdl \
+  $(VHDLDIR)/c4m_jtag_tap_fsm.vhdl \
+  $(VHDLDIR)/c4m_jtag_irblock.vhdl \
+  $(VHDLDIR)/c4m_jtag_iocell.vhdl \
+  $(VHDLDIR)/c4m_jtag_ioblock.vhdl \
+  $(VHDLDIR)/c4m_jtag_idblock.vhdl \
+  $(VHDLDIR)/c4m_jtag_tap_controller.vhdl
+TOPLEVEL=c4m_jtag_tap_controller
+TOPLEVEL_LANG=vhdl
+MODULE=test
+SIM=ghdl
+GPI_IMPL=vhpi
+SIM_ARGS=--wave=test.ghw
+
+COCOTBDIR=$(shell cocotb-path)
+
+include $(COCOTBDIR)/makefiles/Makefile.inc
+include $(COCOTBDIR)/makefiles/Makefile.sim
diff --git a/test/cocotb/controller/c4m_jtag.py b/test/cocotb/controller/c4m_jtag.py
new file mode 120000 (symlink)
index 0000000..f409baa
--- /dev/null
@@ -0,0 +1 @@
+../c4m_jtag.py
\ No newline at end of file
diff --git a/test/cocotb/controller/test.py b/test/cocotb/controller/test.py
new file mode 100644 (file)
index 0000000..9d66ea8
--- /dev/null
@@ -0,0 +1,94 @@
+import cocotb
+from cocotb.utils import get_sim_steps
+from cocotb.binary import BinaryValue
+
+from c4m_jtag import JTAG_Master
+
+@cocotb.test()
+def test01_idcode(dut):
+    """
+    Test the IDCODE command
+    """
+
+    # Run @ 1MHz
+    clk_period = get_sim_steps(1, "us")
+    master = JTAG_Master(dut.tck, dut.tms, dut.tdi, dut.tdo, dut.trst_n, clk_period)
+
+    dut._log.info("Trying to get IDCODE...")
+
+    yield master.idcode()
+    result1 = master.result
+    dut._log.info("IDCODE1: {}".format(result1))
+
+    yield master.idcode()
+    result2 = master.result
+    dut._log.info("IDCODE2: {}".format(result2))
+
+    assert(result1 == result2)
+    
+@cocotb.test()
+def test02_bypass(dut):
+    """
+    Test of BYPASS mode
+    """
+
+    # Run @ 1MHz
+    clk_period = get_sim_steps(1, "us")
+    master = JTAG_Master(dut.tck, dut.tms, dut.tdi, dut.tdo, dut.trst_n, clk_period)
+
+    dut._log.info("Loading BYPASS command")
+    yield master.load_ir(master.BYPASS)
+
+    dut._log.info("Sending data")
+
+    data_in = BinaryValue()
+    data_in.binstr = "01001101"
+    yield master.shift_data(data_in)
+
+    dut._log.info("bypass out: {}".format(master.result.binstr))
+    assert(master.result.binstr[:-1] == data_in.binstr[1:])
+
+@cocotb.test()
+def test03_sample(dut):
+    """
+    Test of SAMPLEPRELOAD and EXTEST
+    """
+    data_in = BinaryValue()
+
+    # Run @ 1MHz
+    clk_period = get_sim_steps(1, "us")
+    master = JTAG_Master(dut.tck, dut.tms, dut.tdi, dut.tdo, dut.trst_n, clk_period)
+
+
+    dut._log.info("Load SAMPLEPRELOAD command")
+    yield master.load_ir(master.SAMPLEPRELOAD)
+
+    data_in.binstr = "011"
+    dut._log.info("  preloading data {}".format(data_in.binstr))
+
+    # Set the ios pins
+    dut.core_out = 0
+    dut.core_en = 0
+    dut.pad_in = 1
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert(master.result.binstr == "100")
+
+
+    dut._log.info("Load EXTEST command")
+    yield master.load_ir(master.EXTEST)
+
+    data_in.binstr = "100"
+    dut._log.info("  input data {}".format(data_in.binstr))
+    
+    # Set the ios pins
+    dut.core_out = 1
+    dut.core_en = 1
+    dut.pad_in = 0
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert(master.result.binstr == "011")
+
+    dut._log.info("Do a capture of the last loaded data")
+    yield master.shift_data([])
+
diff --git a/test/cocotb/dual_parallel/Makefile b/test/cocotb/dual_parallel/Makefile
new file mode 100644 (file)
index 0000000..e7da7cd
--- /dev/null
@@ -0,0 +1,23 @@
+PWD=$(realpath .)
+TOPDIR=$(realpath ../../..)
+VHDLDIR=$(TOPDIR)/rtl/vhdl
+VHDL_SOURCES = \
+  $(VHDLDIR)/c4m_jtag_pkg.vhdl \
+  $(VHDLDIR)/c4m_jtag_tap_fsm.vhdl \
+  $(VHDLDIR)/c4m_jtag_irblock.vhdl \
+  $(VHDLDIR)/c4m_jtag_iocell.vhdl \
+  $(VHDLDIR)/c4m_jtag_ioblock.vhdl \
+  $(VHDLDIR)/c4m_jtag_idblock.vhdl \
+  $(VHDLDIR)/c4m_jtag_tap_controller.vhdl \
+  $(PWD)/dual_parallel.vhdl
+TOPLEVEL=dual_parallel
+TOPLEVEL_LANG=vhdl
+MODULE=test
+SIM=ghdl
+GPI_IMPL=vhpi
+SIM_ARGS=--wave=test.ghw
+
+COCOTBDIR=$(shell cocotb-path)
+
+include $(COCOTBDIR)/makefiles/Makefile.inc
+include $(COCOTBDIR)/makefiles/Makefile.sim
diff --git a/test/cocotb/dual_parallel/c4m_jtag.py b/test/cocotb/dual_parallel/c4m_jtag.py
new file mode 120000 (symlink)
index 0000000..f409baa
--- /dev/null
@@ -0,0 +1 @@
+../c4m_jtag.py
\ No newline at end of file
diff --git a/test/cocotb/dual_parallel/dual_parallel.vhdl b/test/cocotb/dual_parallel/dual_parallel.vhdl
new file mode 100644 (file)
index 0000000..989d15a
--- /dev/null
@@ -0,0 +1,82 @@
+-- Top cell with two instantiations of the tap_controller with parallel scan chains
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity dual_parallel is
+  port (
+    -- Instance 1
+    -- ==========
+    -- JTAG
+    I1_TCK:     in std_logic;
+    I1_TMS:     in std_logic;
+    I1_TDI:     in std_logic;
+    I1_TDO:     out std_logic;
+    I1_TRST_N:  in std_logic;
+
+    -- Instance 2
+    -- ==========
+    -- JTAG
+    I2_TCK:     in std_logic;
+    I2_TMS:     in std_logic;
+    I2_TDI:     in std_logic;
+    I2_TDO:     out std_logic;
+    I2_TRST_N:  in std_logic
+  );
+end dual_parallel;
+
+architecture rtl of dual_parallel is
+  signal I1_PAD_IN:     std_logic;
+  signal I1_PAD_EN:     std_logic;
+  signal I1_PAD_OUT:    std_logic;
+  signal I2_PAD_IN:     std_logic;
+  signal I2_PAD_EN:     std_logic;
+  signal I2_PAD_OUT:    std_logic;
+begin
+  CTRL1: c4m_jtag_tap_controller
+    port map (
+      TCK => I1_TCK,
+      TMS => I1_TMS,
+      TDI => I1_TDI,
+      TDO => I1_TDO,
+      TRST_N => I1_TRST_N,
+      RESET => open,
+      DRCAPTURE => open,
+      DRSHIFT => open,
+      DRUPDATE => open,
+      IR => open,
+      CORE_IN => open,
+      CORE_EN => "1",
+      CORE_OUT => "1",
+      PAD_IN(0) => I1_PAD_IN,
+      PAD_EN(0) => I1_PAD_EN,
+      PAD_OUT(0) => I1_PAD_OUT
+    );
+
+  CTRL2: c4m_jtag_tap_controller
+    port map (
+      TCK => I2_TCK,
+      TMS => I2_TMS,
+      TDI => I2_TDI,
+      TDO => I2_TDO,
+      TRST_N => I2_TRST_N,
+      RESET => open,
+      DRCAPTURE => open,
+      DRSHIFT => open,
+      DRUPDATE => open,
+      IR => open,
+      CORE_IN => open,
+      CORE_EN => "1",
+      CORE_OUT => "0",
+      PAD_IN(0) => I2_PAD_IN,
+      PAD_EN(0) => I2_PAD_EN,
+      PAD_OUT(0) => I2_PAD_OUT
+    );
+
+  I1_PAD_IN <= I2_PAD_OUT when I2_PAD_EN = '1' else
+               'Z';
+  I2_PAD_IN <= I1_PAD_OUT when I1_PAD_EN = '1' else
+               'Z';
+end rtl;
diff --git a/test/cocotb/dual_parallel/test.py b/test/cocotb/dual_parallel/test.py
new file mode 100644 (file)
index 0000000..47cf306
--- /dev/null
@@ -0,0 +1,41 @@
+import cocotb
+from cocotb.utils import get_sim_steps
+
+from c4m_jtag import JTAG_Master
+
+@cocotb.test()
+def test01_dual(dut):
+    """
+    Test the IDCODE command
+    """
+
+    # TODO: Allow parallel operation of the JTAG chains
+
+    # Run @ 1MHz
+    clk_period = get_sim_steps(1, "us")
+    master1 = JTAG_Master(dut.i1_tck, dut.i1_tms, dut.i1_tdi, dut.i1_tdo, dut.i1_trst_n, clk_period)
+    master2 = JTAG_Master(dut.i2_tck, dut.i2_tms, dut.i2_tdi, dut.i2_tdo, dut.i2_trst_n, clk_period)
+
+    dut._log.info("Set command to SAMPLEPRELOAD")
+    yield master1.load_ir(master1.SAMPLEPRELOAD)
+    yield master2.load_ir(master2.SAMPLEPRELOAD)
+    
+    dut._log.info("Load data, scan out first sample")
+    yield master1.shift_data([0, 0, 0])
+    dut._log.info("  master1 scan_out: {}".format(master1.result.binstr))
+    assert(master1.result.binstr == "011")
+    yield master2.shift_data([1, 1, 1])
+    dut._log.info("  master2 scan_out: {}".format(master2.result.binstr))
+    assert(master2.result.binstr == "101")
+    
+    dut._log.info("Set command to EXTEST")
+    yield master1.load_ir(master1.EXTEST)
+    yield master2.load_ir(master2.EXTEST)
+
+    dut._log.info("Second scan")
+    yield master1.shift_data([0, 0, 0])
+    dut._log.info("  master1 scan_out: {}".format(master1.result.binstr))
+    assert(master1.result.binstr == "111")
+    yield master2.shift_data([1, 1, 1])
+    dut._log.info("  master2 scan_out: {}".format(master2.result.binstr))
+    assert(master2.result.binstr == "Z01")
diff --git a/test/ghdl/idcode/bench_idcode.sh b/test/ghdl/idcode/bench_idcode.sh
new file mode 100755 (executable)
index 0000000..e17b656
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_pkg.vhdl
+ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_tap_fsm.vhdl
+ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_irblock.vhdl
+ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_idblock.vhdl
+ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_iocell.vhdl
+ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_ioblock.vhdl
+ghdl -a --std=08 ../../rtl/vhdl/c4m_jtag_tap_controller.vhdl
+ghdl -a --std=08 ../../bench/vhdl/idcode.vhdl
+ghdl -r --std=08 bench_idcode --wave=bench_idcode.ghw
diff --git a/test/rtl/vhdl/idcode.vhdl b/test/rtl/vhdl/idcode.vhdl
new file mode 100644 (file)
index 0000000..550df98
--- /dev/null
@@ -0,0 +1,102 @@
+-- reset JTAG interface and then IDCODE should be shifted out
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity bench_idcode is
+end bench_idcode;
+
+architecture rtl of bench_idcode is
+  signal TCK:   std_logic;
+  signal TMS:   std_logic;
+  signal TDI:   std_logic;
+  signal TDO:   std_logic;
+  signal TRST_N: std_logic;
+
+  constant CLK_PERIOD:  time := 10 ns;
+
+  procedure ClkCycle(
+    signal CLK: out std_logic;
+    CLK_PERIOD: time
+  ) is
+  begin
+    CLK <= '0';
+    wait for CLK_PERIOD/4;
+    CLK <= '1';
+    wait for CLK_PERIOD/2;
+    CLK <= '0';
+    wait for CLK_PERIOD/4;
+  end ClkCycle;
+
+  procedure ClkCycles(
+    N:  integer;
+    signal CLK: out std_logic;
+    CLK_PERIOD: time
+  ) is
+  begin
+    for i in 1 to N loop
+      ClkCycle(CLK, CLK_PERIOD);
+    end loop;
+  end ClkCycles;
+begin
+  JTAG_BLOCK: c4m_jtag_tap_controller
+    -- Use default values
+    port map (
+      TCK => TCK,
+      TMS => TMS,
+      TDI => TDI,
+      TDO => TDO,
+      TRST_N => TRST_N,
+      RESET => open,
+      DRCAPTURE => open,
+      DRSHIFT => open,
+      DRUPDATE => open,
+      IR => open,
+      CORE_OUT => "0",
+      CORE_IN => open,
+      CORE_EN => "0",
+      PAD_OUT => open,
+      PAD_IN => "0",
+      PAD_EN => open
+    );
+
+  SIM: process
+  begin
+    -- Reset
+    TCK <= '0';
+    TMS <= '1';
+    TDI <= '0';
+    TRST_N <= '0';
+    wait for 10*CLK_PERIOD;
+
+    TRST_N <= '1';
+    wait for CLK_PERIOD;
+
+    -- Enter RunTestIdle
+    TMS <= '0';
+    ClkCycle(TCK, CLK_PERIOD);
+    -- Enter SelectDRScan
+    TMS <= '1';
+    ClkCycle(TCK, CLK_PERIOD);
+    -- Enter Capture
+    TMS <= '0';
+    ClkCycle(TCK, CLK_PERIOD);
+    -- Enter Shift, run for 35 CLK cycles
+    TMS <= '0';
+    ClkCycles(35, TCK, CLK_PERIOD);
+    -- Enter Exit1
+    TMS <= '1';
+    ClkCycle(TCK, CLK_PERIOD);
+    -- Enter Update
+    TMS <= '1';
+    ClkCycle(TCK, CLK_PERIOD);
+    -- To TestLogicReset
+    TMS <= '1';
+    ClkCycles(4, TCK, CLK_PERIOD);
+
+    -- end simulation
+    wait;
+  end process;
+end rtl;
diff --git a/test/rtl/vhdl/sampleshift.vhdl b/test/rtl/vhdl/sampleshift.vhdl
new file mode 100644 (file)
index 0000000..62ec28b
--- /dev/null
@@ -0,0 +1,50 @@
+-- Test JTAG in the following way:
+--  * reset JTAG interface
+--  * load samplepreload command
+--  * shift in/out sampled inputs + wanted outputs
+--  * load extest command
+--  * execute
+
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity bench_sampleshift is
+end bench_sampleshift;
+
+architecture rtl of bench_sampleshift is
+  signal TCK:   std_logic;
+  signal TMS:   std_logic;
+  signal TDI:   std_logic;
+  signal TDO:   std_logic;
+  signal TRST_N: std_logic;
+  
+  constant CLK_PERIOD:  time := 10 ns;
+
+  procedure ClkCycle(
+    signal CLK: out std_logic;
+    CLK_PERIOD: time
+  ) is
+  begin
+    CLK <= '0';
+    wait for CLK_PERIOD/4;
+    CLK <= '1';
+    wait for CLK_PERIOD/2;
+    CLK <= '0';
+    wait for CLK_PERIOD/4;
+  end ClkCycle;
+
+  procedure ClkCycles(
+    N:  integer;
+    signal CLK: out std_logic;
+    CLK_PERIOD: time
+  ) is
+  begin
+    for i in 1 to N loop
+      ClkCycle(CLK, CLK_PERIOD);
+    end loop;
+  end ClkCycles;
+  
+  procedure LoadIR(