56aadbb839707b8041cf6fa4fede354508790bf2
3 using Staf Verhaegen (Chips4Makers) wishbone TAP
6 from collections
import OrderedDict
7 from nmigen
import (Module
, Signal
, Elaboratable
, Cat
)
8 from nmigen
.cli
import rtlil
9 from c4m
.nmigen
.jtag
.tap
import IOType
, TAP
11 # map from pinmux to c4m jtag iotypes
12 iotypes
= {'-': IOType
.In
,
18 # nmigen Resources has a different encoding for direction: "i", "o", "io", "oe"
19 resiotypes
= {'i': IOType
.In
,
22 'io': IOType
.InTriOut
,
24 # How many bits in each signal type
25 scanlens
= {IOType
.In
: 1,
32 # sigh this needs to come from pinmux.
35 gpios
.append("%d*" % i
)
36 return {'uart': ['tx+', 'rx-'],
38 'i2c': ['sda*', 'scl+']}
41 # TODO: move to suitable location
43 """declare a list of pins, including name and direction. grouped by fn
44 the pin dictionary needs to be in a reliable order so that the JTAG
45 Boundary Scan is also in a reliable order
47 def __init__(self
, pindict
=None):
50 self
.io_names
= OrderedDict()
51 if isinstance(pindict
, OrderedDict
):
52 self
.io_names
.update(pindict
)
54 keys
= list(pindict
.keys())
57 self
.io_names
[k
] = pindict
[k
]
60 # start parsing io_names and enumerate them to return pin specs
62 for fn
, pins
in self
.io_names
.items():
64 # decode the pin name and determine the c4m jtag io type
65 name
, pin_type
= pin
[:-1], pin
[-1]
66 iotype
= iotypes
[pin_type
]
67 pin_name
= "%s_%s" % (fn
, name
)
68 yield (fn
, name
, iotype
, pin_name
, scan_idx
)
69 scan_idx
+= scanlens
[iotype
] # inc boundary reg scan offset
72 class JTAG(TAP
, Pins
):
73 # 32-bit data width here so that it matches with litex
74 def __init__(self
, pinset
, domain
, wb_data_wid
=32):
76 TAP
.__init
__(self
, ir_width
=4)
77 Pins
.__init
__(self
, pinset
)
79 # enumerate pin specs and create IOConn Records.
80 # we store the boundary scan register offset in the IOConn record
81 self
.ios
= {} # these are enumerated in external_ports
83 self
.add_pins(list(self
))
85 # this is redundant. or maybe part of testing, i don't know.
86 self
.sr
= self
.add_shiftreg(ircode
=4, length
=3,
89 # create and connect wishbone
90 self
.wb
= self
.add_wishbone(ircodes
=[5, 6, 7], features
={'err'},
91 address_width
=30, data_width
=wb_data_wid
,
92 granularity
=8, # 8-bit wide
96 # create DMI2JTAG (goes through to dmi_sim())
97 self
.dmi
= self
.add_dmi(ircodes
=[8, 9, 10],
100 # use this for enable/disable of parts of the ASIC.
101 # XXX make sure to add the _en sig to en_sigs list
102 self
.wb_icache_en
= Signal(reset
=1)
103 self
.wb_dcache_en
= Signal(reset
=1)
104 self
.wb_sram_en
= Signal(reset
=1)
105 self
.en_sigs
= en_sigs
= Cat(self
.wb_icache_en
, self
.wb_dcache_en
,
107 self
.sr_en
= self
.add_shiftreg(ircode
=11, length
=len(en_sigs
),
110 def add_pins(self
, pinlist
):
111 for fn
, pin
, iotype
, pin_name
, scan_idx
in pinlist
:
112 io
= self
.add_io(iotype
=iotype
, name
=pin_name
)
113 io
._scan
_idx
= scan_idx
# hmm shouldn't really do this
114 self
.scan_len
+= scan_idx
# record full length of boundary scan
115 self
.ios
[pin_name
] = io
117 def elaborate(self
, platform
):
118 m
= super().elaborate(platform
)
119 m
.d
.comb
+= self
.sr
.i
.eq(self
.sr
.o
) # loopback as part of test?
121 # provide way to enable/disable wishbone caches and SRAM
122 # just in case of issues
123 # see https://bugs.libre-soc.org/show_bug.cgi?id=520
124 with m
.If(self
.sr_en
.oe
):
125 m
.d
.sync
+= self
.en_sigs
.eq(self
.sr_en
.o
)
126 # also make it possible to read the enable/disable current state
127 with m
.If(self
.sr_en
.ie
):
128 m
.d
.comb
+= self
.sr_en
.i
.eq(self
.en_sigs
)
130 # create a fake "stall"
132 #m.d.comb += wb.stall.eq(wb.cyc & ~wb.ack) # No burst support
136 def external_ports(self
):
137 """create a list of ports that goes into the top level il (or verilog)
139 ports
= super().external_ports() # gets JTAG signal names
140 ports
+= list(self
.wb
.fields
.values()) # wishbone signals
141 for io
in self
.ios
.values():
142 ports
+= list(io
.core
.fields
.values()) # io "core" signals
143 ports
+= list(io
.pad
.fields
.values()) # io "pad" signals"
147 if __name__
== '__main__':
148 pinset
= dummy_pinset()
149 dut
= JTAG(pinset
, "sync")
151 vl
= rtlil
.convert(dut
)
152 with
open("test_jtag.il", "w") as f
: