OpenCores
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;

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.