From 85d7ce239ef57731cc1dcb2c8ffc6ffc85f77a5d Mon Sep 17 00:00:00 2001 From: Staf Verhaegen Date: Thu, 5 Dec 2019 20:43:26 +0100 Subject: [PATCH] Added JTAG bus interface. --- c4m/nmigen/jtag/__init__.py | 1 + c4m/nmigen/jtag/bus.py | 84 +++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 c4m/nmigen/jtag/bus.py diff --git a/c4m/nmigen/jtag/__init__.py b/c4m/nmigen/jtag/__init__.py index bfa7957..9e6cc09 100644 --- a/c4m/nmigen/jtag/__init__.py +++ b/c4m/nmigen/jtag/__init__.py @@ -1 +1,2 @@ from .pmod import * +from .bus import * diff --git a/c4m/nmigen/jtag/bus.py b/c4m/nmigen/jtag/bus.py new file mode 100644 index 0000000..c6015a7 --- /dev/null +++ b/c4m/nmigen/jtag/bus.py @@ -0,0 +1,84 @@ +from nmigen import * +from nmigen.hdl.rec import Direction + +class Interface(Record): + """JTAG Interface. + + Parameters + ---------- + with_reset : bool, default=False + wether to include trst field; if this field is not present a JTAG master + should not rely on this pin for resetting a TAP. + """ + def __init__(self, *, with_reset=False, name=None, src_loc_at=0): + layout = [ + ("tck", 1, Direction.NONE), + ("tms", 1, Direction.NONE), + ("tdo", 1, Direction.FANOUT), + ("tdi", 1, Direction.FANIN), + ] + if with_reset: + layout.append( + ("trst", 1, Direction.FANOUT) + ) + super().__init__(layout, name=name, src_loc_at=src_loc_at+1) + + +class Chain(Elaboratable): + """A chain of JTAG interfaces. + + Parameters + ---------- + buses : iterable of :class:`Interface`, default=[] + Initial value of the buses in the chain. + with_reset : bool, default=False + Wether the generated bus has a reset pin. If value is True all buses in + the chain also have to have a reset signal + + Attributes + ---------- + bus : :class:`Interface` + """ + def __init__(self, *, with_reset=False, buses=[], name=None, src_loc_at=0): + for bus in buses: + if not isinstance(bus, Interface): + raise ValueError("Object in buses that is not a JTAG Interface") + if with_reset and not hasattr(bus, "trst"): + raise ValueError("JTAG bus in buses without a reset signal") + + kwargs = { + "with_reset": with_reset, + "src_loc_at": src_loc_at + 1, + } + if name is not None: + kwargs["name"] = name + "_bus" + self.bus = Interface(**kwargs) + + self._buses = buses + + def add(bus): + """Add a bus to the chain""" + + if not isinstance(bus, Interface): + raise ValueError("bus in not a JTAG Interface") + if hasattr(self.bus, "trst") and not hasattr(bus, "trst"): + raise ValueError("bus needs to have a reset signal") + self._buses.append(bus) + + def elaborate(self, platform): + with_reset = hasattr(self.bus, "trst") + + m = Module() + + # Connect first and last + m.d.comb += [ + self._buses[0].tdi.eq(self.bus.tdo), + self.bus.tdi.eq(self._buses[-1].tdo), + ] + for i in range(len(self._buses)): + if i < len(self._buses) - 1: + m.d.comb += self._buses[i+1].tdi.eq(self._buses[i].tdo) + if with_reset: + m.d.comb += self._buses[i].trst.eq(self.bus.trst) + + return m -- 2.30.2