From 4d36bf859fa6071acf11d86e1d57ab3a65a5f776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= <tomasz.wlostowski@cern.ch> Date: Mon, 17 Sep 2018 00:02:28 +0200 Subject: [PATCH] common: added a multiple input clock frequency meter --- modules/common/Manifest.py | 1 + .../gc_multichannel_frequency_meter.vhd | 143 ++++++++++++++++++ modules/common/gencores_pkg.vhd | 18 ++- 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 modules/common/gc_multichannel_frequency_meter.vhd diff --git a/modules/common/Manifest.py b/modules/common/Manifest.py index 1c975b65..082419e3 100644 --- a/modules/common/Manifest.py +++ b/modules/common/Manifest.py @@ -13,6 +13,7 @@ files = [ "gc_pulse_synchronizer.vhd", "gc_pulse_synchronizer2.vhd", "gc_frequency_meter.vhd", + "gc_multichannel_frequency_meter.vhd", "gc_rr_arbiter.vhd", "gc_prio_encoder.vhd", "gc_word_packer.vhd", diff --git a/modules/common/gc_multichannel_frequency_meter.vhd b/modules/common/gc_multichannel_frequency_meter.vhd new file mode 100644 index 00000000..237483e8 --- /dev/null +++ b/modules/common/gc_multichannel_frequency_meter.vhd @@ -0,0 +1,143 @@ +------------------------------------------------------------------------------- +-- Title : Frequency meter optimized for multiple channels +-- Project : General Cores +------------------------------------------------------------------------------- +-- File : gc_multichannel_frequency_meter.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN +-- Platform : FPGA-generics +-- Standard : VHDL '93 +------------------------------------------------------------------------------- +-- Copyright (c) 2012-2015 CERN +-- +-- Copyright and related rights are licensed under the Solderpad Hardware +-- License, Version 0.51 (the “Licenseâ€) (which enables you, at your option, +-- to treat this file as licensed under the Apache License 2.0); 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-0.51. +-- 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 behavioral 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 behavioral; + + diff --git a/modules/common/gencores_pkg.vhd b/modules/common/gencores_pkg.vhd index f2ced0d3..76b0a34e 100644 --- a/modules/common/gencores_pkg.vhd +++ b/modules/common/gencores_pkg.vhd @@ -208,7 +208,7 @@ package gencores_pkg is end component; ------------------------------------------------------------------------------ - -- Frequency meter + -- Frequency meters ------------------------------------------------------------------------------ component gc_frequency_meter generic ( @@ -224,6 +224,22 @@ package gencores_pkg is freq_valid_o : out std_logic); end component; + component gc_multichannel_frequency_meter is + generic ( + g_with_internal_timebase : boolean; + g_clk_sys_freq : integer; + g_counter_bits : integer; + g_channels : integer); + 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 component gc_multichannel_frequency_meter; + ------------------------------------------------------------------------------ -- Time-division multiplexer with round robin arbitration ------------------------------------------------------------------------------ -- GitLab