tdc_lbc.vhd 3.67 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
-------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_lbc
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Leading bit counter
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-01 SB Created file
-------------------------------------------------------------------------------

-- Copyright (C) 2011 Sebastien Bourdeauducq

library ieee;
use ieee.std_logic_1164.all;

23 24 25
library work;
use work.tdc_package.all;

26
entity tdc_lbc is
27
    generic(
28
        -- Number of output bits.
29 30 31
        g_N : positive;
        -- Number of input bits. Maximum is 2^g_N-1.
        g_NIN: positive
32
    );
33
    port(
34
         clk_i        : in std_logic;
35 36 37
         reset_i      : in std_logic;
         d_i          : in std_logic_vector(g_NIN-1 downto 0);
         polarity_o   : out std_logic;
38 39 40 41 42 43
         count_o      : out std_logic_vector(g_N-1 downto 0)
    );
end entity;

architecture rtl of tdc_lbc is

44
-- "Count leading symbol" function inspired by the post by Ulf Samuelsson
45 46 47 48 49
-- http://www.velocityreviews.com/forums/t25846-p4-how-to-count-zeros-in-registers.html
--
-- The idea is to use a divide-and-conquer approach to process a 2^N bit number.
-- We split the number in two equal halves of 2^(N-1) bits:
--   MMMMLLLL
50
-- then, we check if all bits of MMMM are of the counted symbol.
51
-- If it is,
52
--      then the number of leading symbols is 2^(N-1) + CLS(LLLL)
53
-- If it is not,
54 55
--      then the number of leading symbols is CLS(MMMM)
-- Recursion stops with CLS(0)=0 and CLS(1)=1.
56
--
57 58 59
-- If at least one bit of the input is not the symbol, we never propagate a carry
-- and the additions can be replaced by OR's, giving the result bit per bit.
-- We assume here an implicit LSB with a !symbol value, and work with inputs
60
-- widths that are a power of 2 minus one.
61
function f_cls(d: std_logic_vector; symbol: std_logic) return std_logic_vector is
62 63 64 65
variable v_d: std_logic_vector(d'length-1 downto 0);
begin
    v_d := d; -- fix indices
    if v_d'length = 1 then
66 67 68 69 70
        if v_d(0) = symbol then
            return "1";
        else
            return "0";
        end if;
71
    else
72 73
        if v_d(v_d'length-1 downto v_d'length/2) = (v_d'length-1 downto v_d'length/2 => symbol) then
            return "1" & f_cls(v_d(v_d'length/2-1 downto 0), symbol);
74
        else
75
            return "0" & f_cls(v_d(v_d'length-1 downto v_d'length/2+1), symbol);
76 77 78 79
        end if;
    end if;
end function;

80
signal polarity    : std_logic;
81 82
signal polarity_d1 : std_logic;
signal polarity_d2 : std_logic;
83 84
signal count_reg   : std_logic_vector(g_N-1 downto 0);
signal d_completed : std_logic_vector(2**g_N-2 downto 0);
85
begin
86 87 88 89 90 91 92
    g_expand: if g_NIN < 2**g_N-1 generate
        d_completed <= d_i & (2**g_N-1-g_NIN-1 downto 0 => not polarity);
    end generate;
    g_dontexpand: if g_NIN = 2**g_N-1 generate
        d_completed <= d_i;
    end generate;
    
93 94 95
    process(clk_i)
    begin
        if rising_edge(clk_i) then
96 97
            if reset_i = '1' then
                polarity <= '1';
98 99
                polarity_d1 <= '1';
                polarity_d2 <= '1';
100 101 102 103
                count_reg <= (others => '0');
                count_o <= (others => '0');
            else
                polarity <= not d_completed(2**g_N-2);
104 105
                polarity_d1 <= polarity;
                polarity_d2 <= polarity_d1;
106 107 108
                count_reg <= f_cls(d_completed, polarity);
                count_o <= count_reg;
            end if;
109 110
        end if;
    end process;
111
    polarity_o <= polarity_d2;
112
end architecture;