1
1
/*
2
2
3
- Copyright (c) 2019 Alex Forencich
3
+ Copyright (c) 2019-2024 Alex Forencich
4
4
5
5
Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
of this software and associated documentation files (the "Software"), to deal
@@ -77,15 +77,12 @@ module ptp_perout #
77
77
output wire output_pulse
78
78
);
79
79
80
- localparam [2 :0 ]
80
+ localparam [1 :0 ]
81
81
STATE_IDLE = 3'd0 ,
82
- STATE_UPDATE_RISE_1 = 3'd1 ,
83
- STATE_UPDATE_RISE_2 = 3'd2 ,
84
- STATE_UPDATE_FALL_1 = 3'd3 ,
85
- STATE_UPDATE_FALL_2 = 3'd4 ,
86
- STATE_WAIT_EDGE = 3'd5 ;
82
+ STATE_UPDATE_RISE = 3'd1 ,
83
+ STATE_UPDATE_FALL = 3'd2 ;
87
84
88
- reg [2 :0 ] state_reg = STATE_IDLE, state_next;
85
+ reg [1 :0 ] state_reg = STATE_IDLE, state_next;
89
86
90
87
reg [47 :0 ] time_s_reg = 0 ;
91
88
reg [30 :0 ] time_ns_reg = 0 ;
@@ -95,9 +92,9 @@ reg [47:0] next_rise_s_reg = 0, next_rise_s_next;
95
92
reg [30 :0 ] next_rise_ns_reg = 0 , next_rise_ns_next;
96
93
reg [15 :0 ] next_rise_fns_reg = 0 , next_rise_fns_next;
97
94
98
- reg [47 :0 ] next_fall_s_reg = 0 , next_fall_s_next ;
99
- reg [30 :0 ] next_fall_ns_reg = 0 , next_fall_ns_next ;
100
- reg [15 :0 ] next_fall_fns_reg = 0 , next_fall_fns_next ;
95
+ reg [47 :0 ] next_edge_s_reg = 0 , next_edge_s_next ;
96
+ reg [30 :0 ] next_edge_ns_reg = 0 , next_edge_ns_next ;
97
+ reg [15 :0 ] next_edge_fns_reg = 0 , next_edge_fns_next ;
101
98
102
99
reg [47 :0 ] start_s_reg = OUT_START_S;
103
100
reg [30 :0 ] start_ns_reg = OUT_START_NS;
@@ -116,6 +113,7 @@ reg [15:0] ts_96_fns_inc_reg = 0, ts_96_fns_inc_next;
116
113
reg [30 :0 ] ts_96_ns_ovf_reg = 0 , ts_96_ns_ovf_next;
117
114
reg [15 :0 ] ts_96_fns_ovf_reg = 0 , ts_96_fns_ovf_next;
118
115
116
+ reg restart_reg = 1'b1 ;
119
117
reg locked_reg = 1'b0 , locked_next;
120
118
reg error_reg = 1'b0 , error_next;
121
119
reg ffwd_reg = 1'b0 , ffwd_next;
@@ -133,9 +131,9 @@ always @* begin
133
131
next_rise_ns_next = next_rise_ns_reg;
134
132
next_rise_fns_next = next_rise_fns_reg;
135
133
136
- next_fall_s_next = next_fall_s_reg ;
137
- next_fall_ns_next = next_fall_ns_reg ;
138
- next_fall_fns_next = next_fall_fns_reg ;
134
+ next_edge_s_next = next_edge_s_reg ;
135
+ next_edge_ns_next = next_edge_ns_reg ;
136
+ next_edge_fns_next = next_edge_fns_reg ;
139
137
140
138
ts_96_ns_inc_next = ts_96_ns_inc_reg;
141
139
ts_96_fns_inc_next = ts_96_fns_inc_reg;
@@ -149,97 +147,97 @@ always @* begin
149
147
level_next = level_reg;
150
148
output_next = output_reg;
151
149
152
- if (input_start_valid || input_period_valid || input_ts_step) begin
153
- locked_next = 1'b0 ;
154
- level_next = 1'b0 ;
155
- output_next = 1'b0 ;
156
- error_next = input_ts_step;
157
- state_next = STATE_IDLE;
158
- end else begin
159
- case (state_reg)
160
- STATE_IDLE: begin
161
- // set next rise to start time
162
- next_rise_s_next = start_s_reg;
163
- next_rise_ns_next = start_ns_reg;
164
- if (FNS_ENABLE) begin
165
- next_rise_fns_next = start_fns_reg;
166
- end
167
- locked_next = 1'b0 ;
168
- ffwd_next = 1'b1 ;
169
- output_next = 1'b0 ;
170
- level_next = 1'b0 ;
171
- state_next = STATE_WAIT_EDGE;
172
- end
173
- STATE_UPDATE_RISE_1: begin
174
- // set next rise time to next rise time plus period
150
+ case (state_reg)
151
+ STATE_IDLE: begin
152
+ if (ffwd_reg || level_reg) begin
153
+ // fast forward or falling edge, set up for next rising edge
154
+ // set next rise time to previous rise time plus period
175
155
{ts_96_ns_inc_next, ts_96_fns_inc_next} = {next_rise_ns_reg, next_rise_fns_reg} + {period_ns_reg, period_fns_reg};
176
156
{ts_96_ns_ovf_next, ts_96_fns_ovf_next} = {next_rise_ns_reg, next_rise_fns_reg} + {period_ns_reg, period_fns_reg} - {31'd1_000_000_000 , 16'd0 };
177
- state_next = STATE_UPDATE_RISE_2;
178
- end
179
- STATE_UPDATE_RISE_2: begin
180
- if (! ts_96_ns_ovf_reg[30 ]) begin
181
- // if the overflow lookahead did not borrow, one second has elapsed
182
- next_rise_s_next = next_rise_s_reg + period_s_reg + 1 ;
183
- next_rise_ns_next = ts_96_ns_ovf_reg;
184
- next_rise_fns_next = ts_96_fns_ovf_reg;
185
- end else begin
186
- // no increment seconds field
187
- next_rise_s_next = next_rise_s_reg + period_s_reg;
188
- next_rise_ns_next = ts_96_ns_inc_reg;
189
- next_rise_fns_next = ts_96_fns_inc_reg;
190
- end
191
- state_next = STATE_WAIT_EDGE;
192
- end
193
- STATE_UPDATE_FALL_1: begin
194
- // set next fall time to next rise time plus width
157
+ end else begin
158
+ // rising edge; set up for next falling edge
159
+ // set next fall time to previous rise time plus width
195
160
{ts_96_ns_inc_next, ts_96_fns_inc_next} = {next_rise_ns_reg, next_rise_fns_reg} + {width_ns_reg, width_fns_reg};
196
161
{ts_96_ns_ovf_next, ts_96_fns_ovf_next} = {next_rise_ns_reg, next_rise_fns_reg} + {width_ns_reg, width_fns_reg} - {31'd1_000_000_000 , 16'd0 };
197
- state_next = STATE_UPDATE_FALL_2;
198
162
end
199
- STATE_UPDATE_FALL_2: begin
200
- if (! ts_96_ns_ovf_reg[30 ]) begin
201
- // if the overflow lookahead did not borrow, one second has elapsed
202
- next_fall_s_next = next_rise_s_reg + width_s_reg + 1 ;
203
- next_fall_ns_next = ts_96_ns_ovf_reg;
204
- next_fall_fns_next = ts_96_fns_ovf_reg;
205
- end else begin
206
- // no increment seconds field
207
- next_fall_s_next = next_rise_s_reg + width_s_reg;
208
- next_fall_ns_next = ts_96_ns_inc_reg;
209
- next_fall_fns_next = ts_96_fns_inc_reg;
210
- end
211
- state_next = STATE_WAIT_EDGE;
212
- end
213
- STATE_WAIT_EDGE: begin
214
- if ((! level_reg || ffwd_reg) && ((time_s_reg > next_rise_s_reg) || (time_s_reg == next_rise_s_reg && {time_ns_reg, time_fns_reg} > {next_rise_ns_reg, next_rise_fns_reg}))) begin
215
- // rising edge
216
- if (ffwd_reg) begin
217
- output_next = 1'b0 ;
218
- level_next = 1'b0 ;
219
- state_next = STATE_UPDATE_RISE_1;
220
- end else begin
221
- locked_next = 1'b1 ;
222
- error_next = 1'b0 ;
223
- output_next = enable;
224
- level_next = 1'b1 ;
225
- state_next = STATE_UPDATE_FALL_1;
226
- end
227
- end else if (level_reg && ((time_s_reg > next_fall_s_reg) || (time_s_reg == next_fall_s_reg && {time_ns_reg, time_fns_reg} > {next_fall_ns_reg, next_fall_fns_reg}))) begin
228
- // falling edge
163
+
164
+ // wait for edge
165
+ if ((time_s_reg > next_edge_s_reg) || (time_s_reg == next_edge_s_reg && {time_ns_reg, time_fns_reg} > {next_edge_ns_reg, next_edge_fns_reg})) begin
166
+ if (ffwd_reg || level_reg) begin
167
+ // fast forward or falling edge, set up for next rising edge
229
168
output_next = 1'b0 ;
230
169
level_next = 1'b0 ;
231
- state_next = STATE_UPDATE_RISE_1 ;
170
+ state_next = STATE_UPDATE_RISE ;
232
171
end else begin
233
- ffwd_next = 1'b0 ;
234
- state_next = STATE_WAIT_EDGE;
172
+ // rising edge; set up for next falling edge
173
+ locked_next = 1'b1 ;
174
+ error_next = 1'b0 ;
175
+ output_next = enable;
176
+ level_next = 1'b1 ;
177
+ state_next = STATE_UPDATE_FALL;
235
178
end
179
+ end else begin
180
+ ffwd_next = 1'b0 ;
181
+ state_next = STATE_IDLE;
236
182
end
237
- endcase
183
+ end
184
+ STATE_UPDATE_RISE: begin
185
+ if (! ts_96_ns_ovf_reg[30 ]) begin
186
+ // if the overflow lookahead did not borrow, one second has elapsed
187
+ next_edge_s_next = next_rise_s_reg + period_s_reg + 1 ;
188
+ next_edge_ns_next = ts_96_ns_ovf_reg;
189
+ next_edge_fns_next = ts_96_fns_ovf_reg;
190
+ end else begin
191
+ // no increment seconds field
192
+ next_edge_s_next = next_rise_s_reg + period_s_reg;
193
+ next_edge_ns_next = ts_96_ns_inc_reg;
194
+ next_edge_fns_next = ts_96_fns_inc_reg;
195
+ end
196
+ next_rise_s_next = next_edge_s_next;
197
+ next_rise_ns_next = next_edge_ns_next;
198
+ next_rise_fns_next = next_edge_fns_next;
199
+ state_next = STATE_IDLE;
200
+ end
201
+ STATE_UPDATE_FALL: begin
202
+ if (! ts_96_ns_ovf_reg[30 ]) begin
203
+ // if the overflow lookahead did not borrow, one second has elapsed
204
+ next_edge_s_next = next_rise_s_reg + width_s_reg + 1 ;
205
+ next_edge_ns_next = ts_96_ns_ovf_reg;
206
+ next_edge_fns_next = ts_96_fns_ovf_reg;
207
+ end else begin
208
+ // no increment seconds field
209
+ next_edge_s_next = next_rise_s_reg + width_s_reg;
210
+ next_edge_ns_next = ts_96_ns_inc_reg;
211
+ next_edge_fns_next = ts_96_fns_inc_reg;
212
+ end
213
+ state_next = STATE_IDLE;
214
+ end
215
+ endcase
216
+
217
+ if (restart_reg || input_ts_step) begin
218
+ // set next rise and next edge to start time
219
+ next_rise_s_next = start_s_reg;
220
+ next_rise_ns_next = start_ns_reg;
221
+ if (FNS_ENABLE) begin
222
+ next_rise_fns_next = start_fns_reg;
223
+ end
224
+ next_edge_s_next = start_s_reg;
225
+ next_edge_ns_next = start_ns_reg;
226
+ if (FNS_ENABLE) begin
227
+ next_edge_fns_next = start_fns_reg;
228
+ end
229
+ locked_next = 1'b0 ;
230
+ ffwd_next = 1'b1 ;
231
+ output_next = 1'b0 ;
232
+ level_next = 1'b0 ;
233
+ error_next = input_ts_step;
234
+ state_next = STATE_IDLE;
238
235
end
239
236
end
240
237
241
238
always @(posedge clk) begin
242
239
state_reg <= state_next;
240
+ restart_reg <= 1'b0 ;
243
241
244
242
time_s_reg <= input_ts_96[95 :48 ];
245
243
time_ns_reg <= input_ts_96[45 :16 ];
@@ -253,6 +251,7 @@ always @(posedge clk) begin
253
251
if (FNS_ENABLE) begin
254
252
start_fns_reg <= input_start[15 :0 ];
255
253
end
254
+ restart_reg <= 1'b1 ;
256
255
end
257
256
258
257
if (input_period_valid) begin
@@ -261,6 +260,7 @@ always @(posedge clk) begin
261
260
if (FNS_ENABLE) begin
262
261
period_fns_reg <= input_period[15 :0 ];
263
262
end
263
+ restart_reg <= 1'b1 ;
264
264
end
265
265
266
266
if (input_width_valid) begin
@@ -277,10 +277,10 @@ always @(posedge clk) begin
277
277
next_rise_fns_reg <= next_rise_fns_next;
278
278
end
279
279
280
- next_fall_s_reg <= next_fall_s_next ;
281
- next_fall_ns_reg <= next_fall_ns_next ;
280
+ next_edge_s_reg <= next_edge_s_next ;
281
+ next_edge_ns_reg <= next_edge_ns_next ;
282
282
if (FNS_ENABLE) begin
283
- next_fall_fns_reg <= next_fall_fns_next ;
283
+ next_edge_fns_reg <= next_edge_fns_next ;
284
284
end
285
285
286
286
ts_96_ns_inc_reg <= ts_96_ns_inc_next;
@@ -314,6 +314,7 @@ always @(posedge clk) begin
314
314
width_ns_reg <= OUT_WIDTH_NS;
315
315
width_fns_reg <= OUT_WIDTH_FNS;
316
316
317
+ restart_reg <= 1'b1 ;
317
318
locked_reg <= 1'b0 ;
318
319
error_reg <= 1'b0 ;
319
320
output_reg <= 1'b0 ;
0 commit comments