From: Tobias Weber Date: Mon, 12 Aug 2013 09:49:56 +0000 (+0200) Subject: Initial Upload of sources X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=502a332c257a2637b166a9b0e77671bad0035afa;p=trb3.git Initial Upload of sources --- diff --git a/mupix/sources/MuPix3_board.vhd b/mupix/sources/MuPix3_board.vhd new file mode 100644 index 0000000..7bc6806 --- /dev/null +++ b/mupix/sources/MuPix3_board.vhd @@ -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 index 0000000..a3bf90f --- /dev/null +++ b/mupix/sources/MuPix3_interface.vhd @@ -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 index 0000000..d33adfa --- /dev/null +++ b/mupix/sources/graycounter.vhd @@ -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 index 0000000..88d4784 --- /dev/null +++ b/mupix/sources/injection_generator.vhd @@ -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 index 0000000..5cb4d20 --- /dev/null +++ b/mupix/sources/mupix_components.vhd @@ -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 index 0000000..7c3dd0a --- /dev/null +++ b/mupix/sources/spi_if.vhd @@ -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;