channelbank: support single-channel configuration

parent 96fd461c
......@@ -6,15 +6,13 @@
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Channel bank
-- description: Automatic channel bank
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-18 SB Added histogram
-- 2011-08-17 SB Added frequency counter
-- 2011-08-08 SB Created file
-- 2011-10-25 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
......@@ -29,20 +27,8 @@
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- DESCRIPTION:
-- This module instantiates all the channels and provides a control interface
-- independent of the number of channels.
-- It provides a simple two-wire interface to select the current channel to
-- operate one, using the next_i (switch to next channel) and last_o (current
-- channel is the current channel, next channel is the first channel).
-- It provides multiplexed access to the LUT of the current channel, to the
-- histogram of the current channel, and to the ring oscillator frequency
-- of the current channel.
--
-- To save resources:
-- * the histogram is implemented as one large block RAM common to all
-- channels
-- * the frequency counter logic is shared among all channels, each channel
-- only implements a ring oscillator.
-- This module instantiates the single- or multi-channel bank depending
-- on the g_CHANNEL_COUNT generic.
library ieee;
use ieee.std_logic_1164.all;
......@@ -50,7 +36,6 @@ use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
use work.genram_pkg.all;
entity tdc_channelbank is
generic(
......@@ -119,208 +104,106 @@ entity tdc_channelbank is
end entity;
architecture rtl of tdc_channelbank is
signal detect : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal raw : std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
signal coarse_counter : std_logic_vector(g_COARSE_COUNT-1 downto 0);
signal current_channel_onehot : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal current_channel : std_logic_vector(f_log2_size(g_CHANNEL_COUNT)-1 downto 0);
signal lut_d_o_s : std_logic_vector(g_CHANNEL_COUNT*g_FP_COUNT-1 downto 0);
signal his_full_a : std_logic_vector(f_log2_size(g_CHANNEL_COUNT)+g_RAW_COUNT-1 downto 0);
signal ro_clk_s : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal ro_clk : std_logic;
signal freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal sfreq_s : std_logic_vector(g_CHANNEL_COUNT*g_FCOUNTER_WIDTH-1 downto 0);
begin
-- Per-channel processing.
g_channels: for i in 0 to g_CHANNEL_COUNT-1 generate
signal this_calib_sel : std_logic;
signal this_lut_we : std_logic;
begin
this_calib_sel <= current_channel_onehot(i) and calib_sel_i;
this_lut_we <= current_channel_onehot(i) and lut_we_i;
cmp_channel: tdc_channel
g_single: if g_CHANNEL_COUNT = 1 generate
cmp_channelbank: tdc_channelbank_single
generic map(
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH,
g_FCOUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_FTIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
coarse_i => coarse_counter,
deskew_i =>
deskew_i((i+1)*(g_COARSE_COUNT+g_FP_COUNT)-1 downto i*(g_COARSE_COUNT+g_FP_COUNT)),
signal_i => signal_i(i),
calib_i => calib_i(i),
calib_sel_i => this_calib_sel,
detect_o => detect(i),
polarity_o => polarity_o(i),
raw_o => raw((i+1)*g_RAW_COUNT-1 downto i*g_RAW_COUNT),
fp_o =>
fp_o((i+1)*(g_COARSE_COUNT+g_FP_COUNT)-1 downto i*(g_COARSE_COUNT+g_FP_COUNT)),
lut_a_i => lut_a_i,
lut_we_i => this_lut_we,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o_s((i+1)*g_FP_COUNT-1 downto i*g_FP_COUNT),
clk_i => clk_i,
reset_i => reset_i,
cc_rst_i => cc_rst_i,
cc_cy_o => cc_cy_o,
next_i => next_i,
last_o => last_o,
calib_sel_i => calib_sel_i,
deskew_i => deskew_i,
signal_i => signal_i(0),
calib_i => calib_i(0),
detect_o => detect_o(0),
polarity_o => polarity_o(0),
raw_o => raw_o,
fp_o => fp_o,
lut_a_i => lut_a_i,
lut_we_i => lut_we_i,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o,
c_detect_o => c_detect_o,
c_raw_o => c_raw_o,
his_a_i => his_a_i,
his_we_i => his_we_i,
his_d_i => his_d_i,
his_d_o => his_d_o,
ro_en_i => current_channel_onehot(i),
ro_clk_o => ro_clk_s(i)
oc_start_i => oc_start_i,
oc_ready_o => oc_ready_o,
oc_freq_o => oc_freq_o,
oc_store_i => oc_store_i,
oc_sfreq_o => oc_sfreq_o
);
end generate;
detect_o <= detect;
raw_o <= raw;
-- Histogram memory.
cmp_histogram: generic_spram
generic map(
g_data_width => g_FP_COUNT,
g_size => g_CHANNEL_COUNT*2**g_RAW_COUNT,
g_with_byte_enable => false,
g_init_file => "",
g_addr_conflict_resolution => "read_first"
)
port map(
rst_n_i => '1',
clk_i => clk_i,
bwe_i => (others => '0'),
we_i => his_we_i,
a_i => his_full_a,
d_i => his_d_i,
q_o => his_d_o
);
his_full_a <= current_channel & his_a_i;
-- Frequency counter.
cmp_freqc: tdc_freqc
generic map(
g_COUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_TIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
clk_m_i => ro_clk,
start_i => oc_start_i,
ready_o => oc_ready_o,
freq_o => freq
);
oc_freq_o <= freq;
-- Coarse counter.
process(clk_i)
begin
if rising_edge(clk_i) then
if (reset_i = '1') or (cc_rst_i = '1') then
coarse_counter <= (coarse_counter'range => '0');
cc_cy_o <= '0';
else
coarse_counter <= std_logic_vector(unsigned(coarse_counter) + 1);
if coarse_counter = (coarse_counter'range => '1') then
cc_cy_o <= '1';
else
cc_cy_o <= '0';
end if;
end if;
end if;
end process;
-- Combine LUT outputs.
process(lut_d_o_s, current_channel_onehot)
variable v_lut_d_o: std_logic_vector(g_FP_COUNT-1 downto 0);
begin
v_lut_d_o := (v_lut_d_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_lut_d_o := v_lut_d_o or lut_d_o_s((i+1)*g_FP_COUNT-1 downto i*g_FP_COUNT);
end if;
end loop;
lut_d_o <= v_lut_d_o;
end process;
-- Select detect and raw outputs for histogram generation.
process(detect, raw, current_channel_onehot)
variable v_c_detect_o : std_logic;
variable v_c_raw_o : std_logic_vector(g_RAW_COUNT-1 downto 0);
begin
v_c_detect_o := '0';
v_c_raw_o := (v_c_raw_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_c_detect_o := v_c_detect_o or detect(i);
v_c_raw_o := v_c_raw_o or raw((i+1)*g_RAW_COUNT-1 downto i*g_RAW_COUNT);
end if;
end loop;
c_detect_o <= v_c_detect_o;
c_raw_o <= v_c_raw_o;
end process;
-- Combine ring oscillator outputs. When disabled, a ring oscillator
-- outputs 0, so we can simply OR all outputs together.
ro_clk <= '0' when (ro_clk_s = (ro_clk_s'range => '0')) else '1';
-- Store and retrieve per-channel ring oscillator frequencies.
process(clk_i)
begin
if rising_edge(clk_i) then
if oc_store_i = '1' then
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
sfreq_s((i+1)*g_FCOUNTER_WIDTH-1 downto i*g_FCOUNTER_WIDTH) <= freq;
end if;
end loop;
end if;
end if;
end process;
process(sfreq_s, current_channel_onehot)
variable v_oc_sfreq_o: std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
begin
v_oc_sfreq_o := (v_oc_sfreq_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_oc_sfreq_o := v_oc_sfreq_o
or sfreq_s((i+1)*g_FCOUNTER_WIDTH-1 downto i*g_FCOUNTER_WIDTH);
end if;
end loop;
oc_sfreq_o <= v_oc_sfreq_o;
end process;
-- Generate channel selection signals.
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
current_channel_onehot <= (0 => '1', others => '0');
else
if next_i = '1' then
current_channel_onehot <=
std_logic_vector(rotate_left(unsigned(current_channel_onehot), 1));
end if;
end if;
end if;
end process;
last_o <= current_channel_onehot(g_CHANNEL_COUNT-1);
g_encode: if g_CHANNEL_COUNT > 1 generate
process(current_channel_onehot)
variable v_current_channel: std_logic_vector(f_log2_size(g_CHANNEL_COUNT)-1 downto 0);
begin
v_current_channel := (v_current_channel'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_current_channel := v_current_channel
or std_logic_vector(to_unsigned(i, v_current_channel'length));
end if;
end loop;
current_channel <= v_current_channel;
end process;
end generate;
g_multi: if g_CHANNEL_COUNT > 1 generate
cmp_channelbank: tdc_channelbank_multi
generic map(
g_CHANNEL_COUNT => g_CHANNEL_COUNT,
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH,
g_FCOUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_FTIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
cc_rst_i => cc_rst_i,
cc_cy_o => cc_cy_o,
next_i => next_i,
last_o => last_o,
calib_sel_i => calib_sel_i,
deskew_i => deskew_i,
signal_i => signal_i,
calib_i => calib_i,
detect_o => detect_o,
polarity_o => polarity_o,
raw_o => raw_o,
fp_o => fp_o,
lut_a_i => lut_a_i,
lut_we_i => lut_we_i,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o,
c_detect_o => c_detect_o,
c_raw_o => c_raw_o,
his_a_i => his_a_i,
his_we_i => his_we_i,
his_d_i => his_d_i,
his_d_o => his_d_o,
oc_start_i => oc_start_i,
oc_ready_o => oc_ready_o,
oc_freq_o => oc_freq_o,
oc_store_i => oc_store_i,
oc_sfreq_o => oc_sfreq_o
);
end generate;
end architecture;
-------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_channelbank_multi
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Channel bank (multi-channel)
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Renamed to channelbank_multi
-- 2011-08-18 SB Added histogram
-- 2011-08-17 SB Added frequency counter
-- 2011-08-08 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, version 3 of the License.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- DESCRIPTION:
-- This module instantiates all the channels and provides a control interface
-- independent of the number of channels.
-- It provides a simple two-wire interface to select the current channel to
-- operate one, using the next_i (switch to next channel) and last_o (current
-- channel is the current channel, next channel is the first channel).
-- It provides multiplexed access to the LUT of the current channel, to the
-- histogram of the current channel, and to the ring oscillator frequency
-- of the current channel.
--
-- To save resources:
-- * the histogram is implemented as one large block RAM common to all
-- channels
-- * the frequency counter logic is shared among all channels, each channel
-- only implements a ring oscillator.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
use work.genram_pkg.all;
entity tdc_channelbank_multi is
generic(
-- Number of channels.
g_CHANNEL_COUNT : positive;
-- Number of CARRY4 elements per channel.
g_CARRY4_COUNT : positive;
-- Number of raw output bits.
g_RAW_COUNT : positive;
-- Number of fractional part bits.
g_FP_COUNT : positive;
-- Number of coarse counter bits.
g_COARSE_COUNT : positive;
-- Length of each ring oscillator.
g_RO_LENGTH : positive;
-- Frequency counter width.
g_FCOUNTER_WIDTH : positive;
-- Frequency counter timer width.
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
-- Control.
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
-- Per-channel deskew inputs.
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- Per-channel signal inputs.
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
-- Per-channel detection outputs.
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- LUT access.
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Histogram.
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Online calibration.
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_channelbank_multi is
signal detect : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal raw : std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
signal coarse_counter : std_logic_vector(g_COARSE_COUNT-1 downto 0);
signal current_channel_onehot : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal current_channel : std_logic_vector(f_log2_size(g_CHANNEL_COUNT)-1 downto 0);
signal lut_d_o_s : std_logic_vector(g_CHANNEL_COUNT*g_FP_COUNT-1 downto 0);
signal his_full_a : std_logic_vector(f_log2_size(g_CHANNEL_COUNT)+g_RAW_COUNT-1 downto 0);
signal ro_clk_s : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal ro_clk : std_logic;
signal freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal sfreq_s : std_logic_vector(g_CHANNEL_COUNT*g_FCOUNTER_WIDTH-1 downto 0);
begin
-- Per-channel processing.
g_channels: for i in 0 to g_CHANNEL_COUNT-1 generate
signal this_calib_sel : std_logic;
signal this_lut_we : std_logic;
begin
this_calib_sel <= current_channel_onehot(i) and calib_sel_i;
this_lut_we <= current_channel_onehot(i) and lut_we_i;
cmp_channel: tdc_channel
generic map(
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
coarse_i => coarse_counter,
deskew_i =>
deskew_i((i+1)*(g_COARSE_COUNT+g_FP_COUNT)-1 downto i*(g_COARSE_COUNT+g_FP_COUNT)),
signal_i => signal_i(i),
calib_i => calib_i(i),
calib_sel_i => this_calib_sel,
detect_o => detect(i),
polarity_o => polarity_o(i),
raw_o => raw((i+1)*g_RAW_COUNT-1 downto i*g_RAW_COUNT),
fp_o =>
fp_o((i+1)*(g_COARSE_COUNT+g_FP_COUNT)-1 downto i*(g_COARSE_COUNT+g_FP_COUNT)),
lut_a_i => lut_a_i,
lut_we_i => this_lut_we,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o_s((i+1)*g_FP_COUNT-1 downto i*g_FP_COUNT),
ro_en_i => current_channel_onehot(i),
ro_clk_o => ro_clk_s(i)
);
end generate;
detect_o <= detect;
raw_o <= raw;
-- Histogram memory.
cmp_histogram: generic_spram
generic map(
g_data_width => g_FP_COUNT,
g_size => g_CHANNEL_COUNT*2**g_RAW_COUNT,
g_with_byte_enable => false,
g_init_file => "",
g_addr_conflict_resolution => "read_first"
)
port map(
rst_n_i => '1',
clk_i => clk_i,
bwe_i => (others => '0'),
we_i => his_we_i,
a_i => his_full_a,
d_i => his_d_i,
q_o => his_d_o
);
his_full_a <= current_channel & his_a_i;
-- Frequency counter.
cmp_freqc: tdc_freqc
generic map(
g_COUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_TIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
clk_m_i => ro_clk,
start_i => oc_start_i,
ready_o => oc_ready_o,
freq_o => freq
);
oc_freq_o <= freq;
-- Coarse counter.
process(clk_i)
begin
if rising_edge(clk_i) then
if (reset_i = '1') or (cc_rst_i = '1') then
coarse_counter <= (coarse_counter'range => '0');
cc_cy_o <= '0';
else
coarse_counter <= std_logic_vector(unsigned(coarse_counter) + 1);
if coarse_counter = (coarse_counter'range => '1') then
cc_cy_o <= '1';
else
cc_cy_o <= '0';
end if;
end if;
end if;
end process;
-- Combine LUT outputs.
process(lut_d_o_s, current_channel_onehot)
variable v_lut_d_o: std_logic_vector(g_FP_COUNT-1 downto 0);
begin
v_lut_d_o := (v_lut_d_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_lut_d_o := v_lut_d_o or lut_d_o_s((i+1)*g_FP_COUNT-1 downto i*g_FP_COUNT);
end if;
end loop;
lut_d_o <= v_lut_d_o;
end process;
-- Select detect and raw outputs for histogram generation.
process(detect, raw, current_channel_onehot)
variable v_c_detect_o : std_logic;
variable v_c_raw_o : std_logic_vector(g_RAW_COUNT-1 downto 0);
begin
v_c_detect_o := '0';
v_c_raw_o := (v_c_raw_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_c_detect_o := v_c_detect_o or detect(i);
v_c_raw_o := v_c_raw_o or raw((i+1)*g_RAW_COUNT-1 downto i*g_RAW_COUNT);
end if;
end loop;
c_detect_o <= v_c_detect_o;
c_raw_o <= v_c_raw_o;
end process;
-- Combine ring oscillator outputs. When disabled, a ring oscillator
-- outputs 0, so we can simply OR all outputs together.
ro_clk <= '0' when (ro_clk_s = (ro_clk_s'range => '0')) else '1';
-- Store and retrieve per-channel ring oscillator frequencies.
process(clk_i)
begin
if rising_edge(clk_i) then
if oc_store_i = '1' then
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
sfreq_s((i+1)*g_FCOUNTER_WIDTH-1 downto i*g_FCOUNTER_WIDTH) <= freq;
end if;
end loop;
end if;
end if;
end process;
process(sfreq_s, current_channel_onehot)
variable v_oc_sfreq_o: std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
begin
v_oc_sfreq_o := (v_oc_sfreq_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_oc_sfreq_o := v_oc_sfreq_o
or sfreq_s((i+1)*g_FCOUNTER_WIDTH-1 downto i*g_FCOUNTER_WIDTH);
end if;
end loop;
oc_sfreq_o <= v_oc_sfreq_o;
end process;
-- Generate channel selection signals.
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
current_channel_onehot <= (0 => '1', others => '0');
else
if next_i = '1' then
current_channel_onehot <=
std_logic_vector(rotate_left(unsigned(current_channel_onehot), 1));
end if;
end if;
end if;
end process;
last_o <= current_channel_onehot(g_CHANNEL_COUNT-1);
process(current_channel_onehot)
variable v_current_channel: std_logic_vector(f_log2_size(g_CHANNEL_COUNT)-1 downto 0);
begin
v_current_channel := (v_current_channel'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_current_channel := v_current_channel
or std_logic_vector(to_unsigned(i, v_current_channel'length));
end if;
end loop;
current_channel <= v_current_channel;
end process;
end architecture;
-------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_channelbank_single
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Channel bank (single-channel)
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, version 3 of the License.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- DESCRIPTION:
-- Simplified version of tdc_channelbank_multi for the single-channel case.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
use work.genram_pkg.all;
entity tdc_channelbank_single is
generic(
-- Number of CARRY4 elements per channel.
g_CARRY4_COUNT : positive;
-- Number of raw output bits.
g_RAW_COUNT : positive;
-- Number of fractional part bits.
g_FP_COUNT : positive;
-- Number of coarse counter bits.
g_COARSE_COUNT : positive;
-- Length of each ring oscillator.
g_RO_LENGTH : positive;
-- Frequency counter width.
g_FCOUNTER_WIDTH : positive;
-- Frequency counter timer width.
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
-- Control.
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
-- Per-channel deskew inputs.
deskew_i : in std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
-- Per-channel signal inputs.
signal_i : in std_logic;
calib_i : in std_logic;
-- Per-channel detection outputs.
detect_o : out std_logic;
polarity_o : out std_logic;
raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
-- LUT access.
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Histogram.
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Online calibration.
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_channelbank_single is
signal detect : std_logic;
signal raw : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal coarse_counter : std_logic_vector(g_COARSE_COUNT-1 downto 0);
signal ro_clk : std_logic;
signal freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal sfreq_s : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
begin
-- Per-channel processing.
cmp_channel: tdc_channel
generic map(
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
coarse_i => coarse_counter,
deskew_i => deskew_i,
signal_i => signal_i,
calib_i => calib_i,
calib_sel_i => calib_sel_i,
detect_o => detect,
polarity_o => polarity_o,
raw_o => raw,
fp_o => fp_o,
lut_a_i => lut_a_i,
lut_we_i => lut_we_i,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o,
ro_en_i => '1',
ro_clk_o => ro_clk
);
detect_o <= detect;
raw_o <= raw;
c_detect_o <= detect;
c_raw_o <= raw;
-- Histogram memory.
cmp_histogram: generic_spram
generic map(
g_data_width => g_FP_COUNT,
g_size => 2**g_RAW_COUNT,
g_with_byte_enable => false,
g_init_file => "",
g_addr_conflict_resolution => "read_first"
)
port map(
rst_n_i => '1',
clk_i => clk_i,
bwe_i => (others => '0'),
we_i => his_we_i,
a_i => his_a_i,
d_i => his_d_i,
q_o => his_d_o
);
-- Frequency counter.
cmp_freqc: tdc_freqc
generic map(
g_COUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_TIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
clk_m_i => ro_clk,
start_i => oc_start_i,
ready_o => oc_ready_o,
freq_o => freq
);
oc_freq_o <= freq;
-- Coarse counter.
process(clk_i)
begin
if rising_edge(clk_i) then
if (reset_i = '1') or (cc_rst_i = '1') then
coarse_counter <= (coarse_counter'range => '0');
cc_cy_o <= '0';
else
coarse_counter <= std_logic_vector(unsigned(coarse_counter) + 1);
if coarse_counter = (coarse_counter'range => '1') then
cc_cy_o <= '1';
else
cc_cy_o <= '0';
end if;
end if;
end if;
end process;
-- Store and retrieve per-channel ring oscillator frequencies.
process(clk_i)
begin
if rising_edge(clk_i) then
if oc_store_i = '1' then
sfreq_s <= freq;
end if;
end if;
end process;
oc_sfreq_o <= sfreq_s;
-- Generate channel selection signals.
last_o <= '1';
end architecture;
......@@ -12,6 +12,7 @@
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Added single/multi channel bank components
-- 2011-08-03 SB Created file
-------------------------------------------------------------------------------
......@@ -169,6 +170,107 @@ component tdc_channelbank is
);
end component;
component tdc_channelbank_single is
generic(
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_COARSE_COUNT : positive;
g_RO_LENGTH : positive;
g_FCOUNTER_WIDTH : positive;
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
deskew_i : in std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
signal_i : in std_logic;
calib_i : in std_logic;
detect_o : out std_logic;
polarity_o : out std_logic;
raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end component;
component tdc_channelbank_multi is
generic(
g_CHANNEL_COUNT : positive;
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_COARSE_COUNT : positive;
g_RO_LENGTH : positive;
g_FCOUNTER_WIDTH : positive;
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end component;
component tdc_freqc is
generic(
g_COUNTER_WIDTH : positive;
......
......@@ -32,7 +32,7 @@ module system(
output [3:0] led,
// TDC
input [1:0] tdc_signal
input tdc_signal
);
//------------------------------------------------------------------
......@@ -455,10 +455,10 @@ sysctl #(
//---------------------------------------------------------------------------
// TDC
//---------------------------------------------------------------------------
wire [1:0] tdc_calib;
wire tdc_calib;
tdc_hostif #(
.g_CHANNEL_COUNT(2),
.g_CHANNEL_COUNT(1),
.g_CARRY4_COUNT(100),
.g_RAW_COUNT(9),
.g_FP_COUNT(13),
......@@ -499,6 +499,6 @@ reg [3:0] cal_clkdiv;
always @(posedge cal_clk16x) cal_clkdiv <= cal_clkdiv + 4'd1;
assign cal_clk = cal_clkdiv[3];
assign tdc_calib = {2{cal_clk}};
assign tdc_calib = cal_clk;
endmodule
......@@ -24,9 +24,7 @@ NET "led[3]" LOC = C20 | IOSTANDARD = "LVCMOS18";
# ==== TDC inputs ====
# FIXME
NET "tdc_signal[0]" LOC = AB11 | IOSTANDARD = LVCMOS25 | PULLDOWN;
NET "tdc_signal[1]" LOC = Y11 | IOSTANDARD = LVCMOS25 | PULLDOWN;
NET "tdc_signal" LOC = AB11 | IOSTANDARD = LVCMOS25 | PULLDOWN;
# ==== TDC core ====
NET "tdc/cmp_tdc/cmp_channelbank/g_channels[0].cmp_channel/muxed_signal" TIG;
NET "tdc/cmp_tdc/cmp_channelbank/g_channels[1].cmp_channel/muxed_signal" TIG;
NET "tdc/cmp_tdc/cmp_channelbank/g_single.cmp_channelbank/cmp_channel/muxed_signal" TIG;
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