]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
Initial Upload of sources
authorTobias Weber <webert@kph.uni-mainz.de>
Mon, 12 Aug 2013 09:49:56 +0000 (11:49 +0200)
committerTobias Weber <webert@kph.uni-mainz.de>
Mon, 12 Aug 2013 09:49:56 +0000 (11:49 +0200)
mupix/sources/MuPix3_board.vhd [new file with mode: 0644]
mupix/sources/MuPix3_interface.vhd [new file with mode: 0644]
mupix/sources/graycounter.vhd [new file with mode: 0644]
mupix/sources/injection_generator.vhd [new file with mode: 0644]
mupix/sources/mupix_components.vhd [new file with mode: 0644]
mupix/sources/spi_if.vhd [new file with mode: 0644]

diff --git a/mupix/sources/MuPix3_board.vhd b/mupix/sources/MuPix3_board.vhd
new file mode 100644 (file)
index 0000000..7bc6806
--- /dev/null
@@ -0,0 +1,166 @@
+-------------------------------------------------------------------------------
+--MuPix Block for readout/controll of MuPix3 Sensorboard
+--T. Weber, University Mainz
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.numeric_std.all;
+use work.mupix_components.all;
+
+entity MuPix3_Board is
+  port(
+    --Clock signal
+    clk                        : in  std_logic;  --for MuPix Controll
+    fastclk                    : in  std_logic;  --to the Hitbus Histogram
+    reset                      : in  std_logic;
+    --signals to and from MuPix 3 chip/board DACS
+    timestamp_from_mupix       : in  std_logic_vector(7 downto 0);
+    rowaddr_from_mupix         : in  std_logic_vector(5 downto 0);
+    coladdr_from_mupix         : in  std_logic_vector(5 downto 0);
+    priout_from_mupix          : in  std_logic;
+    sout_c_from_mupix          : in  std_logic;
+    sout_d_from_mupix          : in  std_logic;
+    hbus_form_mupix            : in  std_logic;
+    fpga_aux_from_board        : in  std_logic_vector(9 downto 0);
+    ldpix_to_mupix             : out std_logic;
+    ldcol_to_mupix             : out std_logic;
+    timestamp_to_mupix         : out std_logic_vector(7 downto 0);
+    rdcol_to_mupix             : out std_logic;
+    pulldown_to_mupix          : out std_logic;
+    sin_to_mupix               : out std_logic;
+    ck_d_to_mupix              : out std_logic;
+    ck_c_to_mupix              : out std_logic;
+    ld_c_to_mupix              : out std_logic;
+    testpulse1_to_board        : out std_logic;
+    testpulse2_to_board        : out std_logic;
+    spi_din_to_board           : out std_logic;
+    spi_clk_to_board           : out std_logic;
+    spi_ld_to_board            : out std_logic;
+    fpga_led_to_board          : out std_logic_vector(3 downto 0);
+    fpga_aux_to_board          : out std_logic_vector(9 downto 0);
+    
+    --TRBv3 connections
+    LVL1_TRG_DATA_VALID_IN     : in  std_logic;
+    LVL1_VALID_TIMING_TRG_IN   : in  std_logic;
+    LVL1_VALID_NOTIMING_TRG_IN : in  std_logic;
+    LVL1_INVALID_TRG_IN        : in  std_logic;
+    LVL1_TRG_TYPE_IN           : in  std_logic_vector(3 downto 0);
+    LVL1_TRG_NUMBER_IN         : in  std_logic_vector(15 downto 0);
+    LVL1_TRG_CODE_IN           : in  std_logic_vector(7 downto 0);
+    LVL1_TRG_INFORMATION_IN    : in  std_logic_vector(23 downto 0);
+    LVL1_INT_TRG_NUMBER_IN     : in  std_logic_vector(15 downto 0);
+
+    FEE_TRG_RELEASE_OUT     : out std_logic;
+    FEE_TRG_STATUSBITS_OUT  : out std_logic_vector(31 downto 0);
+    FEE_DATA_OUT            : out std_logic_vector(31 downto 0);
+    FEE_DATA_WRITE_OUT      : out std_logic;
+    FEE_DATA_FINISHED_OUT   : out std_logic;
+    FEE_DATA_ALMOST_FULL_IN : in  std_logic;
+
+    REGIO_ADDR_IN          : in  std_logic_vector(15 downto 0);
+    REGIO_DATA_IN          : in  std_logic_vector(31 downto 0);
+    REGIO_DATA_OUT         : out std_logic_vector(31 downto 0);
+    REGIO_READ_ENABLE_IN   : in  std_logic;
+    REGIO_WRITE_ENABLE_IN  : in  std_logic;
+    REGIO_TIMEOUT_IN       : in  std_logic;
+    REGIO_DATAREADY_OUT    : out std_logic;
+    REGIO_WRITE_ACK_OUT    : out std_logic;
+    REGIO_NO_MORE_DATA_OUT : out std_logic;
+    REGIO_UNKNOWN_ADDR_OUT : out std_logic
+    );
+end MuPix3_Board;
+
+
+architecture Behavioral of MuPix3_Block is
+
+  
+
+begin  -- Behavioral
+
+
+  --Mupix 3 Chip Interface
+  mupix_interface_1 : mupix_interface
+    port map (
+      rstn                 => not Reset,
+      clk                  => clk,
+      ldpix                => ldpix_to_mupix,
+      ldcol                => ldcol_to_mupix,
+      rdcol                => rdcol_to_mupix,
+      pulldown             => pulldown_to_mupix,
+      timestamps           => timestamp_to_mupix,
+      priout               => priout_from_mupix,
+      hit_col              => coladdr_from_mupix,
+      hit_row              => rowaddr_from_mupix,
+      hit_time             => timestamp_from_mupix,
+      memdata              => memdata,
+      memwren              => memwren,
+      ro_busy              => ro_busy,
+      --add signal to indicate readout still in progress
+      roregister           => writeregs(1),
+      roregwritten         => regwritten(1),
+      rocontrolbits        => writeregs(6),
+      timestampcontrolbits => writeregs(7),
+      generatehitswait     => writeregs(8));
+
+  --SPI-Interface to Board DACs
+  spi_if_1 : spi_if
+    port map (
+      clk            => clk,
+      reset_n        => not Reset,
+      threshold_reg  => writeregs(2)(15 downto 0),
+      injection1_reg => writeregs(3)(15 downto 0),
+      injection2_reg => writeregs(3)(31 downto 16),
+      wren           => spi_wren,
+      spi_data       => spi_din_to_board,
+      spi_clk        => spi_clk_to_board,
+      spi_ld         => spi_ld_to_board);
+
+  spi_wren <= '1' when regwritten(2) = '1' else '0';  --maybe add regwritten(3)
+
+  inj_gen : injection_generator
+    port map(
+      rstn               => not reset,
+      clk                => clk,
+      injection_register => writeregs(4),
+      reg_written        => regwritten(4),
+      testpulse1         => testpulse1_to_board,
+      testpulse2         => testpulse2_to_board
+      );
+
+
+  sync_historeg : process
+  begin
+    wait until rising_edge(fastclk);
+    historegwriten_sync <= regwritten(9);
+    historegwriten_last <= historegwriten_sync;
+    if historegwriten_sync = '0' and historegwriten_last = '1' then
+      historeg <= writeregs(9);
+    end if;
+  end process sync_historeg;
+
+
+  HitbusHistogram_1 : HitbusHistogram
+    generic map (
+      HistogramRange => 10)
+    port map (
+      clk       => fastclk,
+      Control   => historeg,
+      trigger   => fpga_aux_to_board(0),
+      hitbus    => hbus_form_mupix,
+      DataValid => DataValidToFormatterFiFo,
+      BinHeight => BinHeightToFormatterFiFo);
+
+
+  write_mupix : process
+  begin
+    wait until rising_edge(clk);
+    sin_to_mupix  <= writeregs(5)(0);
+    ck_c_to_mupix <= writeregs(5)(1);
+    ck_d_to_mupix <= writeregs(5)(2);
+    ld_c_to_mupix <= writeregs(5)(3);
+  end process write_mupix;
+  
+
+end Behavioral;
diff --git a/mupix/sources/MuPix3_interface.vhd b/mupix/sources/MuPix3_interface.vhd
new file mode 100644 (file)
index 0000000..a3bf90f
--- /dev/null
@@ -0,0 +1,554 @@
+-----------------------------------------------------------------------------
+-- MUPIX3 readout interface
+--
+-- Niklaus Berger, Heidelberg University
+-- nberger@physi.uni-heidelberg.de
+--
+-----------------------------------------------------------------------------
+
+
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.mupix_comp.all;
+
+entity mupix_interface is
+  port (
+    rstn       : in  std_logic;
+    clk        : in  std_logic;
+    -- MUPIX IF
+    ldpix      : out std_logic;
+    ldcol      : out std_logic;
+    rdcol      : out std_logic;
+    pulldown   : out std_logic;
+    timestamps : out std_logic_vector(7 downto 0);
+    priout     : in  std_logic;
+    hit_col    : in  std_logic_vector(5 downto 0);
+    hit_row    : in  std_logic_vector(5 downto 0);
+    hit_time   : in  std_logic_vector(7 downto 0);
+
+    -- MEMORY IF
+    memdata    : out std_logic_vector(31 downto 0);
+    memwren    : out std_logic;
+    endofevent : out std_logic;
+
+    --Readout Indicator
+    ro_busy : out std_logic;
+    -- TLU IF
+    trig    : in  std_logic;
+    busy    : out std_logic;
+    trigclk : out std_logic;
+
+    -- Configuration
+    roregister           : in std_logic_vector(31 downto 0);
+    roregwritten         : in std_logic;
+    rocontrolbits        : in std_logic_vector(31 downto 0);
+    timestampcontrolbits : in std_logic_vector(31 downto 0);
+    generatehitswait     : in std_logic_vector(31 downto 0);
+
+    -- test ports  
+    testout     : out std_logic_vector (127 downto 0);
+    testout_ena : out std_logic
+
+    );
+end mupix_interface;
+
+
+architecture RTL of mupix_interface is
+  
+  type   tlu_state_type is (reset, waiting, manual, triggered, rectrignum, waiting_for_ro);
+  signal tlustate : tlu_state_type;
+
+  signal trigclk_r : std_logic;
+  signal busy_r    : std_logic;
+
+  type   ro_state_type is (reset, waiting, readman, loadpix, pulld, loadcol, readcol, hitgenerator, hitgeneratorwait);
+  signal state : ro_state_type;
+
+  signal tlu_counter      : std_logic_vector(4 downto 0);
+  signal trignum_shift    : std_logic_vector(14 downto 0);
+  signal trignum          : std_logic_vector(14 downto 0);
+  signal trignum_ena      : std_logic;
+  signal trignum_ena_last : std_logic;
+  signal tlumanual        : std_logic;
+
+  signal trigcounter : std_logic_vector(14 downto 0);
+
+  signal tlu_divider : std_logic_vector(4 downto 0);
+
+  signal delcounter : std_logic_vector(2 downto 0);
+
+  signal ro_busy_int : std_logic;
+
+  signal graycount : std_logic_vector(7 downto 0);
+
+  signal eventcounter : std_logic_vector(31 downto 0);
+
+  signal hitcounter : std_logic_vector(10 downto 0);
+
+
+  signal triggering            : std_logic;
+  signal continousread         : std_logic;
+  signal readnow               : std_logic;
+  signal readmanual            : std_logic;
+  signal reseteventcount       : std_logic;
+  signal generatehit           : std_logic;
+  signal generatehits          : std_logic;
+  signal generatetriggeredhits : std_logic;
+
+  signal ngeneratehits           : std_logic_vector(15 downto 0);
+  signal ngeneratehitscounter    : std_logic_vector(15 downto 0);
+  signal generatehitswaitcounter : std_logic_vector(31 downto 0);
+
+  signal gen_hit_col  : std_logic_vector(5 downto 0);
+  signal gen_hit_row  : std_logic_vector(5 downto 0);
+  signal gen_hit_time : std_logic_vector(7 downto 0);
+
+  signal testoutro  : std_logic_vector (127 downto 0);
+  signal testouttlu : std_logic_vector (127 downto 0);
+
+  signal resetgraycounter : std_logic;
+  
+begin
+  
+  
+  
+  process(rstn, clk)
+  begin
+    if(rstn = '0') then
+      triggering            <= '0';
+      continousread         <= '0';
+      readnow               <= '0';
+      readmanual            <= '0';
+      reseteventcount       <= '0';
+      generatehit           <= '0';
+      generatehits          <= '0';
+      generatetriggeredhits <= '0';
+      ngeneratehits         <= (others => '0');
+    elsif(clk'event and clk = '1') then
+      triggering    <= roregister(0);
+      continousread <= roregister(1);
+      if(roregister(2) = '1' and roregwritten = '1') then
+        readnow <= '1';
+      else
+        readnow <= '0';
+      end if;
+      readmanual <= roregister(3);
+      if(roregister(4) = '1' and roregwritten = '1') then
+        reseteventcount <= '1';
+      else
+        reseteventcount <= '0';
+      end if;
+      if(roregister(5) = '1' and roregwritten = '1') then
+        generatehit <= '1';
+      else
+        generatehit <= '0';
+      end if;
+      generatehits          <= roregister(6);
+      generatetriggeredhits <= roregister(8);
+      ngeneratehits         <= roregister(31 downto 16);
+    end if;
+  end process;
+
+  trigclk <= trigclk_r;
+  busy    <= busy_r;
+
+  tlu_if :
+  process(rstn, clk)
+  begin
+    if(rstn = '0') then
+      tlu_counter <= (others => '0');
+      busy_r      <= '0';
+      trigclk_r   <= '0';
+      tlustate    <= reset;
+      trignum_ena <= '0';
+      testouttlu  <= (others => '0');
+      trigcounter <= (others => '0');
+      tlumanual   <= '0';
+    elsif(clk'event and clk = '1') then
+      tlumanual                <= roregister(11);
+      testouttlu               <= (others => '0');
+      testouttlu(48)           <= trig;
+      testouttlu(49)           <= trigclk_r;
+      testouttlu(50)           <= busy_r;
+      testouttlu(46 downto 32) <= trignum;
+      testouttlu(30 downto 16) <= trigcounter;
+      case tlustate is
+        when reset =>
+          testouttlu(56) <= '1';
+          tlu_counter    <= (others => '0');
+          busy_r         <= '0';
+          trigclk_r      <= '0';
+          tlustate       <= waiting;
+          trignum_ena    <= '0';
+        when waiting =>
+          testouttlu(57) <= '1';
+          tlu_counter    <= (others => '0');
+          trigclk_r      <= '0';
+          busy_r         <= '0';
+          trignum_ena    <= '0';
+          if(tlumanual = '1') then
+            tlustate <= manual;
+          elsif(trig = '1') then
+            busy_r      <= '1';
+            tlustate    <= triggered;
+            trignum_ena <= '0';
+            trigcounter <= trigcounter + '1';
+          end if;
+        when manual =>
+          testouttlu(61) <= '1';
+          if(tlumanual = '0') then
+            tlustate <= waiting;
+          end if;
+          busy_r    <= roregister(9);
+          trigclk_r <= roregister(10);
+          tlustate  <= manual;
+        when triggered =>
+          testouttlu(58) <= '1';
+          busy_r         <= '1';
+          if(trig = '0') then
+            tlustate    <= rectrignum;
+            trigclk_r   <= '0';
+            tlu_divider <= "00000";
+          end if;
+        when rectrignum =>
+          testouttlu(59) <= '1';
+          tlu_divider    <= tlu_divider + '1';
+          busy_r         <= '1';
+          tlustate       <= rectrignum;
+          trignum_ena    <= trignum_ena;
+          if(tlu_divider = "11111") then
+            trigclk_r <= not trigclk_r;
+            if(trigclk_r = '1')then
+              trignum_shift(14)          <= trig;
+              trignum_shift(13 downto 0) <= trignum_shift(14 downto 1);
+              tlu_counter                <= tlu_counter + '1';
+            end if;
+          end if;
+          if(tlu_counter = "01111" and tlu_divider = "00000") then
+            trignum     <= trignum_shift;
+            trignum_ena <= '1';
+          end if;
+          if(tlu_counter = "10000") then
+            tlustate  <= waiting_for_ro;
+            trigclk_r <= '0';
+          end if;
+        when waiting_for_ro =>
+          testouttlu(60) <= '1';
+          busy_r         <= '1';
+          if(ro_busy_int = '0') then
+            busy_r   <= '0';
+            tlustate <= waiting;
+          end if;
+      end case;
+    end if;
+  end process;
+
+
+  testout_ena <= '1';
+
+  testout(127 downto 64) <= testoutro(127 downto 64);
+  testout(63 downto 16)  <= testouttlu(63 downto 16);
+  testout(15 downto 0)   <= testoutro(15 downto 0);
+
+  ro_statemachine :
+  process(rstn, clk)
+  begin
+    
+    if(rstn = '0') then
+      state        <= waiting;
+      ldpix        <= '0';
+      ldcol        <= '0';
+      rdcol        <= '0';
+      pulldown     <= '0';
+      memwren      <= '0';
+      ro_busy_int  <= '0';
+      eventcounter <= (others => '0');
+      testoutro    <= (others => '0');
+      endofevent   <= '0';
+    elsif(clk'event and clk = '1') then
+      testoutro      <= (others => '0');
+      testoutro(124) <= priout;
+
+      case state is
+        when reset =>
+          testoutro(0) <= '1';
+          state        <= waiting;
+          ldpix        <= '0';
+          ldcol        <= '0';
+          rdcol        <= '0';
+          pulldown     <= '0';
+          memwren      <= '0';
+          ro_busy_int  <= '0';
+          eventcounter <= (others => '0');
+          --timeoutcounter <= (others => '0');
+          endofevent   <= '0';
+        when waiting =>
+          testoutro(1) <= '1';
+          memwren      <= '0';
+          ro_busy_int  <= '0';
+          endofevent   <= '0';
+          hitcounter   <= (others => '0');
+          --timeoutcounter <= (others => '0');
+          eventcounter <= eventcounter;
+          if(reseteventcount = '1') then
+            eventcounter <= (others => '0');
+          end if;
+          ldpix    <= '0';
+          ldcol    <= '0';
+          rdcol    <= '0';
+          pulldown <= '0';
+          if(readmanual = '1') then
+            state <= readman;
+          elsif(continousread = '1' or readnow = '1' or (triggering = '1' and trig = '1' and generatetriggeredhits = '0' and busy_r = '0' and tlumanual = '0')) then
+            state        <= loadpix;
+            ldpix        <= '1';
+            delcounter   <= "100";
+            eventcounter <= eventcounter + '1';
+          elsif(triggering = '1' and trig = '1' and generatetriggeredhits = '1' and busy_r = '0' and tlumanual = '0') then
+            state        <= hitgenerator;
+            delcounter   <= "100";
+            eventcounter <= eventcounter + '1';
+          elsif(generatehit = '1' or generatehits = '1') then
+            state        <= hitgenerator;
+            delcounter   <= "100";
+            eventcounter <= eventcounter + '1';
+          else
+            state <= waiting;
+          end if;
+          
+        when readman =>
+          testoutro(9) <= '1';
+                        ro_busy_int  <= '1';
+          ldpix        <= rocontrolbits(0);
+          pulldown     <= rocontrolbits(1);
+          ldcol        <= rocontrolbits(2);
+          rdcol        <= rocontrolbits(3);
+          if(readmanual = '1') then
+            state <= readman;
+          else
+            state <= waiting;
+          end if;
+          endofevent <= '0';
+        when loadpix =>
+                   ro_busy_int  <= '1';
+          testoutro(2) <= '1';
+          ldpix        <= '0';
+          delcounter   <= delcounter - '1';
+          memwren      <= '0';
+          state        <= loadpix;
+          if(delcounter = "100") then   -- write event header
+            memdata <= "11111010101111101010101110111010";     --0xFABEABBA
+            memwren <= '1';
+          elsif(delcounter = "011") then               -- write event counter
+            memdata <= eventcounter;
+            memwren <= '1';
+          elsif(delcounter = "001" and triggering = '1' and trignum_ena = '1') then  -- write trigger number
+            memdata <= "11001100110011000" & trignum;  -- 0xCCCC foolowed by trignum
+            memwren <= '1';
+          elsif(delcounter = "001" and triggering = '1' and trignum_ena = '0') then  -- wait for trigger number
+            delcounter <= delcounter;
+          elsif(delcounter = "001" and triggering = '0') then
+            memwren <= '1';
+            memdata <= x"00000000";     --add empty trigger
+                                        --number
+          end if;
+          if(delcounter = "000") then
+            state      <= pulld;
+            pulldown   <= '1';
+            delcounter <= "001";
+          end if;
+          endofevent <= '0';
+        when pulld =>
+          testoutro(3) <= '1';
+          memwren      <= '0';
+          pulldown     <= '0';
+          delcounter   <= delcounter - '1';
+          state        <= pulld;
+          if(delcounter = "000") then
+            state      <= loadcol;
+            ldcol      <= '1';
+            delcounter <= "001";
+          end if;
+          endofevent <= '0';
+        when loadcol =>
+          testoutro(4) <= '1';
+          memwren      <= '0';
+          ldcol        <= '0';
+          delcounter   <= delcounter - '1';
+          state        <= loadcol;
+          endofevent   <= '0';
+          if(delcounter = "000" and priout = '1') then
+            state      <= readcol;
+            rdcol      <= '1';
+            delcounter <= "010";
+          elsif(delcounter = "000") then
+            -- end of event
+            memwren    <= '1';
+            memdata    <= "10111110111011111011111011101111";  --0xBEEFBEEF
+            endofevent <= '1';
+            state      <= waiting;
+          end if;
+        when readcol =>
+          testoutro(5) <= '1';
+          rdcol        <= '0';
+          delcounter   <= delcounter - '1';
+          memwren      <= '0';
+          state        <= readcol;
+          endofevent   <= '0';
+          if(delcounter = "010") then
+            memdata    <= "111100001111" & hit_col & hit_row & hit_time;  --0xF0F
+            memwren    <= '1';
+            hitcounter <= hitcounter + '1';
+            state      <= readcol;
+          elsif(delcounter = "000" and hitcounter = "11111111111") then
+            -- 2048 hits - force end of event 
+            memwren    <= '1';
+            memdata    <= "10111110111011111011111011101111";  --0xBEEFBEEF
+            endofevent <= '1';
+            state      <= waiting;
+          elsif(delcounter = "000" and priout = '1') then
+            state      <= readcol;
+            rdcol      <= '1';
+            delcounter <= "010";
+          elsif(delcounter = "000") then
+            state      <= pulld;
+            pulldown   <= '1';
+            delcounter <= "001";
+          end if;
+          
+        when hitgenerator =>
+          ro_busy_int  <= '1';
+          testoutro(6) <= '1';
+          state        <= hitgenerator;
+          if(delcounter = "100") then   -- write event header
+            state                   <= hitgenerator;
+            memdata                 <= "11111010101111101010101110111010";  --0xFABEABBA
+            memwren                 <= '1';
+            ngeneratehitscounter    <= ngeneratehits;
+            generatehitswaitcounter <= generatehitswait;
+            gen_hit_col             <= (others => '0');
+            gen_hit_row             <= (others => '0');
+            gen_hit_time            <= (others => '0');
+            delcounter              <= delcounter - '1';
+            endofevent              <= '0';
+          elsif(delcounter = "011") then                 -- write event counter
+            state      <= hitgenerator;
+            memdata    <= eventcounter;
+            memwren    <= '1';
+            delcounter <= delcounter - '1';
+            endofevent <= '0';
+          elsif(delcounter = "010") then
+            state      <= hitgenerator;
+            memwren    <= '0';
+            delcounter <= delcounter - '1';
+            endofevent <= '0';
+          elsif(delcounter = "001" and triggering = '1' and trignum_ena = '1') then  -- write trigger number
+            state      <= hitgenerator;
+            memdata    <= "11001100110011000" &trignum;  -- 0xCCCC foolowed by trignum
+            memwren    <= '1';
+            delcounter <= delcounter - '1';
+            endofevent <= '0';
+            --          elsif(delcounter = "001" and triggering = '1' and trignum_ena = '0' and timeoutcounter = "1111111111") then -- write fake trigger number
+            --                  state     <= hitgenerator;
+            --                  memdata <= "1100110011001100" & "1111111111111111"; -- 0xCCCC foolowed by trignum
+            --                  memwren <= '1';
+            --                  delcounter <= delcounter - '1';
+            --                  endofevent              <= '0';                 
+          elsif(delcounter = "001" and triggering = '1' and trignum_ena = '0') then  -- wait for trigger number
+            state      <= hitgenerator;
+            memwren    <= '0';
+            delcounter <= delcounter;
+            endofevent <= '0';
+            --timeoutcounter <= timeoutcounter + '1';
+          elsif(delcounter = "001" and triggering = '0') then
+            state      <= hitgenerator;
+            memwren    <= '1';
+            memdata    <= x"00000000";  --add empty trigger
+                                        --number
+            delcounter <= delcounter - '1';
+            endofevent <= '0';
+          elsif(delcounter = "000" and ngeneratehitscounter > "0000000000000000") then
+            state                <= hitgenerator;
+            delcounter           <= delcounter;
+            ngeneratehitscounter <= ngeneratehitscounter - '1';
+            gen_hit_col          <= gen_hit_col + "0101";
+            gen_hit_row          <= gen_hit_row + "0111";
+            if(gen_hit_row > "10000") then
+              gen_hit_row <= "000000";
+            end if;
+            memdata    <= "111100001111" & "0" & gen_hit_col(4 downto 0) & gen_hit_row & graycount;  --0xF0F
+            memwren    <= '1';
+            endofevent <= '0';
+          elsif(delcounter = "000" and ngeneratehitscounter = "0000000000000000" and generatehits = '0') then
+            state      <= waiting;
+            -- end of event
+            memwren    <= '1';
+            memdata    <= "10111110111011111011111011101111";  --0xBEEFBEEF
+            endofevent <= '1';
+          elsif(delcounter = "000" and ngeneratehitscounter = "0000000000000000" and generatehits = '1') then
+            state      <= hitgeneratorwait;
+            -- end of event
+            memwren    <= '1';
+            memdata    <= "10111110111011111011111011101111";  --0xBEEFBEEF
+            endofevent <= '1';
+          else
+            state      <= hitgenerator;
+            memwren    <= '0';
+            endofevent <= '0';
+          end if;
+          
+        when hitgeneratorwait =>
+          ro_busy_int             <= '0';
+          state                   <= hitgeneratorwait;
+          testoutro(7)            <= '1';
+          memwren                 <= '0';
+          endofevent              <= '0';
+          generatehitswaitcounter <= generatehitswaitcounter - '1';
+          if(conv_integer(generatehitswaitcounter) = 0)then
+            state        <= hitgenerator;
+            delcounter   <= "100";
+            eventcounter <= eventcounter + '1';
+          end if;
+          
+        when others =>
+          testoutro(8) <= '1';
+          state        <= waiting;
+          endofevent   <= '0';
+      end case;
+    end if;
+  end process;
+
+  tsgen :
+  process(rstn, clk)
+  begin
+    if(rstn = '0') then
+      timestamps <= (others => '0');
+    elsif(clk'event and clk = '1') then
+      if(timestampcontrolbits(8) = '1') then
+        timestamps <= graycount;
+      else
+        timestamps <= timestampcontrolbits(7 downto 0);
+      end if;
+    end if;
+  end process;
+
+  resetgraycounter <= not rstn;
+
+  grcount : Graycounter
+    generic map(
+      COUNTWIDTH => 8
+      )
+    port map(
+      clk        => clk,
+      reset      => resetgraycounter,
+      sync_reset => timestampcontrolbits(9),
+      counter    => graycount
+      );
+
+  
+  ro_busy <= ro_busy_int;
+end RTL;
diff --git a/mupix/sources/graycounter.vhd b/mupix/sources/graycounter.vhd
new file mode 100644 (file)
index 0000000..d33adfa
--- /dev/null
@@ -0,0 +1,64 @@
+-- Gray counter
+-- Niklaus Berger
+-- 15.5.2012
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+
+entity Graycounter is
+  generic (
+    COUNTWIDTH : integer := 8
+    );
+  port (
+    clk        : in std_logic;          -- clock
+    reset      : in std_logic;          -- asynchronous reset
+    sync_reset : in std_logic;          -- synchronous reset
+
+    counter : out std_logic_vector(COUNTWIDTH-1 downto 0)  -- counter
+    );
+end Graycounter;
+
+architecture rtl of Graycounter is
+  
+  signal msb           : std_logic;
+  signal counter_reg   : std_logic_vector(COUNTWIDTH downto 0);
+  signal no_ones_below : std_logic_vector(COUNTWIDTH downto 0);
+  
+begin
+  
+  counter <= counter_reg(COUNTWIDTH downto 1);
+
+  msb <= counter_reg(COUNTWIDTH) or counter_reg(COUNTWIDTH-1);
+
+  process(clk, reset)
+  begin
+    if(reset = '1') then
+      counter_reg    <= (others => '0');
+      counter_reg(0) <= '1';
+    elsif (clk'event and clk = '1') then
+      if (sync_reset = '1') then
+        counter_reg    <= (others => '0');
+        counter_reg(0) <= '1';
+      else
+        counter_reg(0) <= not counter_reg(0);
+        for i in 1 to COUNTWIDTH-1 loop
+          counter_reg(i) <= counter_reg(i) xor (counter_reg(i-1) and no_ones_below(i-1));
+        end loop;
+        counter_reg(COUNTWIDTH) <= counter_reg(COUNTWIDTH) xor (msb and no_ones_below(COUNTWIDTH-1));
+      end if;
+    end if;
+  end process;
+
+  no_ones_below(0) <= '1';
+
+  process(counter_reg, no_ones_below)
+  begin
+    for j in 1 to COUNTWIDTH loop
+      no_ones_below(j) <= no_ones_below(j-1) and not counter_reg(j-1);
+    end loop;
+  end process;
+  
+end rtl;
diff --git a/mupix/sources/injection_generator.vhd b/mupix/sources/injection_generator.vhd
new file mode 100644 (file)
index 0000000..88d4784
--- /dev/null
@@ -0,0 +1,67 @@
+-----------------------------------------------------------------------------
+-- MUPIX3 injection generator
+--
+-- Niklaus Berger, Heidelberg University
+-- nberger@physi.uni-heidelberg.de
+--
+-----------------------------------------------------------------------------
+
+
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use work.mupix_comp.all;
+
+entity injection_generator is
+  port (
+    rstn               : in  std_logic;
+    clk                : in  std_logic;
+    injection_register : in  std_logic_vector(31 downto 0);
+    reg_written        : in  std_logic;
+    testpulse1         : out std_logic;
+    testpulse2         : out std_logic
+    );
+end injection_generator;
+
+
+architecture rtl of injection_generator is
+
+  signal counter1 : std_logic_vector(15 downto 0);
+  signal counter2 : std_logic_vector(15 downto 0);
+
+
+begin
+
+  process(clk, rstn)
+  begin
+    if(rstn = '0') then
+
+      testpulse1 <= '0';
+      testpulse2 <= '0';
+
+    elsif(clk'event and clk = '1') then
+
+      if(reg_written = '1') then
+        counter1 <= injection_register(15 downto 0);
+        counter2 <= injection_register(31 downto 16);
+      end if;
+
+      if(counter1 > "00000000000000000") then
+        testpulse1 <= '1';
+        counter1   <= counter1 - '1';
+      else
+        testpulse1 <= '0';
+      end if;
+
+      if(counter2 > "00000000000000000") then
+        testpulse2 <= '1';
+        counter2   <= counter2 - '1';
+      else
+        testpulse2 <= '0';
+      end if;
+
+    end if;
+  end process;
+end rtl;
diff --git a/mupix/sources/mupix_components.vhd b/mupix/sources/mupix_components.vhd
new file mode 100644 (file)
index 0000000..5cb4d20
--- /dev/null
@@ -0,0 +1,65 @@
+--type definitions and components for MuPix readout
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package mupix_components is
+
+  --MuPix Board entity with regio to trbv3
+  component MuPix3_Board
+    port (
+      clk                        : in  std_logic;
+      fastclk                    : in  std_logic;
+      reset                      : in  std_logic;
+      timestamp_from_mupix       : in  std_logic_vector(7 downto 0);
+      rowaddr_from_mupix         : in  std_logic_vector(5 downto 0);
+      coladdr_from_mupix         : in  std_logic_vector(5 downto 0);
+      priout_from_mupix          : in  std_logic;
+      sout_c_from_mupix          : in  std_logic;
+      sout_d_from_mupix          : in  std_logic;
+      hbus_form_mupix            : in  std_logic;
+      fpga_aux_from_board        : in  std_logic_vector(9 downto 0);
+      ldpix_to_mupix             : out std_logic;
+      ldcol_to_mupix             : out std_logic;
+      timestamp_to_mupix         : out std_logic_vector(7 downto 0);
+      rdcol_to_mupix             : out std_logic;
+      pulldown_to_mupix          : out std_logic;
+      sin_to_mupix               : out std_logic;
+      ck_d_to_mupix              : out std_logic;
+      ck_c_to_mupix              : out std_logic;
+      ld_c_to_mupix              : out std_logic;
+      testpulse1_to_board        : out std_logic;
+      testpulse2_to_board        : out std_logic;
+      spi_din_to_board           : out std_logic;
+      spi_clk_to_board           : out std_logic;
+      spi_ld_to_board            : out std_logic;
+      fpga_led_to_board          : out std_logic_vector(3 downto 0);
+      fpga_aux_to_board          : out std_logic_vector(9 downto 0);
+      LVL1_TRG_DATA_VALID_IN     : in  std_logic;
+      LVL1_VALID_TIMING_TRG_IN   : in  std_logic;
+      LVL1_VALID_NOTIMING_TRG_IN : in  std_logic;
+      LVL1_INVALID_TRG_IN        : in  std_logic;
+      LVL1_TRG_TYPE_IN           : in  std_logic_vector(3 downto 0);
+      LVL1_TRG_NUMBER_IN         : in  std_logic_vector(15 downto 0);
+      LVL1_TRG_CODE_IN           : in  std_logic_vector(7 downto 0);
+      LVL1_TRG_INFORMATION_IN    : in  std_logic_vector(23 downto 0);
+      LVL1_INT_TRG_NUMBER_IN     : in  std_logic_vector(15 downto 0);
+      FEE_TRG_RELEASE_OUT        : out std_logic;
+      FEE_TRG_STATUSBITS_OUT     : out std_logic_vector(31 downto 0);
+      FEE_DATA_OUT               : out std_logic_vector(31 downto 0);
+      FEE_DATA_WRITE_OUT         : out std_logic;
+      FEE_DATA_FINISHED_OUT      : out std_logic;
+      FEE_DATA_ALMOST_FULL_IN    : in  std_logic;
+      REGIO_ADDR_IN              : in  std_logic_vector(15 downto 0);
+      REGIO_DATA_IN              : in  std_logic_vector(31 downto 0);
+      REGIO_DATA_OUT             : out std_logic_vector(31 downto 0);
+      REGIO_READ_ENABLE_IN       : in  std_logic;
+      REGIO_WRITE_ENABLE_IN      : in  std_logic;
+      REGIO_TIMEOUT_IN           : in  std_logic;
+      REGIO_DATAREADY_OUT        : out std_logic;
+      REGIO_WRITE_ACK_OUT        : out std_logic;
+      REGIO_NO_MORE_DATA_OUT     : out std_logic;
+      REGIO_UNKNOWN_ADDR_OUT     : out std_logic);
+  end component;
+
+end mupix_components;
diff --git a/mupix/sources/spi_if.vhd b/mupix/sources/spi_if.vhd
new file mode 100644 (file)
index 0000000..7c3dd0a
--- /dev/null
@@ -0,0 +1,119 @@
+----------------------------------------------------------------------------
+-- SPI IF
+-- Interface to the SPI bus controlling the three DACs on the mupix test board
+--
+-- Niklaus Berger, Heidelberg University
+-- nberger@physi.uni-heidelberg.de
+--
+-- 
+--
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+use work.mupix_comp.all;
+
+entity spi_if is
+  port(
+    clk            : in  std_logic;
+    reset_n        : in  std_logic;
+    threshold_reg  : in  std_logic_vector(15 downto 0);
+    injection1_reg : in  std_logic_vector(15 downto 0);
+    injection2_reg : in  std_logic_vector(15 downto 0);
+    wren           : in  std_logic;
+    spi_data       : out std_logic;
+    spi_clk        : out std_logic;
+    spi_ld         : out std_logic
+    );          
+end entity spi_if;
+
+
+
+architecture rtl of spi_if is
+
+  type   state_type is (waiting, writing, loading);
+  signal state : state_type;
+
+  signal shiftregister : std_logic_vector(47 downto 0);
+  signal write_again   : std_logic;
+
+  signal ckdiv : std_logic_vector(4 downto 0);
+
+
+
+  signal cyclecounter : std_logic_vector(7 downto 0);
+
+begin
+
+
+  process(clk, reset_n)
+
+  begin
+    if(reset_n = '0') then
+      ckdiv        <= (others => '0');
+      cyclecounter <= (others => '0');
+      spi_data     <= '0';
+      spi_clk      <= '0';
+      spi_ld       <= '0';
+      state        <= waiting;
+    elsif(clk'event and clk = '1') then
+      case state is
+        when waiting =>
+          ckdiv        <= (others => '0');
+          cyclecounter <= (others => '0');
+          spi_data     <= '0';
+          spi_clk      <= '0';
+          spi_ld       <= '0';
+          state        <= waiting;
+
+          if(wren = '1' or write_again = '1') then
+            shiftregister <= injection2_reg & injection1_reg & threshold_reg;
+            state         <= writing;
+            write_again   <= '0';
+          end if;
+        when writing =>
+          if(wren = '1') then
+            write_again <= '1';
+          end if;
+
+          ckdiv <= ckdiv + '1';
+          if(ckdiv = "00000") then
+            cyclecounter <= cyclecounter + '1';
+            if(cyclecounter(0) = '0') then  -- even cycles: push data, clock at '0'
+              spi_data                   <= shiftregister(47);
+              shiftregister(47 downto 1) <= shiftregister(46 downto 0);
+              shiftregister(0)           <= '0';
+              spi_clk                    <= '0';
+            end if;
+            if(cyclecounter(0) = '1') then  --odd cycles: 
+              spi_clk <= '1';
+            end if;
+            if(cyclecounter = "01100000") then  -- we are done...
+              state        <= loading;
+              spi_clk      <= '1';
+              cyclecounter <= "00000000";
+            end if;
+          end if;
+        when loading =>
+          if(wren = '1') then
+            write_again <= '1';
+          end if;
+          ckdiv <= ckdiv + '1';
+          if(ckdiv = "00000") then
+            cyclecounter <= cyclecounter + '1';
+            if(cyclecounter = "00000000") then
+              spi_ld <= '1';
+            elsif(cyclecounter = "00000001") then
+              spi_clk <= '0';
+            elsif(cyclecounter = "00000010") then
+              spi_ld <= '0';
+              state  <= waiting;
+            end if;
+          end if;
+      end case;
+    end if;
+  end process;
+
+end rtl;