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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
|
-------------------------------------------------------------------------------
--
-- Copyright 2018 Ettus Research, a National Instruments Company
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
--
-- Purpose:
--
-- Wrapper for the TDC and register control modules.
--
-- vreview_group Tdc
-- vreview_reviewers dabaker sgupta jmarsar
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.PkgRegs.all;
entity TdcWrapper is
port (
-- Clocks and Resets : --------------------------------------------------------------
-- Bus Clock and synchronous bus reset.
BusClk : in std_logic;
bBusReset : in std_logic;
-- Reference Clock
RefClk : in std_logic;
-- Sample Clock
SampleClk : in std_logic;
-- Measurement Clock must run at a very specific frequency, determined by the
-- SampleClk, RefClk, and Sync Pulse rates... oh and a lot of math.
MeasClk : in std_logic;
-- Register Port: -------------------------------------------------------------------
bSyncRegPortOut : out RegPortOut_t;
bSyncRegPortIn : in RegPortIn_t;
-- PPS In and Out : -----------------------------------------------------------------
-- Only required to pulse 1 RefClk cycle.
rPpsPulse : in std_logic;
-- PPS pulse output on the SampleClk domain.
sPpsPulse : out std_logic;
-- Sync Pulse Outputs : -------------------------------------------------------------
-- The repeating pulses can be useful for many things, including passing triggers.
rRpTransfer : out std_logic;
sSpTransfer : out std_logic;
-- Pin bouncers out and in. Must go to unused and unconnected pins on the FPGA!
rGatedPulseToPin : inout std_logic;
sGatedPulseToPin : inout std_logic
);
end TdcWrapper;
architecture struct of TdcWrapper is
component SyncRegsIfc
port (
aBusReset : in std_logic;
bBusReset : in std_logic;
BusClk : in std_logic;
aTdcReset : out std_logic;
bRegPortInFlat : in std_logic_vector(49 downto 0);
bRegPortOutFlat : out std_logic_vector(33 downto 0);
RefClk : in std_logic;
rResetTdc : out std_logic;
rResetTdcDone : in std_logic;
rEnableTdc : out std_logic;
rReRunEnable : out std_logic;
rEnablePpsCrossing : out std_logic;
rPpsPulseCaptured : in std_logic;
rPulserEnableDelayVal : out std_logic_vector(3 downto 0);
SampleClk : in std_logic;
sPpsClkCrossDelayVal : out std_logic_vector(3 downto 0);
MeasClk : in std_logic;
mRpOffset : in std_logic_vector(39 downto 0);
mSpOffset : in std_logic_vector(39 downto 0);
mOffsetsDone : in std_logic;
mOffsetsValid : in std_logic;
rLoadRePulseCounts : out std_logic;
rRePulsePeriodInRClks : out std_logic_vector(23 downto 0);
rRePulseHighTimeInRClks : out std_logic_vector(23 downto 0);
rLoadRpCounts : out std_logic;
rRpPeriodInRClks : out std_logic_vector(15 downto 0);
rRpHighTimeInRClks : out std_logic_vector(15 downto 0);
rLoadRptCounts : out std_logic;
rRptPeriodInRClks : out std_logic_vector(15 downto 0);
rRptHighTimeInRClks : out std_logic_vector(15 downto 0);
sLoadSpCounts : out std_logic;
sSpPeriodInSClks : out std_logic_vector(15 downto 0);
sSpHighTimeInSClks : out std_logic_vector(15 downto 0);
sLoadSptCounts : out std_logic;
sSptPeriodInSClks : out std_logic_vector(15 downto 0);
sSptHighTimeInSClks : out std_logic_vector(15 downto 0));
end component;
-- Generic values for the TdcTop instantiation below. These generics are the maximum
-- of possible values for all combinations of Sample and Reference clocks for the N3xx
-- family of devices.
constant kRClksPerRePulsePeriodBitsMax : integer := 24;
constant kRClksPerRpPeriodBitsMax : integer := 16;
constant kSClksPerSpPeriodBitsMax : integer := 16;
constant kPulsePeriodCntSize : integer := 13;
-- The following are ideal values for balancing measurement time and accuracy, based
-- on calcs given in the spec doc.
constant kFreqRefPeriodsToCheckSize : integer := 17;
constant kSyncPeriodsToStampSize : integer := 10;
--vhook_sigstart
signal aTdcReset: std_logic;
signal bSyncRegPortInFlat: std_logic_vector(49 downto 0);
signal bSyncRegPortOutFlat: std_logic_vector(33 downto 0);
signal mOffsetsDone: boolean;
signal mOffsetsValid: boolean;
signal mRpOffset: unsigned(kPulsePeriodCntSize+kSyncPeriodsToStampSize+kFreqRefPeriodsToCheckSize-1 downto 0);
signal mSpOffset: unsigned(kPulsePeriodCntSize+kSyncPeriodsToStampSize+kFreqRefPeriodsToCheckSize-1 downto 0);
signal rEnablePpsCrossing: std_logic;
signal rEnableTdc: std_logic;
signal rLoadRePulseCounts: std_logic;
signal rLoadRpCounts: std_logic;
signal rLoadRptCounts: std_logic;
signal rPpsPulseCaptured: boolean;
signal rPulserEnableDelayVal: std_logic_vector(3 downto 0);
signal rRePulseHighTimeInRClks: std_logic_vector(kRClksPerRePulsePeriodBitsMax-1 downto 0);
signal rRePulsePeriodInRClks: std_logic_vector(kRClksPerRePulsePeriodBitsMax-1 downto 0);
signal rReRunEnable: std_logic;
signal rResetTdc: std_logic;
signal rResetTdcDone: boolean;
signal rRpHighTimeInRClks: std_logic_vector(kRClksPerRpPeriodBitsMax-1 downto 0);
signal rRpPeriodInRClks: std_logic_vector(kRClksPerRpPeriodBitsMax-1 downto 0);
signal rRptHighTimeInRClks: std_logic_vector(kRClksPerRpPeriodBitsMax-1 downto 0);
signal rRptPeriodInRClks: std_logic_vector(kRClksPerRpPeriodBitsMax-1 downto 0);
signal rRpTransferBool: boolean;
signal sLoadSpCounts: std_logic;
signal sLoadSptCounts: std_logic;
signal sPpsClkCrossDelayVal: std_logic_vector(3 downto 0);
signal sPpsPulseAsyncReset: boolean;
signal sSpHighTimeInSClks: std_logic_vector(kSClksPerSpPeriodBitsMax-1 downto 0);
signal sSpPeriodInSClks: std_logic_vector(kSClksPerSpPeriodBitsMax-1 downto 0);
signal sSptHighTimeInSClks: std_logic_vector(kSClksPerSpPeriodBitsMax-1 downto 0);
signal sSptPeriodInSClks: std_logic_vector(kSClksPerSpPeriodBitsMax-1 downto 0);
signal sSpTransferBool: boolean;
--vhook_sigend
signal rPpsPulseAsyncReset_ms, rPpsPulseAsyncReset,
sPpsPulseOut_ms, sPpsPulseOut : std_logic := '0';
function to_StdLogic(b : boolean) return std_ulogic is
begin
if b then
return '1';
else
return '0';
end if;
end to_StdLogic;
function to_Boolean (s : std_ulogic) return boolean is
begin
return (To_X01(s)='1');
end to_Boolean;
attribute ASYNC_REG : string;
attribute ASYNC_REG of rPpsPulseAsyncReset_ms : signal is "true";
attribute ASYNC_REG of rPpsPulseAsyncReset : signal is "true";
attribute ASYNC_REG of sPpsPulseOut_ms : signal is "true";
attribute ASYNC_REG of sPpsPulseOut : signal is "true";
begin
-- Cross the PPS from the no-reset domain into the aTdcReset domain since there is a
-- reset crossing going into the TdcWrapper (reset by aTdcReset)! No clock domain
-- crossing here, so crossing a single-cycle pulse is safe.
DoubleSyncToAsyncReset : process (aTdcReset, RefClk)
begin
if to_boolean(aTdcReset) then
rPpsPulseAsyncReset_ms <= '0';
rPpsPulseAsyncReset <= '0';
elsif rising_edge(RefClk) then
rPpsPulseAsyncReset_ms <= rPpsPulse;
rPpsPulseAsyncReset <= rPpsPulseAsyncReset_ms;
end if;
end process;
-- In a similar fashion, cross the output PPS trigger from the async aTdcReset domain
-- to the no-reset of the rest of the design. The odds of this signal triggering a
-- failure are astronomically low (since it only pulses one clock cycle per second),
-- but two flops is worth the assurance it won't mess something else up downstream.
-- Note this double-sync mainly protects against the reset assertion case, since in the
-- de-assertion case sPpsPulseAsyncReset should be zero and not transition for a long
-- time afterwards. Again no clock crossing here, so crossing a single-cycle pulse
-- is safe.
DoubleSyncToNoReset : process (SampleClk)
begin
if rising_edge(SampleClk) then
sPpsPulseOut_ms <= to_stdlogic(sPpsPulseAsyncReset);
sPpsPulseOut <= sPpsPulseOut_ms;
end if;
end process;
sPpsPulse <= sPpsPulseOut;
rRpTransfer <= to_stdlogic(rRpTransferBool);
sSpTransfer <= to_stdlogic(sSpTransferBool);
--vhook_e TdcTop
--vhook_a aReset to_boolean(aTdcReset)
--vhook_a rResetTdc to_boolean(rResetTdc)
--vhook_a rEnableTdc to_boolean(rEnableTdc)
--vhook_a rReRunEnable to_boolean(rReRunEnable)
--vhook_a rPpsPulse to_boolean(rPpsPulseAsyncReset)
--vhook_a rLoadRePulseCounts to_boolean(rLoadRePulseCounts)
--vhook_a rLoadRpCounts to_boolean(rLoadRpCounts)
--vhook_a rLoadRptCounts to_boolean(rLoadRptCounts)
--vhook_a sLoadSpCounts to_boolean(sLoadSpCounts)
--vhook_a sLoadSptCounts to_boolean(sLoadSptCounts)
--vhook_a rEnablePpsCrossing to_boolean(rEnablePpsCrossing)
--vhook_a rPulserEnableDelayVal unsigned(rPulserEnableDelayVal)
--vhook_a sPpsClkCrossDelayVal unsigned(sPpsClkCrossDelayVal)
--vhook_a rRpTransfer rRpTransferBool
--vhook_a sSpTransfer sSpTransferBool
--vhook_a sPpsPulse sPpsPulseAsyncReset
--vhook_p {^rR(.*)In(.*)Clks} unsigned(rR$1In$2Clks)
--vhook_p {^sS(.*)In(.*)Clks} unsigned(sS$1In$2Clks)
TdcTopx: entity work.TdcTop (struct)
generic map (
kRClksPerRePulsePeriodBitsMax => kRClksPerRePulsePeriodBitsMax, --integer range 3:32 :=24
kRClksPerRpPeriodBitsMax => kRClksPerRpPeriodBitsMax, --integer range 3:16 :=16
kSClksPerSpPeriodBitsMax => kSClksPerSpPeriodBitsMax, --integer range 3:16 :=16
kPulsePeriodCntSize => kPulsePeriodCntSize, --integer:=13
kFreqRefPeriodsToCheckSize => kFreqRefPeriodsToCheckSize, --integer:=17
kSyncPeriodsToStampSize => kSyncPeriodsToStampSize) --integer:=10
port map (
aReset => to_boolean(aTdcReset), --in boolean
RefClk => RefClk, --in std_logic
SampleClk => SampleClk, --in std_logic
MeasClk => MeasClk, --in std_logic
rResetTdc => to_boolean(rResetTdc), --in boolean
rResetTdcDone => rResetTdcDone, --out boolean
rEnableTdc => to_boolean(rEnableTdc), --in boolean
rReRunEnable => to_boolean(rReRunEnable), --in boolean
rPpsPulse => to_boolean(rPpsPulseAsyncReset), --in boolean
rPpsPulseCaptured => rPpsPulseCaptured, --out boolean
rPulserEnableDelayVal => unsigned(rPulserEnableDelayVal), --in unsigned(3:0)
rEnablePpsCrossing => to_boolean(rEnablePpsCrossing), --in boolean
sPpsClkCrossDelayVal => unsigned(sPpsClkCrossDelayVal), --in unsigned(3:0)
sPpsPulse => sPpsPulseAsyncReset, --out boolean
mRpOffset => mRpOffset, --out unsigned(kPulsePeriodCntSize+ kSyncPeriodsToStampSize+ kFreqRefPeriodsToCheckSize-1:0)
mSpOffset => mSpOffset, --out unsigned(kPulsePeriodCntSize+ kSyncPeriodsToStampSize+ kFreqRefPeriodsToCheckSize-1:0)
mOffsetsDone => mOffsetsDone, --out boolean
mOffsetsValid => mOffsetsValid, --out boolean
rLoadRePulseCounts => to_boolean(rLoadRePulseCounts), --in boolean
rRePulsePeriodInRClks => unsigned(rRePulsePeriodInRClks), --in unsigned(kRClksPerRePulsePeriodBitsMax-1:0)
rRePulseHighTimeInRClks => unsigned(rRePulseHighTimeInRClks), --in unsigned(kRClksPerRePulsePeriodBitsMax-1:0)
rLoadRpCounts => to_boolean(rLoadRpCounts), --in boolean
rRpPeriodInRClks => unsigned(rRpPeriodInRClks), --in unsigned(kRClksPerRpPeriodBitsMax-1:0)
rRpHighTimeInRClks => unsigned(rRpHighTimeInRClks), --in unsigned(kRClksPerRpPeriodBitsMax-1:0)
rLoadRptCounts => to_boolean(rLoadRptCounts), --in boolean
rRptPeriodInRClks => unsigned(rRptPeriodInRClks), --in unsigned(kRClksPerRpPeriodBitsMax-1:0)
rRptHighTimeInRClks => unsigned(rRptHighTimeInRClks), --in unsigned(kRClksPerRpPeriodBitsMax-1:0)
sLoadSpCounts => to_boolean(sLoadSpCounts), --in boolean
sSpPeriodInSClks => unsigned(sSpPeriodInSClks), --in unsigned(kSClksPerSpPeriodBitsMax-1:0)
sSpHighTimeInSClks => unsigned(sSpHighTimeInSClks), --in unsigned(kSClksPerSpPeriodBitsMax-1:0)
sLoadSptCounts => to_boolean(sLoadSptCounts), --in boolean
sSptPeriodInSClks => unsigned(sSptPeriodInSClks), --in unsigned(kSClksPerSpPeriodBitsMax-1:0)
sSptHighTimeInSClks => unsigned(sSptHighTimeInSClks), --in unsigned(kSClksPerSpPeriodBitsMax-1:0)
rRpTransfer => rRpTransferBool, --out boolean
sSpTransfer => sSpTransferBool, --out boolean
rGatedPulseToPin => rGatedPulseToPin, --inout std_logic
sGatedPulseToPin => sGatedPulseToPin); --inout std_logic
-- Expand/compress the RegPort for moving through the netlist boundary.
bSyncRegPortOut <= Unflatten(bSyncRegPortOutFlat);
bSyncRegPortInFlat <= Flatten(bSyncRegPortIn);
--vhook SyncRegsIfc
--vhook_# Tying this low is safe because the sync reset is used inside SyncRegsIfc.
--vhook_a aBusReset '0'
--vhook_a bRegPortInFlat bSyncRegPortInFlat
--vhook_a bRegPortOutFlat bSyncRegPortOutFlat
--vhook_a rResetTdcDone to_stdlogic(rResetTdcDone)
--vhook_a rPpsPulseCaptured to_stdlogic(rPpsPulseCaptured)
--vhook_a mOffsetsDone to_stdlogic(mOffsetsDone)
--vhook_a mOffsetsValid to_stdlogic(mOffsetsValid)
--vhook_a mRpOffset std_logic_vector(mRpOffset)
--vhook_a mSpOffset std_logic_vector(mSpOffset)
SyncRegsIfcx: SyncRegsIfc
port map (
aBusReset => '0', --in std_logic
bBusReset => bBusReset, --in std_logic
BusClk => BusClk, --in std_logic
aTdcReset => aTdcReset, --out std_logic
bRegPortInFlat => bSyncRegPortInFlat, --in std_logic_vector(49:0)
bRegPortOutFlat => bSyncRegPortOutFlat, --out std_logic_vector(33:0)
RefClk => RefClk, --in std_logic
rResetTdc => rResetTdc, --out std_logic
rResetTdcDone => to_stdlogic(rResetTdcDone), --in std_logic
rEnableTdc => rEnableTdc, --out std_logic
rReRunEnable => rReRunEnable, --out std_logic
rEnablePpsCrossing => rEnablePpsCrossing, --out std_logic
rPpsPulseCaptured => to_stdlogic(rPpsPulseCaptured), --in std_logic
rPulserEnableDelayVal => rPulserEnableDelayVal, --out std_logic_vector(3:0)
SampleClk => SampleClk, --in std_logic
sPpsClkCrossDelayVal => sPpsClkCrossDelayVal, --out std_logic_vector(3:0)
MeasClk => MeasClk, --in std_logic
mRpOffset => std_logic_vector(mRpOffset), --in std_logic_vector(39:0)
mSpOffset => std_logic_vector(mSpOffset), --in std_logic_vector(39:0)
mOffsetsDone => to_stdlogic(mOffsetsDone), --in std_logic
mOffsetsValid => to_stdlogic(mOffsetsValid), --in std_logic
rLoadRePulseCounts => rLoadRePulseCounts, --out std_logic
rRePulsePeriodInRClks => rRePulsePeriodInRClks, --out std_logic_vector(23:0)
rRePulseHighTimeInRClks => rRePulseHighTimeInRClks, --out std_logic_vector(23:0)
rLoadRpCounts => rLoadRpCounts, --out std_logic
rRpPeriodInRClks => rRpPeriodInRClks, --out std_logic_vector(15:0)
rRpHighTimeInRClks => rRpHighTimeInRClks, --out std_logic_vector(15:0)
rLoadRptCounts => rLoadRptCounts, --out std_logic
rRptPeriodInRClks => rRptPeriodInRClks, --out std_logic_vector(15:0)
rRptHighTimeInRClks => rRptHighTimeInRClks, --out std_logic_vector(15:0)
sLoadSpCounts => sLoadSpCounts, --out std_logic
sSpPeriodInSClks => sSpPeriodInSClks, --out std_logic_vector(15:0)
sSpHighTimeInSClks => sSpHighTimeInSClks, --out std_logic_vector(15:0)
sLoadSptCounts => sLoadSptCounts, --out std_logic
sSptPeriodInSClks => sSptPeriodInSClks, --out std_logic_vector(15:0)
sSptHighTimeInSClks => sSptHighTimeInSClks); --out std_logic_vector(15:0)
end struct;
--------------------------------------------------------------------------------
-- Testbench for TdcWrapper
--------------------------------------------------------------------------------
--synopsys translate_off
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.PkgRegs.all;
entity tb_TdcWrapper is end tb_TdcWrapper;
architecture test of tb_TdcWrapper is
--vhook_sigstart
signal bBusReset: std_logic;
signal bSyncRegPortIn: RegPortIn_t;
signal bSyncRegPortOut: RegPortOut_t;
signal BusClk: std_logic := '0';
signal MeasClk: std_logic := '0';
signal RefClk: std_logic := '0';
signal rGatedPulseToPin: std_logic;
signal rPpsPulse: std_logic;
signal rRpTransfer: std_logic;
signal SampleClk: std_logic := '0';
signal sGatedPulseToPin: std_logic;
signal sPpsPulse: std_logic;
signal sSpTransfer: std_logic;
--vhook_sigend
begin
--vhook_e TdcWrapper dutx
dutx: entity work.TdcWrapper (struct)
port map (
BusClk => BusClk, --in std_logic
bBusReset => bBusReset, --in std_logic
RefClk => RefClk, --in std_logic
SampleClk => SampleClk, --in std_logic
MeasClk => MeasClk, --in std_logic
bSyncRegPortOut => bSyncRegPortOut, --out RegPortOut_t
bSyncRegPortIn => bSyncRegPortIn, --in RegPortIn_t
rPpsPulse => rPpsPulse, --in std_logic
sPpsPulse => sPpsPulse, --out std_logic
rRpTransfer => rRpTransfer, --out std_logic
sSpTransfer => sSpTransfer, --out std_logic
rGatedPulseToPin => rGatedPulseToPin, --inout std_logic
sGatedPulseToPin => sGatedPulseToPin); --inout std_logic
main: process
begin
report "TdcWrapper Test is EMPTY! (but that's ok in this case)" severity note;
--vhook_nowarn tb_TdcWrapper.test.*
wait;
end process;
end test;
--synopsys translate_on
|