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 10

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 8 rherveille
//  $Id: simple_spi_top.v,v 1.5 2004-02-28 15:59:50 rherveille Exp $
38 2 rherveille
//
39 8 rherveille
//  $Date: 2004-02-28 15:59:50 $
40
//  $Revision: 1.5 $
41 2 rherveille
//  $Author: rherveille $
42
//  $Locker:  $
43
//  $State: Exp $
44
//
45
// Change History:
46
//               $Log: not supported by cvs2svn $
47 8 rherveille
//               Revision 1.4  2003/08/01 11:41:54  rherveille
48
//               Fixed some timing bugs.
49
//
50 7 rherveille
//               Revision 1.3  2003/01/09 16:47:59  rherveille
51
//               Updated clkcnt size and decoding due to new SPR bit assignments.
52
//
53 6 rherveille
//               Revision 1.2  2003/01/07 13:29:52  rherveille
54
//               Changed SPR bits coding.
55
//
56 5 rherveille
//               Revision 1.1.1.1  2002/12/22 16:07:15  rherveille
57
//               Initial release
58 2 rherveille
//
59 5 rherveille
//
60 2 rherveille
 
61
 
62
 
63
//
64
// Motorola MC68HC11E based SPI interface
65
//
66
// Currently only MASTER mode is supported
67
//
68
 
69
// synopsys translate_off
70
`include "timescale.v"
71
// synopsys translate_on
72
 
73
module simple_spi_top(
74
  // 8bit WISHBONE bus slave interface
75 8 rherveille
  input  wire       clk_i,         // clock
76
  input  wire       rst_i,         // reset (asynchronous active low)
77
  input  wire       cyc_i,         // cycle
78
  input  wire       stb_i,         // strobe
79
  input  wire [1:0] adr_i,         // address
80
  input  wire       we_i,          // write enable
81
  input  wire [7:0] dat_i,         // data input
82
  output reg  [7:0] dat_o,         // data output
83
  output reg        ack_o,         // normal bus termination
84
  output reg        inta_o,        // interrupt output
85 2 rherveille
 
86
  // SPI port
87 8 rherveille
  output reg        sck_o,         // serial clock output
88
  output wire       mosi_o,        // MasterOut SlaveIN
89
  input  wire       miso_i         // MasterIn SlaveOut
90
);
91 2 rherveille
 
92
  //
93
  // Module body
94
  //
95
  reg  [7:0] spcr;       // Serial Peripheral Control Register ('HC11 naming)
96
  wire [7:0] spsr;       // Serial Peripheral Status register ('HC11 naming)
97
  reg  [7:0] sper;       // Serial Peripheral Extension register
98 7 rherveille
  reg  [7:0] treg, rreg; // Transmit/Receive register
99 2 rherveille
 
100
  // fifo signals
101
  wire [7:0] rfdout;
102
  reg        wfre, rfwe;
103
  wire       rfre, rffull, rfempty;
104 7 rherveille
  wire [7:0] wfdout;
105 2 rherveille
  wire       wfwe, wffull, wfempty;
106
 
107
  // misc signals
108 7 rherveille
  wire      tirq;     // transfer interrupt (selected number of transfers done)
109
  wire      wfov;     // write fifo overrun (writing while fifo full)
110
  reg [1:0] state;    // statemachine state
111 2 rherveille
  reg [2:0] bcnt;
112
 
113
  //
114
  // Wishbone interface
115
  wire wb_acc = cyc_i & stb_i;       // WISHBONE access
116
  wire wb_wr  = wb_acc & we_i;       // WISHBONE write access
117
 
118
  // dat_i
119
  always @(posedge clk_i or negedge rst_i)
120
    if (~rst_i)
121
      begin
122
          spcr <= #1 8'h10;  // set master bit
123
          sper <= #1 8'h00;
124
      end
125
    else if (wb_wr)
126
      begin
127
        if (adr_i == 2'b00)
128
          spcr <= #1 dat_i | 8'h10; // always set master bit
129
 
130
        if (adr_i == 2'b11)
131
          sper <= #1 dat_i;
132
      end
133
 
134
  // write fifo
135
  assign wfwe = wb_acc & (adr_i == 2'b10) & ack_o &  we_i;
136
  assign wfov = wfwe & wffull;
137
 
138
  // dat_o
139
  always @(posedge clk_i)
140
    case(adr_i) // synopsys full_case parallel_case
141
      2'b00: dat_o <= #1 spcr;
142
      2'b01: dat_o <= #1 spsr;
143
      2'b10: dat_o <= #1 rfdout;
144
      2'b11: dat_o <= #1 sper;
145
    endcase
146
 
147
  // read fifo
148
  assign rfre = wb_acc & (adr_i == 2'b10) & ack_o & ~we_i;
149
 
150
  // ack_o
151
  always @(posedge clk_i or negedge rst_i)
152
    if (~rst_i)
153
      ack_o <= #1 1'b0;
154
    else
155
      ack_o <= #1 wb_acc & !ack_o;
156
 
157
  // decode Serial Peripheral Control Register
158
  wire       spie = spcr[7];   // Interrupt enable bit
159
  wire       spe  = spcr[6];   // System Enable bit
160
  wire       dwom = spcr[5];   // Port D Wired-OR Mode Bit
161
  wire       mstr = spcr[4];   // Master Mode Select Bit
162
  wire       cpol = spcr[3];   // Clock Polarity Bit
163
  wire       cpha = spcr[2];   // Clock Phase Bit
164
  wire [1:0] spr  = spcr[1:0]; // Clock Rate Select Bits
165
 
166
  // decode Serial Peripheral Extension Register
167
  wire [1:0] icnt = sper[7:6]; // interrupt on transfer count
168
  wire [1:0] spre = sper[1:0]; // extended clock rate select
169
 
170
  wire [3:0] espr = {spre, spr};
171
 
172
  // generate status register
173
  wire wr_spsr = wb_wr & (adr_i == 2'b01);
174
 
175
  reg spif;
176
  always @(posedge clk_i)
177
    if (~spe)
178
      spif <= #1 1'b0;
179
    else
180
      spif <= #1 (tirq | spif) & ~(wr_spsr & dat_i[7]);
181
 
182
  reg wcol;
183
  always @(posedge clk_i)
184
    if (~spe)
185
      wcol <= #1 1'b0;
186
    else
187
      wcol <= #1 (wfov | wcol) & ~(wr_spsr & dat_i[6]);
188
 
189
  assign spsr[7]   = spif;
190
  assign spsr[6]   = wcol;
191
  assign spsr[5:4] = 2'b00;
192
  assign spsr[3]   = wffull;
193
  assign spsr[2]   = wfempty;
194
  assign spsr[1]   = rffull;
195
  assign spsr[0]   = rfempty;
196
 
197
 
198
  // generate IRQ output (inta_o)
199
  always @(posedge clk_i)
200
    inta_o <= #1 spif & spie;
201
 
202
  //
203
  // hookup read/write buffer fifo
204
  fifo4 #(8)
205
  rfifo(
206
        .clk   ( clk_i   ),
207
        .rst   ( rst_i   ),
208
        .clr   ( ~spe    ),
209
        .din   ( treg    ),
210
        .we    ( rfwe    ),
211
        .dout  ( rfdout  ),
212
        .re    ( rfre    ),
213
        .full  ( rffull  ),
214
        .empty ( rfempty )
215
  ),
216
  wfifo(
217
        .clk   ( clk_i   ),
218
        .rst   ( rst_i   ),
219
        .clr   ( ~spe    ),
220
        .din   ( dat_i   ),
221
        .we    ( wfwe    ),
222
        .dout  ( wfdout  ),
223
        .re    ( wfre    ),
224
        .full  ( wffull  ),
225
        .empty ( wfempty )
226
  );
227
 
228
  //
229
  // generate clk divider
230 8 rherveille
  reg [11:0] clkcnt;
231 2 rherveille
  always @(posedge clk_i)
232 7 rherveille
    if(spe & (|clkcnt & |state))
233
      clkcnt <= #1 clkcnt - 11'h1;
234 2 rherveille
    else
235 7 rherveille
      case (espr) // synopsys full_case parallel_case
236 8 rherveille
        4'b0000: clkcnt <= #1 12'h0;   // 2   -- original M68HC11 coding
237
        4'b0001: clkcnt <= #1 12'h1;   // 4   -- original M68HC11 coding
238
        4'b0010: clkcnt <= #1 12'h3;   // 16  -- original M68HC11 coding
239
        4'b0011: clkcnt <= #1 12'hf;   // 32  -- original M68HC11 coding
240
        4'b0100: clkcnt <= #1 12'h1f;  // 8
241
        4'b0101: clkcnt <= #1 12'h7;   // 64
242
        4'b0110: clkcnt <= #1 12'h3f;  // 128
243
        4'b0111: clkcnt <= #1 12'h7f;  // 256
244
        4'b1000: clkcnt <= #1 12'hff;  // 512
245
        4'b1001: clkcnt <= #1 12'h1ff; // 1024
246
        4'b1010: clkcnt <= #1 12'h3ff; // 2048
247
        4'b1011: clkcnt <= #1 12'h7ff; // 4096
248 7 rherveille
      endcase
249 2 rherveille
 
250 7 rherveille
  // generate clock enable signal
251
  wire ena = ~|clkcnt;
252 2 rherveille
 
253
  // transfer statemachine
254
  always @(posedge clk_i)
255
    if (~spe)
256
      begin
257 7 rherveille
          state <= #1 2'b00; // idle
258 2 rherveille
          bcnt  <= #1 3'h0;
259
          treg  <= #1 8'h00;
260
          wfre  <= #1 1'b0;
261
          rfwe  <= #1 1'b0;
262 8 rherveille
          sck_o <= #1 1'b0;
263 2 rherveille
      end
264
    else
265
      begin
266
         wfre <= #1 1'b0;
267
         rfwe <= #1 1'b0;
268
 
269 7 rherveille
         case (state) //synopsys full_case parallel_case
270
           2'b00: // idle state
271
              begin
272 8 rherveille
                  bcnt  <= #1 3'h7;   // set transfer counter
273
                  treg  <= #1 wfdout; // load transfer register
274
                  sck_o <= #1 cpol;   // set sck
275
 
276 7 rherveille
                  if (~wfempty) begin
277
                    wfre  <= #1 1'b1;
278 8 rherveille
                    state <= #1 2'b01;
279
                    if (cpha) sck_o <= #1 ~sck_o;
280 7 rherveille
                  end
281
              end
282
 
283 8 rherveille
           2'b01: // clock-phase2, next data
284 7 rherveille
              if (ena) begin
285 8 rherveille
                sck_o   <= #1 ~sck_o;
286
                state   <= #1 2'b11;
287 7 rherveille
              end
288
 
289 8 rherveille
           2'b11: // clock phase1
290
              if (ena) begin
291
                treg <= #1 {treg[6:0], miso_i};
292
                bcnt <= #1 bcnt -3'h1;
293 7 rherveille
 
294 8 rherveille
                if (~|bcnt) begin
295
                  state <= #1 2'b00;
296
                  sck_o <= #1 cpol;
297
                  rfwe  <= #1 1'b1;
298
                end else begin
299
                  state <= #1 2'b01;
300
                  sck_o <= #1 ~sck_o;
301
                end
302 7 rherveille
              end
303
 
304 8 rherveille
           2'b10: state <= #1 2'b00;
305 7 rherveille
         endcase
306 2 rherveille
      end
307
 
308
  assign mosi_o = treg[7];
309
 
310
 
311
  // count number of transfers (for interrupt generation)
312
  reg [1:0] tcnt; // transfer count
313
  always @(posedge clk_i)
314
    if (~spe)
315
      tcnt <= #1 icnt;
316
    else if (rfwe) // rfwe gets asserted when all bits have been transfered
317
      if (|tcnt)
318
        tcnt <= #1 tcnt - 2'h1;
319
      else
320
        tcnt <= #1 icnt;
321
 
322
  assign tirq = ~|tcnt & rfwe;
323
 
324
endmodule
325
 

powered by: WebSVN 2.1.0

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