soc/cores/jtag: add Xilinx JTAG TAPs support and simple JTAG PHY (can be used for JTAG UART)

This commit is contained in:
Florent Kermarrec 2019-09-06 11:55:41 +02:00
parent 2638393b53
commit d0ebbda4b3
1 changed files with 144 additions and 2 deletions

View File

@ -1,8 +1,10 @@
# This file is Copyright (c) 2019 Antti Lukats <antti.lukats@gmail.com>$
# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
# This file is Copyright (c) 2019 Antti Lukats <antti.lukats@gmail.com>
# This file is Copyright (c) 2017 Robert Jordens <jordens@gmail.com>
# License: BSD
from migen import *
from migen.genlib.cdc import AsyncResetSynchronizer
from litex.soc.interconnect import stream
@ -10,7 +12,7 @@ from litex.soc.interconnect import stream
class JTAGAtlantic(Module):
def __init__(self):
self.sink = sink = stream.Endpoint([("data", 8)])
self.sink = sink = stream.Endpoint([("data", 8)])
self.source = source = stream.Endpoint([("data", 8)])
# # #
@ -32,3 +34,143 @@ class JTAGAtlantic(Module):
i_t_dav=source.ready,
o_t_ena=source.valid,
)
# Xilinx JTAG --------------------------------------------------------------------------------------
class XilinxJTAG(Module):
def __init__(self, primitive, chain=1):
self.reset = Signal()
self.capture = Signal()
self.shift = Signal()
self.update = Signal()
self.tck = Signal()
self.tms = Signal()
self.tdi = Signal()
self.tdo = Signal()
# # #
self.specials += \
Instance(primitive,
p_JTAG_CHAIN=chain,
o_RESET=self.reset,
o_CAPTURE=self.capture,
o_SHIFT=self.shift,
o_UPDATE=self.update,
o_TCK=self.tck,
o_TMS=self.tms,
o_TDI=self.tdi,
i_TDO=self.tdo,
)
class S6JTAG(XilinxJTAG):
def __init__(self, *args, **kwargs):
XilinxJTAG.__init__(self, primitive="BSCAN_SPARTAN6", *args, **kwargs)
class S7JTAG(XilinxJTAG):
def __init__(self, *args, **kwargs):
XilinxJTAG.__init__(self, primitive="BSCANE2", *args, **kwargs)
class USJTAG(XilinxJTAG):
def __init__(self, *args, **kwargs):
XilinxJTAG.__init__(self, primitive="BSCANE2", *args, **kwargs)
# JTAG PHY -----------------------------------------------------------------------------------------
class JTAGPHY(Module):
def __init__(self, jtag=None, device=None, data_width=8, clock_domain="sys"):
"""JTAG PHY
Provides a simple JTAG to LiteX stream module to easily stream data to/from the FPGA
over JTAG.
Wire format: data_width + 2 bits, LSB first.
Host to Target:
- TX ready : bit 0
- RX data: : bit 1 to data_width
- RX valid : bit data_width + 1
Target to Host:
- RX ready : bit 0
- TX data : bit 1 to data_width
- TX valid : bit data_width + 1
"""
self.sink = sink = stream.Endpoint([("data", data_width)])
self.source = source = stream.Endpoint([("data", data_width)])
# # #
valid = Signal()
data = Signal(data_width)
count = Signal(max=data_width)
# JTAG TAP ---------------------------------------------------------------------------------
if jtag is None:
if device[:3] == "xc6":
jtag = S6JTAG()
elif device[:3] == "xc7":
jtag = S7JTAG()
elif device[:4] in ["xcku", "xcvu"]:
jtag = USJTAG()
else:
raise NotImplementedError
self.submodules += jtag
# JTAG clock domain ------------------------------------------------------------------------
self.clock_domains.cd_jtag = ClockDomain()
self.comb += ClockSignal("jtag").eq(jtag.tck)
self.specials += AsyncResetSynchronizer(self.cd_jtag, ResetSignal("sys"))
# JTAG clock domain crossing ---------------------------------------------------------------
if clock_domain != "jtag":
tx_cdc = stream.AsyncFIFO([("data", data_width)], 4)
tx_cdc = ClockDomainsRenamer({"write": clock_domain, "read": "jtag"})(tx_cdc)
rx_cdc = stream.AsyncFIFO([("data", data_width)], 4)
rx_cdc = ClockDomainsRenamer({"write": "jtag", "read": clock_domain})(rx_cdc)
self.submodules += tx_cdc, rx_cdc
self.comb += [
sink.connect(tx_cdc.sink),
rx_cdc.source.connect(source)
]
sink, source = tx_cdc.source, rx_cdc.sink
# JTAG Xfer FSM ----------------------------------------------------------------------------
fsm = FSM(reset_state="XFER-READY")
fsm = ClockDomainsRenamer("jtag")(fsm)
fsm = ResetInserter()(fsm)
self.submodules += fsm
self.comb += fsm.reset.eq(jtag.reset | jtag.capture)
fsm.act("XFER-READY",
jtag.tdo.eq(source.ready),
If(jtag.shift,
sink.ready.eq(jtag.tdi),
NextValue(valid, sink.valid),
NextValue(data, sink.data),
NextValue(count, 0),
NextState("XFER-DATA")
)
)
fsm.act("XFER-DATA",
jtag.tdo.eq(data),
If(jtag.shift,
NextValue(count, count + 1),
NextValue(data, Cat(data[1:], jtag.tdi)),
If(count == (data_width - 1),
NextState("XFER-VALID")
)
)
)
fsm.act("XFER-VALID",
jtag.tdo.eq(valid),
If(jtag.shift,
source.valid.eq(jtag.tdi),
NextState("XFER-READY")
)
)
self.comb += source.data.eq(data)