-------------------------------------------------------------------------------- -- Paul Scherrer Institut -------------------------------------------------------------------------------- -- MODUL NAME: CPLD_IO -- FILENAME: Laser_Trigger.vhd -- AUTHOR: Lukas Kuenzi - Paul Scherrer Institut -- email: lukas.kuenzi@psi.ch -- -- CREATED: 07.11.2017 -------------------------------------------------------------------------------- -- DESCRIPTION: Laser Trigger Firmware for the CPLD I/O card -- -------------------------------------------------------------------------------- -- REVISIONS: -- DATE VERSION AUTHOR DESCRIPTION -- 07.11.2017 1.0 L. Kuenzi Initial version -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; entity Trigger is generic ( CGN_DATA_WIDTH: natural := 32); port ( -- clock CLK : in std_logic; CLK_SEL : out std_logic_vector(3 downto 0); -- SPI interface; Mode CPOL = 0, CPHA = 0, MSB frist SCLK : in std_logic; SS : in std_logic; MOSI : in std_logic; MISO : out std_logic; -- trigger ouput TRIG : out std_logic ); end Trigger; architecture RTL of Trigger is signal ss_reg : std_logic_vector( 2 downto 0 ) := (others=> '1'); signal sclk_reg : std_logic_vector( 2 downto 0 ) := (others=> '0'); signal mosi_reg : std_logic_vector( 2 downto 0 ) := (others=> '0'); constant C_TRIG_DISABLE : unsigned( CGN_DATA_WIDTH-1 downto 0 ) := (others=>'1'); signal divider_reg : unsigned( CGN_DATA_WIDTH-1 downto 0 ) := to_unsigned(99,CGN_DATA_WIDTH); signal downcnt_reg : unsigned( CGN_DATA_WIDTH-1 downto 0 ) := (others=>'0'); signal rx_shift_reg : std_logic_vector( CGN_DATA_WIDTH-1 downto 0 ) := (others=>'0'); signal trig_out_reg : std_logic_vector( 9 downto 0 ) := (others=>'0'); signal tx_reg : unsigned( CGN_DATA_WIDTH-1 downto 0 ) := (others=>'0'); begin -- select 100MHZ input for clock: see MG-7010SA datasheet clk_sel <= "0000"; -- stretch the trigger pulse TRIG <= trig_out_reg( trig_out_reg'left ); MISO <= tx_reg(tx_reg'left) when SS='0' else 'Z'; process( CLK ) begin if rising_edge( CLK ) then -- synchronize inputs, shift register left ss_reg <= ss_reg( 1 downto 0 ) & SS; sclk_reg <= sclk_reg( 1 downto 0 ) & SCLK; mosi_reg <= mosi_reg( 1 downto 0 ) & MOSI; -- rx process: shift if SS=0 and on rising edge of SCLK if( ss_reg(2 downto 1) = "00" and sclk_reg(2) = '0' and sclk_reg(1) = '1' ) then rx_shift_reg <= rx_shift_reg( CGN_DATA_WIDTH - 2 downto 0 ) & mosi_reg(2); end if; -- tx process: shift if SS=0 and on falling edge of SCLK if( ss_reg(2 downto 1) = "00" and sclk_reg(2) = '1' and sclk_reg(1) = '0' ) then tx_reg <= tx_reg(tx_reg'left-1 downto 0) & '0'; end if; -- transfer data at rising edge of SS if( ss_reg(2) = '0' and ss_reg(1) = '1' )then divider_reg <= unsigned(rx_shift_reg); tx_reg <= unsigned(rx_shift_reg); end if; -- trigger output if( divider_reg = C_TRIG_DISABLE ) then trig_out_reg <= (others=>'0'); -- disable trigger elsif( downcnt_reg = 0 ) then trig_out_reg <= (others=>'1'); else trig_out_reg <= trig_out_reg( trig_out_reg'left-1 downto 0 ) & '0'; end if; -- down counter if( divider_reg = C_TRIG_DISABLE ) then downcnt_reg <= (others=>'0'); elsif( downcnt_reg = 0 ) then downcnt_reg <= divider_reg; -- reload downcounter else downcnt_reg <= downcnt_reg - 1; end if; end if; end process; end RTL;