use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
--- Uncomment the following library declaration if instantiating
--- any Xilinx primitives in this code.
---library UNISIM;
---use UNISIM.VComponents.all;
-
entity Histogram is
generic (
HistogramHeight : integer := 12; -- Bin Height in power of two
elsif Reset = '1' then
Histo_fsm <= Clear;
Overflow <= '0';
+ else
+ Histo_fsm <= Idle;
end if;
when WriteHisto =>
if delcounter = 1 then
- MemWrAddr <= BinSelect;
+ MemWrAddr <= MemRdAddr;
MemWrEn <= '1';
delcounter <= 0;
Histo_fsm <= idle;
end if;
when WaitOnMem =>
- Histo_fsm <= ReadHisto;
+ Histo_fsm <= ReadHisto;
+
when ReadHisto =>
BinHeight <= MemDOut;
DataValid <= '1';
entity HitbusHistogram is
generic (
- HistogramRange : integer := 8);
+ HistogramRange : integer := 8;
+ PostOscillationWaitCycles : integer := 5);
port (
clk : in std_logic;
hitbus : in std_logic;
- Trigger : out std_logic; --Trigger to Laser/LED
+ trigger : in std_logic; --Trigger from Laser or scintillator
SLV_READ_IN : in std_logic;
SLV_WRITE_IN : in std_logic;
SLV_DATA_OUT : out std_logic_vector(31 downto 0);
BinHeight : out std_logic_vector(HistogramHeight - 1 downto 0));
end component;
+ component SignalDelay is
+ generic (
+ Width : integer;
+ Delay : integer);
+ port (
+ clk_in : in std_logic;
+ write_en_in : in std_logic;
+ delay_in : in std_logic_vector(Delay - 1 downto 0);
+ sig_in : in std_logic_vector(Width - 1 downto 0);
+ sig_out : out std_logic_vector(Width - 1 downto 0));
+ end component SignalDelay;
signal hitbus_i : std_logic_vector(1 downto 0);
- signal hitbus_buffer : std_logic;
+ signal trigger_i : std_logic_vector(1 downto 0);
--ToT Histogram
type hithisto_fsm_type is (idle, hitbus_high, wait_for_postOscillation);
--Latency Histogram
- type latency_fsm_type is (idle, waittime, generatetrigger, waitforhitbus);
+ type latency_fsm_type is (idle, waitforhitbus);
signal latency_fsm : latency_fsm_type := idle;
- signal trigger_counter : unsigned(2 downto 0) := (others => '0');
- signal wait_counter : unsigned(15 downto 0) := (others => '0');
signal latency_counter : unsigned(HistogramRange - 1 downto 0); --duration of hitbus high
signal latency_HistoWrAddr : std_logic_vector(HistogramRange - 1 downto 0);
signal latency_WriteBin : std_logic;
signal ReadHisto : std_logic := '0';
signal reading_histo_mem : std_logic := '0'; --read in progress
signal readcounter : unsigned(HistogramRange - 1 downto 0) := (others => '0');
+ signal hitbus_wait : unsigned(HistogramRange - 1 downto 0) := (others => '0');
+ signal hitbus_delayed : std_logic;
+
begin
BinSelect => latency_HistoWrAddr,
DataValid => open,
BinHeight => latency_BinValue);
+
+ SignalDelay_1: entity work.SignalDelay
+ generic map (
+ Width => 1,
+ Delay => 5)
+ port map (
+ clk_in => clk,
+ write_en_in => '1',
+ delay_in => std_logic_vector(to_unsigned(5, 5)),
+ sig_in(0) => hitbus,
+ sig_out(0) => hitbus_delayed);
- -- purpose: hitbus synchronize and edge detect
+ -- purpose: hitbus and trigger edge detect
hitbus_edge_proc: process (clk) is
begin -- process hitbus_edge_proc
if rising_edge(clk) then
- hitbus_buffer <= hitbus;
- hitbus_i <= hitbus_i(0) & hitbus_buffer;
+ hitbus_i <= hitbus_i(0) & hitbus_delayed;
+ trigger_i <= trigger_i(0) & trigger;
end if;
end process hitbus_edge_proc;
if rising_edge(clk) then
hitbus_WriteBin <= '0';
postOscillationCounter <= (others => '0');
+ hitbus_HistoWrAddr <= (others => '0');
case hithisto_fsm is
when idle =>
hitbus_counter <= (others => '0');
- if hitbus_i = "01" then --rising edge
+ hithisto_fsm <= idle;
+ if hitbus_i = "01" then --rising edge on hitbus
hithisto_fsm <= hitbus_high;
end if;
when hitbus_high =>
hitbus_counter <= hitbus_counter + 1;
+ hithisto_fsm <= hitbus_high;
if hitbus_i = "10" then --falling edge
hithisto_fsm <= wait_for_postOscillation;
end if;
when wait_for_postOscillation =>
postOscillationCounter <= postOscillationCounter + 1;
- if(to_integer(postOscillationCounter) = 5) then --wait 5 clock cycles
+ if(to_integer(postOscillationCounter) = PostOscillationWaitCycles) then --wait 5 clock cycles
hitbus_WriteBin <= '1';
hitbus_HistoWrAddr <= std_logic_vector(hitbus_counter);
hithisto_fsm <= idle;
- end if;
- if(hitbus_i = "01") then --new rising edge cut belong to the same event
+ elsif(hitbus_i = "01") then --new rising edge, belongs to the same event
hitbus_counter <= hitbus_counter + postOscillationCounter + 1;
hithisto_fsm <= hitbus_high;
+ else
+ hithisto_fsm <= wait_for_postOscillation;
end if;
end case;
end if;
-----------------------------------------------------------------------------
--Latency Histogram
-----------------------------------------------------------------------------
-
LatencyHisto : process(clk)
begin -- process LatencyHisto
- if rising_edge(clk) then
+ if rising_edge(clk) then
+ latency_histoWraddr <= (others => '0');
+ latency_WriteBin <= '0';
case latency_fsm is
when idle =>
- trigger_counter <= (others => '0');
- --latency_histoaddr <= (others => '0');
- latency_counter <= (others => '0');
- latency_WriteBin <= '0';
- if histo_ctrl(3) = '1' then
- latency_fsm <= waittime;
- wait_counter <= wait_counter + 1;
- end if;
-
- when waittime =>
- wait_counter <= wait_counter + 1;
- if std_logic_vector(wait_counter) = histo_ctrl(31 downto 16) then
- trigger <= '1';
- latency_fsm <= generatetrigger;
- end if;
- when generatetrigger => --necessary width of triggersignal in
- --function generator?
- trigger_counter <= trigger_counter + 1;
- if trigger_counter = "111" then
- latency_fsm <= waitforhitbus;
+ if trigger_i = "01" then
+ latency_fsm <= waitforhitbus;
+ latency_counter <= latency_counter + 1;
else
- latency_fsm <= generatetrigger;
+ latency_fsm <= idle;
+ latency_counter <= (others => '0');
end if;
- latency_counter <= latency_counter + 1;
- wait_counter <= (others => '0');
-
+
when waitforhitbus =>
- trigger <= '0';
latency_counter <= latency_counter + 1;
if hitbus_i = "01" then
latency_writebin <= '1';
latency_histoWraddr <= std_logic_vector(latency_counter);
latency_fsm <= idle;
- elsif latency_counter = x"FFFF" then
- latency_fsm <= idle;
+ elsif latency_counter = hitbus_wait then
+ latency_fsm <= idle;
+ else
+ latency_fsm <= waitforhitbus;
end if;
end case;
end if;
--0x0803: Read Histograms
--0x0804: ReadCounter
--0x0805: snapshot of hitbus
+ --0x0806: max wait time for hitbus event after latency trigger has been seen
-----------------------------------------------------------------------------
SLV_BUS_HANDLER : process(clk)
begin -- process SLV_BUS_HANDLER
SLV_UNKNOWN_ADDR_OUT <= '0';
SLV_NO_MORE_DATA_OUT <= '0';
histvalue <= latency_BinValue & hitbus_BinValue;
+
if reading_histo_mem = '1' then
ReadHisto <= '0';
if histvalue_valid = '1' then
when x"0805" =>
SLV_DATA_OUT(0) <= hitbus;
SLV_ACK_OUT <= '1';
+ when x"0806" =>
+ SLV_DATA_OUT(HistogramRange - 1 downto 0) <= std_logic_vector(hitbus_wait);
+ SLV_ACK_OUT <= '1';
when others =>
SLV_UNKNOWN_ADDR_OUT <= '1';
end case;
when x"0804" =>
readcounter <= unsigned(SLV_DATA_IN(HistogramRange - 1 downto 0));
SLV_ACK_OUT <= '1';
+ when x"0806" =>
+ hitbus_wait <= unsigned(SLV_DATA_IN(HistogramRange - 1 downto 0));
+ SLV_ACK_OUT <= '1';
when others =>
SLV_UNKNOWN_ADDR_OUT <= '1';
end case;
-
+
end if;
end if;
signal sout_c_from_mupix_sync : std_logic;
signal sout_d_from_mupix_sync : std_logic;
signal hbus_from_mupix_sync : std_logic;
- signal fpga_aux_from_board_sync : std_logic_vector(5 downto 0);
+ signal hbus_from_mupix_fast_sync : std_logic;
+ signal fpga_aux_from_board_sync : std_logic_vector(4 downto 0);
signal szintilator_sync : std_logic;
+ signal szintilator_fast_sync : std_logic;
signal mupix_ctrl_i : MupixSlowControl;
sout_c_from_mupix_sync => sout_c_from_mupix_sync,
sout_d_from_mupix_sync => sout_d_from_mupix_sync,
hbus_from_mupix_sync => hbus_from_mupix_sync,
+ hbus_from_mupix_fast_sync => hbus_from_mupix_fast_sync,
fpga_aux_from_board_sync => fpga_aux_from_board_sync,
szintilator_sync => szintilator_sync,
+ szintilator_fast_sync => szintilator_fast_sync,
SLV_READ_IN => slv_read(7),
SLV_WRITE_IN => slv_write(7),
HitbusHistogram_1 : HitbusHistogram
generic map (
- HistogramRange => 10)
+ HistogramRange => 9)
port map (
clk => clk,
- trigger => fpga_aux_to_board(0),
+ trigger => szintilator_sync,
hitbus => hbus_from_mupix_sync,
SLV_READ_IN => slv_read(4),
SLV_WRITE_IN => slv_write(4),
trb_slv_clock => clk,
fast_clk => fast_clk,
reset => reset,
- hitbus => hbus_from_mupix_sync,
- szintillator_trigger => szintilator_sync,
+ hitbus => hbus_from_mupix_fast_sync,
+ szintillator_trigger => szintilator_fast_sync,
SLV_READ_IN => slv_read(8),
SLV_WRITE_IN => slv_write(8),
SLV_DATA_OUT => slv_data_rd(8*32+31 downto 8*32),
SLV_UNKNOWN_ADDR_OUT => slv_unknown_addr(8));
--set unused signals to board 0
- fpga_led_to_board <= (others => '0');
- fpga_aux_to_board(3 downto 1) <= (others => '0');
+ fpga_led_to_board <= (others => '0');
+ fpga_aux_to_board(3 downto 0) <= (others => '0');
end Behavioral;
sout_c_from_mupix_sync : out std_logic;
sout_d_from_mupix_sync : out std_logic;
hbus_from_mupix_sync : out std_logic;
- fpga_aux_from_board_sync : out std_logic_vector(5 downto 0);
- szintilator_sync : out std_logic;
+ hbus_from_mupix_fast_sync : out std_logic;
+ fpga_aux_from_board_sync : out std_logic_vector(4 downto 0);
+ szintilator_sync : out std_logic;
+ szintilator_fast_sync : out std_logic;
--Trb Slv-Bus
SLV_READ_IN : in std_logic;
SLV_WRITE_IN : in std_logic;
begin -- process fast_sync
if rising_edge(fast_clk_in) then
hitbus_buf <= hbus_from_mupix;
- szintilator_sync_buf <= fpga_aux_from_board(0);
- szintilator_sync <= szintilator_sync_buf;
+ szintilator_sync_buf <= fpga_aux_from_board(0);
+ szintilator_fast_sync <= szintilator_sync_buf;
if invert_signals_int = '1' then
- hbus_from_mupix_sync <= hitbus_buf;
+ hbus_from_mupix_fast_sync <= hitbus_buf;
else
- hbus_from_mupix_sync <= not hitbus_buf;
+ hbus_from_mupix_fast_sync <= not hitbus_buf;
end if;
end if;
end process fast_sync;
process
begin
wait until rising_edge(clk_in);
- fpga_aux_from_board_sync <= fpga_aux_from_board;
+ fpga_aux_from_board_sync <= fpga_aux_from_board(5 downto 1);
+ szintilator_sync <= fpga_aux_from_board(0);
if invert_signals_int = '1' then
mupixreadout_sync.hit_time <= not mupixreadout.hit_time;
mupixreadout_sync.hit_row <= not mupixreadout.hit_row;
mupixreadout_sync.priout <= mupixreadout.priout; --is inverted on the chip
sout_c_from_mupix_sync <= not sout_c_from_mupix;
sout_d_from_mupix_sync <= not sout_d_from_mupix;
+ hbus_from_mupix_sync <= hbus_from_mupix;
else
mupixreadout_sync.hit_time <= mupixreadout.hit_time;
mupixreadout_sync.hit_row <= mupixreadout.hit_row;
mupixreadout_sync.priout <= not mupixreadout.priout; --is inverted on the chip
sout_c_from_mupix_sync <= sout_c_from_mupix;
sout_d_from_mupix_sync <= sout_d_from_mupix;
+ hbus_from_mupix_sync <= not hbus_from_mupix;
end if;
end process;
measurementData <= std_logic_vector(latencycounter & hitbuscounter);
measurementFinished <= '1';
end if;
- when others => null;
end case;
end if;
end process TimeWalk_Measurement;
port (
clk : in std_logic;
hitbus : in std_logic;
- Trigger : out std_logic;
+ Trigger : in std_logic;
SLV_READ_IN : in std_logic;
SLV_WRITE_IN : in std_logic;
SLV_DATA_OUT : out std_logic_vector(31 downto 0);
clk_in : in std_logic;
fast_clk_in : in std_logic;
mupixreadout : in MupixReadoutData;
- sout_c_from_mupix : in std_logic;
- sout_d_from_mupix : in std_logic;
- hbus_from_mupix : in std_logic;
- fpga_aux_from_board : in std_logic_vector(5 downto 0);
+ sout_c_from_mupix : in std_logic;
+ sout_d_from_mupix : in std_logic;
+ hbus_from_mupix : in std_logic;
+ fpga_aux_from_board : in std_logic_vector(5 downto 0);
mupixreadout_sync : out MupixReadoutData;
sout_c_from_mupix_sync : out std_logic;
sout_d_from_mupix_sync : out std_logic;
- hbus_form_mupix_sync : out std_logic;
- fpga_aux_from_board_sync : out std_logic_vector(5 downto 0);
+ hbus_from_mupix_sync : out std_logic;
+ hbus_from_mupix_fast_sync : out std_logic;
+ fpga_aux_from_board_sync : out std_logic_vector(4 downto 0);
szintilator_sync : out std_logic;
+ szintilator_fast_sync : out std_logic;
SLV_READ_IN : in std_logic;
SLV_WRITE_IN : in std_logic;
SLV_DATA_OUT : out std_logic_vector(31 downto 0);
SLV_ADDR_IN : in std_logic_vector(15 downto 0);
SLV_ACK_OUT : out std_logic;
SLV_NO_MORE_DATA_OUT : out std_logic;
- SLV_UNKNOWN_ADDR_OUT : out std_logic);
+ SLV_UNKNOWN_ADDR_OUT : out std_logic);
end component board_interface;
component resethandler is
--- /dev/null
+------------------------------------------------------------
+--! @file
+--! @brief Testbench for readout of Mupix 3-6
+--! @author Tobias Weber
+--! @date August 2017
+------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.TRBSimulationPkg.all;
+
+entity HitbusHistogramTest is
+end entity HitbusHistogramTest;
+
+architecture simulation of HitbusHistogramTest is
+
+ component HitbusHistogram
+ generic(
+ HistogramRange : integer := 6;
+ PostOscillationWaitCycles : integer := 5
+ );
+ port(
+ clk : in std_logic;
+ hitbus : in std_logic;
+ trigger : in std_logic;
+ SLV_READ_IN : in std_logic;
+ SLV_WRITE_IN : in std_logic;
+ SLV_DATA_OUT : out std_logic_vector(31 downto 0);
+ SLV_DATA_IN : in std_logic_vector(31 downto 0);
+ SLV_ADDR_IN : in std_logic_vector(15 downto 0);
+ SLV_ACK_OUT : out std_logic;
+ SLV_NO_MORE_DATA_OUT : out std_logic;
+ SLV_UNKNOWN_ADDR_OUT : out std_logic
+ );
+ end component HitbusHistogram;
+
+ constant HistogramRange : integer := 6;
+ constant PostOscillationWaitCycles : integer := 5;
+ constant clk_period : time := 10 ns;
+
+ signal clk : std_logic := '0';
+ signal hitbus : std_logic := '0';
+ signal trigger : std_logic := '0';
+ signal SLV_READ_IN : std_logic := '0';
+ signal SLV_WRITE_IN : std_logic := '0';
+ signal SLV_DATA_IN : std_logic_vector(31 downto 0) := (others => '0');
+ signal SLV_ADDR_IN : std_logic_vector(15 downto 0) := (others => '0');
+
+
+ signal SLV_DATA_OUT : std_logic_vector(31 downto 0);
+ signal SLV_ACK_OUT : std_logic;
+ signal SLV_NO_MORE_DATA_OUT : std_logic;
+ signal SLV_UNKNOWN_ADDR_OUT : std_logic;
+
+ procedure HitbusEvent(signal hitbus, trigger : out std_logic;
+ constant latency, tot1 : time;
+ constant postoscillation, tot2 : time := 0 ns) is
+ begin
+ trigger <= '1';
+ wait for latency;
+ trigger <= '0';
+ hitbus <= '1';
+ wait for tot1;
+ hitbus <= '0';
+ if postoscillation > 0 ns then
+ wait for postoscillation;
+ hitbus <= '1';
+ wait for tot2;
+ hitbus <= '0';
+ end if;
+ wait for 200 ns;
+ end procedure HitbusEvent;
+
+
+begin
+
+ HitbusHistogram_1 : entity work.HitbusHistogram
+ generic map(
+ HistogramRange => HistogramRange,
+ PostOscillationWaitCycles => PostOscillationWaitCycles
+ )
+ port map(
+ clk => clk,
+ hitbus => hitbus,
+ trigger => trigger,
+ SLV_READ_IN => SLV_READ_IN,
+ SLV_WRITE_IN => SLV_WRITE_IN,
+ SLV_DATA_OUT => SLV_DATA_OUT,
+ SLV_DATA_IN => SLV_DATA_IN,
+ SLV_ADDR_IN => SLV_ADDR_IN,
+ SLV_ACK_OUT => SLV_ACK_OUT,
+ SLV_NO_MORE_DATA_OUT => SLV_NO_MORE_DATA_OUT,
+ SLV_UNKNOWN_ADDR_OUT => SLV_UNKNOWN_ADDR_OUT
+ );
+
+ clk_gen : process is
+ begin
+ clk <= '1';
+ wait for clk_period/2;
+ clk <= '0';
+ wait for clk_period/2;
+ end process clk_gen;
+
+ stimulus : process is
+ begin
+ wait for 100 ns;
+ TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"000000FF", x"0806");
+ TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, std_logic_vector(to_unsigned(2, 32)), x"0800");
+ for i in 0 to 5 loop
+ HitbusEvent(hitbus, trigger, 50 ns, 100 ns);
+ end loop;
+ for i in 0 to 8 loop
+ HitbusEvent(hitbus, trigger, 50 ns, 120 ns);
+ end loop;
+ HitbusEvent(hitbus, trigger, 50 ns, 100 ns, 20 ns, 30 ns);--test post-oscillation
+ wait;
+ end process stimulus;
+
+
+end architecture simulation;