1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
module time_sync
(input wb_clk_i, input rst_i,
input cyc_i, input stb_i, input [2:0] adr_i,
input we_i, input [31:0] dat_i, output [31:0] dat_o, output ack_o,
input sys_clk_i, output [31:0] master_time_o,
input pps_in, input exp_pps_in, output exp_pps_out,
output reg int_o );
wire [31:0] master_time_rcvd;
reg [31:0] master_time;
reg [31:0] delta_time;
reg internal_tick;
wire sync_rcvd, pps_ext;
reg [31:0] tick_time, tick_time_wb;
wire tick_free_run;
reg tick_int_enable, tick_source, external_sync;
reg [31:0] tick_interval;
reg sync_on_next_pps;
// Generate master time
always @(posedge sys_clk_i)
if(rst_i)
master_time <= 0;
else if(external_sync & sync_rcvd)
master_time <= master_time_rcvd + delta_time;
else if(pps_ext & sync_on_next_pps)
master_time <= 0;
else
master_time <= master_time + 1;
assign master_time_o = master_time;
time_sender time_sender
(.clk(sys_clk_i),.rst(rst_i),
.master_time(master_time),
.send_sync(internal_tick),
.exp_pps_out(exp_pps_out) );
time_receiver time_receiver
(.clk(sys_clk_i),.rst(rst_i),
.master_time(master_time_rcvd),
.sync_rcvd(sync_rcvd),
.exp_pps_in(exp_pps_in) );
assign ack_o = stb_i;
wire wb_write = cyc_i & stb_i & we_i;
wire wb_read = cyc_i & stb_i & ~we_i;
wire wb_acc = cyc_i & stb_i;
always @(posedge wb_clk_i)
if(rst_i)
begin
tick_source <= 0;
tick_int_enable <= 0;
external_sync <= 0;
tick_interval <= 100000-1; // default to 1K times per second
delta_time <= 0;
end
else if(wb_write)
case(adr_i[2:0])
3'd0 :
begin
tick_source <= dat_i[0];
tick_int_enable <= dat_i[1];
external_sync <= dat_i[2];
end
3'd1 :
tick_interval <= dat_i;
3'd2 :
delta_time <= dat_i;
3'd3 :
;
// Do nothing here, this is to arm the sync_on_next
endcase // case(adr_i[2:0])
always @(posedge sys_clk_i)
if(rst_i)
sync_on_next_pps <= 0;
else if(pps_ext)
sync_on_next_pps <= 0;
else if(wb_write & (adr_i[2:0] == 3))
sync_on_next_pps <= 0;
always @(posedge sys_clk_i)
if(internal_tick)
tick_time <= master_time;
always @(posedge wb_clk_i)
tick_time_wb <= tick_time;
assign dat_o = tick_time_wb;
always @(posedge sys_clk_i)
internal_tick <= (tick_source == 0) ? tick_free_run : pps_ext;
reg [31:0] counter;
always @(posedge sys_clk_i)
if(rst_i)
counter <= 0;
else if(tick_free_run)
counter <= 0;
else
counter <= counter + 1;
assign tick_free_run = (counter >= tick_interval);
// Properly Latch and edge detect External PPS input
reg pps_in_d1, pps_in_d2;
always @(posedge sys_clk_i)
begin
pps_in_d1 <= pps_in;
pps_in_d2 <= pps_in_d1;
end
assign pps_ext = pps_in_d1 & ~pps_in_d2;
// Need to register this?
reg internal_tick_d1;
always @(posedge sys_clk_i) internal_tick_d1 <= internal_tick;
always @(posedge wb_clk_i)
if(rst_i)
int_o <= 0;
else if(tick_int_enable & (internal_tick | internal_tick_d1))
int_o <= 1;
else
int_o <= 0;
endmodule // time_sync
|