3 based on Anton Blanchard microwatt dmi_dtm_xilinx.vhdl
7 from enum
import Enum
, unique
8 from nmigen
import (Module
, Signal
, Elaboratable
, Cat
, Signal
)
9 from nmigen
.cli
import main
10 from nmigen
.cli
import rtlil
11 from nmutil
.iocontrol
import RecordObject
12 from nmutil
.byterev
import byte_reverse
13 from nmutil
.mask
import Mask
14 from nmigen
.util
import log2_int
16 # -- Xilinx internal JTAG to DMI interface
20 # -- req : ____/------------\_____
21 # -- addr: xxxx< >xxxxx
22 # -- dout: xxxx< >xxxxx
23 # -- wr : xxxx< >xxxxx
24 # -- din : xxxxxxxxxxxx< >xxx
25 # -- ack : ____________/------\___
27 # -- * addr/dout set along with req, can be latched on same cycle by slave
28 # -- * ack & din remain up until req is dropped by master, the slave must
29 # -- provide a stable output on din on reads during that time.
30 # -- * req remains low at until at least one sysclk after ack seen down.
32 # -- JTAG (tck) DMI (sys_clk)
36 # -- (jtag_req_1) -> * dmi_req = 1 >
41 # -- * jtag_req = 0 (and latch dmi_din)
43 # -- (jtag_req_1) -> * dmi_req = 0 >
48 # -- jtag_req can go back to 1 when jtag_rsp_1 is 0
51 # -- - I use 2 flip fops for sync, is that enough ?
52 # -- - I treat the jtag_reset as an async reset, is that necessary ?
53 # -- - Dbl check reset situation since we have two different resets
54 # -- each only resetting part of the logic...
55 # -- - Look at optionally removing the synchronizer on the ack path,
56 # -- assuming JTAG is always slow enough that ack will have been
57 # -- stable long enough by the time CAPTURE comes in.
58 # -- - We could avoid the latched request by not shifting while a
59 # -- request is in progress (and force TDO to 1 to return a busy
62 # -- WARNING: This isn't the real DMI JTAG protocol (at least not yet).
63 # -- a command while busy will be ignored. A response of "11"
64 # -- means the previous command is still going, try again.
65 # -- As such We don't implement the DMI "error" status, and
66 # -- we don't implement DTMCS yet... This may still all change
67 # -- but for now it's easier that way as the real DMI protocol
68 # -- requires for a command to work properly that enough TCK
69 # -- are sent while IDLE and I'm having trouble getting that
70 # -- working with UrJtag and the Xilinx BSCAN2 for now.
73 # use ieee.std_logic_1164.all;
74 # use ieee.math_real.all;
77 # use work.wishbone_types.all;
80 # use unisim.vcomponents.all;
83 # generic(ABITS : INTEGER:=8;
84 # DBITS : INTEGER:=32);
86 # port(sys_clk : in std_ulogic;
87 # sys_reset : in std_ulogic;
88 # dmi_addr : out std_ulogic_vector(ABITS - 1 downto 0);
89 # dmi_din : in std_ulogic_vector(DBITS - 1 downto 0);
90 # dmi_dout : out std_ulogic_vector(DBITS - 1 downto 0);
91 # dmi_req : out std_ulogic;
92 # dmi_wr : out std_ulogic;
93 # dmi_ack : in std_ulogic
94 # -- dmi_err : in std_ulogic TODO: Add error response
98 # architecture behaviour of dmi_dtm is
100 # -- Signals coming out of the BSCANE2 block
101 # signal jtag_reset : std_ulogic;
102 # signal capture : std_ulogic;
103 # signal update : std_ulogic;
104 # signal drck : std_ulogic;
105 # signal jtag_clk : std_ulogic;
106 # signal sel : std_ulogic;
107 # signal shift : std_ulogic;
108 # signal tdi : std_ulogic;
109 # signal tdo : std_ulogic;
110 # signal tck : std_ulogic;
112 # -- ** JTAG clock domain **
115 # signal shiftr : std_ulogic_vector(ABITS + DBITS + 1 downto 0);
118 # signal request : std_ulogic_vector(ABITS + DBITS + 1 downto 0);
120 # -- A request is present
121 # signal jtag_req : std_ulogic;
123 # -- Synchronizer for jtag_rsp (sys clk -> jtag_clk)
124 # signal dmi_ack_0 : std_ulogic;
125 # signal dmi_ack_1 : std_ulogic;
127 # -- ** sys clock domain **
129 # -- Synchronizer for jtag_req (jtag clk -> sys clk)
130 # signal jtag_req_0 : std_ulogic;
131 # signal jtag_req_1 : std_ulogic;
133 # -- ** combination signals
134 # signal jtag_bsy : std_ulogic;
135 # signal op_valid : std_ulogic;
136 # signal rsp_op : std_ulogic_vector(1 downto 0);
139 # constant DMI_REQ_NOP : std_ulogic_vector(1 downto 0) := "00";
140 # constant DMI_REQ_RD : std_ulogic_vector(1 downto 0) := "01";
141 # constant DMI_REQ_WR : std_ulogic_vector(1 downto 0) := "10";
142 # constant DMI_RSP_OK : std_ulogic_vector(1 downto 0) := "00";
143 # constant DMI_RSP_BSY : std_ulogic_vector(1 downto 0) := "11";
145 # attribute ASYNC_REG : string;
146 # attribute ASYNC_REG of jtag_req_0: signal is "TRUE";
147 # attribute ASYNC_REG of jtag_req_1: signal is "TRUE";
148 # attribute ASYNC_REG of dmi_ack_0: signal is "TRUE";
149 # attribute ASYNC_REG of dmi_ack_1: signal is "TRUE";
152 # -- Implement the Xilinx bscan2 for series 7 devices (TODO: use PoC
153 # -- to wrap this if compatibility is required with older devices).
159 # CAPTURE => capture,
161 # RESET => jtag_reset,
172 # -- Some examples out there suggest buffering the clock so it's
173 # -- treated as a proper clock net. This is probably needed when using
174 # -- drck (the gated clock) but I'm using the real tck here to avoid
175 # -- missing the update phase so maybe not...
184 # -- dmi_req synchronization
185 # dmi_req_sync : process(sys_clk)
187 # -- sys_reset is synchronous
188 # if rising_edge(sys_clk) then
189 # if (sys_reset = '1') then
193 # jtag_req_0 <= jtag_req;
194 # jtag_req_1 <= jtag_req_0;
198 # dmi_req <= jtag_req_1;
200 # -- dmi_ack synchronization
201 # dmi_ack_sync: process(jtag_clk, jtag_reset)
203 # -- jtag_reset is async (see comments)
204 # if jtag_reset = '1' then
207 # elsif rising_edge(jtag_clk) then
208 # dmi_ack_0 <= dmi_ack;
209 # dmi_ack_1 <= dmi_ack_0;
213 # -- jtag_bsy indicates whether we can start a new request,
214 # -- we can when we aren't already processing one (jtag_req)
215 # -- and the synchronized ack of the previous one is 0.
217 # jtag_bsy <= jtag_req or dmi_ack_1;
219 # -- decode request type in shift register
220 # with shiftr(1 downto 0) select op_valid <=
221 # '1' when DMI_REQ_RD,
222 # '1' when DMI_REQ_WR,
225 # -- encode response op
226 # rsp_op <= DMI_RSP_BSY when jtag_bsy = '1' else DMI_RSP_OK;
228 # -- Some DMI out signals are directly driven from the request register
229 # dmi_addr <= request(ABITS + DBITS + 1 downto DBITS + 2);
230 # dmi_dout <= request(DBITS + 1 downto 2);
231 # dmi_wr <= '1' when request(1 downto 0) = DMI_REQ_WR else '0';
233 # -- TDO is wired to shift register bit 0
236 # -- Main state machine. Handles shift registers, request latch and
237 # -- jtag_req latch. Could be split into 3 processes but it's probably
240 # shifter: process(jtag_clk, jtag_reset)
242 # if jtag_reset = '1' then
243 # shiftr <= (others => '0');
245 # elsif rising_edge(jtag_clk) then
247 # -- Handle jtag "commands" when sel is 1
249 # -- Shift state, rotate the register
250 # if shift = '1' then
251 # shiftr <= tdi & shiftr(ABITS + DBITS + 1 downto 1);
254 # -- Update state (trigger)
256 # -- Latch the request if we aren't already processing
257 # -- one and it has a valid command opcode.
259 # if update = '1' and op_valid = '1' then
260 # if jtag_bsy = '0' then
264 # -- Set the shift register "op" to "busy".
265 # -- This will prevent us from re-starting
266 # -- the command on the next update if
267 # -- the command completes before that.
268 # shiftr(1 downto 0) <= DMI_RSP_BSY;
271 # -- Request completion.
273 # -- Capture the response data for reads and
274 # -- clear request flag.
276 # -- Note: We clear req (and thus dmi_req) here which
277 # -- relies on tck ticking and sel set. This means we
278 # -- are stuck with dmi_req up if the jtag interface stops.
279 # -- Slaves must be resilient to this.
281 # if jtag_req = '1' and dmi_ack_1 = '1' then
283 # if request(1 downto 0) = DMI_REQ_RD then
284 # request(DBITS + 1 downto 2) <= dmi_din;
288 # -- Capture state, grab latch content with updated status
289 # if capture = '1' then
290 # shiftr <= request(ABITS + DBITS + 1 downto 2) & rsp_op;
296 # end architecture behaviour;