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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [core/] [rtl/] [verilog/] [omsp_clock_module.v] - Blame information for rev 202

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

Line No. Rev Author Line
1 2 olivier.gi
//----------------------------------------------------------------------------
2 117 olivier.gi
// Copyright (C) 2009 , Olivier Girard
3 2 olivier.gi
//
4 117 olivier.gi
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions
6
// are met:
7
//     * Redistributions of source code must retain the above copyright
8
//       notice, this list of conditions and the following disclaimer.
9
//     * Redistributions in binary form must reproduce the above copyright
10
//       notice, this list of conditions and the following disclaimer in the
11
//       documentation and/or other materials provided with the distribution.
12
//     * Neither the name of the authors nor the names of its contributors
13
//       may be used to endorse or promote products derived from this software
14
//       without specific prior written permission.
15 2 olivier.gi
//
16 117 olivier.gi
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26
// THE POSSIBILITY OF SUCH DAMAGE
27 2 olivier.gi
//
28
//----------------------------------------------------------------------------
29
//
30 34 olivier.gi
// *File Name: omsp_clock_module.v
31 202 olivier.gi
//
32 2 olivier.gi
// *Module Description:
33
//                       Basic clock module implementation.
34
//
35
// *Author(s):
36
//              - Olivier Girard,    olgirard@gmail.com
37
//
38
//----------------------------------------------------------------------------
39 17 olivier.gi
// $Rev: 202 $
40
// $LastChangedBy: olivier.girard $
41
// $LastChangedDate: 2015-07-01 23:13:32 +0200 (Wed, 01 Jul 2015) $
42
//----------------------------------------------------------------------------
43 103 olivier.gi
`ifdef OMSP_NO_INCLUDE
44
`else
45 23 olivier.gi
`include "openMSP430_defines.v"
46 103 olivier.gi
`endif
47 2 olivier.gi
 
48 34 olivier.gi
module  omsp_clock_module (
49 2 olivier.gi
 
50
// OUTPUTs
51 202 olivier.gi
    aclk,                             // ACLK
52
    aclk_en,                          // ACLK enable
53
    cpu_en_s,                         // Enable CPU code execution (synchronous)
54
    cpu_mclk,                         // Main system CPU only clock
55
    dma_mclk,                         // Main system DMA and/or CPU clock
56
    dbg_clk,                          // Debug unit clock
57
    dbg_en_s,                         // Debug interface enable (synchronous)
58
    dbg_rst,                          // Debug unit reset
59
    dco_enable,                       // Fast oscillator enable
60
    dco_wkup,                         // Fast oscillator wake-up (asynchronous)
61
    lfxt_enable,                      // Low frequency oscillator enable
62
    lfxt_wkup,                        // Low frequency oscillator wake-up (asynchronous)
63
    per_dout,                         // Peripheral data output
64
    por,                              // Power-on reset
65
    puc_pnd_set,                      // PUC pending set for the serial debug interface
66
    puc_rst,                          // Main system reset
67
    smclk,                            // SMCLK
68
    smclk_en,                         // SMCLK enable
69
 
70 2 olivier.gi
// INPUTs
71 202 olivier.gi
    cpu_en,                           // Enable CPU code execution (asynchronous)
72
    cpuoff,                           // Turns off the CPU
73
    dbg_cpu_reset,                    // Reset CPU from debug interface
74
    dbg_en,                           // Debug interface enable (asynchronous)
75
    dco_clk,                          // Fast oscillator (fast clock)
76
    lfxt_clk,                         // Low frequency oscillator (typ 32kHz)
77
    mclk_dma_enable,                  // DMA Sub-System Clock enable
78
    mclk_dma_wkup,                    // DMA Sub-System Clock wake-up (asynchronous)
79
    mclk_enable,                      // Main System Clock enable
80
    mclk_wkup,                        // Main System Clock wake-up (asynchronous)
81
    oscoff,                           // Turns off LFXT1 clock input
82
    per_addr,                         // Peripheral address
83
    per_din,                          // Peripheral data input
84
    per_en,                           // Peripheral enable (high active)
85
    per_we,                           // Peripheral write enable (high active)
86
    reset_n,                          // Reset Pin (low active, asynchronous)
87
    scan_enable,                      // Scan enable (active during scan shifting)
88
    scan_mode,                        // Scan mode
89
    scg0,                             // System clock generator 1. Turns off the DCO
90
    scg1,                             // System clock generator 1. Turns off the SMCLK
91
    wdt_reset                         // Watchdog-timer reset
92 2 olivier.gi
);
93
 
94
// OUTPUTs
95
//=========
96 202 olivier.gi
output              aclk;             // ACLK
97
output              aclk_en;          // ACLK enable
98
output              cpu_en_s;         // Enable CPU code execution (synchronous)
99
output              cpu_mclk;         // Main system CPU only clock
100
output              dma_mclk;         // Main system DMA and/or CPU clock
101
output              dbg_clk;          // Debug unit clock
102
output              dbg_en_s;         // Debug unit enable (synchronous)
103
output              dbg_rst;          // Debug unit reset
104
output              dco_enable;       // Fast oscillator enable
105
output              dco_wkup;         // Fast oscillator wake-up (asynchronous)
106
output              lfxt_enable;      // Low frequency oscillator enable
107
output              lfxt_wkup;        // Low frequency oscillator wake-up (asynchronous)
108
output       [15:0] per_dout;         // Peripheral data output
109
output              por;              // Power-on reset
110
output              puc_pnd_set;      // PUC pending set for the serial debug interface
111
output              puc_rst;          // Main system reset
112
output              smclk;            // SMCLK
113
output              smclk_en;         // SMCLK enable
114 2 olivier.gi
 
115
// INPUTs
116
//=========
117 202 olivier.gi
input               cpu_en;           // Enable CPU code execution (asynchronous)
118
input               cpuoff;           // Turns off the CPU
119
input               dbg_cpu_reset;    // Reset CPU from debug interface
120
input               dbg_en;           // Debug interface enable (asynchronous)
121
input               dco_clk;          // Fast oscillator (fast clock)
122
input               lfxt_clk;         // Low frequency oscillator (typ 32kHz)
123
input               mclk_dma_enable;  // DMA Sub-System Clock enable
124
input               mclk_dma_wkup;    // DMA Sub-System Clock wake-up (asynchronous)
125
input               mclk_enable;      // Main System Clock enable
126
input               mclk_wkup;        // Main System Clock wake-up (asynchronous)
127
input               oscoff;           // Turns off LFXT1 clock input
128
input        [13:0] per_addr;         // Peripheral address
129
input        [15:0] per_din;          // Peripheral data input
130
input               per_en;           // Peripheral enable (high active)
131
input         [1:0] per_we;           // Peripheral write enable (high active)
132
input               reset_n;          // Reset Pin (low active, asynchronous)
133
input               scan_enable;      // Scan enable (active during scan shifting)
134
input               scan_mode;        // Scan mode
135
input               scg0;             // System clock generator 1. Turns off the DCO
136
input               scg1;             // System clock generator 1. Turns off the SMCLK
137
input               wdt_reset;        // Watchdog-timer reset
138 2 olivier.gi
 
139
 
140
//=============================================================================
141 134 olivier.gi
// 1)  WIRES & PARAMETER DECLARATION
142 2 olivier.gi
//=============================================================================
143
 
144 111 olivier.gi
// Register base address (must be aligned to decoder bit width)
145
parameter       [14:0] BASE_ADDR   = 15'h0050;
146 2 olivier.gi
 
147 111 olivier.gi
// Decoder bit width (defines how many bits are considered for address decoding)
148
parameter              DEC_WD      =  4;
149
 
150
// Register addresses offset
151
parameter [DEC_WD-1:0] BCSCTL1     =  'h7,
152
                       BCSCTL2     =  'h8;
153
 
154
// Register one-hot decoder utilities
155 134 olivier.gi
parameter              DEC_SZ      =  (1 << DEC_WD);
156 111 olivier.gi
parameter [DEC_SZ-1:0] BASE_REG    =  {{DEC_SZ-1{1'b0}}, 1'b1};
157
 
158 2 olivier.gi
// Register one-hot decoder
159 111 olivier.gi
parameter [DEC_SZ-1:0] BCSCTL1_D   = (BASE_REG << BCSCTL1),
160
                       BCSCTL2_D   = (BASE_REG << BCSCTL2);
161 2 olivier.gi
 
162 134 olivier.gi
// Local wire declarations
163
wire nodiv_mclk;
164
wire nodiv_mclk_n;
165
wire nodiv_smclk;
166 2 olivier.gi
 
167 134 olivier.gi
 
168 2 olivier.gi
//============================================================================
169
// 2)  REGISTER DECODER
170
//============================================================================
171
 
172 111 olivier.gi
// Local register selection
173
wire              reg_sel      =  per_en & (per_addr[13:DEC_WD-1]==BASE_ADDR[14:DEC_WD]);
174
 
175
// Register local address
176
wire [DEC_WD-1:0] reg_addr     =  {1'b0, per_addr[DEC_WD-2:0]};
177
 
178 2 olivier.gi
// Register address decode
179 111 olivier.gi
wire [DEC_SZ-1:0] reg_dec      = (BCSCTL1_D  &  {DEC_SZ{(reg_addr==(BCSCTL1 >>1))}}) |
180
                                 (BCSCTL2_D  &  {DEC_SZ{(reg_addr==(BCSCTL2 >>1))}});
181 2 olivier.gi
 
182
// Read/Write probes
183 111 olivier.gi
wire              reg_lo_write =  per_we[0] & reg_sel;
184
wire              reg_hi_write =  per_we[1] & reg_sel;
185
wire              reg_read     = ~|per_we   & reg_sel;
186 2 olivier.gi
 
187
// Read/Write vectors
188 111 olivier.gi
wire [DEC_SZ-1:0] reg_hi_wr    = reg_dec & {DEC_SZ{reg_hi_write}};
189
wire [DEC_SZ-1:0] reg_lo_wr    = reg_dec & {DEC_SZ{reg_lo_write}};
190
wire [DEC_SZ-1:0] reg_rd       = reg_dec & {DEC_SZ{reg_read}};
191 2 olivier.gi
 
192
 
193
//============================================================================
194
// 3) REGISTERS
195
//============================================================================
196
 
197
// BCSCTL1 Register
198
//--------------
199
reg  [7:0] bcsctl1;
200 111 olivier.gi
wire       bcsctl1_wr  = BCSCTL1[0] ? reg_hi_wr[BCSCTL1] : reg_lo_wr[BCSCTL1];
201
wire [7:0] bcsctl1_nxt = BCSCTL1[0] ? per_din[15:8]      : per_din[7:0];
202 2 olivier.gi
 
203 180 olivier.gi
`ifdef ASIC_CLOCKING
204 134 olivier.gi
  `ifdef ACLK_DIVIDER
205 202 olivier.gi
wire [7:0] divax_mask      = 8'h30;
206 134 olivier.gi
  `else
207 202 olivier.gi
wire [7:0] divax_mask      = 8'h00;
208 134 olivier.gi
  `endif
209 202 olivier.gi
  `ifdef DMA_IF_EN
210
    `ifdef CPUOFF_EN
211
wire [7:0] dma_cpuoff_mask = 8'h01;
212
    `else
213
wire [7:0] dma_cpuoff_mask = 8'h00;
214
    `endif
215
    `ifdef OSCOFF_EN
216
wire [7:0] dma_oscoff_mask = 8'h02;
217
    `else
218
wire [7:0] dma_oscoff_mask = 8'h00;
219
    `endif
220
    `ifdef SCG0_EN
221
wire [7:0] dma_scg0_mask   = 8'h04;
222
    `else
223
wire [7:0] dma_scg0_mask   = 8'h00;
224
    `endif
225
    `ifdef SCG1_EN
226
wire [7:0] dma_scg1_mask   = 8'h08;
227
    `else
228
wire [7:0] dma_scg1_mask   = 8'h00;
229
    `endif
230
  `else
231
wire [7:0] dma_cpuoff_mask = 8'h00;
232
wire [7:0] dma_scg0_mask   = 8'h00;
233
wire [7:0] dma_scg1_mask   = 8'h00;
234
wire [7:0] dma_oscoff_mask = 8'h00;
235
  `endif
236 134 olivier.gi
`else
237 202 olivier.gi
wire [7:0] divax_mask      = 8'h30;
238
wire [7:0] dma_cpuoff_mask = 8'h00;
239
wire [7:0] dma_scg0_mask   = 8'h00;
240
  `ifdef DMA_IF_EN
241
wire [7:0] dma_oscoff_mask = 8'h02;
242
wire [7:0] dma_scg1_mask   = 8'h08;
243
  `else
244
wire [7:0] dma_oscoff_mask = 8'h00;
245
wire [7:0] dma_scg1_mask   = 8'h00;
246
  `endif
247 134 olivier.gi
`endif
248
 
249 202 olivier.gi
always @ (posedge dma_mclk or posedge puc_rst)
250 111 olivier.gi
  if (puc_rst)          bcsctl1  <=  8'h00;
251 202 olivier.gi
  else if (bcsctl1_wr)  bcsctl1  <=  bcsctl1_nxt & (divax_mask      |
252
                                                    dma_cpuoff_mask | dma_oscoff_mask |
253
                                                    dma_scg0_mask   | dma_scg1_mask   ); // Mask unused bits
254 2 olivier.gi
 
255
 
256
// BCSCTL2 Register
257
//--------------
258
reg  [7:0] bcsctl2;
259 134 olivier.gi
wire       bcsctl2_wr    = BCSCTL2[0] ? reg_hi_wr[BCSCTL2] : reg_lo_wr[BCSCTL2];
260
wire [7:0] bcsctl2_nxt   = BCSCTL2[0] ? per_din[15:8]      : per_din[7:0];
261 2 olivier.gi
 
262 134 olivier.gi
`ifdef MCLK_MUX
263
wire [7:0] selmx_mask = 8'h80;
264
`else
265
wire [7:0] selmx_mask = 8'h00;
266
`endif
267
`ifdef MCLK_DIVIDER
268
wire [7:0] divmx_mask = 8'h30;
269
`else
270
wire [7:0] divmx_mask = 8'h00;
271
`endif
272 180 olivier.gi
`ifdef ASIC_CLOCKING
273 134 olivier.gi
  `ifdef SMCLK_MUX
274
wire [7:0] sels_mask  = 8'h08;
275
  `else
276
wire [7:0] sels_mask  = 8'h00;
277
  `endif
278
  `ifdef SMCLK_DIVIDER
279
wire [7:0] divsx_mask = 8'h06;
280
  `else
281
wire [7:0] divsx_mask = 8'h00;
282
  `endif
283
`else
284
wire [7:0] sels_mask  = 8'h08;
285
wire [7:0] divsx_mask = 8'h06;
286
`endif
287
 
288 202 olivier.gi
always @ (posedge dma_mclk or posedge puc_rst)
289 111 olivier.gi
  if (puc_rst)          bcsctl2  <=  8'h00;
290 134 olivier.gi
  else if (bcsctl2_wr)  bcsctl2  <=  bcsctl2_nxt & ( sels_mask  | divsx_mask |
291
                                                     selmx_mask | divmx_mask); // Mask unused bits
292 2 olivier.gi
 
293
 
294
//============================================================================
295
// 4) DATA OUTPUT GENERATION
296
//============================================================================
297
 
298
// Data output mux
299 111 olivier.gi
wire [15:0] bcsctl1_rd   = {8'h00, (bcsctl1  & {8{reg_rd[BCSCTL1]}})}  << (8 & {4{BCSCTL1[0]}});
300
wire [15:0] bcsctl2_rd   = {8'h00, (bcsctl2  & {8{reg_rd[BCSCTL2]}})}  << (8 & {4{BCSCTL2[0]}});
301 2 olivier.gi
 
302
wire [15:0] per_dout =  bcsctl1_rd   |
303
                        bcsctl2_rd;
304
 
305
 
306
//=============================================================================
307 134 olivier.gi
// 5)  DCO_CLK / LFXT_CLK INTERFACES (WAKEUP, ENABLE, ...)
308 2 olivier.gi
//=============================================================================
309
 
310 180 olivier.gi
`ifdef ASIC_CLOCKING
311 134 olivier.gi
   wire cpuoff_and_mclk_enable;
312 202 olivier.gi
   wire cpuoff_and_mclk_dma_enable;
313
   wire cpuoff_and_mclk_dma_wkup;
314
  `ifdef CPUOFF_EN
315
   omsp_and_gate and_cpuoff_mclk_en       (.y(cpuoff_and_mclk_enable),     .a(cpuoff),               .b(mclk_enable));
316
    `ifdef DMA_IF_EN
317
   omsp_and_gate and_cpuoff_mclk_dma_en   (.y(cpuoff_and_mclk_dma_enable), .a(bcsctl1[`DMA_CPUOFF]), .b(mclk_dma_enable));
318
   omsp_and_gate and_cpuoff_mclk_dma_wkup (.y(cpuoff_and_mclk_dma_wkup),   .a(bcsctl1[`DMA_CPUOFF]), .b(mclk_dma_wkup));
319
    `else
320
   assign cpuoff_and_mclk_dma_enable = 1'b0;
321
   assign cpuoff_and_mclk_dma_wkup   = 1'b0;
322
    `endif
323
  `else
324
   assign cpuoff_and_mclk_enable     = 1'b0;
325
   assign cpuoff_and_mclk_dma_enable = 1'b0;
326
   assign cpuoff_and_mclk_dma_wkup   = 1'b0;
327
   wire   UNUSED_cpuoff              = cpuoff;
328
  `endif
329
 
330
   wire scg0_and_mclk_dma_enable;
331
   wire scg0_and_mclk_dma_wkup;
332
  `ifdef DMA_IF_EN
333
    `ifdef SCG0_EN
334
   omsp_and_gate and_scg0_mclk_dma_en     (.y(scg0_and_mclk_dma_enable),   .a(bcsctl1[`DMA_SCG0]),   .b(mclk_dma_enable));
335
   omsp_and_gate and_scg0_mclk_dma_wkup   (.y(scg0_and_mclk_dma_wkup),     .a(bcsctl1[`DMA_SCG0]),   .b(mclk_dma_wkup));
336
    `else
337
   assign scg0_and_mclk_dma_enable   = 1'b0;
338
   assign scg0_and_mclk_dma_wkup     = 1'b0;
339
   wire   UNUSED_scg0_mclk_dma_wkup  = mclk_dma_wkup;
340
    `endif
341
  `else
342
   assign scg0_and_mclk_dma_enable   = 1'b0;
343
   assign scg0_and_mclk_dma_wkup     = 1'b0;
344
  `endif
345
 
346
   wire scg1_and_mclk_dma_enable;
347
   wire scg1_and_mclk_dma_wkup;
348
  `ifdef DMA_IF_EN
349
    `ifdef SCG1_EN
350
   omsp_and_gate and_scg1_mclk_dma_en     (.y(scg1_and_mclk_dma_enable),   .a(bcsctl1[`DMA_SCG1]),   .b(mclk_dma_enable));
351
   omsp_and_gate and_scg1_mclk_dma_wkup   (.y(scg1_and_mclk_dma_wkup),     .a(bcsctl1[`DMA_SCG1]),   .b(mclk_dma_wkup));
352
    `else
353
   assign scg1_and_mclk_dma_enable   = 1'b0;
354
   assign scg1_and_mclk_dma_wkup     = 1'b0;
355
   wire   UNUSED_scg1_mclk_dma_wkup  = mclk_dma_wkup;
356
    `endif
357
  `else
358
   assign scg1_and_mclk_dma_enable   = 1'b0;
359
   assign scg1_and_mclk_dma_wkup     = 1'b0;
360
  `endif
361
 
362
   wire oscoff_and_mclk_dma_enable;
363
   wire oscoff_and_mclk_dma_wkup;
364
  `ifdef DMA_IF_EN
365
    `ifdef OSCOFF_EN
366
   omsp_and_gate and_oscoff_mclk_dma_en   (.y(oscoff_and_mclk_dma_enable), .a(bcsctl1[`DMA_OSCOFF]), .b(mclk_dma_enable));
367
   omsp_and_gate and_oscoff_mclk_dma_wkup (.y(oscoff_and_mclk_dma_wkup),   .a(bcsctl1[`DMA_OSCOFF]), .b(mclk_dma_wkup));
368
    `else
369
   assign oscoff_and_mclk_dma_enable = 1'b0;
370
   assign oscoff_and_mclk_dma_wkup   = 1'b0;
371
   wire   UNUSED_oscoff_mclk_dma_wkup= mclk_dma_wkup;
372
    `endif
373
  `else
374
   assign oscoff_and_mclk_dma_enable = 1'b0;
375
   assign oscoff_and_mclk_dma_wkup   = 1'b0;
376
  wire  UNUSED_mclk_dma_wkup         = mclk_dma_wkup;
377
  `endif
378
`else
379
  wire  UNUSED_cpuoff                = cpuoff;
380
  wire  UNUSED_mclk_enable           = mclk_enable;
381
  wire  UNUSED_mclk_dma_wkup         = mclk_dma_wkup;
382 134 olivier.gi
`endif
383
 
384 202 olivier.gi
 
385 134 olivier.gi
//-----------------------------------------------------------
386
// 5.1) HIGH SPEED SYSTEM CLOCK GENERATOR (DCO_CLK)
387
//-----------------------------------------------------------
388
// Note1: switching off the DCO osillator is only
389
//        supported in ASIC mode with SCG0 low power mode
390
//
391
// Note2: unlike the original MSP430 specification,
392
//        we allow to switch off the DCO even
393
//        if it is selected by MCLK or SMCLK.
394
 
395
wire por_a;
396
wire dco_wkup;
397
wire cpu_en_wkup;
398
 
399
`ifdef SCG0_EN
400
 
401
   // The DCO oscillator is synchronously disabled if:
402
   //      - the cpu pin is disabled (in that case, wait for mclk_enable==0)
403
   //      - the debug interface is disabled
404
   //      - SCG0 is set (in that case, wait for the mclk_enable==0 if selected by SELMx)
405
   //
406
   // Note that we make extensive use of the AND gate module in order
407
   // to prevent glitch propagation on the wakeup logic cone.
408
   wire cpu_enabled_with_dco;
409
   wire dco_not_enabled_by_dbg;
410
   wire dco_disable_by_scg0;
411
   wire dco_disable_by_cpu_en;
412
   wire dco_enable_nxt;
413
   omsp_and_gate and_dco_dis1 (.y(cpu_enabled_with_dco),   .a(~bcsctl2[`SELMx]),     .b(cpuoff_and_mclk_enable));
414 202 olivier.gi
   omsp_and_gate and_dco_dis2 (.y(dco_not_enabled_by_dbg), .a(~dbg_en_s),            .b(~(cpu_enabled_with_dco | scg0_and_mclk_dma_enable)));
415 134 olivier.gi
   omsp_and_gate and_dco_dis3 (.y(dco_disable_by_scg0),    .a(scg0),                 .b(dco_not_enabled_by_dbg));
416
   omsp_and_gate and_dco_dis4 (.y(dco_disable_by_cpu_en),  .a(~cpu_en_s),            .b(~mclk_enable));
417
   omsp_and_gate and_dco_dis5 (.y(dco_enable_nxt),         .a(~dco_disable_by_scg0), .b(~dco_disable_by_cpu_en));
418
 
419
   // Register to prevent glitch propagation
420
   reg  dco_disable;
421
   always @(posedge nodiv_mclk_n or posedge por)
422
   if (por) dco_disable <= 1'b1;
423
   else     dco_disable <= ~dco_enable_nxt;
424
 
425
   // Note that a synchronizer is required if the MCLK mux is included
426
   wire dco_clk_n  = ~dco_clk;
427
   `ifdef MCLK_MUX
428
      omsp_sync_cell sync_cell_dco_disable (
429
         .data_out  (dco_enable),
430
         .data_in   (~dco_disable),
431
         .clk       (dco_clk_n),
432
         .rst       (por)
433
      );
434
   `else
435
      assign dco_enable     = ~dco_disable;
436
   `endif
437
 
438
   // The DCO oscillator will get an asynchronous wakeup if:
439
   //      - the MCLK  generates a wakeup (only if the MCLK mux selects dco_clk)
440
   //      - if the DCO wants to be synchronously enabled (i.e dco_enable_nxt=1)
441
   wire dco_mclk_wkup;
442
   wire dco_en_wkup;
443
   omsp_and_gate and_dco_mclk_wkup (.y(dco_mclk_wkup), .a(mclk_wkup),   .b(~bcsctl2[`SELMx]));
444
   omsp_and_gate and_dco_en_wkup   (.y(dco_en_wkup),   .a(~dco_enable), .b(dco_enable_nxt));
445
 
446 202 olivier.gi
   wire dco_wkup_set = dco_mclk_wkup | scg0_and_mclk_dma_wkup | dco_en_wkup | cpu_en_wkup;
447 134 olivier.gi
 
448
   // Scan MUX for the asynchronous SET
449
   wire dco_wkup_set_scan;
450
   omsp_scan_mux scan_mux_dco_wkup (
451 202 olivier.gi
                                    .scan_mode    (scan_mode),
452
                                    .data_in_scan (por_a),
453
                                    .data_in_func (dco_wkup_set | por),
454
                                    .data_out     (dco_wkup_set_scan)
455
                                   );
456 134 olivier.gi
 
457 202 olivier.gi
   // Scan MUX to increase coverage
458 134 olivier.gi
   wire dco_wkup_clear;
459
   omsp_scan_mux scan_mux_dco_wkup_clear (
460 202 olivier.gi
                                          .scan_mode    (scan_mode),
461
                                          .data_in_scan (dco_wkup_set),
462
                                          .data_in_func (1'b1),
463
                                          .data_out     (dco_wkup_clear)
464
                                         );
465 134 olivier.gi
 
466
   // The wakeup is asynchronously set, synchronously released
467
   wire dco_wkup_n;
468
   omsp_sync_cell sync_cell_dco_wkup (
469
       .data_out  (dco_wkup_n),
470
       .data_in   (dco_wkup_clear),
471
       .clk       (dco_clk_n),
472
       .rst       (dco_wkup_set_scan)
473
   );
474
 
475
   omsp_and_gate and_dco_wkup (.y(dco_wkup), .a(~dco_wkup_n), .b(cpu_en));
476
 
477 111 olivier.gi
`else
478 202 olivier.gi
   assign dco_enable          = 1'b1;
479
   assign dco_wkup            = 1'b1;
480
   wire   UNUSED_scg0         = scg0;
481
   wire   UNUSED_cpu_en_wkup1 = cpu_en_wkup;
482 111 olivier.gi
`endif
483 106 olivier.gi
 
484 134 olivier.gi
 
485
//-----------------------------------------------------------
486
// 5.2) LOW FREQUENCY CRYSTAL CLOCK GENERATOR (LFXT_CLK)
487
//-----------------------------------------------------------
488
 
489
// ASIC MODE
490
//------------------------------------------------
491
// Note: unlike the original MSP430 specification,
492
//       we allow to switch off the LFXT even
493
//       if it is selected by MCLK or SMCLK.
494 180 olivier.gi
`ifdef ASIC_CLOCKING
495 134 olivier.gi
 
496
`ifdef OSCOFF_EN
497
 
498
   // The LFXT is synchronously disabled if:
499
   //      - the cpu pin is disabled (in that case, wait for mclk_enable==0)
500
   //      - the debug interface is disabled
501
   //      - OSCOFF is set (in that case, wait for the mclk_enable==0 if selected by SELMx)
502
   wire cpu_enabled_with_lfxt;
503
   wire lfxt_not_enabled_by_dbg;
504
   wire lfxt_disable_by_oscoff;
505
   wire lfxt_disable_by_cpu_en;
506
   wire lfxt_enable_nxt;
507
   omsp_and_gate and_lfxt_dis1 (.y(cpu_enabled_with_lfxt),   .a(bcsctl2[`SELMx]),         .b(cpuoff_and_mclk_enable));
508 202 olivier.gi
   omsp_and_gate and_lfxt_dis2 (.y(lfxt_not_enabled_by_dbg), .a(~dbg_en_s),               .b(~(cpu_enabled_with_lfxt | oscoff_and_mclk_dma_enable)));
509 134 olivier.gi
   omsp_and_gate and_lfxt_dis3 (.y(lfxt_disable_by_oscoff),  .a(oscoff),                  .b(lfxt_not_enabled_by_dbg));
510
   omsp_and_gate and_lfxt_dis4 (.y(lfxt_disable_by_cpu_en),  .a(~cpu_en_s),               .b(~mclk_enable));
511
   omsp_and_gate and_lfxt_dis5 (.y(lfxt_enable_nxt),         .a(~lfxt_disable_by_oscoff), .b(~lfxt_disable_by_cpu_en));
512
 
513
   // Register to prevent glitch propagation
514
   reg  lfxt_disable;
515
   always @(posedge nodiv_mclk_n or posedge por)
516
   if (por) lfxt_disable <= 1'b1;
517
   else     lfxt_disable <= ~lfxt_enable_nxt;
518
 
519
   // Synchronize the OSCOFF control signal to the LFXT clock domain
520
   wire lfxt_clk_n  = ~lfxt_clk;
521
   omsp_sync_cell sync_cell_lfxt_disable (
522
      .data_out  (lfxt_enable),
523
      .data_in   (~lfxt_disable),
524
      .clk       (lfxt_clk_n),
525
      .rst       (por)
526
   );
527
 
528
   // The LFXT will get an asynchronous wakeup if:
529
   //      - the MCLK  generates a wakeup (only if the MCLK  mux selects lfxt_clk)
530
   //      - if the LFXT wants to be synchronously enabled (i.e lfxt_enable_nxt=1)
531
   wire lfxt_mclk_wkup;
532
   wire lfxt_en_wkup;
533
   omsp_and_gate and_lfxt_mclk_wkup (.y(lfxt_mclk_wkup), .a(mclk_wkup),    .b(bcsctl2[`SELMx]));
534
   omsp_and_gate and_lfxt_en_wkup   (.y(lfxt_en_wkup),   .a(~lfxt_enable), .b(lfxt_enable_nxt));
535
 
536 202 olivier.gi
   wire   lfxt_wkup_set  = lfxt_mclk_wkup | oscoff_and_mclk_dma_wkup | lfxt_en_wkup | cpu_en_wkup;
537 134 olivier.gi
 
538
   // Scan MUX for the asynchronous SET
539
   wire lfxt_wkup_set_scan;
540
   omsp_scan_mux scan_mux_lfxt_wkup (
541 202 olivier.gi
                                     .scan_mode    (scan_mode),
542
                                     .data_in_scan (por_a),
543
                                     .data_in_func (lfxt_wkup_set | por),
544
                                     .data_out     (lfxt_wkup_set_scan)
545
                                    );
546 134 olivier.gi
 
547 202 olivier.gi
   // Scan MUX to increase coverage
548 134 olivier.gi
   wire lfxt_wkup_clear;
549
   omsp_scan_mux scan_mux_lfxt_wkup_clear (
550 202 olivier.gi
                                           .scan_mode    (scan_mode),
551
                                           .data_in_scan (lfxt_wkup_set),
552
                                           .data_in_func (1'b1),
553
                                           .data_out     (lfxt_wkup_clear)
554
                                          );
555 134 olivier.gi
 
556
   // The wakeup is asynchronously set, synchronously released
557
   wire lfxt_wkup_n;
558
   omsp_sync_cell sync_cell_lfxt_wkup (
559
       .data_out  (lfxt_wkup_n),
560
       .data_in   (lfxt_wkup_clear),
561
       .clk       (lfxt_clk_n),
562
       .rst       (lfxt_wkup_set_scan)
563
   );
564
 
565
   omsp_and_gate and_lfxt_wkup (.y(lfxt_wkup), .a(~lfxt_wkup_n), .b(cpu_en));
566
 
567
`else
568 202 olivier.gi
   assign lfxt_enable                   = 1'b1;
569
   assign lfxt_wkup                     = 1'b0;
570
   wire   UNUSED_oscoff                 = oscoff;
571
  wire    UNUSED_cpuoff_and_mclk_enable = cpuoff_and_mclk_enable;
572
   wire   UNUSED_cpu_en_wkup2           = cpu_en_wkup;
573 134 olivier.gi
`endif
574
 
575
 
576
// FPGA MODE
577
//---------------------------------------
578 2 olivier.gi
// Synchronize LFXT_CLK & edge detection
579 134 olivier.gi
`else
580
 
581 111 olivier.gi
wire lfxt_clk_s;
582
 
583
omsp_sync_cell sync_cell_lfxt_clk (
584 134 olivier.gi
    .data_out  (lfxt_clk_s),
585
    .data_in   (lfxt_clk),
586 202 olivier.gi
    .clk       (nodiv_mclk),
587 134 olivier.gi
    .rst       (por)
588 111 olivier.gi
);
589
 
590
reg  lfxt_clk_dly;
591 202 olivier.gi
 
592
always @ (posedge nodiv_mclk or posedge por)
593 111 olivier.gi
  if (por) lfxt_clk_dly <=  1'b0;
594 202 olivier.gi
  else     lfxt_clk_dly <=  lfxt_clk_s;
595 2 olivier.gi
 
596 202 olivier.gi
wire   lfxt_clk_en = (lfxt_clk_s & ~lfxt_clk_dly) & (~oscoff | (mclk_dma_enable & bcsctl1[`DMA_OSCOFF]));
597 134 olivier.gi
assign lfxt_enable = 1'b1;
598
assign lfxt_wkup   = 1'b0;
599 202 olivier.gi
`endif
600 134 olivier.gi
 
601 202 olivier.gi
 
602 134 olivier.gi
//=============================================================================
603
// 6)  CLOCK GENERATION
604
//=============================================================================
605
 
606
//-----------------------------------------------------------
607
// 6.1) GLOBAL CPU ENABLE
608 202 olivier.gi
//----------------------------------------------------------
609 134 olivier.gi
// ACLK and SMCLK are directly switched-off
610
// with the cpu_en pin (after synchronization).
611
// MCLK will be switched off once the CPU reaches
612
// its IDLE state (through the mclk_enable signal)
613
 
614
 
615
// Synchronize CPU_EN signal to the MCLK domain
616
//----------------------------------------------
617
`ifdef SYNC_CPU_EN
618
   omsp_sync_cell sync_cell_cpu_en (
619
      .data_out  (cpu_en_s),
620
      .data_in   (cpu_en),
621
      .clk       (nodiv_mclk),
622
      .rst       (por)
623
   );
624
   omsp_and_gate and_cpu_en_wkup (.y(cpu_en_wkup), .a(cpu_en), .b(~cpu_en_s));
625
`else
626
   assign cpu_en_s    = cpu_en;
627
   assign cpu_en_wkup = 1'b0;
628
`endif
629
 
630
// Synchronize CPU_EN signal to the ACLK domain
631
//----------------------------------------------
632
`ifdef LFXT_DOMAIN
633
   wire cpu_en_aux_s;
634
   omsp_sync_cell sync_cell_cpu_aux_en (
635
      .data_out  (cpu_en_aux_s),
636
      .data_in   (cpu_en),
637
      .clk       (lfxt_clk),
638
      .rst       (por)
639
   );
640
`else
641
   wire   cpu_en_aux_s    = cpu_en_s;
642
`endif
643
 
644
// Synchronize CPU_EN signal to the SMCLK domain
645
//----------------------------------------------
646
// Note: the synchronizer is only required if there is a SMCLK_MUX
647 180 olivier.gi
`ifdef ASIC_CLOCKING
648 134 olivier.gi
  `ifdef SMCLK_MUX
649
     wire cpu_en_sm_s;
650
     omsp_sync_cell sync_cell_cpu_sm_en (
651
        .data_out  (cpu_en_sm_s),
652
        .data_in   (cpu_en),
653
        .clk       (nodiv_smclk),
654
        .rst       (por)
655
     );
656
  `else
657
   wire   cpu_en_sm_s    = cpu_en_s;
658
  `endif
659
`endif
660
 
661
 
662
//-----------------------------------------------------------
663
// 6.2) MCLK GENERATION
664
//-----------------------------------------------------------
665
 
666
// Clock MUX
667
//----------------------------
668
`ifdef MCLK_MUX
669
omsp_clock_mux clock_mux_mclk (
670
   .clk_out   (nodiv_mclk),
671
   .clk_in0   (dco_clk),
672
   .clk_in1   (lfxt_clk),
673
   .reset     (por),
674
   .scan_mode (scan_mode),
675 202 olivier.gi
   .select_in (bcsctl2[`SELMx])
676 134 olivier.gi
);
677
`else
678
assign nodiv_mclk   =  dco_clk;
679
`endif
680
assign nodiv_mclk_n = ~nodiv_mclk;
681
 
682 202 olivier.gi
 
683 134 olivier.gi
// Wakeup synchronizer
684
//----------------------------
685 202 olivier.gi
wire cpuoff_and_mclk_dma_wkup_s;
686 134 olivier.gi
wire mclk_wkup_s;
687
 
688
`ifdef CPUOFF_EN
689 202 olivier.gi
  `ifdef DMA_IF_EN
690
omsp_sync_cell sync_cell_mclk_dma_wkup (
691
   .data_out  (cpuoff_and_mclk_dma_wkup_s),
692
   .data_in   (cpuoff_and_mclk_dma_wkup),
693
   .clk       (nodiv_mclk),
694
   .rst       (puc_rst)
695
);
696
  `else
697
   assign cpuoff_and_mclk_dma_wkup_s = 1'b0;
698
  `endif
699 134 olivier.gi
omsp_sync_cell sync_cell_mclk_wkup (
700
   .data_out  (mclk_wkup_s),
701
   .data_in   (mclk_wkup),
702
   .clk       (nodiv_mclk),
703
   .rst       (puc_rst)
704
);
705
`else
706 202 olivier.gi
   assign cpuoff_and_mclk_dma_wkup_s = 1'b0;
707
   assign mclk_wkup_s                = 1'b0;
708
   wire   UNUSED_mclk_wkup           = mclk_wkup;
709 134 olivier.gi
`endif
710
 
711
 
712
// Clock Divider
713
//----------------------------
714
// No need for extra synchronizer as bcsctl2
715
// comes from the same clock domain.
716
 
717
`ifdef CPUOFF_EN
718 202 olivier.gi
wire mclk_active     = mclk_enable                | mclk_wkup_s                | (dbg_en_s & cpu_en_s);
719
wire mclk_dma_active = cpuoff_and_mclk_dma_enable | cpuoff_and_mclk_dma_wkup_s | mclk_active;
720 134 olivier.gi
`else
721 202 olivier.gi
wire mclk_active     = 1'b1;
722
wire mclk_dma_active = 1'b1;
723 134 olivier.gi
`endif
724 202 olivier.gi
 
725 134 olivier.gi
`ifdef MCLK_DIVIDER
726
reg [2:0] mclk_div;
727
always @ (posedge nodiv_mclk or posedge puc_rst)
728
  if (puc_rst)                       mclk_div <=  3'h0;
729
  else if ((bcsctl2[`DIVMx]!=2'b00)) mclk_div <=  mclk_div+3'h1;
730
 
731 202 olivier.gi
  wire  mclk_div_sel    = (bcsctl2[`DIVMx]==2'b00) ?  1'b1          :
732
                          (bcsctl2[`DIVMx]==2'b01) ?  mclk_div[0]   :
733
                          (bcsctl2[`DIVMx]==2'b10) ? &mclk_div[1:0] :
734
                                                     &mclk_div[2:0] ;
735
 
736
  wire  mclk_div_en     = mclk_active     & mclk_div_sel;
737
  wire  mclk_dma_div_en = mclk_dma_active & mclk_div_sel;
738
 
739 134 olivier.gi
`else
740 202 olivier.gi
  wire  mclk_div_en     = mclk_active;
741
  wire  mclk_dma_div_en = mclk_dma_active;
742 134 olivier.gi
`endif
743
 
744
 
745 2 olivier.gi
// Generate main system clock
746
//----------------------------
747 134 olivier.gi
`ifdef MCLK_CGATE
748 2 olivier.gi
 
749 134 olivier.gi
omsp_clock_gate clock_gate_mclk (
750 202 olivier.gi
    .gclk        (cpu_mclk),
751 134 olivier.gi
    .clk         (nodiv_mclk),
752
    .enable      (mclk_div_en),
753
    .scan_enable (scan_enable)
754
);
755 202 olivier.gi
  `ifdef DMA_IF_EN
756
omsp_clock_gate clock_gate_dma_mclk (
757
    .gclk        (dma_mclk),
758
    .clk         (nodiv_mclk),
759
    .enable      (mclk_dma_div_en),
760
    .scan_enable (scan_enable)
761
);
762
  `else
763
   assign dma_mclk   = cpu_mclk;
764
  `endif
765 134 olivier.gi
`else
766 202 olivier.gi
   assign cpu_mclk   = nodiv_mclk;
767
   assign dma_mclk   = nodiv_mclk;
768 134 olivier.gi
`endif
769 2 olivier.gi
 
770
 
771 134 olivier.gi
//-----------------------------------------------------------
772
// 6.3) ACLK GENERATION
773
//-----------------------------------------------------------
774
 
775
// ASIC MODE
776 2 olivier.gi
//----------------------------
777 180 olivier.gi
`ifdef ASIC_CLOCKING
778 2 olivier.gi
 
779 134 olivier.gi
  `ifdef ACLK_DIVIDER
780
    `ifdef LFXT_DOMAIN
781 2 olivier.gi
 
782 134 olivier.gi
   wire nodiv_aclk = lfxt_clk;
783 85 olivier.gi
 
784 202 olivier.gi
   // Synchronizers
785
   //------------------------------------------------------
786
 
787 134 olivier.gi
   // Local Reset synchronizer
788 202 olivier.gi
   wire puc_lfxt_noscan_n;
789 134 olivier.gi
   wire puc_lfxt_rst;
790
   omsp_sync_cell sync_cell_puc_lfxt (
791
       .data_out     (puc_lfxt_noscan_n),
792
       .data_in      (1'b1),
793
       .clk          (nodiv_aclk),
794
       .rst          (puc_rst)
795
   );
796
   omsp_scan_mux scan_mux_puc_lfxt (
797
       .scan_mode    (scan_mode),
798
       .data_in_scan (por_a),
799
       .data_in_func (~puc_lfxt_noscan_n),
800
       .data_out     (puc_lfxt_rst)
801
   );
802 85 olivier.gi
 
803 202 olivier.gi
   // If the OSCOFF mode is enabled synchronize OSCOFF signal
804
   wire oscoff_s;
805
   `ifdef OSCOFF_EN
806
       omsp_sync_cell sync_cell_oscoff (
807
         .data_out     (oscoff_s),
808
         .data_in      (oscoff),
809
         .clk          (nodiv_aclk),
810
         .rst          (puc_lfxt_rst)
811
       );
812
   `else
813
   assign oscoff_s = 1'b0;
814
   `endif
815
 
816 134 olivier.gi
   // Local synchronizer for the bcsctl1.DIVAx configuration
817
   // (note that we can live with a full bus synchronizer as
818
   //  it won't hurt if we get a wrong DIVAx value for a single clock cycle)
819
   reg [1:0] divax_s;
820
   reg [1:0] divax_ss;
821
   always @ (posedge nodiv_aclk or posedge puc_lfxt_rst)
822
     if (puc_lfxt_rst)
823
       begin
824 202 olivier.gi
          divax_s  <=  2'h0;
825
          divax_ss <=  2'h0;
826 134 olivier.gi
       end
827
     else
828
       begin
829 202 olivier.gi
          divax_s  <=  bcsctl1[`DIVAx];
830
          divax_ss <=  divax_s;
831 134 olivier.gi
       end
832 2 olivier.gi
 
833 134 olivier.gi
  `else
834
   wire       puc_lfxt_rst = puc_rst;
835
   wire       nodiv_aclk   = dco_clk;
836
   wire [1:0] divax_ss     = bcsctl1[`DIVAx];
837
   wire       oscoff_s     = oscoff;
838 202 olivier.gi
  `endif
839 85 olivier.gi
 
840 202 olivier.gi
   // Wakeup synchronizer
841
   //----------------------------
842
   wire oscoff_and_mclk_dma_enable_s;
843
 
844
   `ifdef OSCOFF_EN
845
     `ifdef DMA_IF_EN
846
          omsp_sync_cell sync_cell_aclk_dma_wkup (
847
             .data_out  (oscoff_and_mclk_dma_enable_s),
848
             .data_in   (oscoff_and_mclk_dma_wkup | oscoff_and_mclk_dma_enable),
849
             .clk       (nodiv_aclk),
850
             .rst       (puc_lfxt_rst)
851
          );
852
     `else
853
      assign oscoff_and_mclk_dma_enable_s = 1'b0;
854
     `endif
855
   `else
856
      assign oscoff_and_mclk_dma_enable_s = 1'b0;
857
   `endif
858
 
859
   // Clock Divider
860
   //----------------------------
861
 
862
   wire      aclk_active  =  cpu_en_aux_s & (~oscoff_s | oscoff_and_mclk_dma_enable_s);
863
 
864 134 olivier.gi
   reg [2:0] aclk_div;
865
   always @ (posedge nodiv_aclk or posedge puc_lfxt_rst)
866
     if (puc_lfxt_rst)           aclk_div <=  3'h0;
867
     else if ((divax_ss!=2'b00)) aclk_div <=  aclk_div+3'h1;
868
 
869 202 olivier.gi
   wire      aclk_div_sel =  ((divax_ss==2'b00) ?  1'b1          :
870
                              (divax_ss==2'b01) ?  aclk_div[0]   :
871
                              (divax_ss==2'b10) ? &aclk_div[1:0] :
872
                                                  &aclk_div[2:0]);
873 134 olivier.gi
 
874 202 olivier.gi
   wire      aclk_div_en  =  aclk_active & aclk_div_sel;
875
 
876 134 olivier.gi
   // Clock gate
877
   omsp_clock_gate clock_gate_aclk (
878
      .gclk        (aclk),
879
      .clk         (nodiv_aclk),
880
      .enable      (aclk_div_en),
881
      .scan_enable (scan_enable)
882
   );
883
 
884 202 olivier.gi
  `else
885 134 olivier.gi
    `ifdef LFXT_DOMAIN
886 202 olivier.gi
    assign  aclk                = lfxt_clk;
887 134 olivier.gi
    `else
888 202 olivier.gi
    assign  aclk                = dco_clk;
889 134 olivier.gi
    `endif
890 202 olivier.gi
    wire    UNUSED_cpu_en_aux_s = cpu_en_aux_s;
891 134 olivier.gi
  `endif
892
 
893 202 olivier.gi
 `ifdef LFXT_DOMAIN
894
 `else
895
    wire    UNUSED_lfxt_clk     = lfxt_clk;
896
 `endif
897 134 olivier.gi
 
898 202 olivier.gi
    assign  aclk_en             = 1'b1;
899 134 olivier.gi
 
900 202 olivier.gi
 
901 134 olivier.gi
// FPGA MODE
902 2 olivier.gi
//----------------------------
903 134 olivier.gi
`else
904
  reg       aclk_en;
905
  reg [2:0] aclk_div;
906
  wire      aclk_en_nxt =  lfxt_clk_en & ((bcsctl1[`DIVAx]==2'b00) ?  1'b1          :
907
                                          (bcsctl1[`DIVAx]==2'b01) ?  aclk_div[0]   :
908
                                          (bcsctl1[`DIVAx]==2'b10) ? &aclk_div[1:0] :
909
                                                                     &aclk_div[2:0]);
910 2 olivier.gi
 
911 202 olivier.gi
  always @ (posedge nodiv_mclk or posedge puc_rst)
912 134 olivier.gi
    if (puc_rst)                                     aclk_div <=  3'h0;
913
    else if ((bcsctl1[`DIVAx]!=2'b00) & lfxt_clk_en) aclk_div <=  aclk_div+3'h1;
914
 
915 202 olivier.gi
  always @ (posedge nodiv_mclk or posedge puc_rst)
916 134 olivier.gi
    if (puc_rst)  aclk_en <=  1'b0;
917
    else          aclk_en <=  aclk_en_nxt & cpu_en_s;
918
 
919 202 olivier.gi
  assign  aclk               = nodiv_mclk;
920
 
921
  wire    UNUSED_scan_enable = scan_enable;
922
  wire    UNUSED_scan_mode   = scan_mode;
923 134 olivier.gi
`endif
924 202 olivier.gi
 
925
 
926 134 olivier.gi
//-----------------------------------------------------------
927
// 6.4) SMCLK GENERATION
928
//-----------------------------------------------------------
929
 
930
// Clock MUX
931
//----------------------------
932
`ifdef SMCLK_MUX
933
omsp_clock_mux clock_mux_smclk (
934
   .clk_out   (nodiv_smclk),
935
   .clk_in0   (dco_clk),
936
   .clk_in1   (lfxt_clk),
937
   .reset     (por),
938
   .scan_mode (scan_mode),
939 202 olivier.gi
   .select_in (bcsctl2[`SELS])
940 134 olivier.gi
);
941
`else
942
assign nodiv_smclk = dco_clk;
943
`endif
944
 
945
 
946
// ASIC MODE
947
//----------------------------
948 180 olivier.gi
`ifdef ASIC_CLOCKING
949 134 olivier.gi
  `ifdef SMCLK_MUX
950
 
951 202 olivier.gi
    // SMCLK_MUX Synchronizers
952 134 olivier.gi
    //------------------------------------------------------
953
    // When the SMCLK MUX is enabled, the reset and DIVSx
954
    // and SCG1 signals must be synchronized, otherwise not.
955 202 olivier.gi
 
956 134 olivier.gi
     // Local Reset synchronizer
957
     wire puc_sm_noscan_n;
958
     wire puc_sm_rst;
959
     omsp_sync_cell sync_cell_puc_sm (
960
         .data_out     (puc_sm_noscan_n),
961
         .data_in      (1'b1),
962
         .clk          (nodiv_smclk),
963
         .rst          (puc_rst)
964
     );
965
     omsp_scan_mux scan_mux_puc_sm (
966
         .scan_mode    (scan_mode),
967
         .data_in_scan (por_a),
968
         .data_in_func (~puc_sm_noscan_n),
969
         .data_out     (puc_sm_rst)
970
     );
971
 
972
     // SCG1 synchronizer
973 202 olivier.gi
     wire scg1_s;
974 134 olivier.gi
     `ifdef SCG1_EN
975
     omsp_sync_cell sync_cell_scg1 (
976
         .data_out     (scg1_s),
977
         .data_in      (scg1),
978
         .clk          (nodiv_smclk),
979
         .rst          (puc_sm_rst)
980
     );
981
     `else
982 202 olivier.gi
     assign scg1_s            = 1'b0;
983
     wire   UNUSED_scg1       = scg1;
984
     wire   UNUSED_puc_sm_rst = puc_sm_rst;
985 134 olivier.gi
     `endif
986
 
987
    `ifdef SMCLK_DIVIDER
988
     // Local synchronizer for the bcsctl2.DIVSx configuration
989
     // (note that we can live with a full bus synchronizer as
990
     //  it won't hurt if we get a wrong DIVSx value for a single clock cycle)
991
     reg [1:0] divsx_s;
992
     reg [1:0] divsx_ss;
993
     always @ (posedge nodiv_smclk or posedge puc_sm_rst)
994
       if (puc_sm_rst)
995
         begin
996 202 olivier.gi
            divsx_s  <=  2'h0;
997
            divsx_ss <=  2'h0;
998
         end
999 134 olivier.gi
       else
1000 202 olivier.gi
         begin
1001
            divsx_s  <=  bcsctl2[`DIVSx];
1002
            divsx_ss <=  divsx_s;
1003
         end
1004 134 olivier.gi
    `endif
1005 202 olivier.gi
 
1006
  `else
1007
 
1008 134 olivier.gi
      wire       puc_sm_rst   = puc_rst;
1009
      wire [1:0] divsx_ss     = bcsctl2[`DIVSx];
1010
      wire       scg1_s       = scg1;
1011
  `endif
1012
 
1013 202 olivier.gi
   // Wakeup synchronizer
1014
   //----------------------------
1015
   wire scg1_and_mclk_dma_enable_s;
1016
 
1017
   `ifdef SCG1_EN
1018
     `ifdef DMA_IF_EN
1019
       `ifdef SMCLK_MUX
1020
          omsp_sync_cell sync_cell_smclk_dma_wkup (
1021
             .data_out  (scg1_and_mclk_dma_enable_s),
1022
             .data_in   (scg1_and_mclk_dma_wkup | scg1_and_mclk_dma_enable),
1023
             .clk       (nodiv_smclk),
1024
             .rst       (puc_sm_rst)
1025
          );
1026
       `else
1027
           wire scg1_and_mclk_dma_wkup_s;
1028
           omsp_sync_cell sync_cell_smclk_dma_wkup (
1029
             .data_out  (scg1_and_mclk_dma_wkup_s),
1030
             .data_in   (scg1_and_mclk_dma_wkup),
1031
             .clk       (nodiv_smclk),
1032
             .rst       (puc_sm_rst)
1033
          );
1034
          assign scg1_and_mclk_dma_enable_s = scg1_and_mclk_dma_wkup_s | scg1_and_mclk_dma_enable;
1035
       `endif
1036
     `else
1037
      assign scg1_and_mclk_dma_enable_s = 1'b0;
1038
     `endif
1039
   `else
1040
      assign scg1_and_mclk_dma_enable_s = 1'b0;
1041
   `endif
1042
 
1043
 
1044 134 olivier.gi
   // Clock Divider
1045
   //----------------------------
1046 202 olivier.gi
 `ifdef SCG1_EN
1047
   wire smclk_active  =  cpu_en_sm_s & (~scg1_s | scg1_and_mclk_dma_enable_s);
1048
 `else
1049
   wire smclk_active  =  cpu_en_sm_s;
1050
 `endif
1051
 
1052 134 olivier.gi
 `ifdef SMCLK_DIVIDER
1053
   reg [2:0] smclk_div;
1054
   always @ (posedge nodiv_smclk or posedge puc_sm_rst)
1055
     if (puc_sm_rst)             smclk_div <=  3'h0;
1056
     else if ((divsx_ss!=2'b00)) smclk_div <=  smclk_div+3'h1;
1057
 
1058 202 olivier.gi
   wire  smclk_div_sel = ((divsx_ss==2'b00) ?  1'b1           :
1059
                          (divsx_ss==2'b01) ?  smclk_div[0]   :
1060
                          (divsx_ss==2'b10) ? &smclk_div[1:0] :
1061
                                              &smclk_div[2:0]);
1062
 
1063
   wire  smclk_div_en  = smclk_active & smclk_div_sel;
1064 134 olivier.gi
 `else
1065 202 olivier.gi
   wire  smclk_div_en  = smclk_active;
1066 134 olivier.gi
 `endif
1067
 
1068 202 olivier.gi
 
1069 134 olivier.gi
   // Generate sub-system clock
1070
   //----------------------------
1071
 `ifdef SMCLK_CGATE
1072
   omsp_clock_gate clock_gate_smclk (
1073
      .gclk        (smclk),
1074
      .clk         (nodiv_smclk),
1075
      .enable      (smclk_div_en),
1076
      .scan_enable (scan_enable)
1077
   );
1078
 `else
1079
   assign  smclk    = nodiv_smclk;
1080
 `endif
1081 202 olivier.gi
 
1082 134 olivier.gi
   assign  smclk_en = 1'b1;
1083
 
1084
 
1085
// FPGA MODE
1086
//----------------------------
1087
`else
1088 85 olivier.gi
reg       smclk_en;
1089 2 olivier.gi
reg [2:0] smclk_div;
1090
 
1091 202 olivier.gi
wire      smclk_in     = (scg1 & ~(mclk_dma_enable & bcsctl1[`DMA_SCG1])) ? 1'b0        :
1092
                          bcsctl2[`SELS]                                  ? lfxt_clk_en : 1'b1;
1093 2 olivier.gi
 
1094 85 olivier.gi
wire      smclk_en_nxt = smclk_in & ((bcsctl2[`DIVSx]==2'b00) ?  1'b1           :
1095
                                     (bcsctl2[`DIVSx]==2'b01) ?  smclk_div[0]   :
1096
                                     (bcsctl2[`DIVSx]==2'b10) ? &smclk_div[1:0] :
1097
                                                                &smclk_div[2:0]);
1098 202 olivier.gi
 
1099
always @ (posedge nodiv_mclk or posedge puc_rst)
1100 111 olivier.gi
  if (puc_rst)  smclk_en <=  1'b0;
1101
  else          smclk_en <=  smclk_en_nxt & cpu_en_s;
1102 85 olivier.gi
 
1103 202 olivier.gi
always @ (posedge nodiv_mclk or posedge puc_rst)
1104 111 olivier.gi
  if (puc_rst)                                  smclk_div <=  3'h0;
1105 2 olivier.gi
  else if ((bcsctl2[`DIVSx]!=2'b00) & smclk_in) smclk_div <=  smclk_div+3'h1;
1106
 
1107 202 olivier.gi
wire  smclk  = nodiv_mclk;
1108 2 olivier.gi
 
1109 134 olivier.gi
`endif
1110 106 olivier.gi
 
1111 134 olivier.gi
//-----------------------------------------------------------
1112
// 6.5) DEBUG INTERFACE CLOCK GENERATION (DBG_CLK)
1113
//-----------------------------------------------------------
1114 106 olivier.gi
 
1115 134 olivier.gi
// Synchronize DBG_EN signal to MCLK domain
1116
//------------------------------------------
1117
`ifdef DBG_EN
1118
`ifdef SYNC_DBG_EN
1119
    wire dbg_en_n_s;
1120
    omsp_sync_cell sync_cell_dbg_en (
1121
       .data_out  (dbg_en_n_s),
1122
       .data_in   (~dbg_en),
1123 202 olivier.gi
       .clk       (cpu_mclk),
1124 134 olivier.gi
       .rst       (por)
1125
    );
1126 202 olivier.gi
    assign dbg_en_s      = ~dbg_en_n_s;
1127
    wire   dbg_rst_nxt   =  dbg_en_n_s;
1128 134 olivier.gi
`else
1129 202 olivier.gi
    assign dbg_en_s      =  dbg_en;
1130
    wire   dbg_rst_nxt   = ~dbg_en;
1131 134 olivier.gi
`endif
1132
`else
1133 202 olivier.gi
    assign dbg_en_s      =  1'b0;
1134
    wire   dbg_rst_nxt   =  1'b0;
1135
    wire   UNUSED_dbg_en =  dbg_en;
1136 134 olivier.gi
`endif
1137 106 olivier.gi
 
1138 134 olivier.gi
 
1139 202 olivier.gi
 
1140 134 olivier.gi
// Serial Debug Interface Clock gate
1141
//------------------------------------------------
1142
`ifdef DBG_EN
1143 180 olivier.gi
  `ifdef ASIC_CLOCKING
1144 134 olivier.gi
  omsp_clock_gate clock_gate_dbg_clk (
1145
      .gclk        (dbg_clk),
1146 202 olivier.gi
      .clk         (cpu_mclk),
1147 134 olivier.gi
      .enable      (dbg_en_s),
1148
      .scan_enable (scan_enable)
1149
  );
1150
  `else
1151
     assign dbg_clk = dco_clk;
1152
  `endif
1153
`else
1154
     assign dbg_clk = 1'b0;
1155
`endif
1156
 
1157
 
1158 2 olivier.gi
//=============================================================================
1159 134 olivier.gi
// 7)  RESET GENERATION
1160 2 olivier.gi
//=============================================================================
1161 134 olivier.gi
//
1162
// Whenever the reset pin (reset_n) is deasserted, the internal resets of the
1163
// openMSP430 will be released in the following order:
1164
//                1- POR
1165
//                2- DBG_RST (if the sdi interface is enabled, i.e. dbg_en=1)
1166
//                3- PUC
1167
//
1168
// Note: releasing the DBG_RST before PUC is particularly important in order
1169
//       to allow the sdi interface to halt the cpu immediately after a PUC.
1170
//
1171 202 olivier.gi
 
1172 134 olivier.gi
// Generate synchronized POR to MCLK domain
1173
//------------------------------------------
1174 2 olivier.gi
 
1175 134 olivier.gi
// Asynchronous reset source
1176
assign    por_a         =  !reset_n;
1177
wire      por_noscan;
1178 2 olivier.gi
 
1179 134 olivier.gi
// Reset Synchronizer
1180
omsp_sync_reset sync_reset_por (
1181
    .rst_s        (por_noscan),
1182
    .clk          (nodiv_mclk),
1183
    .rst_a        (por_a)
1184 111 olivier.gi
);
1185 2 olivier.gi
 
1186 134 olivier.gi
// Scan Reset Mux
1187
`ifdef ASIC
1188
omsp_scan_mux scan_mux_por (
1189
    .scan_mode    (scan_mode),
1190
    .data_in_scan (por_a),
1191
    .data_in_func (por_noscan),
1192
    .data_out     (por)
1193
);
1194
`else
1195
 assign por = por_noscan;
1196
`endif
1197 106 olivier.gi
 
1198 134 olivier.gi
// Generate synchronized reset for the SDI
1199
//------------------------------------------
1200
`ifdef DBG_EN
1201 111 olivier.gi
 
1202 134 olivier.gi
// Reset Generation
1203
reg  dbg_rst_noscan;
1204 202 olivier.gi
always @ (posedge cpu_mclk or posedge por)
1205 134 olivier.gi
  if (por)  dbg_rst_noscan <=  1'b1;
1206
  else      dbg_rst_noscan <=  dbg_rst_nxt;
1207 2 olivier.gi
 
1208 134 olivier.gi
  // Scan Reset Mux
1209
  `ifdef ASIC
1210
  omsp_scan_mux scan_mux_dbg_rst (
1211
      .scan_mode    (scan_mode),
1212
      .data_in_scan (por_a),
1213
      .data_in_func (dbg_rst_noscan),
1214
      .data_out     (dbg_rst)
1215
  );
1216 111 olivier.gi
  `else
1217 134 olivier.gi
   assign dbg_rst = dbg_rst_noscan;
1218 111 olivier.gi
  `endif
1219
 
1220 106 olivier.gi
`else
1221 134 olivier.gi
   wire   dbg_rst_noscan = 1'b1;
1222
   assign dbg_rst        = 1'b1;
1223 106 olivier.gi
`endif
1224
 
1225
 
1226 134 olivier.gi
// Generate main system reset (PUC_RST)
1227
//--------------------------------------
1228
wire puc_noscan_n;
1229
wire puc_a_scan;
1230 106 olivier.gi
 
1231 134 olivier.gi
// Asynchronous PUC reset
1232
wire puc_a = por | wdt_reset;
1233
 
1234
// Synchronous PUC reset
1235
wire puc_s = dbg_cpu_reset |                              // With the debug interface command
1236
 
1237
            (dbg_en_s & dbg_rst_noscan & ~puc_noscan_n);  // Sequencing making sure PUC is released
1238
                                                          // after DBG_RST if the debug interface is
1239
                                                          // enabled at power-on-reset time
1240
// Scan Reset Mux
1241
`ifdef ASIC
1242
omsp_scan_mux scan_mux_puc_rst_a (
1243
    .scan_mode    (scan_mode),
1244
    .data_in_scan (por_a),
1245
    .data_in_func (puc_a),
1246
    .data_out     (puc_a_scan)
1247
);
1248
`else
1249
  assign puc_a_scan = puc_a;
1250
`endif
1251
 
1252
// Reset Synchronizer
1253
// (required because of the asynchronous watchdog reset)
1254
omsp_sync_cell sync_cell_puc (
1255
    .data_out  (puc_noscan_n),
1256
    .data_in   (~puc_s),
1257 202 olivier.gi
    .clk       (cpu_mclk),
1258 134 olivier.gi
    .rst       (puc_a_scan)
1259
);
1260
 
1261
// Scan Reset Mux
1262
`ifdef ASIC
1263
omsp_scan_mux scan_mux_puc_rst (
1264
    .scan_mode    (scan_mode),
1265
    .data_in_scan (por_a),
1266
    .data_in_func (~puc_noscan_n),
1267
    .data_out     (puc_rst)
1268
);
1269
`else
1270
  assign puc_rst = ~puc_noscan_n;
1271
`endif
1272
 
1273
// PUC pending set the serial debug interface
1274
assign puc_pnd_set = ~puc_noscan_n;
1275
 
1276
 
1277 34 olivier.gi
endmodule // omsp_clock_module
1278 2 olivier.gi
 
1279 103 olivier.gi
`ifdef OMSP_NO_INCLUDE
1280
`else
1281 33 olivier.gi
`include "openMSP430_undefines.v"
1282 103 olivier.gi
`endif

powered by: WebSVN 2.1.0

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