Newer
Older
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
-- unit name: gc_frequency_meter
--
-- description: Frequency meter with internal or external timebase.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2012-2019
--------------------------------------------------------------------------------
-- 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.
--------------------------------------------------------------------------------
-- Principle of operation:
--
-- This block counts the number of pulses on CLK_IN_I during a period.
-- At the end of the period, the value is saved and the counter reset.
-- The saved value is available on FREQ_O, which is synchronized with
-- CLK_SYS_I if G_SYNC_OUT is True.
-- The width of the counter is defined by G_COUNTER_BITS.
--
-- - If g_WITH_INTERNAL_TIMEBASE is True:
-- The period is defined by an internal counter that generates a pulse
-- every G_CLK_SYS_FREQ CLK_SYS_I ticks.
--
-- - If g_WITH_INTERNAL_TIMEBASE is False:
-- The period is defined by PPS_P1_I
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
entity gc_frequency_meter is
generic (
g_WITH_INTERNAL_TIMEBASE : boolean := TRUE;
g_CLK_SYS_FREQ : integer;
-- if true, sync freq_o to the clk_sys domain
g_SYNC_OUT : boolean := FALSE;
g_COUNTER_BITS : integer := 32);
port (
clk_sys_i : in std_logic;
clk_in_i : in std_logic;
rst_n_i : in std_logic; -- not used, kept for backward compatibility
pps_p1_i : in std_logic;
-- synced to clk_in_i or clk_sys_i, depending on g_SYNC_OUT value
freq_o : out std_logic_vector(g_COUNTER_BITS-1 downto 0);
-- synced to clk_sys_i, always
freq_valid_o : out std_logic);
end gc_frequency_meter;
architecture arch of gc_frequency_meter is
signal gate_pulse, gate_pulse_synced : std_logic := '0';
signal cntr_gate : unsigned(g_COUNTER_BITS-1 downto 0) := (others => '0');
signal cntr_meas : unsigned(g_COUNTER_BITS-1 downto 0) := (others => '0');
signal freq_reg : std_logic_vector(g_COUNTER_BITS-1 downto 0) := (others => '0');
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 cntr_gate = g_CLK_SYS_FREQ-1 then
cntr_gate <= (others => '0');
cntr_gate <= cntr_gate + 1;
gate_pulse <= '0';
end if;
end if;
end process;
U_Sync_Gate : gc_pulse_synchronizer
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_in_i,
rst_n_i => '1',
d_ready_o => freq_valid_o,
d_p_i => gate_pulse,
q_p_o => gate_pulse_synced);
Tomasz Wlostowski
committed
end generate gen_internal_timebase;
gen_external_timebase : if g_WITH_INTERNAL_TIMEBASE = FALSE generate
Tomasz Wlostowski
committed
Tomasz Wlostowski
committed
U_Sync_Gate : gc_pulse_synchronizer
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_in_i,
rst_n_i => '1',
d_ready_o => freq_valid_o,
d_p_i => pps_p1_i,
q_p_o => gate_pulse_synced);
Tomasz Wlostowski
committed
end generate gen_external_timebase;
p_freq_counter : process (clk_in_i)
if rising_edge(clk_in_i) then
if gate_pulse_synced = '1' then
freq_reg <= std_logic_vector(cntr_meas);
cntr_meas <= (others => '0');
else
cntr_meas <= cntr_meas + 1;
end if;
end if;
end process p_freq_counter;
gen_with_sync_out : if g_SYNC_OUT generate
cmp_gc_sync_word_wr : gc_sync_word_wr
generic map (
g_AUTO_WR => TRUE,
g_WIDTH => g_COUNTER_BITS)
port map (
clk_in_i => clk_in_i,
rst_in_n_i => '1',
clk_out_i => clk_sys_i,
rst_out_n_i => '1',
data_i => freq_reg,
data_o => freq_o);
end generate gen_with_sync_out;
gen_without_sync_out : if not g_SYNC_OUT generate
freq_o <= freq_reg;
end generate gen_without_sync_out;