3 based on Staf Verhaegen (Chips4Makers) wishbone TAP
6 from nmigen
import (Module
, Signal
, Elaboratable
, Const
)
7 from nmigen
.cli
import rtlil
8 from c4m
.nmigen
.jtag
.tap
import TAP
, IOType
9 from soc
.debug
.dmi
import DMIInterface
, DBGCore
11 from nmigen_soc
.wishbone
.sram
import SRAM
12 from nmigen
import Memory
, Signal
, Module
14 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
, Tick
15 from nmutil
.util
import wrap
18 # JTAG to DMI interface
23 # req : ____/------------\_____
27 # din : xxxxxxxxxxxx< >xxx
28 # ack : ____________/------\___
30 # * addr/dout set along with req, can be latched on same cycle by slave
31 # * ack & din remain up until req is dropped by master, the slave must
32 # provide a stable output on din on reads during that time.
33 # * req remains low at until at least one sysclk after ack seen down.
37 def __init__(self
, *args
, **kwargs
):
38 super().__init
__(*args
, **kwargs
)
41 def elaborate(self
, platform
):
42 m
= super().elaborate(platform
)
43 self
._elaborate
_dmis
(m
)
46 def add_dmi(self
, *, ircodes
, address_width
=8, data_width
=64,
47 domain
="sync", name
=None):
48 """Add a DMI interface
50 * writing to DMIADDR will automatically trigger a DMI READ.
51 the DMI address does not alter (so writes can be done at that addr)
52 * reading from DMIREAD triggers a DMI READ at the current DMI addr
53 the address is automatically incremented by 1 after.
54 * writing to DMIWRITE triggers a DMI WRITE at the current DMI addr
55 the address is automatically incremented by 1 after.
59 ircodes: sequence of three integer for the JTAG IR codes;
60 they represent resp. DMIADDR, DMIREAD and DMIWRITE.
61 First code has a shift register of length 'address_width',
62 the two other codes share a shift register of length
65 address_width: width of the address
66 data_width: width of the data
69 dmi: soc.debug.dmi.DMIInterface
73 raise ValueError("3 IR Codes have to be provided")
76 name
= "dmi" + str(len(self
._dmis
))
78 # add 2 shift registers: one for addr, one for data.
79 sr_addr
= self
.add_shiftreg(ircode
=ircodes
[0], length
=address_width
,
80 domain
=domain
, name
=name
+"_addrsr")
81 sr_data
= self
.add_shiftreg(ircode
=ircodes
[1:], length
=data_width
,
82 domain
=domain
, name
=name
+"_datasr")
84 dmi
= DMIInterface(name
=name
)
85 self
._dmis
.append((sr_addr
, sr_data
, dmi
, domain
))
89 def _elaborate_dmis(self
, m
):
90 for sr_addr
, sr_data
, dmi
, domain
in self
._dmis
:
92 m
.d
.comb
+= sr_addr
.i
.eq(dmi
.addr_i
)
94 with m
.FSM(domain
=domain
) as ds
:
96 # detect mode based on whether jtag addr or data read/written
98 with m
.If(sr_addr
.oe
): # DMIADDR code
99 cd
+= dmi
.addr_i
.eq(sr_addr
.o
)
101 with m
.Elif(sr_data
.oe
[0]): # DMIREAD code
103 cd
+= dmi
.addr_i
.eq(dmi
.addr_i
+ 1)
105 with m
.Elif(sr_data
.oe
[1]): # DMIWRITE code
106 cd
+= dmi
.din
.eq(sr_data
.o
)
109 # req_i raises for 1 clock
110 with m
.State("READ"):
114 with m
.State("READACK"):
115 with m
.If(dmi
.ack_o
):
116 # Store read data in sr_data.i hold till next read
117 cd
+= sr_data
.i
.eq(dmi
.dout
)
120 # req_i raises for 1 clock
121 with m
.State("WRRD"):
125 with m
.State("WRRDACK"):
126 with m
.If(dmi
.ack_o
):
127 cd
+= dmi
.addr_i
.eq(dmi
.addr_i
+ 1)
128 m
.next
= "READ" # for readwrite
130 # set DMI req and write-enable based on ongoing FSM states
132 dmi
.req_i
.eq(ds
.ongoing("READ") | ds
.ongoing("WRRD")),
133 dmi
.we_i
.eq(ds
.ongoing("WRRD")),
136 def external_ports(self
):
137 return [self
.bus
.tdo
, self
.bus
.tdi
, self
.bus
.tms
, self
.bus
.tck
]
140 if __name__
== '__main__':
141 dut
= DMITAP(ir_width
=4)
142 iotypes
= (IOType
.In
, IOType
.Out
, IOType
.TriOut
, IOType
.InTriOut
)
143 ios
= [dut
.add_io(iotype
=iotype
) for iotype
in iotypes
]
144 dut
.sr
= dut
.add_shiftreg(ircode
=4, length
=3) # test loopback register
146 # create and connect wishbone SRAM (a quick way to do WB test)
147 dut
.wb
= dut
.add_wishbone(ircodes
=[5, 6, 7],
148 address_width
=16, data_width
=16)
150 # create DMI2JTAG (goes through to dmi_sim())
151 dut
.dmi
= dut
.add_dmi(ircodes
=[8, 9, 10])
153 vl
= rtlil
.convert(dut
)
154 with
open("test_dmi2jtag.il", "w") as f
: