OpenCores
URL https://opencores.org/ocsvn/spicxif/spicxif/trunk

Subversion Repositories spicxif

[/] [spicxif/] [trunk/] [RTL/] [SPIxIF.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 MichaelA
////////////////////////////////////////////////////////////////////////////////
2
//
3
//  Copyright 2008-2013 by Michael A. Morris, dba M. A. Morris & Associates
4
//
5
//  All rights reserved. The source code contained herein is publicly released
6
//  under the terms and conditions of the GNU Lesser Public License. No part of
7
//  this source code may be reproduced or transmitted in any form or by any
8
//  means, electronic or mechanical, including photocopying, recording, or any
9
//  information storage and retrieval system in violation of the license under
10
//  which the source code is released.
11
//
12
//  The source code contained herein is free; it may be redistributed and/or
13
//  modified in accordance with the terms of the GNU Lesser General Public
14
//  License as published by the Free Software Foundation; either version 2.1 of
15
//  the GNU Lesser General Public License, or any later version.
16
//
17
//  The source code contained herein is freely released WITHOUT ANY WARRANTY;
18
//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19
//  PARTICULAR PURPOSE. (Refer to the GNU Lesser General Public License for
20
//  more details.)
21
//
22
//  A copy of the GNU Lesser General Public License should have been received
23
//  along with the source code contained herein; if not, a copy can be obtained
24
//  by writing to:
25
//
26
//  Free Software Foundation, Inc.
27
//  51 Franklin Street, Fifth Floor
28
//  Boston, MA  02110-1301 USA
29
//
30
//  Further, no use of this source code is permitted in any form or means
31
//  without inclusion of this banner prominently in any derived works.
32
//
33
//  Michael A. Morris
34
//  Huntsville, AL
35
//
36
////////////////////////////////////////////////////////////////////////////////
37
 
38
`timescale 1ns / 1ps
39
 
40
////////////////////////////////////////////////////////////////////////////////
41
// Company:         M. A. Morris & Associates 
42
// Engineer:        Michael A. Morris
43
// 
44
// Create Date:     20:31:58 03/17/2008 
45
// Design Name:     Serial Peripheral Interconnect (SPI) Master Interface
46
// Module Name:     SPIxIF.v 
47
// Project Name:    VerilogComponentsLib\SPI and SSP Components\SPI Master
48
// Target Devices:  FPGA
49
// Tool versions:   ISE 10.1i SP3 
50
//
51
// Description:
52
//
53
//  This module implements a full-duplex (Master) SPI interface. It is a major
54
//  revision of the previous implementation which basically implemented the SPI
55
//  operating modes within a Synchronous Serial Peripheral (SSP) as used in NXP
56
//  ARM LPC21xx microcontrollers. In an NXP SSP, an SPI-like peripheral is used
57
//  that has a programmable length shift register which performs serial I/O
58
//  data transfers in a single cycle: Slave Select (SS) is asserted and de-
59
//  asserted for each data transfer cycle. The only SPI-like feature of the pre-
60
//  vious implementation was the ability to program the clock idle state and the
61
//  data sampling edge, i.e. the SPI operating modes. Because a transfer cycle
62
//  always deasserted SS, the original implementation would require substan-
63
//  tial modification in order to be useful with standard SPI-compatible devices
64
//  such as Serial EEPROMs, serial FRAMs/MRAMs, ADCs/DACs, UARTs, I/O expanders,
65
//  etc.
66
//  
67
//  This module will implement an SPI Master interface that avoids the limita-
68
//  tions of the previous implementation. It will use a fixed 8-bit interface,
69
//  but it will support variable length cycles. To operate in this manner, the
70
//  basic control interface will support an interface that can be easily attach-
71
//  ed to FIFOs. (The transmit FIFO will use a 9-bit interface, and the receive
72
//  FIFO will use an 8-bit interface.) An SPI data transfer cycle will start
73
//  when the transmit FIFO EF indicates that there is data to transmit, and the
74
//  SPI transfer cycle will terminate when the last bit is shifted out and the
75
//  transmit FIFO EF indicates that it is empty.
76
// 
77
//  The 9th bit of the transmit data will be used to enable the writing of the
78
//  receive data into the receive FIFO. If the bit is not set, the data shifted
79
//  in during an 8-bit SPI shift cycle is not captured into the receive FIFO.
80
//  If the 9th bit is set, then the data shifted into the SPI shift register is
81
//  captured into the receive FIFO. The 9th bit is expected to be part of the
82
//  transmit FIFO, so it can be set or cleared for each 8-bit SPI transfer cy-
83
//  cle. (Note: the 9th bit can be implemented separate from the transmit FIFO,
84
//  but it would need to be merged into the transmit data bus by the external
85
//  logic.)
86
//
87
//  The explicit read capability provided by the 9th bit is useful when working
88
//  with SPI devices such as SPI memory devices which do not return any data
89
//  until a command code and an address have been written. Generally, these
90
//  devices require several command codes and address bytes to be sent to it
91
//  before it enables its serial output signal driver and returns the requested
92
//  data. Therefore, for these devices, the 9th bit is cleared when the command
93
//  and address bytes are being sent, and the 9th bit set while dummy data is
94
//  written to and the data received from the device is written into the receive
95
//  FIFO.
96
//
97
//  On the other hand, there are many devices where the data on MISO is consi-
98
//  dered valid from the onset of a transfer cycle. Devices such as ADCs provide
99
//  data on MISO that is valid while the conversion command for the next sample
100
//  is being simultaneously shifted out to the ADC on MOSI. For these devices,
101
//  the 9th bit is set in the transmit FIFO for each output byte. This causes
102
//  each received byte to be written to the receive FIFO.
103
//
104
//  The SPI interface operates in four modes: Mode 0, 1, 2, and 3. Generally,
105
//  the mode is selected by two control signals, CPOL and CPHA. CPHA determines
106
//  the idle state of the SPI clock signal, SCK. The interface shifts data at
107
//  the beginning of each bit cell. The four operating SPI modes are tabulated
108
//  in the following table:
109
//
110
//  Mode    CPOL    CPHA    :   SCK Idle Level    Sample Edge
111
//    0       0       0     :         0             Rising
112
//    1       0       1     :         1             Falling
113
//    2       1       0     :         0             Falling
114
//    3       1       1     :         1             Rising
115
//
116
//  Examining the table, the sampling edge is set to rising when CPOL and CPHA
117
//  are the same logic level, and it is set to falling when CPOL and CPHA are
118
//  complementary logic levels. In other words, the rising edge of SCK occurs in
119
//  the middle of the bit cell when (CPOL XNOR CPHA) == 1, and the falling edge
120
//  occurs in the middle of the bit cell when (CPOL XOR CPHA) == 1.
121
//
122
//  Two internal signals derived from Mode[1:0] determine the idle state of
123
//  SCK, SCK_Lvl, and the polarity of SCK used for data sampling, SCK_Inv. A
124
//  change-of-state (COS) detector is used to dynamically detect changes in the
125
//  value of SCK_Lvl, and to load the SCK register with the appropriate value
126
//  when the SPI interface idle, i.e. SS == 0. SCK_Lvl is taken from Mode[0],
127
//  and SCK_Inv is the XOR of Mode[1] and Mode[0], as indicated in the table
128
//  above.
129
//
130
//  The implementation shifts at one half of the CE frequency. The shift direc-
131
//  tion is programmable, but MSB first is the default.
132
//
133
//  The module contains the SCK generator. A three bit rate select input deter-
134
//  mines the rate of the SPI clock signal. A 50% duty cycle clock is produced,
135
//  and two separate clock enables are generated internally for loading and
136
//  shifting (propagating) the transmit data, and for shifting and writing the
137
//  receive data. The basic frequency is set by the equation:
138
//  
139
//      F(SCK) = Clk / (2**(Rate + 1))
140
//
141
//  If rate is set to 0, then the frequency of SCK is one half that of the
142
//  module's input clock frequency. With Rate set to 7, the SCK frequecy is
143
//  Clk/256.
144
//
145
//  The output shift enable always asserts at the trailing edge of the bit cell,
146
//  and the input shift enable always asserts in the middle of the bit cell. 
147
//  These shift enables are independent of the sampling and propagating edges
148
//  of SCK. The leading edge of the initial output is generated by the output
149
//  shift register load signal, which is itself generated by a rising edge
150
//  detector monitoring the DAV signal while slave select is not asserted. Once
151
//  SS is asserted, the output shift register is synchronously loaded on the TC
152
//  of the bit counter coincident with output shift register enable signal,
153
//  CE_OSR. This event also extends SS and reloads the receive enable signal,
154
//  RdEn. (RdEn was discussed above, and is determined by the 9th of the trans-
155
//  mit data.) If there is no more data to transmit, SS and RdEn are both de-
156
//  asserted.
157
//
158
//  All of the module control signals are resampled while SS is not asserted.
159
//  The control signals are held for the duration of a transfer cycle, which is
160
//  determined by the number of bytes loaded into the external transmit FIFO.
161
//  To limit the logic complexity, the module does not make prevent the control
162
//  signals from being changed as the initial transmit data is written. It is
163
//  necessary for the client of the module to ensure that the control signals
164
//  signals are stable at least one clock cycle before transmit data is availa-
165
//  ble.
166
//
167
//  With that limitation in mind, the control signals can be changed at any time
168
//  during a transfer cycle. They will be processed by the module with a one cy-
169
//  cle delay when SS is not asserted. In this manner, the client logic can dy-
170
//  namically change the shift direction, SCK operating mode, and SCK operating
171
//  frequency. This allows the module to be used in situations where the SPI
172
//  slave devices change modes, rates, and shift directions. For example, a sin-
173
//  gle SPI interface can be used to support both SPI memory devices (mode 0/3)
174
//  and SPI ADCs (mode 2) devices.
175
//
176
// Dependencies: none
177
//
178
// Revision History:
179
//
180
//  0.01    08C17   MAM     File Created
181
//
182
//  0.02    08C18   MAM     Modified to incorporate SCK_Lvl and a COS detector
183
//                          on SCK_Lvl to allow the Idle State SCK state to be
184
//                          dynamically changed.
185
//
186
//  0.03    08E09   MAM     Changed comment to reflect that this module is an 
187
//                          SPI Master Interface.
188
//
189
//  1.00    12I07   MAM     Modified to bring into compliance with Verilog 2001.
190
//                          Modified the interface to use standard control sig-
191
//                          nals {CPOL, CPHA} and to map the SCK_Lvl and SCK_Inv
192
//                          signals to the standard SPI modes. To do this, the
193
//                          standard mode control signals, {CPOL, CPHA}, are run
194
//                          through a mapping function at the beginning of the
195
//                          module.
196
//
197
//  1.10    12I09   MAM     Restored use of separate transmit and receive shift
198
//                          registers. Single, combined shift register can't be
199
//                          used because input data is shifted on the opposite
200
//                          edge from that used to shift the output data.
201
//
202
//  1.20    12I10   MAM     Converted FRE and FWE output signals to FFs. FRE now
203
//                          pulsed one cycle after the OSR is loaded. FWE now
204
//                          pulsed one cycle after the last bit is loaded into
205
//                          the ISR. Converted CE_Cntr from up counter to a down
206
//                          counter. CE remains a combinatorial signal, but the
207
//                          CE counter is loaded from a ROM when CE asserts on
208
//                          basis of the rate captured before SS asserts. CE now
209
//                          asserts on a fixed value, 0, and the counter is re-
210
//                          loaded from a ROM. This contrasts with up-counter
211
//                          implementation which reloaded a fixed value, 0, and
212
//                          terminated on a variable value. The variable decode
213
//                          of the counter for CE apparently caused an issue in
214
//                          simulation that the new down counter resolves.
215
//
216
//  1.30    13G06   MAM     Removed code previously commented out. Corrected the
217
//                          SCK equation. A Rst_SCK was being generated at the
218
//                          end of every 8 bits. This introduced a discontinuity
219
//                          in SCK which does not allow frames greater than 8
220
//                          bits in length to be transmitted. With the removal
221
//                          the incorrect conditional logic in Rst_SCK, the SSP
222
//                          Slave and UART modules operate in either SPI Mode 0
223
//                          or Mode 3.  
224
//
225
// Additional Comments:
226
//
227
//  The module control signals, LSB, Mode, and Rate, must be set at least one
228
//  clock cycle before DAV is asserted. Changing these control signals at the
229
//  same time that DAV is asserted will result in incorrect operation. 
230
//
231
////////////////////////////////////////////////////////////////////////////////
232
 
233
module SPIxIF (
234
    input   Rst,                // System Reset (synchronous)
235
    input   Clk,                // System Clk
236
//
237
    input   LSB,                // SPI LSB First Shift Direction
238
    input   [1:0] Mode,         // SPI Operating Mode
239
    input   [2:0] Rate,         // SPI Shift Rate Select: SCK = Clk/2**(Rate+1)
240
//
241
    input   DAV,                // SPI Transmit Data Available
242
    output  reg FRE,            // SPI Transmit FIFO Read Enable
243
    input   [8:0] TD,           // SPI Transmit Data 
244
//
245
    output  reg FWE,            // SPI Receive FIFO Write Enable
246
    output  [7:0] RD,           // SPI Receive Data
247
//
248
    output  reg SS,             // SPI Slave Select
249
    output  reg SCK,            // SPI Shift Clock
250
    output  MOSI,               // SPI Master Out, Slave In: Serial Data Output
251
    input   MISO                // SPI Master In, Slave Out: Serial Data In
252
);
253
 
254
////////////////////////////////////////////////////////////////////////////////
255
//
256
//  Module Parameters
257
// 
258
 
259
////////////////////////////////////////////////////////////////////////////////    
260
//
261
//  Module Declarations
262
//
263
 
264
reg     Dir;                                // Shift Register Shift Direction
265
 
266
reg     SCK_Lvl, SCK_Inv, COS_SCK_Lvl;      // SCK level and edge control
267
 
268
reg     [2:0] rRate;                        // SPI SCK Rate Select Register
269
reg     [6:0] CE_Cntr;                      // SPI CE Counter (2x SCK)
270
wire    CE;                                 // SPI Clock Enable (TC CE_Cntr)
271
 
272
wire    CE_SCK, Rst_SCK;                    // SCK generator control signals
273
 
274
reg     Ld;                                 // SPI Transfer Cycle Start Pulse
275
 
276
wire    CE_OSR, CE_ISR;                     // SPI Shift Register Clock Enables
277
reg     [7:0] OSR, ISR;                     // SPI Output/Input Shift Registers
278
reg     RdEn;                               // SPI Read Enable (9th bit in TD)
279
 
280
reg     [2:0] BitCnt;                       // SPI Transfer Cycle Length Cntr
281
wire    TC_BitCnt;                          // SPI Bit Counter Terminal Count
282
 
283
////////////////////////////////////////////////////////////////////////////////
284
//
285
//  Implementation
286
//
287
 
288
//  Capture the shift direction and hold until end of transfer cycle
289
 
290
always @(posedge Clk)
291
begin
292
    if(Rst)
293
        Dir <= #1 0;            // Default to MSB first
294
    else if(~SS)
295
        Dir <= #1 LSB;          // Set shift direction for transfer cycle
296
end
297
 
298
//  Assign SCK idle level and invert control signals based on Mode
299
 
300
always @(posedge Clk)
301
begin
302
    if(Rst) begin
303
        SCK_Inv <= #1 0;
304
        SCK_Lvl <= #1 0;
305
    end else if(~SS) begin
306
        SCK_Inv <= #1 ^Mode;    // Invert SCK if Mode == 1 or Mode == 2
307
        SCK_Lvl <= #1 Mode[0];  // Set SCK idle level from LSB of Mode
308
    end
309
end
310
 
311
//  Generate change of state pulse when SPI clock idle level changes
312
//      while Slave Select not asserted
313
 
314
always @(posedge Clk)
315
begin
316
    if(Rst)
317
        COS_SCK_Lvl <= #1 0;
318
    else
319
        COS_SCK_Lvl <= #1 ((~SS) ? (SCK_Lvl ^ Mode[0]) : 0);
320
end
321
 
322
//  Capture SCK rate and hold until the transfer cycle is complete
323
 
324
always @(posedge Clk)
325
begin
326
    if(Rst)
327
        rRate <= #1 ~0;             // Default to slowest rate
328
    else if(~SS)
329
        rRate <= #1 Rate;
330
end
331
 
332
//
333
//  SPI Transfer Cycle Load Pulse Generator
334
//
335
 
336
always @(posedge Clk)
337
begin
338
    if(Rst)
339
        Ld <= #1 0;
340
    else if(~SS)
341
        Ld <= #1 DAV & ~Ld;
342
    else if(Ld)
343
        Ld <= #1 0;
344
end
345
 
346
//
347
//  Serial SPI Clock Generator
348
//
349
 
350
always @(posedge Clk)
351
begin
352
    if(Rst)
353
        CE_Cntr <= #1 ~0;
354
    else if(CE)
355
        case(rRate)
356
            3'b000  : CE_Cntr <= #1 0;
357
            3'b001  : CE_Cntr <= #1 1;
358
            3'b010  : CE_Cntr <= #1 3;
359
            3'b011  : CE_Cntr <= #1 7;
360
            3'b100  : CE_Cntr <= #1 15;
361
            3'b101  : CE_Cntr <= #1 31;
362
            3'b110  : CE_Cntr <= #1 63;
363
            3'b111  : CE_Cntr <= #1 127;
364
        endcase
365
    else if(SS)
366
        CE_Cntr <= #1 (CE_Cntr - 1);
367
end
368
 
369
assign CE = (Ld | (~|CE_Cntr));
370
 
371
assign CE_SCK  = CE & SS; // Clock starts with Slave Select Strobe
372
assign Rst_SCK = Rst | Ld | (COS_SCK_Lvl & ~SS) | (TC_BitCnt & CE_OSR & ~DAV);
373
 
374
always @(posedge Clk)
375
begin
376
    if(Rst_SCK)
377
        #1 SCK <= (Ld ? SCK_Inv : SCK_Lvl);
378
    else if(CE_SCK)
379
        #1 SCK <= ~SCK;
380
end
381
 
382
//
383
//  SPI Output Shift Register
384
//
385
 
386
assign CE_OSR = CE_SCK & (SCK_Inv ^ SCK);
387
assign Ld_OSR = Ld | (TC_BitCnt & CE_OSR);
388
 
389
always @(posedge Clk)
390
begin
391
    if(Rst)
392
        OSR <= #1 0;
393
    else if(Ld_OSR)
394
        OSR <= #1 TD;
395
    else if(CE_OSR)
396
        OSR <= #1 ((Dir) ? {SCK_Lvl, OSR[7:1]} : {OSR[6:0], SCK_Lvl});
397
end
398
 
399
assign MOSI = SS & ((Dir) ? OSR[0] : OSR[7]);
400
 
401
//
402
//  SPI Input Shift Register
403
//
404
 
405
assign CE_ISR = CE_SCK & (SCK_Inv ^ ~SCK);
406
 
407
always @(posedge Clk)
408
begin
409
    if(Rst)
410
        ISR <= #1 0;
411
    else if(Ld)
412
        ISR <= #1 0;
413
    else if(CE_ISR)
414
        ISR <= #1 ((Dir) ? {MISO, ISR[7:1]} : {ISR[6:0], MISO});
415
end
416
 
417
//
418
//  SPI SR Bit Counter
419
//
420
 
421
assign CE_BitCnt  = CE_OSR & SS;
422
assign Rst_BitCnt = Rst | Ld | (TC_BitCnt & CE_OSR);
423
 
424
always @(posedge Clk)
425
begin
426
    if(Rst_BitCnt)
427
        BitCnt <= #1 7;
428
    else if(CE_BitCnt)
429
        BitCnt <= #1 (BitCnt - 1);
430
end
431
 
432
assign TC_BitCnt = ~|BitCnt;
433
 
434
//
435
//  SPI Slave Select Generator
436
//
437
 
438
always @(posedge Clk)
439
begin
440
    if(Rst)
441
        SS <= #1 0;
442
    else if(Ld_OSR)
443
        SS <= #1 DAV;
444
end
445
 
446
//
447
//  SPI MISO Read Enable Register
448
//
449
 
450
always @(posedge Clk)
451
begin
452
    if(Rst)
453
        RdEn <= #1 0;
454
    else if(Ld_OSR)
455
        RdEn <= #1 ((DAV) ? TD[8] : 0);
456
end
457
 
458
//
459
//  SPI Transmit FIFO Read Pulse Generator
460
//
461
 
462
always @(posedge Clk)
463
begin
464
    if(Rst)
465
        FRE <= #1 0;
466
    else
467
        FRE <= #1 (Ld | (DAV & (TC_BitCnt & CE_OSR)));
468
end
469
 
470
//
471
//  SPI Receive FIFO Write Pulse Generator
472
//
473
 
474
always @(posedge Clk)
475
begin
476
    if(Rst)
477
        FWE <= #1 0;
478
    else
479
        FWE <= #1 (RdEn & (TC_BitCnt & CE_ISR));
480
end
481
 
482
assign RD = ISR;
483
 
484
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.