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;