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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [gpsclock.v] - Blame information for rev 34

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

Line No. Rev Author Line
1 3 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    gpsclock.v
4
//              
5
// Project:     A GPS Schooled Clock Core
6
//
7
// Purpose:     The purpose of this module is to school a counter, run off of
8
//              the FPGA's local oscillator, to match a GPS 1PPS signal.  Should
9
//              the GPS 1PPS vanish, the result will flywheel with its last
10
//              solution (both frequency and phase) until GPS is available
11
//              again.
12
//
13
//              This approach can be used to measure the speed of the
14
//              local oscillator, although there may be other more appropriate
15
//              means to do this.
16
//
17
//              Note that this core does not produce anything more than
18
//              subsecond timing resolution.
19
//
20
// Parameters:  This core needs two parameters set below, the DEFAULT_STEP
21
//              and the DEFAULT_WORD_STEP.  The first must be set to
22
//              2^RW / (nominal local clock rate), whereas the second must be
23
//              set to 2^(RW/2) / (nominal clock rate), where RW is the register
24
//              width used for our computations.  (64 is sufficient for up to
25
//              4 GHz clock speeds, 56 is minimum for 100 MHz.)  Although
26
//              RW is listed as a variable parameter, I have no plans to 
27
//              test values other than 64.  So your mileage might vary there.
28
//
29
//              Other parameters, alpha, beta, and gamma are specific to the
30
//              loop bandwidth you would like to choose.  Please see the
31
//              accompanying specification for a selection of what values
32
//              may be useful.
33
//
34
// Inputs:
35
//      i_clk   A synchronous clock signal for all logic.  Must be slow enough
36
//              that the FPGA can accomplish 64 bit math.
37
//
38
//      i_rst   Resets the clock speed / counter step to be the nominal
39
//              value given by our parameter.  This is useful in case the
40
//              control loop has gone off into never never land and doesn't
41
//              seem to be returning.
42
//
43
//      i_pps   The 1PPS signal from the GPS chip.
44
//
45
//      Wishbone bus
46
//
47
// Outputs:     
48
//      o_led   No circuit would be complete without a properly blinking LED.
49
//              This one blinks an LED at the top of the GPS 1PPS and the
50
//              internal 1PPS.  When the two match, the LED will be on for
51
//              1/16th of a second.  When no GPS 1PPS is present, the LED
52
//              will blink with a 50% duty cycle.
53
//
54
//      o_tracking      A boolean value indicating whether the control loop
55
//              is open (0) or closed (1).  Does not indicate performance.
56
//
57
//      o_count         A counter, from zero to 2^RW-1, indicating the position
58
//              of the current clock within a second.  (This'll be off by 
59
//              two clocks due to internal latencies.)
60
//
61
//      o_step          The amount the counter, o_count, is stepped each clock.
62
//              This is related to the actual speed of the oscillator (when
63
//              locked) by f_XO = 2^(RW) / o_step.
64
//
65
//      o_err   For those interested in how well this device is performing,
66
//              this is the error signal coming out of the device.
67
//
68
//      o_locked        Indicates a locked condition.  While it should work,
69
//              it isn't the best and most versatile lock indicator.  A better
70
//              indicator should be based upon how good the user wants the
71
//              lock indicator to be.  This isn't that.
72
//
73
//
74
// Creator:     Dan Gisselquist, Ph.D.
75
//              Gisselquist Technology, LLC
76
//
77
////////////////////////////////////////////////////////////////////////////////
78
//
79
// Copyright (C) 2015, Gisselquist Technology, LLC
80
//
81
// This program is free software (firmware): you can redistribute it and/or
82
// modify it under the terms of  the GNU General Public License as published
83
// by the Free Software Foundation, either version 3 of the License, or (at
84
// your option) any later version.
85
//
86
// This program is distributed in the hope that it will be useful, but WITHOUT
87
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
88
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
89
// for more details.
90
//
91
// You should have received a copy of the GNU General Public License along
92
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
93
// target there if the PDF file isn't present.)  If not, see
94
// <http://www.gnu.org/licenses/> for a copy.
95
//
96
// License:     GPL, v3, as defined and found on www.gnu.org,
97
//              http://www.gnu.org/licenses/gpl.html
98
//
99
//
100
////////////////////////////////////////////////////////////////////////////////
101 34 dgisselq
//
102
//
103
// `define      DEBUG
104
//
105 3 dgisselq
module  gpsclock(i_clk, i_rst, i_pps, o_pps, o_led,
106
                i_wb_cyc_stb, i_wb_we, i_wb_addr, i_wb_data,
107
                        o_wb_ack, o_wb_stall, o_wb_data,
108
                o_tracking, o_count, o_step, o_err, o_locked, o_dbg);
109 25 dgisselq
        parameter       DEFAULT_STEP = 32'h834d_c736;//2^64/81.25 MHz
110 3 dgisselq
        parameter       RW=64, // Needs to be 2ceil(Log_2(i_clk frequency))
111
                        DW=32, // The width of our data bus
112
                        ONE_SECOND = 0,
113
                        NPW=RW-DW, // Width of non-parameter data
114
                        HRW=RW/2; // Half of RW
115
        input           i_clk, i_rst;
116
        input           i_pps;  // From the GPS device
117
        output  reg     o_pps;  // To our local circuitry
118
        output  reg     o_led;  // A blinky light showing how well we're doing
119
        // Wishbone Configuration interface
120
        input                           i_wb_cyc_stb, i_wb_we;
121
        input           [1:0]            i_wb_addr;
122
        input           [(DW-1):0]       i_wb_data;
123
        output  reg                     o_wb_ack;
124
        output  wire                    o_wb_stall;
125
        output  reg     [(DW-1):0]       o_wb_data;
126
        // Status and timing outputs
127
        output  reg                     o_tracking; // 1=closed loop, 0=open
128
        output  reg     [(RW-1):0]       o_count, // Fraction of a second
129
                                        o_step, // 2^RW / clock speed (in Hz)
130
                                        o_err; // Fraction of a second err
131
        output  reg                     o_locked; // 1 if Locked, 0 o.w.
132
        output  wire    [1:0]            o_dbg;
133
 
134
 
135
        // Clock resynchronization variables
136
        reg     pps_d, ck_pps, lst_pps;
137
        wire    tick;           // And a variable indicating the top of GPS 1PPS
138
 
139
        //
140
        // Configuration variables.  These control the loop bandwidth, the speed
141
        // of convergence, the speed of adaptation to changes, and more.  If
142
        // you adjust these outside of what the specification recommends, 
143
        // be careful that the control loop still synchronizes!
144
        reg                     new_config;
145
        reg     [5:0]            r_alpha;
146
        reg     [(DW-1):0]       r_beta, r_gamma, r_def_step;
147
        reg     [(RW-1):0]       pre_step;
148
 
149
        //
150
        // This core really operates rather slowly, in FPGA time.  Of the
151
        // millions of ticks per second, we only do things on about less than
152
        // a handful.  These timing signals below help us to determine when
153
        // our data is valid during those handful.
154
        //
155
        // Timing
156 34 dgisselq
        reg     err_tick, shift_tick, config_tick, mpy_aux, mpy_sync_two,
157
                delay_step_clk, step_carry_tick;
158 3 dgisselq
        wire    sub_tick, fltr_tick;
159
 
160
        //
161
        // When tracking, each second we'll produce a lowpass filtered_err
162
        // (via a recursive average), a count_correction and a step_correction.
163
        // The two _correction terms then get applied at the top of the second.
164
        // Here's the declaration of those parameters.  The
165
        // 'pre_count_correction' parameter allows us to avoid adding three
166
        // 64-bit numbers in a single clock, splitting part of that amount into
167
        // an earlier clock.
168
        //
169
        // Tracking
170 34 dgisselq
        reg                     config_filter_errors;
171
        reg     [(RW-1):0]       pre_count_correction, r_count_correction,
172
                                r_filtered_err;
173
        wire    [(RW-1):0]       count_correction;
174 3 dgisselq
        reg     [(HRW-1):0]      step_correction;
175
        reg     [(HRW-1):0]      delayed_step_correction, delayed_step;
176
        reg     signed [(HRW-1):0]       mpy_input;
177
        wire            [(RW-1):0]       w_mpy_out;
178
        wire    signed [(RW-1):0]        filter_sub_count, filtered_err;
179
 
180
 
181
 
182
        //
183
        //
184
        //
185
        // Wishbone access ... adjust our tracking parameters
186
        //
187
        //
188
        //
189 34 dgisselq
        // DEFAULT_STEP = 64'h0000_0034_dc73_67da, // 2^64 / 81.25 MHz
190
        //    = 28'hd371cd9 << (20-10), and hence we have 32'had37_1cd9
191
        // Other useful values:
192
        //      32'had6bf94d    //  80MHz
193
        //      32'haabcc771    // 100MHz
194
        //      32'hbd669d0e    // 160.5MHz
195 25 dgisselq
        initial r_def_step = DEFAULT_STEP;
196 3 dgisselq
        always @(posedge i_clk)
197
                pre_step <= { 16'h00,
198
                        (({ r_def_step[27:0], 20'h00 })>>r_def_step[31:28])};
199
 
200 12 dgisselq
        // Delay writes by one clock
201
        wire    [1:0]    wb_addr;
202
        wire    [31:0]   wb_data;
203
        reg             wb_write;
204
        reg     [1:0]    r_wb_addr;
205
        reg     [31:0]   r_wb_data;
206 34 dgisselq
        reg     [7:0]    lost_ticks;
207
        initial lost_ticks = 0;
208 12 dgisselq
        always @(posedge i_clk)
209
                wb_write <= (i_wb_cyc_stb)&&(i_wb_we);
210
        always @(posedge i_clk)
211
                r_wb_data <= i_wb_data;
212
        always @(posedge i_clk)
213
                r_wb_addr <= i_wb_addr;
214
        assign  wb_data = r_wb_data;
215
        assign  wb_addr = r_wb_addr;
216
 
217 34 dgisselq
        initial config_filter_errors = 1'b1;
218
        initial r_alpha = 6'h2;
219
        initial r_beta  = 32'h14bda12f;
220
        initial r_gamma = 32'h1f533ae8;
221 3 dgisselq
        initial new_config = 1'b0;
222
        always @(posedge i_clk)
223 12 dgisselq
                if (wb_write)
224 3 dgisselq
                begin
225 34 dgisselq
                        new_config <= 1'b1;
226 12 dgisselq
                        case(wb_addr)
227 34 dgisselq
                        2'b00: begin
228
                                r_alpha    <= wb_data[5:0];
229
                                config_filter_errors <= (wb_data[5:0] != 6'h0);
230
                                end
231 12 dgisselq
                        2'b01: r_beta     <= wb_data;
232
                        2'b10: r_gamma    <= wb_data;
233
                        2'b11: r_def_step <= wb_data;
234 25 dgisselq
                        // default: begin end
235 3 dgisselq
                        // r_defstep <= i_wb_data;
236
                        endcase
237
                end else
238 34 dgisselq
                        new_config <= 1'b0;
239 3 dgisselq
        always @(posedge i_clk)
240
                case (i_wb_addr)
241 34 dgisselq
                        2'b00: o_wb_data <= { lost_ticks, 18'h00, r_alpha };
242 3 dgisselq
                        2'b01: o_wb_data <= r_beta;
243
                        2'b10: o_wb_data <= r_gamma;
244
                        2'b11: o_wb_data <= r_def_step;
245 25 dgisselq
                        // default: o_wb_data <= 0;
246 3 dgisselq
                endcase
247
 
248
        reg     dly_config;
249
        initial dly_config = 1'b0;
250
        always @(posedge i_clk)
251
                dly_config <= new_config;
252
        always @(posedge i_clk)
253
                o_wb_ack <= i_wb_cyc_stb;
254
        assign  o_wb_stall = 1'b0;
255
 
256
 
257
        //
258
        //
259
        // Deal with the realities of an unsynchronized 1PPS signal: 
260
        // register it with two flip flops to avoid metastability issues.
261
        // Create a 'tick' variable to note the top of a second.
262
        //
263
        //
264
        always @(posedge i_clk)
265 34 dgisselq
        begin // This will delay our resulting time by a known 2 clock ticks
266 3 dgisselq
                pps_d <= i_pps;
267
                ck_pps <= pps_d;
268
                lst_pps <= ck_pps;
269
        end
270
 
271
        // Provide a touch of debounce protection ... equal to about
272 34 dgisselq
        // one quarter of a second.  This is a coarse predictor, however,
273
        // since it uses only the top 32-bits of the step.
274
        //
275
        // Here's the idea: on any tick, we start a 32-bit counter, stepping
276
        // unevenly by o_step[61:30] at each tick.  Once the counter crosses
277
        // zero, we stop counting and we enable the clock tick.  Since the
278
        // counter should overflow 4x per second (assuming our clock rate is
279
        // less than 16GHz), we should be good to go.  Oh, and we also round
280
        // our step up by one ... to guarantee that we always end earlier than
281
        // designed, rather than ever later.
282
        //
283
        wire            w_tick_enable;
284
        reg     [31:0]   tick_enable_counter;
285
        reg             tick_enable_carry;
286
        initial tick_enable_carry   = 0;
287 3 dgisselq
        initial tick_enable_counter = 0;
288
        always @(posedge i_clk)
289
        begin
290 34 dgisselq
                if ((ck_pps)&&(~lst_pps))
291
                        { tick_enable_carry, tick_enable_counter } <= 0;
292
                else if (tick_enable_carry)
293
                        tick_enable_counter <= 32'hffff_ffff;
294 3 dgisselq
                else
295 34 dgisselq
                        {tick_enable_carry, tick_enable_counter}
296
                                <= o_step[(RW-3):(RW-34)]
297
                                        + tick_enable_counter + 1'b1;
298 3 dgisselq
        end
299 34 dgisselq
        assign  w_tick_enable = tick_enable_carry;
300 3 dgisselq
 
301
        assign  tick= (ck_pps)&&(~lst_pps)&&(w_tick_enable);
302 34 dgisselq
        always @(posedge i_clk)
303
                if (wb_write)
304
                        lost_ticks <= 8'h00;
305
                else if ((ck_pps)&&(~lst_pps)&&(!w_tick_enable))
306
                        lost_ticks <= lost_ticks+1'b1;
307 3 dgisselq
        assign  o_dbg[0] = tick;
308
        assign  o_dbg[1] = w_tick_enable;
309
 
310
        //
311
        //
312
        // Here's our counter proper: Add o_step to o_count each clock tick
313
        // to have a current time value.  Corrections are applied at the top
314
        // of the second if we are in tracking mode.  The 'o_pps' signal is
315
        // generated from the carry/overflow of the o_count addition.
316
        //
317 34 dgisselq
        // The output of this loop, both o_pps and o_count, is the current
318
        // subsecond time as determined by this clock.
319 3 dgisselq
        //
320 34 dgisselq
        //
321 3 dgisselq
        reg     cnt_carry;
322
        reg     [31:0]   p_count;
323
        initial o_count = 0;
324
        initial o_pps = 1'b0;
325
        always @(posedge i_clk)
326 34 dgisselq
`ifndef USE_THE_OLD_CODE
327
                begin
328
                // Very simple: we add the count correction, which is given by
329
                // a pre-determined sum of the step and any error, to our
330
                // "count" at every clock tick.  If this ever overflows, the
331
                // overflow or carry is our PPS signal.  Unlike the last time
332
                // we built this logic, here we acknowledge that the count
333
                // correction can never be negative.  As a result, we have no
334
                // o_pps suppression.
335
                { cnt_carry, p_count } <= p_count[31:0] + r_count_correction[31:0];
336
                { o_pps, o_count[63:32] } <= o_count[63:32]
337
                                + r_count_correction[63:32]
338
                                + { 31'h00, cnt_carry };
339
                if (r_count_correction[(RW-1)])
340
                        o_pps <= 1'b0;
341
                // Delay the bottom bits of o_count by one clock, so that they
342
                // now match up with the top bits.
343
                o_count[31:0] <= p_count;
344
                end
345
`else
346 3 dgisselq
                if ((o_tracking)&&(tick))
347
                begin
348 34 dgisselq
                        // Save the carry to be applied at the next clock, so
349
                        // that we never have to do more than a 32-bit add.
350
                        // (well, okay, a 33-bit add ...)
351
                        //
352
                        // The count_correction value here is really our step,
353
                        // plus a value determined from our filter loop.
354
                        { cnt_carry, p_count }
355
                           <= p_count[31:0] + count_correction[31:0];
356
                        //
357
                        // On the second clock, we add the high order bits
358
                        // together, and possibly get a carry.  We use this
359
                        // carry as our o_pps output.
360 3 dgisselq
                        if (~count_correction[(RW-1)])
361
                        begin
362 34 dgisselq
                                // Here, we need to correct by jumping forward.
363
                                //
364 3 dgisselq
                                // Note that we don't create an o_pps just
365
                                // because the gps_pps states that there should
366
                                // be one.  Instead, we hold to the normal
367
                                // means of business.  At the tick, however,
368
                                // we add both the step and the correction to
369
                                // the current count.
370 34 dgisselq
                                { o_pps, o_count[63:32] } <= o_count[63:32]
371
                                        + count_correction[63:32]
372
                                        + { 31'h00, cnt_carry };
373 3 dgisselq
                        end else begin
374
                                // If the count correction is negative, it means
375
                                // we need to go backwards.  In this case,
376
                                // there shouldn't be any o_pps, least we get
377 34 dgisselq
                                // two of them.  So ... we skip an output PPS,
378
                                // knowing the correct PPS is coming next.
379 3 dgisselq
                                o_pps <= 1'b0;
380 34 dgisselq
                                o_count[63:32] <= o_count[63:32]
381
                                                + count_correction[63:32]
382
                                        + { 31'h00, cnt_carry };
383 3 dgisselq
                        end
384
                end else begin
385
                        // The difference between count_correction and
386
                        // o_step is the phase correction from the last tick.
387
                        // If we aren't tracking, we don't want to use the
388
                        // correction.  Likewise, even if we are, we only
389
                        // want to use it on the ticks.
390
                        { cnt_carry, p_count } <= p_count + o_step[31:0];
391 34 dgisselq
                        { o_pps, o_count[63:32] } <= o_count[63:32]
392
                                                + o_step[63:32]
393
                                                + { 31'h00, cnt_carry};
394 3 dgisselq
                end
395 34 dgisselq
 
396
        // Here we delay the bottom bits of o_count by one clock, so that they
397
        // now match up with the top bits.
398 3 dgisselq
        always @(posedge i_clk)
399
                o_count[31:0] <= p_count;
400 34 dgisselq
`endif
401 3 dgisselq
 
402 34 dgisselq
 
403
 
404
        //
405
        // The step
406
        //
407
        // The counter above is only as good as the step size given to it.
408
        // Here, we work with that step size, and apply a correction based
409
        // upon the last tick.  The idea in the step correction is that we
410
        // wish to add this step correction to our step amount.  We have one
411
        // clock tick (i.e. one second) from when we make our error measurement
412
        // until we must apply the correction.
413
        //
414
        // The correction, calculated far below, will be placed into the value
415
        //
416
        //      step_correction
417
        //
418
        // We just need to figure out what the new step will be here, given
419
        // that correction.
420
        //
421 3 dgisselq
        reg     [(HRW):0]        step_correction_plus_carry;
422
        always @(posedge i_clk)
423 34 dgisselq
                if (step_carry_tick)
424
                        step_correction_plus_carry
425
                                <= { step_correction[(HRW-1)],step_correction }
426
                                        + { 32'h00, delayed_carry };
427 3 dgisselq
 
428 34 dgisselq
 
429 3 dgisselq
        wire    w_step_correct_unused;
430
        wire    [(RW-1):0]       new_step;
431
        bigadd  getnewstep(i_clk, 1'b0, o_step,
432
                        { { (HRW-1){step_correction_plus_carry[HRW]} },
433
                                step_correction_plus_carry},
434
                        new_step, w_step_correct_unused);
435
 
436
        reg     delayed_carry;
437
        initial delayed_carry = 0;
438 34 dgisselq
 
439
        wire    [31:0]   initial_default_step = DEFAULT_STEP;
440
        // initial      o_step = 64'h002af31dc461; // 100MHz
441
        initial o_step = { 16'h00, (({ initial_default_step[27:0], 20'h00 })
442
                                >> initial_default_step[31:28])};
443 3 dgisselq
        always @(posedge i_clk)
444
                if ((i_rst)||(dly_config))
445
                        o_step <= pre_step;
446 34 dgisselq
`ifndef DEBUG
447 3 dgisselq
                else if ((o_tracking) && (tick))
448 34 dgisselq
                         o_step <= new_step;
449
`endif
450 3 dgisselq
 
451
        initial delayed_step = 0;
452
        always @(posedge i_clk)
453
                if ((i_rst)||(dly_config))
454 34 dgisselq
                        { delayed_carry, delayed_step } <= 0;
455 3 dgisselq
                else if (delay_step_clk)
456
                        { delayed_carry, delayed_step } <= delayed_step
457
                                        + delayed_step_correction;
458
 
459
 
460
 
461
        //
462
        //
463
        // Now to start our tracking loop.  The steps are:
464
        //      1. Measure our error
465
        //      2. Filter our error (lowpass, recursive averager)
466
        //      3. Multiply the filtered error by two user-supplied constants
467
        //              (beta and gamma)
468
        //      4. The results of this multiply then become the new
469
        //              count and step corrections.
470
        //
471
        //
472
        // A negative error means we were too fast ... the count rolled over
473
        // and is near zero, the o_err is then the negation of this when the
474
        // tick does show up.
475
        //
476 34 dgisselq
 
477
        // Note that our measured error, o_err, will be valid one tick *after*
478
        // the top of the second tick (tick).
479
        //
480
        // ONE_SECOND in this equation is set to 2^64, or zero during
481
        // implementation.  This makes the 64-bit subtract ... doable.
482 3 dgisselq
        initial o_err = 0;
483
        always @(posedge i_clk)
484
                if (tick)
485
                        o_err <= ONE_SECOND - o_count;
486
 
487 34 dgisselq
        // Because o_err is delayed one clock from the tick, we create a strobe
488
        // capturing when the error is valid.
489 3 dgisselq
        initial err_tick = 1'b0;
490
        always @(posedge i_clk)
491
                err_tick <= tick;
492
 
493 34 dgisselq
        //
494
        // We are now going to filter this error, via:
495
        //
496
        //      filtered_err <= o_err>>r_alpha + (1-1>>r_alpha)*filtered_err
497
        //
498
        // This implements a very simple recursive averager.
499
        //
500
        // You may not recognize it below, though, since we have simplified the
501
        // equation into:
502
        //
503
        //      filtered_err <= filtered_err + (o_err - filtered_err)>>r_alpha
504
        //
505
 
506
        // On some architectures, adding and subtracting 64'bit number cannot
507
        // be done in a single clock tick.  On these architectures, we may
508
        // take a couple clocks.  Here, the "bigsub" module captures what it 
509
        // takes to subtract 64-bit numbers.
510
        //
511
        // Either way, here we subtract our error from our filtered_err.  This
512
        // is the first step of the recursive average--figuring out what value
513
        // we are going to apply to the recursive average.
514 3 dgisselq
        bigsub  suberri(i_clk, err_tick, o_err,
515
                        filtered_err, filter_sub_count, sub_tick);
516
 
517
        //
518
        // This shouldn't be required: We only want to shift our 
519
        // filter_sub_count by r_alpha bits, why the extra struggles?
520
        // Why is because Verilator decides that these values are unsigned,
521
        // and so despite being told that they are signed values, verilator
522
        // doesn't sign extend them upon shifting.  Put together,
523 34 dgisselq
        // { shift_hi[low-bits], shift_lo[low-bits] } make up a full RW (i.e.64)
524 3 dgisselq
        // bit correction factor.
525
        reg     signed [(RW-1):0] shift_hi, shift_lo;
526
        always @(posedge i_clk)
527
        begin
528 34 dgisselq
                shift_tick<= sub_tick;
529
 
530
                // Because we do our add (below) on *every* clock tick, we must
531
                // make certain that the value we add to it is only non-zero
532
                // on one clock tick.  Hence, we wait for sub_tick to be true,
533
                // set the value, and otherwise keep it clear.
534
                if (sub_tick)
535
                begin
536
                        shift_hi <= { {(HRW){filter_sub_count[(RW-1)]}},
537 3 dgisselq
                                filter_sub_count[(RW-1):HRW] }>>r_alpha;
538 34 dgisselq
                        shift_lo <= filter_sub_count[(RW-1):0]>>r_alpha;
539
                end else begin
540
                        shift_hi <= 0;
541
                        shift_lo <= 0;
542
                end
543 3 dgisselq
        end
544
 
545 34 dgisselq
        // You may notice, it's now been several clocks since the top of the
546
        // second.  Still, filtered_err hasn't changed.  It only changes once
547
        // a second based upon the results of these computations.  Here we take
548
        // another clock (or two) to figure out the next step in our algorithm.
549
        bigadd adderr(i_clk, shift_tick, r_filtered_err,
550 3 dgisselq
                        { shift_hi[(HRW-1):0], shift_lo[(HRW-1):0] },
551
                        filtered_err, fltr_tick);
552 34 dgisselq
 
553 3 dgisselq
        always @(posedge i_clk)
554 34 dgisselq
                if (fltr_tick)
555
                        r_filtered_err <= filtered_err;
556
                else if ((dly_config)||(!o_tracking))
557
                        r_filtered_err <= 0;
558 3 dgisselq
 
559 34 dgisselq
        reg     [(RW-1):0]       r_mpy_err;
560 3 dgisselq
        always @(posedge i_clk)
561 34 dgisselq
                if (err_tick)
562
                r_mpy_err <= (config_filter_errors) ? r_filtered_err : o_err;
563
        always @(posedge i_clk)
564
                config_tick <= err_tick;
565
 
566
        // Okay, so we've gone from our original tick to the err_tick, the
567
        // sub_tick, the shift_tick, and now the fltr_tick. 
568
        //
569
        // We want to multiply our filtered error by one of two constants.
570
        // Here, we set up those constants.  We use the fltr_tick as a strobe,
571
        // but also to select one particular constant.  When the multiply comes
572
        // back, and the strobe is true, we'll know that the constant going
573
        // in with the strobe on (r_beta) corresponds to the product coming out,
574
        // and that the second product we need will be on the next clock.
575
        always @(posedge i_clk)
576
                if (err_tick)
577 3 dgisselq
                        mpy_input <= r_beta;
578
                else
579
                        mpy_input <= r_gamma;
580
        always @(posedge i_clk)
581 34 dgisselq
                mpy_aux <= err_tick;
582 3 dgisselq
 
583
        //
584
        // The multiply
585
        //
586 34 dgisselq
        // Remember, we take our filtered error and multiply it by a constant
587
        // to determine our step correction and another constant to determine
588
        // our count correction?  We'll ... here's that multiply.
589
        //
590 3 dgisselq
        wire                    mpy_sync;
591
        initial mpy_sync_two = 1'b0;
592
        // Sign extend all inputs to RW bits
593
        wire    signed  [(RW-1):0]       w_mpy_input, w_mpy_err;
594 34 dgisselq
        assign  w_mpy_input = { {(RW-DW){mpy_input[(DW-1)]}},
595
                                                mpy_input[(DW-1):0]};
596
        assign  w_mpy_err   = { {(RW-NPW){r_mpy_err[(RW-1)]}},
597
                                                r_mpy_err[(RW-1):(RW-NPW)]};
598
        //
599
        // Here's our big multiply.
600
        //
601
        bigsmpy #(.NCLOCKS(1))
602
                mpyi(i_clk, mpy_aux, 1'b1, w_mpy_input[31:0], w_mpy_err[31:0],
603
                        w_mpy_out, mpy_sync);
604
 
605
        // We use this to grab the second product from the multiply.  This
606
        // second product is true the clock after mpy_sync is high, so we
607
        // just do a simple delay to get this strobe logic.
608 3 dgisselq
        always @(posedge i_clk)
609
                mpy_sync_two <= mpy_sync;
610
 
611 34 dgisselq
 
612 3 dgisselq
        // The post-multiply
613 34 dgisselq
        //
614
        // Remember, the mpy_sync line coming out of the multiply will be true
615
        // when the product of the error and i_beta comes out.
616
        //
617 3 dgisselq
        initial pre_count_correction    = 0;
618
        initial step_correction         = 0;
619
        initial delayed_step_correction = 0;
620
        always @(posedge i_clk)
621 34 dgisselq
                if (mpy_sync)   // i_beta product
622 3 dgisselq
                        pre_count_correction <= w_mpy_out;
623 34 dgisselq
        always @(posedge i_clk)
624
                if (mpy_sync_two) begin // i_gamma product
625 3 dgisselq
                        step_correction <= w_mpy_out[(RW-1):HRW];
626
                        delayed_step_correction <= w_mpy_out[(HRW-1):0];
627
                end
628 34 dgisselq
 
629
`ifdef  DEBUG
630
        assign  count_correction = o_step;
631
`else
632
        // The correction for the number of counts in our counter is given
633
        // by pre_count_correction.  When we add this to the counter, we'll
634
        // need to add the step to it as well.  To help timing out with 64-bit
635
        // math, let's do that step+correction math here, so that we can later
636
        // do 
637
        //      counts = counts + count_correction
638
        // instead of
639
        //      counts = counts + step + pre_count_correction
640
        // saves us one addition--especially since we have the clock to do this.
641
        wire    count_correction_strobe;
642
        bigadd  ccounts(i_clk, mpy_sync_two, o_step, pre_count_correction,
643
                        count_correction, count_correction_strobe);
644
 
645
        // Our original plan was to apply this correction at the top of the
646
        // second.  The problem is that our loop filter math depends upon this
647
        // correction being applied before the top of the second error gets
648
        // measured.  Hence, we'll apply it at some time mid-second, not
649
        // long after the error is measured (w/in 16 clocks or so), and never
650
        // notice the difference until the top of the next second where it 
651
        // now appears to have properly taken place.
652 3 dgisselq
        always @(posedge i_clk)
653 34 dgisselq
                if (count_correction_strobe)
654
                        r_count_correction <= count_correction;
655
                else
656
                        r_count_correction <= o_step;
657
`endif
658 3 dgisselq
 
659
        initial delay_step_clk = 1'b0;
660
        always @(posedge i_clk)
661
                delay_step_clk <= mpy_sync_two;
662 34 dgisselq
        initial step_carry_tick = 1'b0;
663
        always @(posedge i_clk)
664
                step_carry_tick <= delay_step_clk;
665 3 dgisselq
 
666
        //
667
        //
668
        // LED Logic -- Note that this is where we tell if we've had a GPS
669
        // 1PPS pulse or not.  To have had such a pulse, it needs to have
670
        // been within the last two seconds.
671
        //
672
        //
673
        reg     no_pulse;
674
        reg     [32:0]   time_since_pps;
675
        initial no_pulse = 1'b1;
676
        initial time_since_pps = 33'hffffffff;
677
        always @(posedge i_clk)
678
                if (tick)
679
                begin
680
                        time_since_pps <= 0;
681
                        no_pulse <= 0;
682
                end else if (time_since_pps[32:29] == 4'hf)
683
                begin
684
                        time_since_pps <= 33'hffffffff;
685
                        no_pulse <= 1'b1;
686
                end else
687
                        time_since_pps <= time_since_pps + pre_step[(RW-1):HRW];
688
 
689
        //
690
        // 1. Pulse with a 50% duty cycle every second if no GPS is available.
691
        // 2. Pulse with a 6% duty cycle any time a pulse is present, and any
692
        //      time we think (when a pulse is present) that we have time.
693
        //
694
        // This should produce a set of conflicting pulses when out of lock,
695
        // and a nice short once per second pulse when locked.  Further, you
696
        // should be able to tell when the core is flywheeling by the duration
697
        // of the pulses (50% vs 6%).
698
        //
699
        always @(posedge i_clk)
700
                if (no_pulse)
701
                        o_led <= o_count[(RW-1)];
702
                else
703
                        o_led <= ((time_since_pps[31:28] == 4'h0)
704
                                ||(o_count[(RW-1):(RW-4)]== 4'h0));
705
 
706
        //
707
        //
708
        // Now, are we tracking or not?
709
        // We'll attempt to close the loop after seeing 7 valid GPS 1PPS
710
        // rising edges.
711
        //
712
        //
713
        reg     [2:0]    count_valid_ticks;
714
        initial count_valid_ticks = 3'h0;
715
        always @(posedge i_clk)
716
                if ((tick)&&(count_valid_ticks < 3'h7))
717
                        count_valid_ticks <= count_valid_ticks+1;
718
                else if (no_pulse)
719
                        count_valid_ticks <= 3'h0;
720
        initial o_tracking = 1'b0;
721
        always @(posedge i_clk)
722 34 dgisselq
                if (dly_config) // Break the tracking loop on a config change
723
                        o_tracking <= 1'b0;
724
                else if ((tick)&&(&count_valid_ticks))
725 3 dgisselq
                        o_tracking <= 1'b1;
726
                else if ((tick)||(count_valid_ticks == 0))
727
                        o_tracking <= 1'b0;
728
 
729
        //
730
        //
731
        // Are we locked or not?
732
        // We'll use the top eight bits of our error to tell.  If the top eight
733
        // bits are all ones or all zeros, then we'll call ourselves locked.
734
        // This is equivalent to calling ourselves locked if, at the top of
735
        // the second, we are within 1/128th of a second of the GPS 1PPS.
736
        //
737
        initial o_locked = 1'b0;
738
        always @(posedge i_clk)
739
                if ((o_tracking)&&(tick)&&(
740
                        ((   o_err[(RW-1)])&&(o_err[(RW-1):(RW-8)]==8'hff))
741
                        ||((~o_err[(RW-1)])&&(o_err[(RW-1):(RW-8)]==8'h00))))
742
                        o_locked <= 1'b1;
743
                else if (tick)
744
                        o_locked <= 1'b0;
745
 
746
endmodule
747
 

powered by: WebSVN 2.1.0

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