-
Notifications
You must be signed in to change notification settings - Fork 1
/
opentdc_core2.vhdl
306 lines (276 loc) · 8.51 KB
/
opentdc_core2.vhdl
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
-- Time to Digital Conversion (TDC) core
-- SPDX-FileCopyrightText: (c) 2020 Tristan Gingold <[email protected]>
-- SPDX-License-Identifier: Apache-2.0
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.opentdc_pkg.all;
entity opentdc_core2 is
generic (
g_with_ref : boolean := True;
g_with_scan : boolean := False;
-- Number of taps
length : natural := 1024;
-- Number of bits in fine_o
-- 2**fine_bits >= length
fine_bits : natural := 10);
port (
clk_i : std_logic;
rst_n_i : std_logic;
itaps : std_logic_vector(length - 1 downto 0);
rtaps : std_logic_vector(length - 1 downto 0);
-- Source of ref taps
rin_o : out std_logic;
bin : dev_bus_in;
bout : out dev_bus_out);
end opentdc_core2;
-- This core is made of 2 submodules, so that it is easy to harden
-- the tapline.
architecture behav of opentdc_core2 is
signal trigger, rtrigger : std_logic;
signal restart, rrestart : std_logic;
signal coarse, rcoarse : std_logic_vector(31 downto 0);
signal fine, rfine : std_logic_vector(fine_bits - 1 downto 0);
signal detect_rise, detect_fall : std_logic;
signal rdetect_rise, rdetect_fall : std_logic;
signal detect : std_logic;
signal clk_div : std_logic_vector(3 downto 0);
signal clk_cnt : std_logic_vector(7 downto 0);
signal clk_dir : std_logic;
signal scan_tap : std_logic_vector(length - 1 downto 0);
signal scan_reg : std_logic_vector(31 downto 0);
signal scan_cnt : std_logic_vector(7 downto 0);
signal scan_rd : std_logic;
signal cur_icycles : std_logic_vector(31 downto 0);
begin
i_icycles: entity work.counter
port map (
clk_i => clk_i,
rst_n_i => bin.cycles_rst_n,
cur_cycles_o => cur_icycles);
inst_itime: entity work.opentdc_time
generic map (
length => length,
fine_bits => fine_bits)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
cur_cycles_i => cur_icycles,
restart_i => restart,
detect_rise_i => detect_rise,
detect_fall_i => detect_fall,
tap_i => itaps,
triggered_o => trigger,
detect_o => detect,
coarse_o => coarse,
fine_o => fine);
gen_scan: if g_with_scan generate
process (clk_i)
constant tap_words : natural := length / 32;
begin
if rising_edge(clk_i) then
if detect = '1' then
scan_tap <= itaps;
scan_cnt <= (others => '0');
elsif scan_rd = '1' then
if length mod 32 = 0 then
scan_tap (length - 32 - 1 downto 0) <=
scan_tap (length - 1 downto 32);
scan_tap (length - 1 downto length - 32) <=
(others => '0');
elsif length > 32 then
-- The bulk
scan_tap (tap_words * 32 - 32 - 1 downto 0) <=
scan_tap (tap_words * 32 - 1 downto 32);
-- The remaining
scan_tap (length - 32 - 1 downto tap_words * 32 - 32) <=
scan_tap (length - 1 downto tap_words * 32);
-- Clear the top
scan_tap (length - 1 downto length - 32) <=
(others => '0');
else
scan_tap <= (others => '0');
end if;
scan_cnt <= std_logic_vector(unsigned(scan_cnt) + 1);
end if;
end if;
end process;
process (scan_tap) is
begin
if length >= 32 then
scan_reg <= scan_tap (31 downto 0);
else
scan_reg <= (31 downto length => '0') & scan_tap;
end if;
end process;
end generate;
gen_no_scan: if not g_with_scan generate
scan_reg <= (others => '0');
scan_cnt <= (others => '0');
end generate;
gen_rtime: if g_with_ref generate
signal cur_rcycles : std_logic_vector(31 downto 0);
begin
i_rcycles: entity work.counter
port map (
clk_i => clk_i,
rst_n_i => bin.cycles_rst_n,
cur_cycles_o => cur_rcycles);
inst_rtime: entity work.opentdc_time
generic map (
length => length)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
cur_cycles_i => cur_rcycles,
restart_i => rrestart,
detect_rise_i => rdetect_rise,
detect_fall_i => rdetect_fall,
tap_i => rtaps,
triggered_o => rtrigger,
coarse_o => rcoarse,
fine_o => rfine);
end generate;
gen_no_rtime: if not g_with_ref generate
rtrigger <= '0';
rcoarse <= (others => '0');
rfine <= (others => '0');
end generate;
-- Read process
process (clk_i) is
begin
if rising_edge (clk_i) then
bout.trig <= trigger or rtrigger;
scan_rd <= '0';
bout.dato <= (others => '0');
bout.rack <= '0';
if bin.re = '1' then
case bin.adr is
when "000" =>
bout.dato <= (19 => rdetect_fall,
18 => rdetect_rise,
17 => detect_fall,
16 => detect_rise,
9 => rrestart,
8 => restart,
1 => rtrigger,
0 => trigger,
others => '0');
bout.dato (27 downto 24) <= clk_div;
when "001" =>
bout.dato (31 downto 16) <= rcoarse(15 downto 0);
bout.dato (fine_bits - 1 downto 0) <= rfine(fine_bits - 1 downto 0);
when "010" =>
bout.dato <= coarse;
when "011" =>
bout.dato (fine_bits - 1 downto 0) <= fine;
when "100" =>
bout.dato (7 downto 0) <= scan_cnt;
when "101" =>
bout.dato <= scan_reg;
scan_rd <= '1';
when "110" =>
null;
when "111" =>
bout.dato (0) <= '1'; -- Config
bout.dato (1) <= '1'; -- TDC
if g_with_ref then
bout.dato (2) <= '1';
end if;
if g_with_scan then
bout.dato (3) <= '1';
end if;
bout.dato (31 downto 16) <=
std_logic_vector (to_unsigned(length, 16));
when others =>
bout.dato <= (others => 'X');
end case;
bout.rack <= '1';
end if;
end if;
end process;
-- Write process
process (clk_i) is
begin
if rising_edge (clk_i) then
-- restart is a pulse
rrestart <= '0';
restart <= '0';
bout.wack <= '0';
if rst_n_i = '0' then
rdetect_fall <= '0';
rdetect_rise <= '0';
detect_fall <= '0';
detect_rise <= '0';
clk_div <= x"0";
else
if bin.we = '1' then
case bin.adr is
when "000" =>
if bin.sel(1) = '1' then
rrestart <= bin.dati (9);
restart <= bin.dati (8);
end if;
if bin.sel(2) = '1' then
rdetect_fall <= bin.dati (19);
rdetect_rise <= bin.dati (18);
detect_fall <= bin.dati (17);
detect_rise <= bin.dati (16);
end if;
if bin.sel(3) = '1' then
clk_div <= bin.dati (27 downto 24);
end if;
if not g_with_ref then
rrestart <= '0';
rdetect_fall <= '0';
rdetect_rise <= '0';
clk_div <= (others => '0');
end if;
when "001" =>
null;
when "010" =>
null;
when "011" =>
null;
when others =>
null;
end case;
bout.wack <= '1';
end if;
end if;
end if;
end process;
gen_rin: if g_with_ref generate
process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
clk_cnt <= (others => '0');
else
clk_cnt <= std_logic_vector(unsigned(clk_cnt) + 1);
end if;
end if;
end process;
process (clk_i) is
begin
if rising_edge (clk_i) then
clk_dir <= '0';
case clk_div is
when x"0" => rin_o <= '0';
when x"1" => rin_o <= clk_cnt(0);
when x"2" => rin_o <= clk_cnt(1);
when x"3" => rin_o <= clk_cnt(2);
when x"4" => rin_o <= clk_cnt(3);
when x"5" => rin_o <= clk_cnt(4);
when x"6" => rin_o <= clk_cnt(5);
when x"7" => rin_o <= clk_cnt(6);
when x"8" => rin_o <= clk_cnt(7);
when others => rin_o <= '0';
end case;
end if;
end process;
end generate;
gen_no_rin: if not g_with_ref generate
rin_o <= '0';
end generate;
end behav;