nmigen explicit imports
[c4m-jtag.git] / c4m / nmigen / jtag / tap.py
index 9e260c3d9df74086331d1d6aa59f10625a54e6a0..c10ff3a7c59dc476a09a7146fa65d9f1b00ee5cf 100755 (executable)
@@ -1,10 +1,9 @@
-#!/bin/env python3
+#!/usr/bin/env python3
 import os, textwrap
 from enum import Enum, auto
 
-from nmigen import *
-from nmigen.build import *
-from nmigen.lib.io import *
+from nmigen import (Elaboratable, Signal, Module, ClockDomain, Cat, Record,
+                    Const, Mux)
 from nmigen.hdl.rec import Direction, Layout
 from nmigen.tracer import get_var_name
 
@@ -26,6 +25,7 @@ class _FSM(Elaboratable):
         self.shift = Signal()
         self.update = Signal()
 
+        # JTAG uses both edges of the incoming clock (TCK). set them up here
         self.posjtag = ClockDomain("posjtag", local=True)
         self.negjtag = ClockDomain("negjtag", local=True, clk_edge="neg")
 
@@ -119,6 +119,7 @@ class _FSM(Elaboratable):
 
         return m
 
+
 class _IRBlock(Elaboratable):
     """TAP subblock for handling the IR shift register"""
     def __init__(self, *, ir_width, cmd_idcode,
@@ -151,12 +152,14 @@ class _IRBlock(Elaboratable):
 
         return m
 
+
 class IOType(Enum):
     In = auto()
     Out = auto()
     TriOut = auto()
     InTriOut = auto()
 
+
 class IOConn(Record):
     """TAP subblock representing the interface for an JTAG IO cell.
     It contains signal to connect to the core and to the pad
@@ -198,6 +201,7 @@ class IOConn(Record):
 
         self._iotype = iotype
 
+
 class _IDBypassBlock(Elaboratable):
     """TAP subblock for the ID shift register"""
     def __init__(self, *, manufacturer_id, part_number, version,
@@ -399,9 +403,8 @@ class TAP(Elaboratable):
             m.d.comb += tdo.eq(irblock.tdo)
         with m.Elif(select_id):
             m.d.comb += tdo.eq(idblock.tdo)
-        if io_tdo is not None:
-            with m.Elif(select_io):
-                m.d.comb += tdo.eq(io_tdo)
+        with m.Elif(select_io):
+            m.d.comb += tdo.eq(io_tdo)
 
         # shiftregs block
         self._elaborate_shiftregs(
@@ -440,11 +443,12 @@ class TAP(Elaboratable):
         }
         length = sum(connlength[conn._iotype] for conn in self._ios)
         if length == 0:
-            return None
+            return self.bus.tdi
 
         io_sr = Signal(length)
         io_bd = Signal(length)
 
+        # Boundary scan "capture" mode.  makes I/O status available via SR
         with m.If(capture):
             idx = 0
             for conn in self._ios:
@@ -470,11 +474,17 @@ class TAP(Elaboratable):
                 else:
                     raise("Internal error")
             assert idx == length, "Internal error"
+
+        # "Shift" mode (sends out captured data on tdo, sets incoming from tdi)
         with m.Elif(shift):
             m.d.posjtag += io_sr.eq(Cat(self.bus.tdi, io_sr[:-1]))
+
+        # "Update" mode
         with m.Elif(update):
             m.d.negjtag += io_bd.eq(io_sr)
 
+        # sets up IO (pad<->core) or in testing mode depending on requested
+        # mode, via Muxes controlled by bd2core and bd2io
         idx = 0
         for conn in self._ios:
             if conn._iotype == IOType.In: