blob: 0a1cce683953881bc9b8b47d4bf3ff52d671a53a [file] [log] [blame]
Tim Edwards19ddfd02020-10-04 22:09:54 -04001//-------------------------------------
2// SPI controller for Caravel (PicoSoC)
3//-------------------------------------
4// Written by Tim Edwards
5// efabless, inc. September 27, 2020
6//-------------------------------------
7
8//-----------------------------------------------------------
9// This is a standalone slave SPI for the caravel chip that is
10// intended to be independent of the picosoc and independent
11// of all IP blocks except the power-on-reset. This SPI has
12// register outputs controlling the functions that critically
13// affect operation of the picosoc and so cannot be accessed
14// from the picosoc itself. This includes the PLL enables
15// and trim, and the crystal oscillator enable. It also has
16// a general reset for the picosoc, an IRQ input, a bypass for
17// the entire crystal oscillator and PLL chain, the
18// manufacturer and product IDs and product revision number.
19// To be independent of the 1.8V regulator, the slave SPI is
20// synthesized with the 3V digital library and runs off of
21// the 3V supply.
22//
23// This module is designed to be decoupled from the chip
24// padframe and redirected to the wishbone bus under
25// register control from the management SoC, such that the
26// contents can be accessed from the management core via the
27// SPI master.
28//
29//-----------------------------------------------------------
30
31//------------------------------------------------------------
32// Caravel defined registers:
33// Register 0: SPI status and control (unused & reserved)
34// Register 1 and 2: Manufacturer ID (0x0456) (readonly)
35// Register 3: Product ID (= 2) (readonly)
36// Register 4-7: Mask revision (readonly) --- Externally programmed
37// with via programming. Via programmed with a script to match
38// each customer ID.
39//
40// Register 8: PLL enable (1 bit)
41// Register 9: PLL bypass (1 bit)
42// Register 10: IRQ (1 bit)
43// Register 11: reset (1 bit)
44// Register 12: trap (1 bit) (readonly)
45// Register 13-16: PLL trim (26 bits)
46// Register 17: PLL output select (3 bits)
47// Register 18: PLL divider (5 bits)
48//------------------------------------------------------------
49
50module housekeeping_spi(
51`ifdef LVS
52 vdd, vss,
53`endif
54 RSTB, SCK, SDI, CSB, SDO, sdo_enb,
Tim Edwards19ddfd02020-10-04 22:09:54 -040055 pll_dco_ena, pll_div, pll_sel,
56 pll_trim, pll_bypass, irq, reset, trap,
57 mask_rev_in, pass_thru_reset,
58 pass_thru_mgmt_sck, pass_thru_mgmt_csb,
59 pass_thru_mgmt_sdi, pass_thru_mgmt_sdo,
60 pass_thru_user_sck, pass_thru_user_csb,
61 pass_thru_user_sdi, pass_thru_user_sdo
62);
63
64`ifdef LVS
65 inout vdd; // 3.3V supply
66 inout vss; // common ground
67`endif
68
69 input RSTB; // from padframe
70
71 input SCK; // from padframe
72 input SDI; // from padframe
73 input CSB; // from padframe
74 output SDO; // to padframe
75 output sdo_enb; // to padframe
76
Tim Edwards19ddfd02020-10-04 22:09:54 -040077 output pll_dco_ena;
78 output [4:0] pll_div;
79 output [2:0] pll_sel;
80 output [25:0] pll_trim;
81 output pll_bypass;
82 output irq;
83 output reset;
84 input trap;
85 input [31:0] mask_rev_in; // metal programmed; 3.3V domain
86
87 // Pass-through programming mode for management area SPI flash
88 output pass_thru_reset;
89 output pass_thru_mgmt_sck;
90 output pass_thru_mgmt_csb;
91 output pass_thru_mgmt_sdi;
92 input pass_thru_mgmt_sdo;
93
94 // Pass-through programming mode for user area SPI flash
95 output pass_thru_user_sck;
96 output pass_thru_user_csb;
97 output pass_thru_user_sdi;
98 input pass_thru_user_sdo;
99
100 reg [25:0] pll_trim;
101 reg [4:0] pll_div;
102 reg [2:0] pll_sel;
103 reg pll_dco_ena;
104 reg pll_bypass;
105 reg reset_reg;
106 reg irq;
107
108 wire [7:0] odata;
109 wire [7:0] idata;
110 wire [7:0] iaddr;
111
112 wire trap;
113 wire rdstb;
114 wire wrstb;
115 wire pass_thru_mgmt; // Mode detected by spi_slave
116 wire pass_thru_mgmt_delay;
117 wire pass_thru_user; // Mode detected by spi_slave
118 wire pass_thru_user_delay;
Tim Edwards19ddfd02020-10-04 22:09:54 -0400119 wire loc_sdo;
Tim Edwards19ddfd02020-10-04 22:09:54 -0400120
121 // Pass-through mode handling
122
123 assign pass_thru_mgmt_csb = ~pass_thru_mgmt_delay;
124 assign pass_thru_mgmt_sck = pass_thru_mgmt ? SCK : 1'b0;
125 assign pass_thru_mgmt_sdi = pass_thru_mgmt ? SDI : 1'b0;
126
127 assign pass_thru_user_csb = ~pass_thru_user_delay;
128 assign pass_thru_user_sck = pass_thru_user ? SCK : 1'b0;
129 assign pass_thru_user_sdi = pass_thru_user ? SDI : 1'b0;
130
131 assign SDO = pass_thru_mgmt ? pass_thru_mgmt_sdo :
132 pass_thru_user ? pass_thru_user_sdo : loc_sdo;
133 assign reset = pass_thru_reset ? 1'b1 : reset_reg;
134
135 // Instantiate the SPI slave module
136
137 housekeeping_spi_slave U1 (
138 .reset(~RSTB),
Tim Edwards22a74352020-10-06 10:05:11 -0400139 .SCK(SCK),
140 .SDI(SDI),
141 .CSB(CSB),
Tim Edwards19ddfd02020-10-04 22:09:54 -0400142 .SDO(loc_sdo),
Tim Edwards22a74352020-10-06 10:05:11 -0400143 .sdoenb(sdo_enb),
Tim Edwards19ddfd02020-10-04 22:09:54 -0400144 .idata(odata),
145 .odata(idata),
146 .oaddr(iaddr),
147 .rdstb(rdstb),
148 .wrstb(wrstb),
149 .pass_thru_mgmt(pass_thru_mgmt),
150 .pass_thru_mgmt_delay(pass_thru_mgmt_delay),
151 .pass_thru_user(pass_thru_user),
152 .pass_thru_user_delay(pass_thru_user_delay),
153 .pass_thru_reset(pass_thru_reset)
154 );
155
156 wire [11:0] mfgr_id;
157 wire [7:0] prod_id;
158 wire [31:0] mask_rev;
159
160 assign mfgr_id = 12'h456; // Hard-coded
161 assign prod_id = 8'h10; // Hard-coded
162 assign mask_rev = mask_rev_in; // Copy in to out.
163
164 // Send register contents to odata on SPI read command
165 // All values are 1-4 bits and no shadow registers are required.
166
167 assign odata =
168 (iaddr == 8'h00) ? 8'h00 : // SPI status (fixed)
169 (iaddr == 8'h01) ? {4'h0, mfgr_id[11:8]} : // Manufacturer ID (fixed)
170 (iaddr == 8'h02) ? mfgr_id[7:0] : // Manufacturer ID (fixed)
171 (iaddr == 8'h03) ? prod_id : // Product ID (fixed)
172 (iaddr == 8'h04) ? mask_rev[31:24] : // Mask rev (metal programmed)
173 (iaddr == 8'h05) ? mask_rev[23:16] : // Mask rev (metal programmed)
174 (iaddr == 8'h06) ? mask_rev[15:8] : // Mask rev (metal programmed)
175 (iaddr == 8'h07) ? mask_rev[7:0] : // Mask rev (metal programmed)
176
177 (iaddr == 8'h08) ? {7'b0000000, pll_dco_ena} :
178 (iaddr == 8'h09) ? {7'b0000000, pll_bypass} :
179 (iaddr == 8'h0a) ? {7'b0000000, irq} :
180 (iaddr == 8'h0b) ? {7'b0000000, reset} :
181 (iaddr == 8'h0c) ? {7'b0000000, trap} :
182 (iaddr == 8'h0d) ? pll_trim[7:0] :
183 (iaddr == 8'h0e) ? pll_trim[15:8] :
184 (iaddr == 8'h0f) ? pll_trim[23:16] :
185 (iaddr == 8'h10) ? {6'b000000, pll_trim[25:24]} :
186 (iaddr == 8'h11) ? {5'b00000, pll_sel} :
187 (iaddr == 8'h12) ? {3'b000, pll_div} :
188 8'h00; // Default
189
190 // Register mapping and I/O to slave module
191
192 always @(posedge SCK or negedge RSTB) begin
193 if (RSTB == 1'b0) begin
194 // Set trim for PLL at (almost) slowest rate (~90MHz). However,
195 // pll_trim[12] must be set to zero for proper startup.
196 pll_trim <= 26'b11111111111110111111111111;
197 pll_sel <= 3'b000;
198 pll_div <= 5'b00100; // Default divide-by-8
199 pll_dco_ena <= 1'b1; // Default free-running PLL
200 pll_bypass <= 1'b1; // NOTE: Default bypass mode (don't use PLL)
201 irq <= 1'b0;
202 reset_reg <= 1'b0;
203 end else if (wrstb == 1'b1) begin
204 case (iaddr)
205 8'h08: begin
206 pll_dco_ena <= idata[0];
207 end
208 8'h09: begin
209 pll_bypass <= idata[0];
210 end
211 8'h0a: begin
212 irq <= idata[0];
213 end
214 8'h0b: begin
215 reset_reg <= idata[0];
216 end
217 // Register 0xc is read-only
218 8'h0d: begin
219 pll_trim[7:0] <= idata;
220 end
221 8'h0e: begin
222 pll_trim[15:8] <= idata;
223 end
224 8'h0f: begin
225 pll_trim[23:16] <= idata;
226 end
227 8'h10: begin
228 pll_trim[25:24] <= idata[1:0];
229 end
230 8'h11: begin
231 pll_sel <= idata[2:0];
232 end
233 8'h12: begin
234 pll_div <= idata[4:0];
235 end
236 endcase // (iaddr)
237 end
238 end
239endmodule // housekeeping_spi
240
241//------------------------------------------------------
242// housekeeping_spi_slave.v
243//------------------------------------------------------
244// General purpose SPI slave module for the Caravel chip
245//------------------------------------------------------
246// Written by Tim Edwards
247// efabless, inc., September 28, 2020
248//------------------------------------------------
249// This file is distributed free and open source
250//------------------------------------------------
251
252// SCK --- Clock input
253// SDI --- Data input
254// SDO --- Data output
255// CSB --- Chip select (sense negative)
256// idata --- Data from chip to transmit out, in 8 bits
257// odata --- Input data to chip, in 8 bits
258// addr --- Decoded address to upstream circuits
259// rdstb --- Read strobe, tells upstream circuit to supply next byte to idata
260// wrstb --- Write strobe, tells upstream circuit to latch odata.
261
262// Data format (general purpose):
263// 8 bit format
264// 1st byte: Command word (see below)
265// 2nd byte: Address word (register 0 to 255)
266// 3rd byte: Data word (value 0 to 255)
267
268// Command format:
269// 00000000 No operation
270// 10000000 Write until CSB raised
271// 01000000 Read until CSB raised
272// 11000000 Simultaneous read/write until CSB raised
273// 11000100 Pass-through read/write to management area flash SPI until CSB raised
274// 11000101 Pass-through read/write to user area flash SPI until CSB raised
275// wrnnn000 Read/write as above, for nnn = 1 to 7 bytes, then terminate
276
277// Lower three bits are reserved for future use.
278// All serial bytes are read and written msb first.
279
280// Fixed control and status registers
281
282// Address 0 is reserved and contains flags for SPI mode. This is
283// currently undefined and is always value 0.
284// Address 1 is reserved and contains manufacturer ID low 8 bits.
285// Address 2 is reserved and contains manufacturer ID high 4 bits.
286// Address 3 is reserved and contains product ID (8 bits).
287// Addresses 4 to 7 are reserved and contain the mask ID (32 bits).
288// Addresses 8 to 255 are available for general purpose use.
289
290`define COMMAND 3'b000
291`define ADDRESS 3'b001
292`define DATA 3'b010
293`define USERPASS 3'b100
294`define MGMTPASS 3'b101
295
296module housekeeping_spi_slave(reset, SCK, SDI, CSB, SDO,
297 sdoenb, idata, odata, oaddr, rdstb, wrstb,
298 pass_thru_mgmt, pass_thru_mgmt_delay,
299 pass_thru_user, pass_thru_user_delay, pass_thru_reset);
300
301 input reset;
302 input SCK;
303 input SDI;
304 input CSB;
305 output SDO;
306 output sdoenb;
307 input [7:0] idata;
308 output [7:0] odata;
309 output [7:0] oaddr;
310 output rdstb;
311 output wrstb;
312 output pass_thru_mgmt;
313 output pass_thru_mgmt_delay;
314 output pass_thru_user;
315 output pass_thru_user_delay;
316 output pass_thru_reset;
317
318 reg [7:0] addr;
319 reg wrstb;
320 reg rdstb;
321 reg sdoenb;
322 reg [2:0] state;
323 reg [2:0] count;
324 reg writemode;
325 reg readmode;
326 reg [2:0] fixed;
327 wire [7:0] odata;
328 reg [6:0] predata;
329 wire [7:0] oaddr;
330 reg [7:0] ldata;
331 reg pass_thru_mgmt;
332 reg pass_thru_mgmt_delay;
333 reg pre_pass_thru_mgmt;
334 reg pass_thru_user;
335 reg pass_thru_user_delay;
336 reg pre_pass_thru_user;
337 wire csb_reset;
338
339 assign odata = {predata, SDI};
340 assign oaddr = (state == `ADDRESS) ? {addr[6:0], SDI} : addr;
341 assign SDO = ldata[7];
342 assign csb_reset = CSB | reset;
343 assign pass_thru_reset = pass_thru_mgmt_delay | pre_pass_thru_mgmt;
344
345 // Readback data is captured on the falling edge of SCK so that
346 // it is guaranteed valid at the next rising edge.
347 always @(negedge SCK or posedge csb_reset) begin
348 if (csb_reset == 1'b1) begin
349 wrstb <= 1'b0;
350 ldata <= 8'b00000000;
351 sdoenb <= 1'b1;
352 end else begin
353
354 // After CSB low, 1st SCK starts command
355
356 if (state == `DATA) begin
357 if (readmode == 1'b1) begin
358 sdoenb <= 1'b0;
359 if (count == 3'b000) begin
360 ldata <= idata;
361 end else begin
362 ldata <= {ldata[6:0], 1'b0}; // Shift out
363 end
364 end else begin
365 sdoenb <= 1'b1;
366 end
367
368 // Apply write strobe on SCK negative edge on the next-to-last
369 // data bit so that it updates data on the rising edge of SCK
370 // on the last data bit.
371
372 if (count == 3'b111) begin
373 if (writemode == 1'b1) begin
374 wrstb <= 1'b1;
375 end
376 end else begin
377 wrstb <= 1'b0;
378 end
379 end else if (state == `MGMTPASS || state == `USERPASS) begin
380 wrstb <= 1'b0;
381 sdoenb <= 1'b0;
382 end else begin
383 wrstb <= 1'b0;
384 sdoenb <= 1'b1;
385 end // ! state `DATA
386 end // ! csb_reset
387 end // always @ ~SCK
388
389 always @(posedge SCK or posedge csb_reset) begin
390 if (csb_reset == 1'b1) begin
391 // Default state on reset
392 addr <= 8'h00;
393 rdstb <= 1'b0;
394 predata <= 7'b0000000;
395 state <= `COMMAND;
396 count <= 3'b000;
397 readmode <= 1'b0;
398 writemode <= 1'b0;
399 fixed <= 3'b000;
400 pass_thru_mgmt <= 1'b0;
401 pass_thru_mgmt_delay <= 1'b0;
402 pre_pass_thru_mgmt <= 1'b0;
403 pass_thru_user = 1'b0;
404 pass_thru_user_delay <= 1'b0;
405 pre_pass_thru_user <= 1'b0;
406 end else begin
407 // After csb_reset low, 1st SCK starts command
408 if (state == `COMMAND) begin
409 rdstb <= 1'b0;
410 count <= count + 1;
411 if (count == 3'b000) begin
412 writemode <= SDI;
413 end else if (count == 3'b001) begin
414 readmode <= SDI;
415 end else if (count < 3'b101) begin
416 fixed <= {fixed[1:0], SDI};
417 end else if (count < 3'b110) begin
418 pass_thru_mgmt_delay <= pre_pass_thru_mgmt;
419 pass_thru_user_delay <= pre_pass_thru_user;
420 end else if (count == 3'b111) begin
421 if (pre_pass_thru_mgmt == 1'b1) begin
422 state <= `MGMTPASS;
423 pre_pass_thru_mgmt <= 1'b0;
424 end else if (pre_pass_thru_user == 1'b1) begin
425 state <= `USERPASS;
426 pre_pass_thru_user <= 1'b0;
427 end else begin
428 state <= `ADDRESS;
429 end
430 end
431 end else if (state == `ADDRESS) begin
432 count <= count + 1;
433 addr <= {addr[6:0], SDI};
434 if (count == 3'b111) begin
435 if (readmode == 1'b1) begin
436 rdstb <= 1'b1;
437 end
438 state <= `DATA;
439 end else begin
440 rdstb <= 1'b0;
441 end
442 end else if (state == `DATA) begin
443 predata <= {predata[6:0], SDI};
444 count <= count + 1;
445 if (count == 3'b111) begin
446 if (fixed == 3'b001) begin
447 state <= `COMMAND;
448 end else if (fixed != 3'b000) begin
449 fixed <= fixed - 1;
450 addr <= addr + 1; // Auto increment address (fixed)
451 end else begin
452 addr <= addr + 1; // Auto increment address (streaming)
453 end
454 end else begin
455 rdstb <= 1'b0;
456 end
457 end // ! state `DATA
458 end // ! csb_reset
459 end // always @ SCK
460
461endmodule // housekeeping_spi_slave