Frequency counter

parent 7071d905
-------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_freqm
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Frequency counter
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-13 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 Sebastien Bourdeauducq
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
entity tdc_freqc is
generic(
g_COUNTER_WIDTH : positive;
g_TIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
clk_m_i : in std_logic;
start_i : in std_logic;
ready_o : out std_logic;
freq_o : out std_logic_vector(g_COUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_freqc is
-- clk_m domain
signal m_counter : std_logic_vector(g_COUNTER_WIDTH-1 downto 0);
signal m_start : std_logic;
signal m_stop : std_logic;
signal m_started : std_logic;
-- clk domain
signal start : std_logic;
signal stop : std_logic;
signal stop_ack : std_logic;
signal counter_r : std_logic_vector(g_COUNTER_WIDTH-1 downto 0);
signal timer : std_logic_vector(g_TIMER_WIDTH-1 downto 0);
signal timer_start : std_logic;
signal timer_done : std_logic;
type t_state is (IDLE, MEASURING, TERMINATING);
signal state : t_state;
-- Prevent inference of a SRL* primitive, which does not
-- have good metastability resistance.
attribute keep: string;
attribute keep of counter_r: signal is "true";
begin
-- clk_m clock domain.
process(clk_m_i)
begin
if rising_edge(clk_m_i) then
if (m_started = '1') and (m_stop = '0') then
m_counter <= std_logic_vector(unsigned(m_counter) + 1);
end if;
if m_start = '1' then
m_started <= '1';
m_counter <= (m_counter'range => '0');
end if;
if m_stop = '1' then
m_started <= '0';
end if;
end if;
end process;
-- Synchronisers.
cmp_sync_start: tdc_psync
port map(
clk_src_i => clk_i,
p_i => start,
clk_dst_i => clk_m_i,
p_o => m_start
);
cmp_sync_stop: tdc_psync
port map(
clk_src_i => clk_i,
p_i => stop,
clk_dst_i => clk_m_i,
p_o => m_stop
);
cmp_sync_stop_ack: tdc_psync
port map(
clk_src_i => clk_m_i,
p_i => m_stop,
clk_dst_i => clk_i,
p_o => stop_ack
);
process(clk_i)
begin
if rising_edge(clk_i) then
counter_r <= m_counter;
freq_o <= counter_r;
end if;
end process;
-- Controller.
process(clk_i)
begin
if rising_edge(clk_i) then
if timer_start = '1' then
timer <= (timer'range => '1');
elsif timer_done = '0' then
timer <= std_logic_vector(unsigned(timer) - 1);
end if;
end if;
end process;
timer_done <= '1' when (timer = (timer'range => '0')) else '0';
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
state <= IDLE;
else
case state is
when IDLE =>
if start_i = '1' then
state <= MEASURING;
end if;
when MEASURING =>
if timer_done = '1' then
state <= TERMINATING;
end if;
when TERMINATING =>
if stop_ack = '1' then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
process(state, start_i, timer_done, stop_ack)
begin
ready_o <= '0';
start <= '0';
stop <= '0';
timer_start <= '0';
case state is
when IDLE =>
ready_o <= '1';
if start_i = '1' then
start <= '1';
timer_start <= '1';
end if;
when MEASURING =>
if timer_done = '1' then
stop <= '1';
end if;
when TERMINATING =>
null;
end case;
end process;
end architecture;
......@@ -130,4 +130,14 @@ component tdc_delayline is
);
end component;
component tdc_psync is
port(
clk_src_i : in std_logic;
p_i : in std_logic;
clk_dst_i : in std_logic;
p_o : out std_logic
);
end component;
end package;
......@@ -20,6 +20,9 @@
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.tdc_package.all;
entity tdc_psync is
port(
clk_src_i : in std_logic;
......@@ -63,6 +66,6 @@ begin
end if;
end process;
-- Convert level flips back into pulses synchronous to clk_dest domain.
-- Convert level flips back into pulses synchronous to clk_dst domain.
p_o <= level_d2 xor level_d3;
end architecture;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment