OpenCores
URL https://opencores.org/ocsvn/pulse_processing_algorithm/pulse_processing_algorithm/trunk

Subversion Repositories pulse_processing_algorithm

[/] [pulse_processing_algorithm/] [adc_flowcontrol.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	:	adc_flow_control.vhd
-- Description	:	The SIS3301/2 has several options for external triggering and turn on/off
--						It also has some requirements concerning (vme-)memory use, the most
--						important of which is that memory can only be written 2x64-bit chunks/words
--						These 64-bit chunks are written into a 32bit-wide data-fifo accompanied by
--						32bit addresses written into a address-fifo. These write-actions have to
--						be done in groups of 4, in which each cycle contains a data-write-cycle
--						and the 2nd and 4th contain a address-write cycle. If this rule is not
--						observed, the interface fpga get screwed-up and the board has to be reset.
--						The flow-state-machine in this module takes care of this in that is keeps
--						resets pending until the proper moment and adds dummy-writecycles when 
--						you run out of data unexcpetedly.
--						
--						
-----------------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity adc_flowcontrol is
	port(	rst					: in	std_logic;
			clk					: in	std_logic;
			program_in			: in	std_logic;
			data_available		: in	std_logic;
			start_adc			: in	std_logic;
			ext_trigger			: in	std_logic;
			soft_trigger		: in	std_logic;
			running				: out	std_logic;
			chain_enable		: out	std_logic;
			sync_init_out		: out	std_logic;
			sync_rst_out		: out	std_logic;
			rst_addr_gen_out	: out	std_logic;
			write_count			: out	std_logic_vector(15 downto 0)
		);
end adc_flowcontrol;
 
architecture Behavioral of adc_flowcontrol is
 
	type	flow_state_type is (reset_state, program_state, idle_state, start_state, word_a, word_b, word_c, word_d, no_data);
	signal flow_state_S			: flow_state_type := idle_state;
 
   signal rst_S					: std_logic := '1';
   signal old_rst_S				: std_logic := '1';
   signal rst_pulse_S			: std_logic := '1';
   signal rst_pending_S			: std_logic := '0';
   signal rst_out_S				: std_logic := '0';
   signal clk_S					: std_logic := '0';
   signal program_in_S			: std_logic := '0';
   signal old_program_in_S		: std_logic := '0';
   signal program_pulse_S		: std_logic := '1';
   signal program_out_S			: std_logic := '0';
   signal data_available_S		: std_logic := '0';
   signal start_adc_S			: std_logic := '0';
   signal old_start_adc_S		: std_logic := '0';
   signal ext_trigger_S			: std_logic := '0';
   signal old_ext_trigger_S	: std_logic := '0';
   signal soft_trigger_S		: std_logic := '0';
   signal old_soft_trigger_S	: std_logic := '0';
   signal trigger_pulse_S		: std_logic := '0';
   signal start_pulse_S			: std_logic := '0';
   signal terminate_S			: std_logic := '0';
   signal chain_enable_S		: std_logic := '0';
   signal rst_addr_gen_S		: std_logic := '0';
   signal running_S				: std_logic := '0';
   signal write_count_S			: std_logic_vector(15 downto 0) := (others => '0');
 
	begin
 
		clk_S						<= clk;
		rst_S						<= rst;
		program_in_S			<= program_in;
		data_available_S		<= data_available;
		start_adc_S				<= start_adc;
		ext_trigger_S			<= ext_trigger;
		soft_trigger_S			<= soft_trigger;
		chain_enable			<= chain_enable_S;
		running					<= running_S;
		write_count				<= write_count_S;
 
		sync_init_out			<=	program_out_S;
		sync_rst_out			<=	rst_out_S;
		rst_addr_gen_out		<=	rst_addr_gen_S;
 
		fsm_flow_state_control : process(clk_S, rst, rst_S, program_in, program_in_S)
		begin
			if rising_edge(clk_S) then
 
				case flow_state_S is
					when idle_state	=>
						if (rst = '1') or (rst_pulse_S = '1') or (program_pulse_S = '1') then
							flow_state_S 	<= reset_state;
						elsif (start_pulse_S = '1') then
							flow_state_S 	<= start_state;
							write_count_S		<= (others => '0');
						else
							flow_state_S 		<= flow_state_S;
						end if;
					when no_data		=>
						if (rst_pulse_S = '1') or (program_pulse_S = '1') then
							flow_state_S 	<= reset_state;
						elsif (trigger_pulse_S) = '1' then
							terminate_S			<= '0';
							flow_state_S 		<= idle_state;
						elsif (data_available_S = '1') then
							flow_state_S 		<= word_a;
						else
							flow_state_S 		<= flow_state_S;
						end if;
					when reset_state		=>
						if (rst = '0') then
							rst_pending_S	<= '0';
							flow_state_S 	<= program_state;
						else
							flow_state_S 		<= no_data;
						end if;
					when program_state	=>
						if ((rst = '1')) then
							flow_state_S 	<= reset_state;
						else
							flow_state_S	<= idle_state;
						end if;
					when start_state		=>
						if (rst_pulse_S = '1') or (program_pulse_S = '1') then
							flow_state_S 	<= reset_state;
						elsif (data_available_S = '1') then
							flow_state_S 		<= word_a;
						else
							flow_state_S 		<= no_data;
						end if;
					when word_a			=>
						if (rst_pulse_S = '1') or (program_pulse_S = '1') then
							rst_pending_S	<= '1';
						elsif (trigger_pulse_S) = '1' then
							terminate_S		<= '1';
						end if;
						flow_state_S		<= word_b;
						write_count_S		<= write_count_S + 1;
					when word_b			=>
						if (rst_pulse_S = '1') or (program_pulse_S = '1') then
							rst_pending_S	<= '1';
						elsif (trigger_pulse_S) = '1' then
							terminate_S		<= '1';
						end if;
						flow_state_S		<= word_c;
						write_count_S		<= write_count_S + 1;
					when word_c			=>
						if (rst_pulse_S = '1') or (program_pulse_S = '1') then
							rst_pending_S	<= '1';
						elsif (trigger_pulse_S) = '1' then
							terminate_S		<= '1';
						end if;
						flow_state_S		<= word_d;
						write_count_S		<= write_count_S + 1;
					when word_d			=>
						if (rst_pulse_S = '1') or (program_pulse_S = '1') or (rst_pending_S = '1') then
							rst_pending_S	<= '0';
							flow_state_S 	<= reset_state;
						elsif (terminate_S = '1') or (trigger_pulse_S = '1') then
							terminate_S		<= '0';
							flow_state_S	<= idle_state;
						elsif (data_available_S = '0') then
							flow_state_S	<= no_data;
						else
							flow_state_S	<= word_a;		-- running_S and chain_enable are allready '1'
						end if;
						write_count_S	<= write_count_S + 1;
				end case;
			end if;
		end process;
 
	output_signals : process(flow_state_S)
	begin
		case flow_state_S is
			when idle_state		=>
				chain_enable_S			<= '0';
				running_S				<= '0';
				rst_out_S				<= '0';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
			when no_data			=>
				chain_enable_S			<= '0';
				running_S				<= '1';
				rst_out_S				<= '0';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
			when reset_state		=>
				chain_enable_S			<= '0';
				running_S				<= '0';
				rst_out_S				<= '1';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
			when program_state		=>
				chain_enable_S			<= '0';
				running_S				<= '0';
				rst_out_S				<= '0';
				program_out_S			<= '1';
				rst_addr_gen_S			<=	'0';
			when start_state		=>
				chain_enable_S			<= '0';
				running_S				<= '0';
				rst_out_S				<= '0';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'1';
			when word_a				=>
				chain_enable_S			<= '1';
				running_S				<= '1';
				rst_out_S				<= '0';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
			when word_b				=>
				chain_enable_S			<= '1';
				running_S				<= '1';
				rst_out_S				<= '0';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
			when word_c				=>
				chain_enable_S			<= '1';
				running_S				<= '1';
				rst_out_S				<= '0';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
			when word_d				=>
				chain_enable_S			<= '1';
				running_S				<= '1';
				rst_out_S				<= '0';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
			when others				=>
				chain_enable_S			<= '0';
				running_S				<= '0';
				rst_out_S				<= '1';
				program_out_S			<= '0';
				rst_addr_gen_S			<=	'0';
		end case;
	end process;
 
		fsm_edge_detect : process(clk_S)
		begin
			if rising_edge(clk_S) then
 
				old_rst_S				<= rst_S;
				old_program_in_S		<= program_in_S;
				old_start_adc_S		<= start_adc_S;
				old_ext_trigger_S		<= ext_trigger_S;
				old_soft_trigger_S	<= soft_trigger_S;
 
				if (old_rst_S = '0' and rst_S = '1') then
					rst_pulse_S			<= '1';
				else 
					rst_pulse_S			<= '0';
				end if;
 
				if (old_program_in_S = '0' and program_in_S = '1') then
					program_pulse_S	<= '1';
				else 
					program_pulse_S	<= '0';
				end if;
 
				if (old_start_adc_S = '0' and start_adc_S = '1') then
				   start_pulse_S	 <= '1';
				else 
					start_pulse_S	<= '0';
				end if;
 
				if ((old_ext_trigger_S = '0' and ext_trigger_S = '1') or (old_soft_trigger_S = '0' and soft_trigger_S = '1')) then
					trigger_pulse_S	<= '1';
				else 
					trigger_pulse_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.