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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [fpga/] [xilinx_avnet_lx9microbard/] [rtl/] [verilog/] [openmsp430/] [omsp_clock_module.v] - Blame information for rev 205

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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