Channel bank (synthesis ok, untested)

parent f3c2a15e
...@@ -31,28 +31,34 @@ entity tdc_channel is ...@@ -31,28 +31,34 @@ entity tdc_channel is
-- Number of raw output bits. -- Number of raw output bits.
g_RAW_COUNT : positive; g_RAW_COUNT : positive;
-- Number of fractional part bits. -- Number of fractional part bits.
g_FP_COUNT : positive g_FP_COUNT : positive;
-- Length of the ring oscillator.
g_RO_LENGTH : positive
); );
port( port(
clk_i : in std_logic; clk_i : in std_logic;
reset_i : in std_logic; reset_i : in std_logic;
-- Signal input. -- Signal input.
signal_i : in std_logic; signal_i : in std_logic;
calib_i : in std_logic; calib_i : in std_logic;
calib_sel_i : in std_logic; calib_sel_i : in std_logic;
-- Detection outputs. -- Detection outputs.
detect_o : out std_logic; detect_o : out std_logic;
polarity_o : out std_logic; polarity_o : out std_logic;
raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0); raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_FP_COUNT-1 downto 0); fp_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- LUT access. -- LUT access.
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0); lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic; lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0); 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) lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Calibration ring oscillator.
ro_en_i : in std_logic;
ro_clk_o : out std_logic
); );
end entity; end entity;
...@@ -62,7 +68,7 @@ signal taps : std_logic_vector(4*g_CARRY4_COUNT-1 downto 0); ...@@ -62,7 +68,7 @@ signal taps : std_logic_vector(4*g_CARRY4_COUNT-1 downto 0);
signal polarity, polarity_d1 : std_logic; signal polarity, polarity_d1 : std_logic;
signal raw : std_logic_vector(g_RAW_COUNT-1 downto 0); signal raw : std_logic_vector(g_RAW_COUNT-1 downto 0);
begin begin
with signal_i select with calib_sel_i select
muxed_signal <= calib_i when '1', signal_i when others; muxed_signal <= calib_i when '1', signal_i when others;
cmp_delayline: tdc_delayline cmp_delayline: tdc_delayline
...@@ -117,6 +123,15 @@ begin ...@@ -117,6 +123,15 @@ begin
qb_o => lut_d_o qb_o => lut_d_o
); );
cmp_ringosc: tdc_ringosc
generic map(
g_LENGTH => g_RO_LENGTH
)
port map(
en_i => ro_en_i,
clk_o => ro_clk_o
);
polarity_o <= polarity_d1; polarity_o <= polarity_d1;
process(clk_i) process(clk_i)
......
-------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_channelbank
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Channel bank
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-08 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_channelbank 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;
-- Length of each ring oscillator.
g_RO_LENGTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
-- Control.
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
-- 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_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);
-- Online calibration ring oscillator.
ro_clk_o : out std_logic
);
end entity;
architecture rtl of tdc_channelbank is
signal current_channel_onehot : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal lut_d_o_s : std_logic_vector(g_CHANNEL_COUNT*g_FP_COUNT-1 downto 0);
signal ro_clk_o_s : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
begin
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_RO_LENGTH => g_RO_LENGTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
signal_i => signal_i(i),
calib_i => calib_i(i),
calib_sel_i => this_calib_sel,
detect_o => detect_o(i),
polarity_o => polarity_o(i),
raw_o => raw_o((i+1)*g_RAW_COUNT-1 downto i*g_RAW_COUNT),
fp_o => fp_o((i+1)*g_FP_COUNT-1 downto i*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_o_s(i)
);
end generate;
-- 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 := (g_FP_COUNT-1 downto 0 => '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;
-- Combine ring oscillator outputs. When disabled, a ring oscillator
-- outputs 0, so we can simply OR all outputs together.
ro_clk_o <= '0' when (ro_clk_o_s = (ro_clk_o_s'range => '0')) else '1';
-- Generate channel selection signal.
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);
end architecture;
...@@ -22,6 +22,69 @@ use ieee.std_logic_1164.all; ...@@ -22,6 +22,69 @@ use ieee.std_logic_1164.all;
package tdc_package is package tdc_package is
component tdc_channelbank is
generic(
g_CHANNEL_COUNT : positive;
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_RO_LENGTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
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_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);
ro_clk_o : out std_logic
);
end component;
component tdc_channel is
generic(
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_RO_LENGTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
signal_i : in std_logic;
calib_i : in std_logic;
calib_sel_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_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);
ro_en_i : in std_logic;
ro_clk_o : out std_logic
);
end component;
component tdc_ringosc is component tdc_ringosc is
generic( generic(
g_LENGTH: positive g_LENGTH: positive
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- --
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org -- author: Sebastien Bourdeauducq, sebastien@milkymist.org
-- --
-- description: Ring oscillator based on LUT2 primitives -- description: Ring oscillator based on LUT primitives
-- --
-- references: http://www.ohwr.org/projects/tdc-core -- references: http://www.ohwr.org/projects/tdc-core
-- --
...@@ -32,7 +32,10 @@ entity tdc_ringosc is ...@@ -32,7 +32,10 @@ entity tdc_ringosc is
g_LENGTH: positive g_LENGTH: positive
); );
port( port(
-- Enable/reset_n input. The oscillator should be reset at least once.
-- When disabled, the output is 0.
en_i : in std_logic; en_i : in std_logic;
-- Oscillator output.
clk_o : out std_logic clk_o : out std_logic
); );
end entity; end entity;
...@@ -44,7 +47,8 @@ attribute keep of s: signal is "true"; ...@@ -44,7 +47,8 @@ attribute keep of s: signal is "true";
begin begin
g_luts: for i in 0 to g_LENGTH-1 generate g_luts: for i in 0 to g_LENGTH-1 generate
g_firstlut: if i = 0 generate g_firstlut: if i = 0 generate
cmp_LUT: LUT2 generic map( cmp_LUT: LUT2
generic map(
INIT => "0100" INIT => "0100"
) )
port map( port map(
...@@ -54,7 +58,8 @@ begin ...@@ -54,7 +58,8 @@ begin
); );
end generate; end generate;
g_nextlut: if i > 0 generate g_nextlut: if i > 0 generate
cmp_LUT: LUT1 generic map( cmp_LUT: LUT1
generic map(
INIT => "01" INIT => "01"
) )
port map( port map(
......
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