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

Subversion Repositories simple_spi

[/] [simple_spi/] [trunk/] [rtl/] [verilog/] [simple_spi_top.v] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 rherveille
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  OpenCores                    MC68HC11E based SPI interface ////
4
////                                                             ////
5
////  Author: Richard Herveille                                  ////
6
////          richard@asics.ws                                   ////
7
////          www.asics.ws                                       ////
8
////                                                             ////
9
/////////////////////////////////////////////////////////////////////
10
////                                                             ////
11
//// Copyright (C) 2002 Richard Herveille                        ////
12
////                    richard@asics.ws                         ////
13
////                                                             ////
14
//// This source file may be used and distributed without        ////
15
//// restriction provided that this copyright statement is not   ////
16
//// removed from the file and that any derivative work contains ////
17
//// the original copyright notice and the associated disclaimer.////
18
////                                                             ////
19
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
20
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
21
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
22
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
23
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
24
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
25
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
26
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
27
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
28
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
29
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
30
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
31
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
32
////                                                             ////
33
/////////////////////////////////////////////////////////////////////
34
 
35
//  CVS Log
36
//
37 6 rherveille
//  $Id: simple_spi_top.v,v 1.3 2003-01-09 16:47:59 rherveille Exp $
38 2 rherveille
//
39 6 rherveille
//  $Date: 2003-01-09 16:47:59 $
40
//  $Revision: 1.3 $
41 2 rherveille
//  $Author: rherveille $
42
//  $Locker:  $
43
//  $State: Exp $
44
//
45
// Change History:
46
//               $Log: not supported by cvs2svn $
47 6 rherveille
//               Revision 1.2  2003/01/07 13:29:52  rherveille
48
//               Changed SPR bits coding.
49
//
50 5 rherveille
//               Revision 1.1.1.1  2002/12/22 16:07:15  rherveille
51
//               Initial release
52 2 rherveille
//
53 5 rherveille
//
54 2 rherveille
 
55
 
56
 
57
//
58
// Motorola MC68HC11E based SPI interface
59
//
60
// Currently only MASTER mode is supported
61
//
62
 
63
// synopsys translate_off
64
`include "timescale.v"
65
// synopsys translate_on
66
 
67
module simple_spi_top(
68
  clk_i, rst_i, cyc_i, stb_i, adr_i, we_i, dat_i, dat_o, ack_o,
69
  inta_o,
70
  sck_o, mosi_o, miso_i
71
);
72
 
73
  //
74
  // Inputs & outputs
75
  //
76
 
77
  // 8bit WISHBONE bus slave interface
78
  input        clk_i;         // clock
79
  input        rst_i;         // reset (asynchronous active low)
80
  input        cyc_i;         // cycle
81
  input        stb_i;         // strobe
82
  input  [1:0] adr_i;         // address
83
  input        we_i;          // write enable
84
  input  [7:0] dat_i;         // data output
85
  output [7:0] dat_o;         // data input
86
  output       ack_o;         // normal bus termination
87
  output       inta_o;        // interrupt output
88
 
89
  // SPI port
90
  output       sck_o;         // serial clock output
91
  output       mosi_o;        // MasterOut SlaveIN
92
  input        miso_i;        // MasterIn SlaveOut
93
 
94
  //
95
  // Module body
96
  //
97
  reg  [7:0] spcr;       // Serial Peripheral Control Register ('HC11 naming)
98
  wire [7:0] spsr;       // Serial Peripheral Status register ('HC11 naming)
99
  reg  [7:0] sper;       // Serial Peripheral Extension register
100
  reg  [7:0] treg;       // Transfer register
101
 
102
  // fifo signals
103
  wire [7:0] rfdout;
104
  reg        wfre, rfwe;
105
  wire       rfre, rffull, rfempty;
106
  wire [7:0] wfdin, wfdout;
107
  wire       wfwe, wffull, wfempty;
108
 
109
  // misc signals
110
  wire tirq;     // transfer interrupt (selected number of transfers done)
111
  wire wfov;     // write fifo overrun (writing while fifo full)
112
  reg  state;    // statemachine state
113
  reg  ena_mosi; // mosi_o clock-enable
114
  reg [2:0] bcnt;
115
 
116
  //
117
  // Wishbone interface
118
  wire wb_acc = cyc_i & stb_i;       // WISHBONE access
119
  wire wb_wr  = wb_acc & we_i;       // WISHBONE write access
120
 
121
  // dat_i
122
  always @(posedge clk_i or negedge rst_i)
123
    if (~rst_i)
124
      begin
125
          spcr <= #1 8'h10;  // set master bit
126
          sper <= #1 8'h00;
127
      end
128
    else if (wb_wr)
129
      begin
130
        if (adr_i == 2'b00)
131
          spcr <= #1 dat_i | 8'h10; // always set master bit
132
 
133
        if (adr_i == 2'b11)
134
          sper <= #1 dat_i;
135
      end
136
 
137
  // write fifo
138
  assign wfwe = wb_acc & (adr_i == 2'b10) & ack_o &  we_i;
139
  assign wfov = wfwe & wffull;
140
 
141
  // dat_o
142
  reg [7:0] dat_o;
143
  always @(posedge clk_i)
144
    case(adr_i) // synopsys full_case parallel_case
145
      2'b00: dat_o <= #1 spcr;
146
      2'b01: dat_o <= #1 spsr;
147
      2'b10: dat_o <= #1 rfdout;
148
      2'b11: dat_o <= #1 sper;
149
    endcase
150
 
151
  // read fifo
152
  assign rfre = wb_acc & (adr_i == 2'b10) & ack_o & ~we_i;
153
 
154
  // ack_o
155
  reg ack_o;
156
  always @(posedge clk_i or negedge rst_i)
157
    if (~rst_i)
158
      ack_o <= #1 1'b0;
159
    else
160
      ack_o <= #1 wb_acc & !ack_o;
161
 
162
  // decode Serial Peripheral Control Register
163
  wire       spie = spcr[7];   // Interrupt enable bit
164
  wire       spe  = spcr[6];   // System Enable bit
165
  wire       dwom = spcr[5];   // Port D Wired-OR Mode Bit
166
  wire       mstr = spcr[4];   // Master Mode Select Bit
167
  wire       cpol = spcr[3];   // Clock Polarity Bit
168
  wire       cpha = spcr[2];   // Clock Phase Bit
169
  wire [1:0] spr  = spcr[1:0]; // Clock Rate Select Bits
170
 
171
  // decode Serial Peripheral Extension Register
172
  wire [1:0] icnt = sper[7:6]; // interrupt on transfer count
173
  wire [1:0] spre = sper[1:0]; // extended clock rate select
174
 
175
  wire [3:0] espr = {spre, spr};
176
 
177
  // generate status register
178
  wire wr_spsr = wb_wr & (adr_i == 2'b01);
179
 
180
  reg spif;
181
  always @(posedge clk_i)
182
    if (~spe)
183
      spif <= #1 1'b0;
184
    else
185
      spif <= #1 (tirq | spif) & ~(wr_spsr & dat_i[7]);
186
 
187
  reg wcol;
188
  always @(posedge clk_i)
189
    if (~spe)
190
      wcol <= #1 1'b0;
191
    else
192
      wcol <= #1 (wfov | wcol) & ~(wr_spsr & dat_i[6]);
193
 
194
  assign spsr[7]   = spif;
195
  assign spsr[6]   = wcol;
196
  assign spsr[5:4] = 2'b00;
197
  assign spsr[3]   = wffull;
198
  assign spsr[2]   = wfempty;
199
  assign spsr[1]   = rffull;
200
  assign spsr[0]   = rfempty;
201
 
202
 
203
  // generate IRQ output (inta_o)
204
  reg inta_o;
205
  always @(posedge clk_i)
206
    inta_o <= #1 spif & spie;
207
 
208
  //
209
  // hookup read/write buffer fifo
210
  fifo4 #(8)
211
  rfifo(
212
        .clk   ( clk_i   ),
213
        .rst   ( rst_i   ),
214
        .clr   ( ~spe    ),
215
        .din   ( treg    ),
216
        .we    ( rfwe    ),
217
        .dout  ( rfdout  ),
218
        .re    ( rfre    ),
219
        .full  ( rffull  ),
220
        .empty ( rfempty )
221
  ),
222
  wfifo(
223
        .clk   ( clk_i   ),
224
        .rst   ( rst_i   ),
225
        .clr   ( ~spe    ),
226
        .din   ( dat_i   ),
227
        .we    ( wfwe    ),
228
        .dout  ( wfdout  ),
229
        .re    ( wfre    ),
230
        .full  ( wffull  ),
231
        .empty ( wfempty )
232
  );
233
 
234
  //
235
  // generate clk divider
236 6 rherveille
  reg [10:0] clkcnt;
237 2 rherveille
  always @(posedge clk_i)
238
    if(~spe)
239 6 rherveille
        clkcnt <= #1 11'h0;
240 2 rherveille
    else if (|clkcnt & state)
241 6 rherveille
        clkcnt <= #1 clkcnt - 11'h1;
242 2 rherveille
    else
243
        case (espr) // synopsys full_case parallel_case
244 6 rherveille
          4'b0000: clkcnt <= #1 11'h0;   // 2   -- original M68HC11 coding
245
          4'b0001: clkcnt <= #1 11'h1;   // 4   -- original M68HC11 coding
246
          4'b0010: clkcnt <= #1 11'h7;   // 16  -- original M68HC11 coding
247
          4'b0011: clkcnt <= #1 11'hf;   // 32  -- original M68HC11 coding
248
          4'b0100: clkcnt <= #1 11'h3;   // 8
249
          4'b0101: clkcnt <= #1 11'h1f;  // 64
250
          4'b0110: clkcnt <= #1 11'h3f;  // 128
251
          4'b0111: clkcnt <= #1 11'h7f;  // 256
252
          4'b1000: clkcnt <= #1 11'hff;  // 512
253
          4'b1001: clkcnt <= #1 11'h1ff; // 1024
254
          4'b1010: clkcnt <= #1 11'h3ff; // 2048
255
          4'b1011: clkcnt <= #1 11'h7ff; // 4096
256 2 rherveille
        endcase
257
 
258
  // generate internal SCK
259
  reg sck;
260
  always @(posedge clk_i)
261
    if (~spe)
262
      sck <= #1 1'b0;
263
    else
264
      sck <= #1 sck ^ ~(|clkcnt);
265
 
266
  // generate SCK_O
267
  reg sck_o;
268
  always @(posedge clk_i)
269
    sck_o <= #1 sck ^ cpol;
270
 
271
  // generate clock-enable signal
272
  reg ena;
273
  always @(posedge clk_i)
274
    ena <= #1 ~(|clkcnt) & (~sck ^ cpha);
275
 
276
  // generate ena_mosi (clock data in)
277
  reg hold_ena;
278
  always @(posedge clk_i or negedge rst_i)
279
    if(~rst_i)
280
      hold_ena <= #1 1'b0;
281
    else
282
      hold_ena <= state & (ena | hold_ena) & ~ena_mosi;
283
 
284
  always @(posedge clk_i)
285
    ena_mosi <= #1 ~(|clkcnt) & hold_ena;
286
 
287
  // store miso
288
  reg smiso;
289
  always @(posedge clk_i)
290
    if(ena)
291
      smiso <= #1 miso_i;
292
 
293
  // transfer statemachine
294
  //reg [2:0] bcnt; // bit count
295
  always @(posedge clk_i)
296
    if (~spe)
297
      begin
298
          state <= #1 1'b0; // idle
299
          bcnt  <= #1 3'h0;
300
          treg  <= #1 8'h00;
301
          wfre  <= #1 1'b0;
302
          rfwe  <= #1 1'b0;
303
      end
304
    else
305
      begin
306
         wfre <= #1 1'b0;
307
         rfwe <= #1 1'b0;
308
 
309
         if(~state) // idle
310
         begin
311
             bcnt <= #1 3'h7;   // set transfer counter
312
             treg <= #1 wfdout; // load transfer register
313
             if (~wfempty)
314
             begin
315
                 state <= #1 1'b1; // goto transfer state
316
                 wfre  <= #1 1'b1;
317
             end
318
         end
319
 
320
         if(state & ena_mosi)
321
         begin
322
             treg <= #1 {treg[6:0], smiso}; //miso_i};
323
             bcnt <= #1 bcnt -3'h1;
324
             if (~|bcnt)
325
             begin
326
                 state <= #1 1'b0; // goto idle state
327
                 rfwe  <= #1 1'b1;
328
             end
329
         end
330
      end
331
 
332
  assign mosi_o = treg[7];
333
 
334
 
335
  // count number of transfers (for interrupt generation)
336
  reg [1:0] tcnt; // transfer count
337
  always @(posedge clk_i)
338
    if (~spe)
339
      tcnt <= #1 icnt;
340
    else if (rfwe) // rfwe gets asserted when all bits have been transfered
341
      if (|tcnt)
342
        tcnt <= #1 tcnt - 2'h1;
343
      else
344
        tcnt <= #1 icnt;
345
 
346
  assign tirq = ~|tcnt & rfwe;
347
 
348
endmodule
349
 

powered by: WebSVN 2.1.0

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