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