Skip to content

Commit 6f2ffc3

Browse files
author
Gwenhael Goavec-Merou
committed
spiOverJtag: introduce a new spiOverJtag (v2) core able to work with complex JTAG chain
1 parent 513033a commit 6f2ffc3

File tree

4 files changed

+414
-134
lines changed

4 files changed

+414
-134
lines changed

spiOverJtag/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ tmp_efinix_%/efinix_spiOverJtag.bit : efinix_spiOverJtag.v
3939

4040
$(XILINX_BIT_FILES) : spiOverJtag_%.bit.gz : tmp_%/spiOverJtag.bit
4141
gzip -9 -c $< > $@
42-
tmp_%/spiOverJtag.bit : xilinx_spiOverJtag.v
42+
tmp_%/spiOverJtag.bit : xilinx_spiOverJtag.v spiOverJtag_core.v
4343
./build.py $*
4444

4545
$(ALTERA_BIT_FILES): spiOverJtag_%.rbf.gz: tmp_%/spiOverJtag.rbf

spiOverJtag/build.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@
220220
'file_type': 'SDC'})
221221
tool_options = {'device': full_part, 'family':family}
222222

223+
files.append({'name': currDir + 'spiOverJtag_core.v',
224+
'file_type': 'verilogSource'})
225+
223226
parameters[family.lower().replace(' ', '')]= {
224227
'datatype': 'int',
225228
'paramtype': 'vlogdefine',

spiOverJtag/spiOverJtag_core.v

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
`default_nettype none
2+
/*
3+
* JTAG: rising edge: sampling
4+
* falling esge: update
5+
* SPI:
6+
*/
7+
8+
module spiOverJtag_core (
9+
/* JTAG state/controls */
10+
input wire sel,
11+
input wire capture,
12+
input wire update,
13+
input wire shift,
14+
input wire drck,
15+
input wire tdi,
16+
output wire tdo,
17+
18+
/* JTAG endpoint to version */
19+
input wire ver_sel,
20+
input wire ver_cap,
21+
input wire ver_shift,
22+
input wire ver_drck,
23+
input wire ver_tdi,
24+
output wire ver_tdo,
25+
/* phys */
26+
output reg csn,
27+
output wire sck,
28+
output reg sdi_dq0,
29+
input wire sdo_dq1,
30+
output wire wpn_dq2,
31+
output wire hldn_dq3,
32+
33+
/* debug signals */
34+
output wire [ 6:0] dbg_header1,
35+
output wire [13:0] dbg_header,
36+
output wire [ 3:0] dbg_hdr_cnt,
37+
output wire [ 2:0] dbg_jtag_state,
38+
output wire dbg_rst,
39+
output wire dbg_clk,
40+
output wire dbg_start_header,
41+
42+
output wire dbg_ver_start,
43+
output wire dbg_ver_rst,
44+
output wire dbg_ver_state,
45+
output wire [15:0] dbg_ver_cnt,
46+
output wire [39:0] dbg_ver_shft
47+
);
48+
49+
/* no global reset at start time:
50+
* reset system at capture time (before shift)
51+
* and at update time (after shift)
52+
*/
53+
wire rst = ((capture | update) & sel);
54+
55+
/*
56+
* if the FPGAs executing this code is somewhere in a complex
57+
* JTAG chain first bit isn't necessary for him
58+
* Fortunately dummy bits sent are equal to '0' -> we sent a 'start bit'
59+
*/
60+
wire start_header = (tdi & shift & sel);
61+
62+
localparam hdr_len = 16;
63+
reg [hdr_len-1:0] header; /* number of bits to receive / send in XFER state */
64+
reg [hdr_len-1:0] header_d;
65+
/* Primary header with mode and length LSB
66+
* 6:5: mode (00: normal, 01: no header2, 10: infinite loop)
67+
* 4:0: Byte length LSB
68+
*/
69+
reg [ 6:0] header1;
70+
reg [ 6:0] header1_d;
71+
wire [ 6:0] header1_next = {tdi, header1[6:1]};
72+
wire [ 1:0] mode = header1[1:0];
73+
/* Secondary header with extended length */
74+
reg [ 7:0] header2;
75+
reg [ 7:0] header2_d;
76+
wire [ 7:0] header2_next = {tdi, header2[7:1]};
77+
reg [ 3:0] hdr_cnt; /* counter of bit received in RECV_HEADERx states */
78+
reg [ 3:0] hdr_cnt_d;
79+
80+
/* ---------------- */
81+
/* FSM */
82+
/* ---------------- */
83+
84+
localparam IDLE = 3'b000,
85+
RECV_HEADER1 = 3'b001,
86+
RECV_HEADER2 = 3'b010,
87+
XFER = 3'b011,
88+
WAIT_END = 3'b100;
89+
90+
reg [2:0] jtag_state, jtag_state_d;
91+
92+
/*
93+
* 1. receives 8bits (
94+
*/
95+
always @(*) begin
96+
jtag_state_d = jtag_state;
97+
hdr_cnt_d = hdr_cnt;
98+
header_d = header;
99+
header1_d = header1;
100+
header2_d = header2;
101+
case (jtag_state)
102+
IDLE: begin /* nothing: wait for the 'start bit' */
103+
hdr_cnt_d = 6;
104+
if (start_header) begin
105+
jtag_state_d = RECV_HEADER1;
106+
header2_d = 8'd0;
107+
end
108+
end
109+
RECV_HEADER1: begin /* first header with 1:0 : mode, 6:2: XFER length (LSB) */
110+
hdr_cnt_d = hdr_cnt - 1'b1;
111+
header1_d = header1_next;
112+
if (hdr_cnt == 0) begin
113+
header_d = {8'b0, header1_next[6:2], 3'b000};
114+
if (header1_next[1:0] == 2'b00) begin
115+
hdr_cnt_d = 7;
116+
jtag_state_d = RECV_HEADER2;
117+
end else begin
118+
jtag_state_d = XFER;
119+
//header_d = {8'b0, header1_next[6:2], 3'b000} - 1'b1;
120+
end
121+
end
122+
end
123+
124+
RECV_HEADER2: begin /* fill a counter with 16bits (number of bits to pass to the flash) */
125+
hdr_cnt_d = hdr_cnt - 1'b1;
126+
header2_d = header2_next;
127+
if (hdr_cnt == 0) begin
128+
header_d[hdr_len-1:8] = header2_next;
129+
jtag_state_d = XFER;
130+
end
131+
end
132+
XFER: begin
133+
header_d = header - 1;
134+
if (header == 1 && mode != 2'b10)
135+
jtag_state_d = WAIT_END;
136+
end
137+
WAIT_END: begin /* move to this state when header bits have been transfered to the SPI flash */
138+
// /* nothing to do: rst will move automagically state in IDLE */
139+
end
140+
default: begin
141+
jtag_state_d = IDLE;
142+
end
143+
endcase
144+
end
145+
146+
always @(posedge drck) begin
147+
header <= header_d;
148+
header1 <= header1_d;
149+
header2 <= header2_d;
150+
end
151+
152+
always @(posedge drck or posedge rst) begin
153+
if (rst) begin
154+
jtag_state <= IDLE;
155+
hdr_cnt <= hdr_len - 1;
156+
end else begin
157+
jtag_state <= jtag_state_d;
158+
hdr_cnt <= hdr_cnt_d;
159+
end
160+
end
161+
162+
/* JTAG <-> phy SPI */
163+
always @(posedge drck or posedge rst) begin
164+
if (rst) begin
165+
sdi_dq0 <= 1'b0;
166+
csn <= 1'b1;
167+
end else begin
168+
sdi_dq0 <= tdi;
169+
csn <= ~(jtag_state == XFER);
170+
end
171+
end
172+
173+
assign sck = ~drck;
174+
assign tdo = sdo_dq1;
175+
assign wpn_dq2 = 1'b1;
176+
assign hldn_dq3 = 1'b1;
177+
178+
/* ------------- */
179+
/* Version */
180+
/* ------------- */
181+
/* no global reset at start time: reset system at capture time (before shift) */
182+
wire ver_rst = (ver_cap & ver_sel);
183+
184+
/* start bit */
185+
wire ver_start = (ver_tdi & ver_shift & ver_sel);
186+
187+
localparam VER_VALUE = 40'h30_30_2E_32_30; // 02.00
188+
reg [ 6:0] ver_cnt, ver_cnt_d;
189+
reg [39:0] ver_shft, ver_shft_d;
190+
191+
reg [2:0] ver_state, ver_state_d;
192+
always @(*) begin
193+
ver_state_d = ver_state;
194+
ver_cnt_d = ver_cnt;
195+
ver_shft_d = ver_shft;
196+
case (ver_state)
197+
IDLE: begin /* nothing: wait for the 'start bit' */
198+
ver_cnt_d = 6;
199+
if (ver_start) begin
200+
ver_state_d = RECV_HEADER1;
201+
end
202+
end
203+
RECV_HEADER1: begin
204+
ver_cnt_d = ver_cnt - 1'b1;
205+
if (ver_cnt == 0) begin
206+
ver_state_d = XFER;
207+
ver_cnt_d = 39;
208+
ver_shft_d = VER_VALUE;
209+
end
210+
end
211+
XFER: begin
212+
ver_cnt_d = ver_cnt - 1;
213+
ver_shft_d = {1'b1, ver_shft[39:1]};
214+
if (ver_cnt == 0)
215+
ver_state_d = WAIT_END;
216+
end
217+
WAIT_END: begin /* move to this state when header bits have been transfered to the SPI flash */
218+
// /* nothing to do: rst will move automagically state in IDLE */
219+
end
220+
default: begin
221+
ver_state_d = IDLE;
222+
end
223+
endcase
224+
end
225+
226+
always @(posedge ver_drck) begin
227+
ver_cnt <= ver_cnt_d;
228+
ver_shft <= ver_shft_d;
229+
end
230+
231+
always @(posedge ver_drck or posedge ver_rst) begin
232+
if (ver_rst)
233+
ver_state <= IDLE;
234+
else
235+
ver_state <= ver_state_d;
236+
end
237+
238+
assign ver_tdo = ver_shft[0];
239+
240+
/* --------- */
241+
/* debug */
242+
/* --------- */
243+
assign dbg_header1 = header1;
244+
assign dbg_header = header;
245+
assign dbg_hdr_cnt = hdr_cnt;
246+
assign dbg_jtag_state = jtag_state;
247+
assign dbg_rst = rst;
248+
assign dbg_clk = ~drck;
249+
assign dbg_start_header = start_header;
250+
251+
assign dbg_ver_start = ver_start;
252+
assign dbg_ver_state = ver_state;
253+
assign dbg_ver_cnt = ver_cnt;
254+
assign dbg_ver_shft = ver_shft;
255+
assign dbg_ver_rst = ver_rst;
256+
257+
endmodule

0 commit comments

Comments
 (0)