-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathgc_multichannel_frequency_meter.vhd
143 lines (114 loc) · 4.39 KB
/
gc_multichannel_frequency_meter.vhd
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
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_multichannel_frequency_meter
--
-- description: Frequency meter optimized for multiple channels.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2012-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
entity gc_multichannel_frequency_meter is
generic(
g_WITH_INTERNAL_TIMEBASE : boolean := true;
g_CLK_SYS_FREQ : integer;
g_COUNTER_BITS : integer := 32;
g_CHANNELS : integer := 1);
port(
clk_sys_i : in std_logic;
clk_in_i : in std_logic_vector(g_CHANNELS -1 downto 0);
rst_n_i : in std_logic;
pps_p1_i : in std_logic;
channel_sel_i : in std_logic_vector(3 downto 0);
freq_o : out std_logic_vector(g_COUNTER_BITS-1 downto 0);
freq_valid_o : out std_logic
);
end gc_multichannel_frequency_meter;
architecture arch of gc_multichannel_frequency_meter is
signal gate_pulse : std_logic;
signal gate_pulse_synced : std_logic_vector(g_CHANNELS-1 downto 0);
signal cntr_gate : unsigned(g_COUNTER_BITS-1 downto 0);
type t_channel_state is record
cntr : unsigned(g_COUNTER_BITS-1 downto 0);
freq : unsigned(g_COUNTER_BITS-1 downto 0);
freq_valid : std_logic;
end record;
type t_channel_state_array is array(0 to g_CHANNELS-1) of t_channel_state;
signal ch : t_channel_state_array;
begin
gen_internal_timebase : if(g_WITH_INTERNAL_TIMEBASE = true) generate
p_gate_counter : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
cntr_gate <= (others => '0');
gate_pulse <= '0';
else
if(cntr_gate = g_CLK_SYS_FREQ-1) then
cntr_gate <= (others => '0');
gate_pulse <= '1';
else
cntr_gate <= cntr_gate + 1;
gate_pulse <= '0';
end if;
end if;
end if;
end process;
end generate gen_internal_timebase;
gen_external_timebase : if(g_WITH_INTERNAL_TIMEBASE = false) generate
gate_pulse <= pps_p1_i;
end generate gen_external_timebase;
gen_channels : for i in 0 to g_CHANNELS-1 generate
U_Sync_Gate : gc_pulse_synchronizer
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_in_i(i),
rst_n_i => rst_n_i,
d_ready_o => open,
d_p_i => gate_pulse,
q_p_o => gate_pulse_synced(i));
p_freq_counter : process (clk_in_i(i), rst_n_i)
begin
if rst_n_i = '0' then -- asynchronous reset (active low)
ch(i).cntr <= (others => '0');
ch(i).freq <= (others => '0');
ch(i).freq_valid <= '0';
elsif rising_edge(clk_in_i(i)) then
if(gate_pulse_synced(i) = '1') then
ch(i).freq_valid <= '1';
ch(i).freq <= ch(i).cntr;
ch(i).cntr <= (others => '0');
else
ch(i).cntr <= ch(i).cntr + 1;
end if;
end if;
end process p_freq_counter;
end generate gen_channels;
p_freq_output : process(clk_sys_i)
variable idx : integer range 0 to g_CHANNELS-1;
begin
if rising_edge(clk_sys_i) then
idx := to_integer(unsigned(channel_sel_i));
freq_o <= std_logic_vector(ch(idx).freq);
freq_valid_o <= ch(idx).freq_valid;
end if;
end process;
end arch;