Index: firmware/FTU/FTU_control.vhd
===================================================================
--- firmware/FTU/FTU_control.vhd	(revision 9843)
+++ firmware/FTU/FTU_control.vhd	(revision 9880)
@@ -1,5 +1,5 @@
 ----------------------------------------------------------------------------------
 -- Company:        ETH Zurich, Institute for Particle Physics
--- Engineer:       P. Vogler, Q. Weitzel
+-- Engineer:       Q. Weitzel, P. Vogler
 -- 
 -- Create Date:    08/06/2010
@@ -26,4 +26,5 @@
 library ftu_definitions;
 USE ftu_definitions.ftu_array_types.all;
+USE ftu_definitions.ftu_constants.all;
 
 ---- Uncomment the following library declaration if instantiating
@@ -34,9 +35,25 @@
 entity FTU_control is
   port(
-    clk_50MHz    : IN  std_logic;
-    clk_ready    : IN  std_logic;
-    config_ready : IN std_logic;
-    reset        : OUT std_logic;
-    config_start : OUT std_logic
+    clk_50MHz      : IN  std_logic;
+    clk_ready      : IN  std_logic;
+    config_started : IN  std_logic;
+    config_ready   : IN  std_logic;
+    ram_doa        : IN  STD_LOGIC_VECTOR(7 downto 0);
+    ram_dob        : IN  STD_LOGIC_VECTOR(15 downto 0);
+    rate_array     : IN  rate_array_type;
+    reset          : OUT std_logic;
+    config_start   : OUT std_logic;
+    ram_ena        : OUT std_logic;
+    ram_enb        : OUT std_logic;
+    ram_wea        : OUT STD_LOGIC_VECTOR(0 downto 0);
+    ram_web        : OUT STD_LOGIC_VECTOR(0 downto 0);
+    ram_ada        : OUT STD_LOGIC_VECTOR(4 downto 0);
+    ram_adb        : OUT STD_LOGIC_VECTOR(3 downto 0);
+    ram_dia        : OUT STD_LOGIC_VECTOR(7 downto 0);
+    ram_dib        : OUT STD_LOGIC_VECTOR(15 downto 0);
+    dac_array      : OUT dac_array_type;
+    enable_array   : OUT enable_array_type;
+    cntr_reset     : OUT STD_LOGIC;
+    prescaling     : OUT STD_LOGIC_VECTOR(7 downto 0)
   );
 end FTU_control;
@@ -44,67 +61,234 @@
 architecture Behavioral of FTU_control is
 
-  signal reset_sig : STD_LOGIC := '0';
-
+  signal reset_sig : STD_LOGIC := '0';  --initialize reset to 0 at power up
+
+  --DAC/SPI interface, default DACs come from RAM during INIT
   signal config_start_sig : STD_LOGIC := '0';
-  signal config_ready_sig : STD_LOGIC := '0';
-  
-  type FTU_control_StateType is (IDLE, INIT, RUNNING, RESET_ALL);
-  signal FTU_control_State, FTU_control_NextState: FTU_control_StateType;
+  signal dac_array_sig : dac_array_type := (0,0,0,0,0,0,0,0);
+
+  --enable signals for pixels in trigger, default values come from RAM during INIT
+  signal enable_array_sig : enable_array_type := ("0000000000000000", --patch A
+                                                  "0000000000000000", --patch B
+                                                  "0000000000000000", --patch C
+                                                  "0000000000000000");--patch D
+
+  signal rate_array_sig : rate_array_type;  -- initialized in FTU_top  
+  signal cntr_reset_sig : STD_LOGIC := '0';
+  signal prescaling_sig : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
+  
+  signal ram_ena_sig  : STD_LOGIC := '0';  -- RAM enable for port A
+  signal ram_enb_sig  : STD_LOGIC := '0';  -- RAM enable for port B
+  signal ram_wea_sig  : STD_LOGIC_VECTOR(0 downto 0) := "0";  -- RAM write enable for port A
+  signal ram_web_sig  : STD_LOGIC_VECTOR(0 downto 0) := "0";  -- RAM write enable for port B  
+  signal ram_ada_sig  : STD_LOGIC_VECTOR(4 downto 0) := (others => '0');  --RAM port A address
+  signal ram_adb_sig  : STD_LOGIC_VECTOR(3 downto 0) := (others => '0');  --RAM port B address
+  signal ram_dia_sig  : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');  --RAM data in A
+  signal ram_dib_sig  : STD_LOGIC_VECTOR(15 downto 0) := (others => '0'); --RAM data in B
+
+  --counter to loop through RAM
+  signal ram_ada_cntr    : INTEGER range 0 to 2**RAM_ADDR_WIDTH_A := 0;
+  signal ram_adb_cntr    : INTEGER range 0 to 2**RAM_ADDR_WIDTH_B := 0;
+  signal ram_dac_cntr    : INTEGER range 0 to (NO_OF_DAC - NO_OF_DAC_NOT_USED + 2) := 0;
+  signal ram_enable_cntr : INTEGER range 0 to (NO_OF_ENABLE + 1) := 0;
+
+  signal wait_cntr : INTEGER range 0 to 2**RAM_ADDR_WIDTH_A := 0;
+  
+  signal new_DACs_in_RAM       : STD_LOGIC := '0';
+  signal new_enables_in_RAM    : STD_LOGIC := '0';
+  signal new_prescaling_in_RAM : STD_LOGIC := '0';
+
+  type FTU_control_StateType is (IDLE, INIT, RUNNING, CONFIG_ENABLE, CONFIG_DAC, CONFIG_COUNTER, RESET_ALL);
+  signal FTU_control_State : FTU_control_StateType;
   
 begin
    
-  --FTU control state machine (two-process implementation)
-
-  FTU_control_Registers: process (clk_50MHz)
+  --FTU control finite state machine
+
+  FTU_control_FSM: process (clk_50MHz)
+
   begin
+
     if Rising_edge(clk_50MHz) then
-      FTU_control_State <= FTU_control_NextState;
+
+      case FTU_control_State is
+        
+        when IDLE =>  -- wait for DCMs to lock
+          reset_sig <= '0';
+          config_start_sig <= '0';
+          ram_ena_sig <= '0';
+          ram_wea_sig <= "0";                    
+          if (clk_ready = '1') then
+            FTU_control_State <= INIT;
+          end if;
+          
+        when INIT =>  -- load default config data to RAM, see also ftu_definitions.vhd for more info
+          reset_sig <= '0';
+          config_start_sig <= '0';
+          ram_ena_sig <= '1';
+          ram_wea_sig <= "1";
+          ram_ada_cntr <= ram_ada_cntr + 1;
+          ram_ada_sig <= conv_std_logic_vector(ram_ada_cntr, RAM_ADDR_WIDTH_A);        
+          if (ram_ada_cntr < NO_OF_ENABLE*RAM_ADDR_RATIO) then  -- default enables
+            if (ram_ada_cntr mod 2 = 0) then
+              ram_dia_sig <= DEFAULT_ENABLE(ram_ada_cntr / 2)(7 downto 0);
+            else
+              ram_dia_sig <= DEFAULT_ENABLE(ram_ada_cntr / 2)(15 downto 8);
+            end if;
+            FTU_control_State <= INIT;
+          elsif (ram_ada_cntr < (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) then  -- default counter values
+            ram_dia_sig <= (others => '0');
+            FTU_control_State <= INIT;
+          elsif (ram_ada_cntr < (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO)) then  -- default DACs
+            if (ram_ada_cntr < NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED - 1)*RAM_ADDR_RATIO) then
+              if (ram_ada_cntr mod 2 = 0) then
+                ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2),16)(7 downto 0);
+              else
+                ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2),16)(15 downto 8);
+              end if;
+            else
+              if (ram_ada_cntr mod 2 = 0) then
+                ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC(((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2) + NO_OF_DAC_NOT_USED),16)(7 downto 0);
+              else
+                ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC(((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2) + NO_OF_DAC_NOT_USED),16)(15 downto 8);
+              end if;
+            end if;
+            FTU_control_State <= INIT;
+          elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO)) then  -- default prescaling
+            ram_dia_sig <= conv_std_logic_vector(DEFAULT_PRESCALING,8);
+            FTU_control_State <= INIT;
+          elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO) + 1) then  -- default overflow register
+            ram_dia_sig <= (others => '0');
+            FTU_control_State <= INIT;
+          elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO) + 2) then  -- default checksum
+            ram_dia_sig <= (others => '0');
+            FTU_control_State <= INIT;
+          elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO) + 3) then  -- empty RAM cell
+            ram_dia_sig <= (others => '0');
+            FTU_control_State <= INIT;
+          else
+            ram_dia_sig <= (others => '0');
+            ram_ada_cntr <= 0;
+            ram_ada_sig <= (others => '0');
+            ram_ena_sig <= '0';
+            ram_wea_sig <= "0";
+            new_DACs_in_RAM <= '1';
+            new_enables_in_RAM <= '1';
+            new_prescaling_in_RAM <= '1';
+            FTU_control_State <= RUNNING;
+          end if;
+                    
+        when RUNNING =>  -- count triggers and react to commands from FTM
+          reset_sig <= '0';
+          config_start_sig <= '0';
+          if (new_DACs_in_RAM = '1') then
+            ram_enb_sig <= '1';
+            ram_adb_sig <= conv_std_logic_vector((NO_OF_ENABLE + NO_OF_COUNTER), RAM_ADDR_WIDTH_B);
+            FTU_control_State <= CONFIG_DAC;
+          elsif (new_DACs_in_RAM = '0' and new_enables_in_RAM = '1') then
+            ram_enb_sig <= '1';
+            ram_adb_sig <= conv_std_logic_vector(0, RAM_ADDR_WIDTH_B);
+            FTU_control_State <= CONFIG_ENABLE;
+          elsif (new_DACs_in_RAM = '0' and new_enables_in_RAM = '0' and new_prescaling_in_RAM = '1') then
+            ram_ena_sig <= '1';
+            ram_ada_sig <= conv_std_logic_vector((NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO), RAM_ADDR_WIDTH_A);
+            FTU_control_State <= CONFIG_COUNTER;
+          else
+            FTU_control_State <= RUNNING;
+          end if;
+
+        when CONFIG_COUNTER =>
+          wait_cntr <= wait_cntr + 1;
+          if (wait_cntr = 0) then
+            FTU_control_State <= CONFIG_COUNTER;
+          elsif (wait_cntr = 1) then
+            prescaling_sig <= ram_doa;
+            cntr_reset_sig <= '1';
+            FTU_control_State <= CONFIG_COUNTER;
+          else
+            cntr_reset_sig <= '0';
+            ram_ada_sig <= (others => '0');
+            wait_cntr <= 0;
+            new_prescaling_in_RAM <= '0';
+            ram_ena_sig <= '0';
+            FTU_control_State <= RUNNING;
+          end if;
+          
+        when CONFIG_ENABLE =>
+          ram_enable_cntr <= ram_enable_cntr + 1;
+          if (ram_enable_cntr = 0) then
+            ram_adb_sig <= conv_std_logic_vector(ram_enable_cntr + 1, RAM_ADDR_WIDTH_B);
+            FTU_control_State <= CONFIG_ENABLE;
+          elsif (ram_enable_cntr > 0 and ram_enable_cntr < NO_OF_ENABLE + 1) then
+            ram_adb_sig <= conv_std_logic_vector(ram_enable_cntr + 1, RAM_ADDR_WIDTH_B);
+            enable_array_sig(ram_enable_cntr - 1) <= ram_dob;
+            FTU_control_State <= CONFIG_ENABLE;            
+          else
+            ram_adb_sig <= (others => '0');
+            ram_enable_cntr <= 0;
+            new_enables_in_RAM <= '0';
+            ram_enb_sig <= '0';
+            FTU_control_State <= RUNNING;
+          end if;
+          
+        when CONFIG_DAC =>
+          if (ram_dac_cntr <= (NO_OF_DAC - NO_OF_DAC_NOT_USED + 2)) then            
+            ram_dac_cntr <= ram_dac_cntr + 1;
+            if (ram_dac_cntr = 0) then
+              FTU_control_State <= CONFIG_DAC;
+              ram_adb_sig <= conv_std_logic_vector((NO_OF_ENABLE + NO_OF_COUNTER + ram_dac_cntr + 1), RAM_ADDR_WIDTH_B);
+            elsif (ram_dac_cntr > 0 and ram_dac_cntr < (NO_OF_DAC - NO_OF_DAC_NOT_USED)) then
+              dac_array_sig(ram_dac_cntr - 1) <= conv_integer(unsigned(ram_dob));
+              ram_adb_sig <= conv_std_logic_vector((NO_OF_ENABLE + NO_OF_COUNTER + ram_dac_cntr + 1), RAM_ADDR_WIDTH_B);
+              FTU_control_State <= CONFIG_DAC;
+            elsif (ram_dac_cntr > 0 and ram_dac_cntr < (NO_OF_DAC - NO_OF_DAC_NOT_USED + 1)) then
+              dac_array_sig(ram_dac_cntr - 1 + NO_OF_DAC_NOT_USED) <= conv_integer(unsigned(ram_dob));
+              ram_adb_sig <= (others => '0');
+              FTU_control_State <= CONFIG_DAC;
+            else
+              ram_adb_sig <= (others => '0');
+              config_start_sig <= '1';
+              FTU_control_State <= CONFIG_DAC;
+            end if;
+          else
+            if (config_ready = '1') then
+              ram_dac_cntr <= 0;
+              new_DACs_in_RAM <= '0';
+              FTU_control_State <= RUNNING;
+            elsif (config_ready = '0' and config_started = '1') then
+              ram_enb_sig <= '0';
+              config_start_sig <= '0';
+              FTU_control_State <= CONFIG_DAC;
+            else
+              FTU_control_State <= CONFIG_DAC;
+            end if;
+          end if;
+          
+        when RESET_ALL =>  -- reset/clear and start from scratch
+          reset_sig <= '1';
+          config_start_sig <= '0';
+          FTU_control_State <= IDLE;
+      end case;
     end if;
-  end process FTU_control_Registers;
-
-  FTU_control_C_logic: process (FTU_control_State, clk_ready, config_ready_sig)
-  begin
-    FTU_control_NextState <= FTU_control_State;
-    case FTU_control_State is
-      when IDLE =>                      -- wait for DMCs to lock
-        reset_sig <= '0';
-        config_start_sig <= '0';
-        --ram_web_sig <= "0";
-        if (clk_ready = '1') then
-          FTU_control_NextState <= RUNNING;
-        end if;          
-      when INIT =>                      -- load default config data to RAM 
-        reset_sig <= '0';
-        config_start_sig <= '0';
-        --ram_web_sig <= "1";
-        --ram_adb_cntr <= ram_adb_cntr + 1;
-        --ram_adb_sig <= conv_std_logic_vector(ram_adb_cntr, 4);        
-        --if (ram_adb_cntr < 4) then
-        --  ram_dib_sig <= DEFAULT_ENABLE(ram_adb_cntr);
-        --  FTU_top_NextState <= INIT;
-        --elsif (ram_adb_cntr < 4 + 5) then
-        --  ram_dib_sig <= conv_std_logic_vector(DEFAULT_DAC(ram_adb_cntr - 4), 16);
-        --  FTU_top_NextState <= INIT;
-        --elsif (ram_adb_cntr < 32) then
-        --  ram_dib_sig <= (others => '0');
-        --  FTU_top_NextState <= INIT;
-        --else
-        --  ram_adb_cntr <= 0;
-        --  ram_web_sig <= "0";
-        --  FTU_top_NextState <= RUNNING;
-        --end if;
-      when RUNNING =>                   -- count triggers and react to commands
-        reset_sig <= '0';
-        config_start_sig <= '0';
-        --ram_web_sig <= "0";
-      when RESET_ALL =>                     -- reset/clear and start from scratch
-        reset_sig <= '1';
-        config_start_sig <= '0';
-        --ram_web_sig <= "0";
-        FTU_control_NextState <= IDLE;
-    end case;
-  end process FTU_control_C_logic;
+  end process FTU_control_FSM;
 
   reset <= reset_sig;
   
+  config_start <= config_start_sig;
+  dac_array <= dac_array_sig;
+
+  enable_array <= enable_array_sig;
+
+  rate_array_sig <= rate_array;
+  cntr_reset <= cntr_reset_sig;
+  prescaling <= prescaling_sig;
+  
+  ram_ena <= ram_ena_sig;
+  ram_enb <= ram_enb_sig;
+  ram_wea <= ram_wea_sig;
+  ram_web <= ram_web_sig;
+  ram_ada <= ram_ada_sig;
+  ram_adb <= ram_adb_sig;
+  ram_dia <= ram_dia_sig;
+  ram_dib <= ram_dib_sig;
+      
 end Behavioral;
Index: firmware/FTU/FTU_top.vhd
===================================================================
--- firmware/FTU/FTU_top.vhd	(revision 9843)
+++ firmware/FTU/FTU_top.vhd	(revision 9880)
@@ -1,5 +1,5 @@
 ----------------------------------------------------------------------------------
 -- Company:        ETH Zurich, Institute for Particle Physics
--- Engineer:       P. Vogler, Q. Weitzel
+-- Engineer:       Q. Weitzel, P. Vogler
 -- 
 -- Create Date:    11:59:40 01/19/2010 
@@ -30,6 +30,6 @@
 ---- Uncomment the following library declaration if instantiating
 ---- any Xilinx primitives in this code.
---library UNISIM;
---use UNISIM.VComponents.all;
+library UNISIM;
+use UNISIM.VComponents.all;
 
 entity FTU_top is
@@ -78,24 +78,43 @@
 architecture Behavioral of FTU_top is
 
-  signal reset_sig   : STD_LOGIC := '0';  -- initialize reset to 0 at power up
-  signal dac_clr_sig : STD_LOGIC := '1';  -- initialize dac_clr to 1 at power up
-  
-  signal config_start_sig : STD_LOGIC := '0';
-  signal config_ready_sig : STD_LOGIC := '0';
+  signal reset_sig   : STD_LOGIC;         -- initialized in FTU_control
+  signal dac_clr_sig : STD_LOGIC := '1';  -- not used in hardware, initialize to 1 at power up
+
+  --single-ended trigger signals for rate counter
+  signal patch_A_sig : STD_LOGIC := '0';
+  signal patch_B_sig : STD_LOGIC := '0';
+  signal patch_C_sig : STD_LOGIC := '0';
+  signal patch_D_sig : STD_LOGIC := '0';
+  signal trigger_sig : STD_LOGIC := '0';
+  
+  --DAC/SPI interface 
+  signal config_start_sig   : STD_LOGIC;  -- initialized in FTU_control
+  signal config_started_sig : STD_LOGIC;  -- initialized in spi_interface
+  signal config_ready_sig   : STD_LOGIC;  -- initialized in spi_interface
+  signal dac_array_sig      : dac_array_type;  -- initialized in FTU_control
+
+  signal enable_array_sig : enable_array_type;  -- initialized in FTU_control
+
+  --rate counter signals
+  signal cntr_reset_sig : STD_LOGIC;  -- initialized in FTU_control  
+  signal rate_array_sig : rate_array_type := (0,0,0,0,0);
+  signal prescaling_sig : STD_LOGIC_VECTOR(7 downto 0);
+  signal overflow_array : STD_LOGIC_VECTOR(7 downto 0) := "00000000";
   
   signal clk_50M_sig   : STD_LOGIC;         -- generated by internal DCM
   signal clk_ready_sig : STD_LOGIC := '0';  -- set high by FTU_clk_gen when DCMs have locked
 
-  --signal ram_wea_sig  : STD_LOGIC_VECTOR(0 downto 0) := "0";  -- RAM write enable for port A
-  --signal ram_web_sig  : STD_LOGIC_VECTOR(0 downto 0) := "0";  -- RAM write enable for port B
-  --signal ram_ada_cntr : INTEGER range 0 to 2**5 - 1 := 0;
-  --signal ram_adb_cntr : INTEGER range 0 to 2**4 - 1 := 0;
-  --signal ram_ada_sig  : STD_LOGIC_VECTOR(4 downto 0);
-  --signal ram_adb_sig  : STD_LOGIC_VECTOR(3 downto 0);
-  --signal ram_dia_sig  : STD_LOGIC_VECTOR(7 downto 0);
-  --signal ram_dib_sig  : STD_LOGIC_VECTOR(15 downto 0);
-  --signal ram_doa_sig  : STD_LOGIC_VECTOR(7 downto 0);
-  --signal ram_dob_sig  : STD_LOGIC_VECTOR(15 downto 0);
-    
+  --signals for RAM control, all initialized in FTU_control
+  signal ram_ena_sig : STD_LOGIC;
+  signal ram_enb_sig : STD_LOGIC;
+  signal ram_wea_sig : STD_LOGIC_VECTOR(0 downto 0);
+  signal ram_web_sig : STD_LOGIC_VECTOR(0 downto 0); 
+  signal ram_ada_sig : STD_LOGIC_VECTOR(4 downto 0);
+  signal ram_adb_sig : STD_LOGIC_VECTOR(3 downto 0);
+  signal ram_dia_sig : STD_LOGIC_VECTOR(7 downto 0);
+  signal ram_dib_sig : STD_LOGIC_VECTOR(15 downto 0);
+  signal ram_doa_sig : STD_LOGIC_VECTOR(7 downto 0);
+  signal ram_dob_sig : STD_LOGIC_VECTOR(15 downto 0);
+
   component FTU_clk_gen
     port(
@@ -107,11 +126,38 @@
   end component;
 
+  component FTU_rate_counter is
+    port(
+      clk        : in  std_logic;
+      cntr_reset : in  std_logic;
+      trigger    : in  std_logic;
+      prescaling : in  std_logic_vector(7 downto 0);
+      counts     : out integer range 0 to 2**16 - 1;
+      overflow   : out std_logic
+      );
+  end component;
+  
   component FTU_control
     port(
-      clk_50MHz    : IN std_logic;
-      clk_ready    : IN std_logic;
-      config_ready : IN std_logic;
-      reset        : OUT std_logic;
-      config_start : OUT std_logic
+      clk_50MHz      : IN  std_logic;
+      clk_ready      : IN  std_logic;
+      config_started : IN  std_logic;
+      config_ready   : IN  std_logic;
+      ram_doa        : IN  STD_LOGIC_VECTOR(7 downto 0);
+      ram_dob        : IN  STD_LOGIC_VECTOR(15 downto 0);
+      rate_array     : IN  rate_array_type;
+      reset          : OUT std_logic;
+      config_start   : OUT std_logic;
+      ram_ena        : OUT std_logic;
+      ram_enb        : OUT std_logic;
+      ram_wea        : OUT STD_LOGIC_VECTOR(0 downto 0);
+      ram_web        : OUT STD_LOGIC_VECTOR(0 downto 0);
+      ram_ada        : OUT STD_LOGIC_VECTOR(4 downto 0);
+      ram_adb        : OUT STD_LOGIC_VECTOR(3 downto 0);
+      ram_dia        : OUT STD_LOGIC_VECTOR(7 downto 0);
+      ram_dib        : OUT STD_LOGIC_VECTOR(15 downto 0);
+      dac_array      : OUT dac_array_type;
+      enable_array   : OUT enable_array_type;
+      cntr_reset     : OUT STD_LOGIC;
+      prescaling     : OUT STD_LOGIC_VECTOR(7 downto 0)
     );
   end component;
@@ -130,28 +176,73 @@
   end component;
 
-  --component FTU_dual_port_ram
-  --  port(
-  --    clka  : IN  std_logic;
-  --    ena   : IN  std_logic;
-  --    wea   : IN  std_logic_VECTOR(0 downto 0);
-  --    addra : IN  std_logic_VECTOR(4 downto 0);
-  --    dina  : IN  std_logic_VECTOR(7 downto 0);
-  --    douta : OUT std_logic_VECTOR(7 downto 0);
-  --    clkb  : IN  std_logic;
-  --    enb   : IN  std_logic;
-  --    web   : IN  std_logic_VECTOR(0 downto 0);
-  --    addrb : IN  std_logic_VECTOR(3 downto 0);
-  --    dinb  : IN  std_logic_VECTOR(15 downto 0);
-  --    doutb : OUT std_logic_VECTOR(15 downto 0)
-  --  );
-  --end component;
+  component FTU_dual_port_ram
+    port(
+      clka  : IN  std_logic;
+      ena   : IN  std_logic;
+      wea   : IN  std_logic_VECTOR(0 downto 0);
+      addra : IN  std_logic_VECTOR(4 downto 0);
+      dina  : IN  std_logic_VECTOR(7 downto 0);
+      douta : OUT std_logic_VECTOR(7 downto 0);
+      clkb  : IN  std_logic;
+      enb   : IN  std_logic;
+      web   : IN  std_logic_VECTOR(0 downto 0);
+      addrb : IN  std_logic_VECTOR(3 downto 0);
+      dinb  : IN  std_logic_VECTOR(15 downto 0);
+      doutb : OUT std_logic_VECTOR(15 downto 0)
+    );
+  end component;
 
   -- Synplicity black box declaration
-  --attribute syn_black_box : boolean;
-  --attribute syn_black_box of FTU_dual_port_ram: component is true;
+  attribute syn_black_box : boolean;
+  attribute syn_black_box of FTU_dual_port_ram: component is true;
   
 begin
 
   clr <= dac_clr_sig;
+
+  enables_A <= enable_array_sig(0)(8 downto 0);
+  enables_B <= enable_array_sig(1)(8 downto 0);
+  enables_C <= enable_array_sig(2)(8 downto 0);
+  enables_D <= enable_array_sig(3)(8 downto 0);
+
+  --differential input buffer for patch A
+  IBUFDS_LVDS_33_A : IBUFDS_LVDS_33
+    port map(
+      O  => patch_A_sig,
+      I  => patch_A_p,
+      IB => patch_A_n
+    );
+
+  --differential input buffer for patch B
+  IBUFDS_LVDS_33_B : IBUFDS_LVDS_33
+    port map(
+      O  => patch_B_sig,
+      I  => patch_B_p,
+      IB => patch_B_n
+    );
+
+  --differential input buffer for patch C
+  IBUFDS_LVDS_33_C : IBUFDS_LVDS_33
+    port map(
+      O  => patch_C_sig,
+      I  => patch_C_p,
+      IB => patch_C_n
+    );
+
+  --differential input buffer for patch D
+  IBUFDS_LVDS_33_D : IBUFDS_LVDS_33
+    port map(
+      O  => patch_D_sig,
+      I  => patch_D_p,
+      IB => patch_D_n
+    );
+
+  --differential input buffer for trigger
+  IBUFDS_LVDS_33_t : IBUFDS_LVDS_33
+    port map(
+      O  => trigger_sig,
+      I  => trig_prim_p,
+      IB => trig_prim_n
+    );
   
   Inst_FTU_clk_gen : FTU_clk_gen
@@ -163,11 +254,77 @@
     );
 
+  Inst_FTU_rate_counter_A : FTU_rate_counter
+    port map(
+      clk        => clk_50M_sig,
+      cntr_reset => cntr_reset_sig,
+      trigger    => patch_A_sig,
+      prescaling => prescaling_sig,
+      counts     => rate_array_sig(0),
+      overflow   => overflow_array(0)
+    );
+
+  Inst_FTU_rate_counter_B : FTU_rate_counter
+    port map(
+      clk        => clk_50M_sig,
+      cntr_reset => cntr_reset_sig,
+      trigger    => patch_B_sig,
+      prescaling => prescaling_sig,
+      counts     => rate_array_sig(1),
+      overflow   => overflow_array(1)
+    );
+
+  Inst_FTU_rate_counter_C : FTU_rate_counter
+    port map(
+      clk        => clk_50M_sig,
+      cntr_reset => cntr_reset_sig,
+      trigger    => patch_C_sig,
+      prescaling => prescaling_sig,
+      counts     => rate_array_sig(2),
+      overflow   => overflow_array(2)
+    );
+
+  Inst_FTU_rate_counter_D : FTU_rate_counter
+    port map(
+      clk        => clk_50M_sig,
+      cntr_reset => cntr_reset_sig,
+      trigger    => patch_D_sig,
+      prescaling => prescaling_sig,
+      counts     => rate_array_sig(3),
+      overflow   => overflow_array(3)
+    );
+
+  Inst_FTU_rate_counter_t : FTU_rate_counter
+    port map(
+      clk        => clk_50M_sig,
+      cntr_reset => cntr_reset_sig,
+      trigger    => trigger_sig,
+      prescaling => prescaling_sig,
+      counts     => rate_array_sig(4),
+      overflow   => overflow_array(4)
+    );
+  
   Inst_FTU_control : FTU_control
     port map(
-      clk_50MHz    => clk_50M_sig,
-      clk_ready    => clk_ready_sig,
-      config_ready => config_ready_sig,
-      reset        => reset_sig,
-      config_start => config_start_sig
+      clk_50MHz      => clk_50M_sig,
+      clk_ready      => clk_ready_sig,
+      config_started => config_started_sig,
+      config_ready   => config_ready_sig,
+      ram_doa        => ram_doa_sig,
+      ram_dob        => ram_dob_sig,
+      rate_array     => rate_array_sig,
+      reset          => reset_sig,
+      config_start   => config_start_sig,
+      ram_ena        => ram_ena_sig,
+      ram_enb        => ram_enb_sig,
+      ram_wea        => ram_wea_sig,
+      ram_web        => ram_web_sig,
+      ram_ada        => ram_ada_sig,
+      ram_adb        => ram_adb_sig,
+      ram_dia        => ram_dia_sig,
+      ram_dib        => ram_dib_sig,
+      dac_array      => dac_array_sig,
+      enable_array   => enable_array_sig,
+      cntr_reset     => cntr_reset_sig,
+      prescaling     => prescaling_sig
     );
   
@@ -176,7 +333,7 @@
       clk_50MHz      => clk_50M_sig,
       config_start   => config_start_sig,
-      dac_array      => DEFAULT_DAC,  -- has to come from RAM
+      dac_array      => dac_array_sig,
       config_ready   => config_ready_sig,
-      config_started => open,
+      config_started => config_started_sig,
       dac_cs         => cs_ld,
       mosi           => mosi,
@@ -184,19 +341,19 @@
     );
 
-  --Inst_FTU_dual_port_ram : FTU_dual_port_ram
-  --  port map(
-  --    clka  => clk_50M_sig,
-  --    ena   => '1',
-  --    wea   => ram_wea_sig,
-  --    addra => ram_ada_sig,
-  --    dina  => ram_dia_sig,
-  --    douta => ram_doa_sig,
-  --    clkb  => clk_50M_sig,
-  --    enb   => '1',
-  --    web   => ram_web_sig,
-  --    addrb => ram_adb_sig,
-  --    dinb  => ram_dib_sig,
-  --    doutb => ram_dob_sig
-  --  );
+  Inst_FTU_dual_port_ram : FTU_dual_port_ram
+    port map(
+      clka  => clk_50M_sig,
+      ena   => ram_ena_sig,
+      wea   => ram_wea_sig,
+      addra => ram_ada_sig,
+      dina  => ram_dia_sig,
+      douta => ram_doa_sig,
+      clkb  => clk_50M_sig,
+      enb   => ram_enb_sig,
+      web   => ram_web_sig,
+      addrb => ram_adb_sig,
+      dinb  => ram_dib_sig,
+      doutb => ram_dob_sig
+    );
   
 end Behavioral;
Index: firmware/FTU/FTU_top_tb.vhd
===================================================================
--- firmware/FTU/FTU_top_tb.vhd	(revision 9843)
+++ firmware/FTU/FTU_top_tb.vhd	(revision 9880)
@@ -1,5 +1,5 @@
 --------------------------------------------------------------------------------
 -- Company:       ETH Zurich, Institute for Particle Physics
--- Engineer:      P. Vogler, Q. Weitzel
+-- Engineer:      Q. Weitzel, P. Vogler
 --
 -- Create Date:   12.07.2010
@@ -30,5 +30,8 @@
 use IEEE.STD_LOGIC_UNSIGNED.ALL;
 use IEEE.NUMERIC_STD.ALL;
- 
+
+library UNISIM;
+use UNISIM.VComponents.all;
+
 entity FTU_top_tb is
 end FTU_top_tb;
@@ -110,4 +113,11 @@
   signal tx_en     : STD_LOGIC;
   signal TP_A      : STD_LOGIC_VECTOR(11 downto 0);
+
+  --single-ended trigger signals
+  signal patch_A_sig : STD_LOGIC := '0';
+  signal patch_B_sig : STD_LOGIC := '0';
+  signal patch_C_sig : STD_LOGIC := '0';
+  signal patch_D_sig : STD_LOGIC := '0';
+  signal trigger_sig : STD_LOGIC := '0';
   
   -- Clock period definitions
@@ -147,4 +157,40 @@
     );
 
+  --differential output buffer for patch A
+  OBUFDS_LVDS_33_A : OBUFDS_LVDS_33
+    port map(
+      O  => patch_A_p,
+      OB => patch_A_n,
+      I  => patch_A_sig
+    );
+
+  OBUFDS_LVDS_33_B : OBUFDS_LVDS_33
+    port map(
+      O  => patch_B_p,
+      OB => patch_B_n,
+      I  => patch_B_sig
+    );
+
+  OBUFDS_LVDS_33_C : OBUFDS_LVDS_33
+    port map(
+      O  => patch_C_p,
+      OB => patch_C_n,
+      I  => patch_C_sig
+    );
+
+  OBUFDS_LVDS_33_D : OBUFDS_LVDS_33
+    port map(
+      O  => patch_D_p,
+      OB => patch_D_n,
+      I  => patch_D_sig
+    );
+
+  OBUFDS_LVDS_33_t : OBUFDS_LVDS_33
+    port map(
+      O  => trig_prim_p,
+      OB => trig_prim_n,
+      I  => trigger_sig
+    );
+  
   -- Clock process definitions
   ext_clk_proc: process
@@ -158,13 +204,29 @@
   -- Stimulus process
   stim_proc: process
-  begin		
-    -- hold reset state for 100ms.
-    wait for 100ms;	
+  begin
+    -- FTU not yet initialized
+    wait for 10us;
+    trigger_sig <= '1';
+    wait for 5ns;
+    trigger_sig <= '0';
+    wait for 100us;
+    trigger_sig <= '1';
+    wait for 5ns;
+    trigger_sig <= '0';
+    -- now FTU is initialized
+    wait for 4us; 
+    trigger_sig <= '1';
+    wait for 5ns;
+    trigger_sig <= '0';
+    wait for 4us; 
+    trigger_sig <= '1';
+    wait for 5ns;
+    trigger_sig <= '0';
+    wait for 22us; 
+    trigger_sig <= '1';
+    wait for 5ns;
+    trigger_sig <= '0';
+    wait;
     
-    wait for ext_clk_period*10;
-
-    -- insert stimulus here 
-
-    wait;
   end process stim_proc;
 
Index: firmware/FTU/clock/FTU_clk_gen.vhd
===================================================================
--- firmware/FTU/clock/FTU_clk_gen.vhd	(revision 9843)
+++ firmware/FTU/clock/FTU_clk_gen.vhd	(revision 9880)
@@ -61,3 +61,2 @@
   
 end Behavioral;
-
Index: firmware/FTU/counter/FTU_rate_counter.vhd
===================================================================
--- firmware/FTU/counter/FTU_rate_counter.vhd	(revision 9880)
+++ firmware/FTU/counter/FTU_rate_counter.vhd	(revision 9880)
@@ -0,0 +1,146 @@
+----------------------------------------------------------------------------------
+-- Company:        ETH Zurich, Institute for Particle Physics
+-- Engineer:       Q. Weitzel, P. Vogler
+-- 
+-- Create Date:    10:38:40 08/18/2010 
+-- Design Name: 
+-- Module Name:    FTU_rate_counter - Behavioral 
+-- Project Name: 
+-- Target Devices: 
+-- Tool versions: 
+-- Description:    Entity to count trigger and sum patch rates of FTU board
+--
+-- Dependencies: 
+--
+-- Revision: 
+-- Revision 0.01 - File Created
+-- Additional Comments: 
+--
+----------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+library ftu_definitions;
+USE ftu_definitions.ftu_array_types.all;
+USE ftu_definitions.ftu_constants.all;
+
+---- Uncomment the following library declaration if instantiating
+---- any Xilinx primitives in this code.
+--library UNISIM;
+--use UNISIM.VComponents.all;
+
+entity FTU_rate_counter is
+  port(
+    clk        : in  std_logic;
+    cntr_reset : in  std_logic;
+    trigger    : in  std_logic;
+    prescaling : in  std_logic_vector(7 downto 0);
+    counts     : out integer range 0 to 2**16 - 1;
+    overflow   : out std_logic
+  );
+end FTU_rate_counter;
+
+architecture Behavioral of FTU_rate_counter is
+
+  signal counting_period : integer range 0 to 128*COUNTER_FREQUENCY := 128*COUNTER_FREQUENCY;
+  signal period_finished : std_logic := '0';
+  signal trigger_counts  : integer range 0 to 2**16 - 1 := 0;
+  signal clk_1M_sig      : std_logic;
+  signal overflow_sig    : std_logic := '0';
+  
+  component Clock_Divider
+    port(
+      clock_in  : IN  STD_LOGIC;
+      clock_out : OUT STD_LOGIC
+    );
+  end component;
+  
+begin
+
+  Inst_Clock_Divider : Clock_Divider
+    port map (
+      clock_in  => clk,
+      clock_out => clk_1M_sig
+    );
+  
+  process(cntr_reset, clk_1M_sig)    
+    variable clk_cntr : integer range 0 to 128*COUNTER_FREQUENCY := 0;
+  begin
+    if (cntr_reset = '1') then
+      counting_period <= ((conv_integer(unsigned(prescaling)) + 1) / 2)*COUNTER_FREQUENCY;
+      clk_cntr := 0;
+      period_finished <= '1';
+    elsif rising_edge(clk_1M_sig) then
+      if (clk_cntr < counting_period - 1) then
+        clk_cntr := clk_cntr + 1;
+        period_finished <= '0';
+      else
+        clk_cntr := 0;
+        period_finished <= '1';
+        counts <= trigger_counts;
+      end if;
+    end if;
+  end process;
+
+  process(trigger, period_finished)
+  begin
+    if rising_edge(period_finished) then
+      trigger_counts <= 0;
+    else
+      if rising_edge(trigger) then
+        trigger_counts <= trigger_counts + 1;
+      end if;
+    end if;
+  end process;
+
+  overflow <= overflow_sig;
+  
+end Behavioral;
+
+----------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+library ftu_definitions;
+USE ftu_definitions.ftu_array_types.all;
+USE ftu_definitions.ftu_constants.all;
+
+entity Clock_Divider is
+  generic(
+    divider : integer := INT_CLK_FREQUENCY / COUNTER_FREQUENCY
+  );
+  port(
+    clock_in  : in  std_logic;
+    clock_out : out std_logic := '0'
+  );
+end entity Clock_Divider;
+
+architecture RTL of Clock_Divider is
+
+begin
+    
+  process (clock_in)
+    variable Z: integer range 0 to divider - 1;
+  begin
+    if rising_edge(clock_in) then
+      if (Z < divider - 1) then
+        Z := Z + 1;
+      else
+        Z := 0;
+      end if;
+      if (Z = 0) then
+        clock_out <= '1';
+      end if;
+      if (Z = divider / 2) then
+        clock_out <= '0';
+      end if;
+    end if;
+  end process;
+
+end architecture RTL;
Index: firmware/FTU/ftu_definitions.vhd
===================================================================
--- firmware/FTU/ftu_definitions.vhd	(revision 9843)
+++ firmware/FTU/ftu_definitions.vhd	(revision 9880)
@@ -1,2 +1,24 @@
+----------------------------------------------------------------------------------
+-- Company:        ETH Zurich, Institute for Particle Physics
+-- Engineer:       Q. Weitzel
+-- 
+-- Create Date:    July 2010 
+-- Design Name:    
+-- Module Name:    ftu_definitions 
+-- Project Name: 
+-- Target Devices: 
+-- Tool versions: 
+-- Description:    library file for FTU design										
+--
+-- Dependencies: 
+--
+-- Revision: 
+-- Revision 0.01 - File Created
+-- Revision 0.02 - New package "ftu_constants" added, Aug 2010, Q. Weitzel
+-- Additional Comments: 
+--
+----------------------------------------------------------------------------------
+
+
 library IEEE;
 use IEEE.STD_LOGIC_1164.all;
@@ -7,4 +29,5 @@
 package ftu_array_types is
 
+  --enable signals to switch on/off pixels in trigger (9 pixels per patch)
   type enable_array_type is array (0 to 3) of std_logic_vector(15 downto 0);
   constant DEFAULT_ENABLE : enable_array_type := ("0000000111111111", --patch A
@@ -12,7 +35,40 @@
                                                   "0000000111111111", --patch C
                                                   "0000000111111111");--patch D
-  
+
+  --DAC values to steer trigger thresholds, 12bit octal DAC, 2.5V reference voltage
+  --First 4 values: patches A-D, DACs 5-7 not used, last value: majority coincidence
   type dac_array_type is array (0 to 7) of integer range 0 to 2**12 - 1;
   constant DEFAULT_DAC : dac_array_type := (500, 500, 500, 500, 0, 0, 0, 100);
-   
+
+  --array to hold current values of rate counters (as integers)
+  type rate_array_type is array (0 to 4) of integer range 0 to 2**16 - 1;
+  
 end ftu_array_types;
+
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+-- use IEEE.NUMERIC_STD.ALL;
+
+package ftu_constants is
+
+  --internal FPGA clock frequency and rate counter frequency 
+  constant INT_CLK_FREQUENCY : integer := 50000000;  -- 50MHz
+  constant COUNTER_FREQUENCY : integer :=  1000000;  --  1MHZ, has to be smaller than INT_CLK_FREQUENCY
+    
+  --32byte dual-port RAM, port A: 8byte, port B: 16byte
+  constant RAM_ADDR_WIDTH_A : integer := 5;
+  constant RAM_ADDR_WIDTH_B : integer := 4;
+  constant RAM_ADDR_RATIO   : integer := 2;
+
+  --normalization time for trigger counters
+  constant DEFAULT_PRESCALING : integer := 59; --30s integration time
+
+  constant NO_OF_ENABLE       : integer := 4;
+  constant NO_OF_DAC          : integer := 8;
+  constant NO_OF_DAC_NOT_USED : integer := 3;
+  constant NO_OF_COUNTER      : integer := 5;
+  
+end ftu_constants;
