URL
https://opencores.org/ocsvn/pulse_processing_algorithm/pulse_processing_algorithm/trunk
Subversion Repositories pulse_processing_algorithm
[/] [pulse_processing_algorithm/] [successive_interp.vhd] - Rev 2
Compare with Previous | Blame | View Log
----------------------------------------------------------------------------------------------- -- -- Copyright (C) 2011 Peter Lemmens, PANDA collaboration -- p.j.j.lemmens@rug.nl -- http://www-panda.gsi.de -- -- As a reference, please use: -- E. Guliyev, M. Kavatsyuk, P.J.J. Lemmens, G. Tambave, H. Loehner, -- "VHDL Implementation of Feature-Extraction Algorithm for the PANDA Electromagnetic Calorimeter" -- Nuclear Inst. and Methods in Physics Research, A .... -- -- -- 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; either version 3 of the License, or -- (at your option) any later version. -- -- 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 Lesser General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA -- ----------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------- -- Company : KVI (Kernfysisch Versneller Instituut -- Groningen, The Netherlands -- Author : P.J.J. Lemmens -- Design Name : Feature Extraction -- Module Name : successive_interp.vhd -- Description : Linear interpolation through the 'successive approximation' method. The actual -- zero crossing of the signal will practically allways be located between samples. -- The assumption is that the 'sub-sample time ratio' equals the ratio between -- the absolute value of the older sample (negative) and the value of the -- newer sample (positive). To maintain precision the choice was made to -- multiply the sample values by 2 at each iteration, instead of dividing the -- difference by 2. I theory you can calculate as many bits as you like; it's -- up to you to decide what is meaningfull -- The number of iterations also determines (to a large extent) the latency of -- the processing of an event (and thus the dead-time of the system). -- Room for improvement ! ----------------------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_SIGNED.ALL; entity successive_interp is generic( ITERATIONS : natural := 1); Port ( rst : in STD_LOGIC; clk : in STD_LOGIC; enable : in STD_LOGIC := '1'; trigger : in STD_LOGIC; samplenr_in : in STD_LOGIC_VECTOR; base_in : in STD_LOGIC_VECTOR; diff_in : in STD_LOGIC_VECTOR; output_valid : out STD_LOGIC; fraction_out : out STD_LOGIC_VECTOR; eventnr_out : out STD_LOGIC_VECTOR ); end successive_interp; architecture Behavioral of successive_interp is constant WIDTH : natural := diff_in'length; constant E_WIDTH : natural := WIDTH + ITERATIONS; constant LEADING_BITS : STD_LOGIC_VECTOR(ITERATIONS - 2 downto 0) := ('1', others => '0'); -- always <0 therefore signbit ='1' constant FRACTION_SIZE : natural := ITERATIONS; -------------------------------------------------------------------------------------------------- signal rst_S : std_logic := '1'; signal clk_S : std_logic := '0'; signal enable_S : std_logic := '0'; signal trigger_S : std_logic := '0'; signal sample_nr_S : std_logic_vector (samplenr_in'high downto 0) := (others => '0'); signal base_in_S : std_logic_vector (WIDTH -1 downto 0) := (others => '0'); signal diff_in_S : std_logic_vector (WIDTH -1 downto 0) := (others => '0'); signal fraction_out_S : std_logic_vector (ITERATIONS - 1 downto 0) := (others => '0'); -- holds index of last negative data signal cstate_count_S : std_logic_vector(4 downto 0) := (others => '0'); -- extra states needed to wait for input signals signal output_valid_S : std_logic := '0'; signal intermediate_S : std_logic_vector(WIDTH + ITERATIONS - 1 downto 0) := (others => '0'); signal stepsize_S : std_logic_vector(WIDTH - 1 downto 0) := (others => '0'); -------------------------------------------------------------------------------------------------- begin rst_S <= rst; clk_S <= clk; enable_S <= enable; trigger_S <= trigger; base_in_S <= base_in; diff_in_S <= diff_in; fraction_out <= fraction_out_S(FRACTION_SIZE - 1 downto 0); eventnr_out <= sample_nr_S; output_valid <= output_valid_S; interp_fsm : process(clk_S) begin if rising_edge(clk_S) then if (rst_S = '1') then cstate_count_S <= (others => '0'); elsif (cstate_count_S > 0) then cstate_count_S <= cstate_count_S - 1; elsif (trigger_S = '1' and enable_S = '1') then cstate_count_S <= conv_std_logic_vector(ITERATIONS + 1, cstate_count_S'length); -- one cycle extra to get the delayed 'difference' end if; if (cstate_count_S = ITERATIONS + 1) then intermediate_S <= (others => '0'); sample_nr_S <= samplenr_in - 4; -- remember the sample at the base of the window - 1.5*MovingWindowPower stepsize_S <= diff_in_S; intermediate_S <= conv_std_logic_vector(conv_integer(signed(base_in_S) & '0'), intermediate_S'length); output_valid_S <= '0'; elsif ((cstate_count_S <= ITERATIONS) and cstate_count_S > 1) then if ((signed(intermediate_S) + signed(stepsize_S)) <= 0) then intermediate_S <= conv_std_logic_vector(conv_integer(signed((intermediate_S(intermediate_S'high - 1 downto 0) + stepsize_S) & '0')), intermediate_S'length); fraction_out_S <= fraction_out_S(fraction_out_S'high - 1 downto 0) & '1'; else intermediate_S <= conv_std_logic_vector(conv_integer(signed((intermediate_S(intermediate_S'high - 1 downto 0)) & '0')), intermediate_S'length); fraction_out_S <= fraction_out_S(fraction_out_S'high - 1 downto 0) & '0'; end if; elsif (cstate_count_S = 1) then output_valid_S <= '1'; if ((signed(intermediate_S) + signed(stepsize_S)) <= 0) then intermediate_S <= conv_std_logic_vector(conv_integer(signed((intermediate_S(intermediate_S'high - 1 downto 0) + stepsize_S) & '0')), intermediate_S'length); fraction_out_S <= fraction_out_S(fraction_out_S'high - 1 downto 0) & '1'; else intermediate_S <= conv_std_logic_vector(conv_integer(signed((intermediate_S(intermediate_S'high - 1 downto 0)) & '0')), intermediate_S'length); fraction_out_S <= fraction_out_S(fraction_out_S'high - 1 downto 0) & '0'; end if; elsif (cstate_count_S = 0) then stepsize_S <= (others => '0'); intermediate_S <= (others => '0'); fraction_out_S <= (others => '0'); output_valid_S <= '0'; end if; end if; end process; end Behavioral;