Line 11... |
Line 11... |
// finely tracked clock speed output, to allow for fine clock precision
|
// finely tracked clock speed output, to allow for fine clock precision
|
// and good freewheeling even if/when GPS is lost.
|
// and good freewheeling even if/when GPS is lost.
|
//
|
//
|
//
|
//
|
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Tecnology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
//
|
//
|
Line 50... |
Line 50... |
// Output controls
|
// Output controls
|
o_sseg, o_led, o_interrupt,
|
o_sseg, o_led, o_interrupt,
|
// A once-per-day strobe on the last clock of the day
|
// A once-per-day strobe on the last clock of the day
|
o_ppd,
|
o_ppd,
|
// GPS interface
|
// GPS interface
|
i_gps_valid, i_gps_pps, i_gps_ckspeed);
|
i_gps_valid, i_gps_pps, i_gps_ckspeed,
|
|
// Our personal timing, for debug purposes
|
|
o_rtc_pps);
|
parameter DEFAULT_SPEED = 32'd2814750; //2af31e = 2^48 / 100e6 MHz
|
parameter DEFAULT_SPEED = 32'd2814750; //2af31e = 2^48 / 100e6 MHz
|
input i_clk;
|
input i_clk;
|
input i_wb_cyc, i_wb_stb, i_wb_we;
|
input i_wb_cyc, i_wb_stb, i_wb_we;
|
input [1:0] i_wb_addr;
|
input [1:0] i_wb_addr;
|
input [31:0] i_wb_data;
|
input [31:0] i_wb_data;
|
Line 64... |
Line 66... |
output wire [15:0] o_led;
|
output wire [15:0] o_led;
|
output wire o_interrupt, o_ppd;
|
output wire o_interrupt, o_ppd;
|
// GPS interface
|
// GPS interface
|
input i_gps_valid, i_gps_pps;
|
input i_gps_valid, i_gps_pps;
|
input [31:0] i_gps_ckspeed;
|
input [31:0] i_gps_ckspeed;
|
|
// Personal PPS
|
|
output wire o_rtc_pps;
|
|
|
reg [23:0] clock;
|
reg [23:0] clock;
|
reg [31:0] stopwatch, ckspeed;
|
reg [31:0] stopwatch, ckspeed;
|
reg [25:0] timer;
|
reg [25:0] timer;
|
|
|
Line 78... |
Line 82... |
assign al_sel = ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_addr==2'b11));
|
assign al_sel = ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_addr==2'b11));
|
|
|
reg [39:0] ck_counter;
|
reg [39:0] ck_counter;
|
reg ck_carry;
|
reg ck_carry;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
|
if ((i_gps_valid)&&(i_gps_pps))
|
|
begin
|
|
ck_carry <= 0;
|
|
// Start our counter 2 clocks into the future.
|
|
// Why? Because if we hit the PPS, we'll be delayed
|
|
// one clock from true time. This (hopefully) locks
|
|
// us back onto true time. Further, if we end up
|
|
// off (i.e., go off before the GPS tick ...) then
|
|
// the GPS tick will put us back on track ... likewise
|
|
// we've got code following that should keep us from
|
|
// ever producing two PPS's per second.
|
|
ck_counter <= { 7'h00, ckspeed, 1'b0 };
|
|
end else
|
{ ck_carry, ck_counter } <= ck_counter + { 8'h00, ckspeed };
|
{ ck_carry, ck_counter } <= ck_counter + { 8'h00, ckspeed };
|
|
|
wire ck_pps;
|
reg ck_pps;
|
reg ck_prepps, ck_ppm, ck_pph, ck_ppd;
|
reg ck_ppm, ck_pph, ck_ppd;
|
reg [7:0] ck_sub;
|
reg [7:0] ck_sub;
|
initial clock = 24'h00000000;
|
initial clock = 24'h00000000;
|
assign ck_pps = (ck_carry)&&(ck_prepps);
|
always @(posedge i_clk)
|
|
if ((i_gps_pps)&&(i_gps_valid)&&(ck_sub[7]))
|
|
ck_pps <= 1'b1;
|
|
else if ((ck_carry)&&(ck_sub == 8'hff))
|
|
ck_pps <= 1'b1;
|
|
else
|
|
ck_pps <= 1'b0;
|
|
|
|
assign o_rtc_pps = ck_pps;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
if ((i_gps_valid)&&(i_gps_pps))
|
if ((i_gps_valid)&&(i_gps_pps))
|
ck_sub <= 0;
|
ck_sub <= 0;
|
else if (ck_carry)
|
else if (ck_carry)
|
ck_sub <= ck_sub + 1;
|
ck_sub <= ck_sub + 1;
|
if (i_gps_valid)
|
|
ck_prepps <= i_gps_pps;
|
|
else
|
|
ck_prepps <= (ck_sub == 8'hff);
|
|
|
|
if (ck_pps)
|
if (ck_pps)
|
begin // advance the seconds
|
begin // advance the seconds
|
if (clock[3:0] >= 4'h9)
|
if (clock[3:0] >= 4'h9)
|
clock[3:0] <= 4'h0;
|
clock[3:0] <= 4'h0;
|
Line 425... |
Line 446... |
dmask[3] <= (2'b00 != clock[21:20]);
|
dmask[3] <= (2'b00 != clock[21:20]);
|
end
|
end
|
endcase
|
endcase
|
|
|
wire [31:0] w_sseg;
|
wire [31:0] w_sseg;
|
assign w_sseg[ 0] = (~ck_sub[7]);
|
assign w_sseg[ 0] = (i_gps_valid)?(ck_sub[7:5]==3'h0):(~ck_sub[0]);
|
assign w_sseg[ 8] = (~ck_sub[6])&&(~ck_sub[7]);
|
assign w_sseg[ 8] = (i_gps_valid)?(ck_sub[7:5]==3'h0):(~ck_sub[0]);
|
assign w_sseg[16] = (~ck_sub[5])&&(~ck_sub[6])&&(~ck_sub[7]);
|
assign w_sseg[16] = (i_gps_valid)?(ck_sub[7:5]==3'h0):(~ck_sub[0]);
|
|
// assign w_sseg[ 8] = w_sseg[0];
|
|
// assign w_sseg[16] = w_sseg[0];
|
assign w_sseg[24] = 1'b0;
|
assign w_sseg[24] = 1'b0;
|
hexmap ha(i_clk, h_sseg[ 3: 0], w_sseg[ 7: 1]);
|
hexmap ha(i_clk, h_sseg[ 3: 0], w_sseg[ 7: 1]);
|
hexmap hb(i_clk, h_sseg[ 7: 4], w_sseg[15: 9]);
|
hexmap hb(i_clk, h_sseg[ 7: 4], w_sseg[15: 9]);
|
hexmap hc(i_clk, h_sseg[11: 8], w_sseg[23:17]);
|
hexmap hc(i_clk, h_sseg[11: 8], w_sseg[23:17]);
|
hexmap hd(i_clk, h_sseg[15:12], w_sseg[31:25]);
|
hexmap hd(i_clk, h_sseg[15:12], w_sseg[31:25]);
|