From 472fee5e4341f8c3ba731da9d35cb68d83dca0aa Mon Sep 17 00:00:00 2001 From: Tobias Weber Date: Tue, 10 Oct 2017 10:47:42 +0200 Subject: [PATCH] partial commit of initial mupix 8 source code and test benches. --- ...eriph_mupix.lpf => trb3_periph_mupix6.lpf} | 0 mupix/Mupix8/sources/ADS1018SPI.vhd | 32 + mupix/Mupix8/sources/BlockMemory.vhd | 37 + mupix/Mupix8/sources/CRC.vhd | 70 ++ mupix/Mupix8/sources/FIFO.vhd | 100 +++ mupix/Mupix8/sources/GrayCounter.vhd | 83 +++ mupix/Mupix8/sources/Histogram.vhd | 131 ++++ mupix/Mupix8/sources/HitbusHistogram.vhd | 300 ++++++++ mupix/Mupix8/sources/InputSynchronizer.vhd | 39 + mupix/Mupix8/sources/LTC1658SPI.vhd | 128 ++++ mupix/Mupix8/sources/MupixBoard.vhd | 362 +++++++++ mupix/Mupix8/sources/MupixBoardDAC.vhd | 219 ++++++ mupix/Mupix8/sources/MupixBoardInterface.vhd | 88 +++ mupix/Mupix8/sources/PixelControl.vhd | 378 ++++++++++ mupix/Mupix8/sources/SignalDelay.vhd | 44 ++ mupix/Mupix8/sources/TestpulseGenerator.vhd | 118 +++ mupix/Mupix8/sources/TriggerHandler.vhd | 427 +++++++++++ mupix/Mupix8/tb/CRCTest.vhd | 67 ++ mupix/Mupix8/tb/HitbusHistogramTest.vhd | 120 +++ mupix/Mupix8/tb/LTC1658SPITest.vhd | 99 +++ mupix/Mupix8/tb/MupixShiftReg.vhd | 46 ++ mupix/Mupix8/tb/PixCtrlTest.vhd | 121 +++ mupix/Mupix8/tb/TRBSimulation.vhd | 66 ++ mupix/Mupix8/trb3_periph.vhd | 691 ++++++++++++++++++ 24 files changed, 3766 insertions(+) rename base/{trb3_periph_mupix.lpf => trb3_periph_mupix6.lpf} (100%) create mode 100644 mupix/Mupix8/sources/ADS1018SPI.vhd create mode 100644 mupix/Mupix8/sources/BlockMemory.vhd create mode 100644 mupix/Mupix8/sources/CRC.vhd create mode 100644 mupix/Mupix8/sources/FIFO.vhd create mode 100644 mupix/Mupix8/sources/GrayCounter.vhd create mode 100644 mupix/Mupix8/sources/Histogram.vhd create mode 100644 mupix/Mupix8/sources/HitbusHistogram.vhd create mode 100644 mupix/Mupix8/sources/InputSynchronizer.vhd create mode 100644 mupix/Mupix8/sources/LTC1658SPI.vhd create mode 100644 mupix/Mupix8/sources/MupixBoard.vhd create mode 100644 mupix/Mupix8/sources/MupixBoardDAC.vhd create mode 100644 mupix/Mupix8/sources/MupixBoardInterface.vhd create mode 100644 mupix/Mupix8/sources/PixelControl.vhd create mode 100644 mupix/Mupix8/sources/SignalDelay.vhd create mode 100644 mupix/Mupix8/sources/TestpulseGenerator.vhd create mode 100644 mupix/Mupix8/sources/TriggerHandler.vhd create mode 100644 mupix/Mupix8/tb/CRCTest.vhd create mode 100644 mupix/Mupix8/tb/HitbusHistogramTest.vhd create mode 100644 mupix/Mupix8/tb/LTC1658SPITest.vhd create mode 100644 mupix/Mupix8/tb/MupixShiftReg.vhd create mode 100644 mupix/Mupix8/tb/PixCtrlTest.vhd create mode 100644 mupix/Mupix8/tb/TRBSimulation.vhd create mode 100644 mupix/Mupix8/trb3_periph.vhd diff --git a/base/trb3_periph_mupix.lpf b/base/trb3_periph_mupix6.lpf similarity index 100% rename from base/trb3_periph_mupix.lpf rename to base/trb3_periph_mupix6.lpf diff --git a/mupix/Mupix8/sources/ADS1018SPI.vhd b/mupix/Mupix8/sources/ADS1018SPI.vhd new file mode 100644 index 0000000..0af2474 --- /dev/null +++ b/mupix/Mupix8/sources/ADS1018SPI.vhd @@ -0,0 +1,32 @@ +---------------------------------------------------------------------------------- +-- SPI Interface for the ADS1018 ADC on the mupix 8 sensorboard +-- used for temperature measurement +-- Tobias Weber +-- Ruhr Unversitaet Bochum +----------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity ADS1018SPI is + generic( + fpga_clock_speed : integer := 1e8; + spi_clock_speed : integer := 1e4 + ); + port( + clk : in std_logic; + reset : in std_logic; + start_write : in std_logic; --start writing data to adc/start conversion + config_in : in std_logic_vector(15 downto 0); --config data to adc + spi_data_from_chip : in std_logic; --serial data from dac + spi_data_to_chip : out std_logic; --seral data to dac shift register + spi_data_out : out std_logic_vector(31 downto 0); --conversion data and config readback + spi_clk : out std_logic; --SPI interface clock + spi_ld : out std_logic); --SPI load/chip select +end entity ADS1018SPI; + +architecture RTL of ADS1018SPI is + +begin + +end architecture RTL; diff --git a/mupix/Mupix8/sources/BlockMemory.vhd b/mupix/Mupix8/sources/BlockMemory.vhd new file mode 100644 index 0000000..8be5746 --- /dev/null +++ b/mupix/Mupix8/sources/BlockMemory.vhd @@ -0,0 +1,37 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; + +entity BlockMemory is + generic ( + DataWidth : integer := 10; --data width + AddressWidth : integer := 10); --address width + port ( + clk : in std_logic;-- clock + WrEn : in std_logic;-- write enable + WrAddr : in std_logic_vector(AddressWidth - 1 downto 0);-- write address + Din : in std_logic_vector(DataWidth - 1 downto 0);-- data in + ReAddr : in std_logic_vector(AddressWidth - 1 downto 0);--read address + Dout : out std_logic_vector(DataWidth - 1 downto 0));--data out (1 clock period delay) +end BlockMemory; + +architecture Behavioral of BlockMemory is + + type memory_type is array ((2**AddressWidth) - 1 downto 0) of std_logic_vector(DataWidth - 1 downto 0); + signal memory : memory_type := (others => (others => '0')); + +begin + + MemoryControll : process(clk) + begin -- process MemoryControll + if rising_edge(clk) then + Dout <= memory(to_integer(unsigned(ReAddr))); --read memory + if(WrEn = '1') then + memory(to_integer(unsigned(WrAddr))) <= Din; -- write memory + end if; + end if; + end process MemoryControll; + + +end Behavioral; + diff --git a/mupix/Mupix8/sources/CRC.vhd b/mupix/Mupix8/sources/CRC.vhd new file mode 100644 index 0000000..9803375 --- /dev/null +++ b/mupix/Mupix8/sources/CRC.vhd @@ -0,0 +1,70 @@ +------------------------------------------------------------------------------- +--Computation of cyclic redundancy check +--We use the CRC5 polynomial f(x) = 1 + x^2 + x^ 5 used by the USB2.0 protocol +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity CRC is + generic( + detect_enable_edge : boolean := false + ); + port( + clk : in std_logic; + rst : in std_logic; + enable : in std_logic; + data_in : in std_logic; + crc_out : out std_logic_vector(4 downto 0)); +end entity CRC; + +architecture rtl of CRC is + signal lfsr : std_logic_vector(4 downto 0) := (others => '1'); + signal edge_detect : std_logic_vector(1 downto 0) := (others => '0'); +begin + + normal_gen : if detect_enable_edge = false generate + CRC_proc : process(clk) is + begin + if rising_edge(clk) then + if rst = '1' then + lfsr <= (others => '1'); + else + lfsr <= lfsr; + if enable = '1' then + lfsr(0) <= lfsr(4) xor data_in; + lfsr(1) <= lfsr(0); + lfsr(2) <= (lfsr(4) xor data_in) xor lfsr(1); + lfsr(3) <= lfsr(2); + lfsr(4) <= lfsr(3); + end if; + end if; + end if; + end process CRC_proc; + end generate; + + detect_enable_edge_gen : if detect_enable_edge = true generate + CRC_edge_proc : process(clk) is + begin + if rising_edge(clk) then + if rst = '1' then + lfsr <= (others => '1'); + edge_detect <= (others => '0'); + else + edge_detect <= edge_detect(0) & enable; + lfsr <= lfsr; + if edge_detect = "01" then + lfsr(0) <= lfsr(4) xor data_in; + lfsr(1) <= lfsr(0); + lfsr(2) <= (lfsr(4) xor data_in) xor lfsr(1); + lfsr(3) <= lfsr(2); + lfsr(4) <= lfsr(3); + end if; + end if; + end if; + end process CRC_edge_proc; + end generate; + + crc_out <= lfsr; + +end architecture rtl; \ No newline at end of file diff --git a/mupix/Mupix8/sources/FIFO.vhd b/mupix/Mupix8/sources/FIFO.vhd new file mode 100644 index 0000000..2d286aa --- /dev/null +++ b/mupix/Mupix8/sources/FIFO.vhd @@ -0,0 +1,100 @@ +------------------------------------------------------------------------------- +--Dummy implementation of FIFO for simulation +--For production system use FPGA manufacturer IP core +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; + +entity STD_FIFO is + generic ( + constant DATA_WIDTH : positive := 8; + constant FIFO_DEPTH : positive := 256 + ); + port ( + CLK : in std_logic; + RST : in std_logic; + WriteEn : in std_logic; + DataIn : in std_logic_vector (DATA_WIDTH - 1 downto 0); + ReadEn : in std_logic; + DataOut : out std_logic_vector (DATA_WIDTH - 1 downto 0); + Empty : out std_logic; + Full : out std_logic + ); +end STD_FIFO; + +architecture Behavioral of STD_FIFO is + +begin + + -- Memory Pointer Process + fifo_proc : process (CLK) + type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of std_logic_vector (DATA_WIDTH - 1 downto 0); + variable Memory : FIFO_Memory; + + variable Head : natural range 0 to FIFO_DEPTH - 1; + variable Tail : natural range 0 to FIFO_DEPTH - 1; + + variable Looped : boolean; + begin + if rising_edge(CLK) then + if RST = '1' then + Head := 0; + Tail := 0; + + Looped := false; + + Full <= '0'; + Empty <= '1'; + else + if (ReadEn = '1') then + if ((Looped = true) or (Head /= Tail)) then + -- Update data output + DataOut <= Memory(Tail); + + -- Update Tail pointer as needed + if (Tail = FIFO_DEPTH - 1) then + Tail := 0; + + Looped := false; + else + Tail := Tail + 1; + end if; + + + end if; + end if; + + if (WriteEn = '1') then + if ((Looped = false) or (Head /= Tail)) then + -- Write Data to Memory + Memory(Head) := DataIn; + + -- Increment Head pointer as needed + if (Head = FIFO_DEPTH - 1) then + Head := 0; + + Looped := true; + else + Head := Head + 1; + end if; + end if; + end if; + + -- Update Empty and Full flags + if (Head = Tail) then + if Looped then + Full <= '1'; + else + Empty <= '1'; + end if; + else + Empty <= '0'; + Full <= '0'; + end if; + end if; + end if; + end process; + +end Behavioral; diff --git a/mupix/Mupix8/sources/GrayCounter.vhd b/mupix/Mupix8/sources/GrayCounter.vhd new file mode 100644 index 0000000..2722c1a --- /dev/null +++ b/mupix/Mupix8/sources/GrayCounter.vhd @@ -0,0 +1,83 @@ +-- Gray counter +-- Niklaus Berger +-- 15.5.2012 + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity Graycounter is + generic ( + COUNTWIDTH : integer := 8 + ); + port ( + clk : in std_logic; -- clock + reset : in std_logic; -- reset + clk_divcounter : in std_logic_vector(7 downto 0); -- clockdivider for + -- graycounter clock + counter : out std_logic_vector(COUNTWIDTH-1 downto 0) -- counter + ); +end Graycounter; + +architecture rtl of Graycounter is + + signal msb : std_logic := '0'; + signal counter_reg : std_logic_vector(COUNTWIDTH downto 0) := (others => '0'); + signal no_ones_below : std_logic_vector(COUNTWIDTH downto 0) := "000000001"; + signal clk_enable : std_logic := '0'; + signal divcounter : unsigned(7 downto 0) := (others => '0'); + +begin + + counter <= counter_reg(COUNTWIDTH downto 1); + + msb <= counter_reg(COUNTWIDTH) or counter_reg(COUNTWIDTH-1); + + clock_divider_proc : process (clk) is + begin -- process clock_divider_proc + if rising_edge(clk) then + if reset = '1' then + divcounter <= (others => '0'); + clk_enable <= '0'; + else + divcounter <= divcounter + 1; + clk_enable <= '0'; + if std_logic_vector(divcounter) = clk_divcounter then + clk_enable <= '1'; + divcounter <= (others => '0'); + end if; + end if; + end if; + end process clock_divider_proc; + + process(clk) + begin + if rising_edge(clk) then + if (reset = '1') then + no_ones_below(0) <= '1'; + counter_reg <= (others => '0'); + counter_reg(0) <= '1'; + else + if clk_enable = '1' then + 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)); + else + counter_reg <= counter_reg; + end if; + end if; + end if; + end process; + + 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/Mupix8/sources/Histogram.vhd b/mupix/Mupix8/sources/Histogram.vhd new file mode 100644 index 0000000..e2e0e15 --- /dev/null +++ b/mupix/Mupix8/sources/Histogram.vhd @@ -0,0 +1,131 @@ +---------------------------------------------------------------------------- +-- Histogram using block memory +-- Tobias Weber +-- Ruhr Unversitaet Bochum +----------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; + +entity Histogram is + generic ( + HistogramHeight : integer := 12; -- Bin Height 2**HistogramHeight + HistogramRange : integer := 10); -- Histogram Range 2**HistogramRange + port ( + clk : in std_logic; --clock + reset : in std_logic; --reset + StartRun : in std_logic; --start acquiring data + StartRd : in std_logic; --start reading the histogram + ReadAddr : in std_logic_vector(HistogramRange - 1 downto 0); --read address + Wr : in std_logic; --write enable + BinSelect : in std_logic_vector(HistogramRange - 1 downto 0); --select bin to write data + DataValid : out std_logic; --output data is valid + BinHeight : out std_logic_vector(HistogramHeight - 1 downto 0)); --value of bin at ReadAddr +end Histogram; + +architecture Behavioral of Histogram is + + component BlockMemory + generic ( + DataWidth : integer; + AddressWidth : integer); + port ( + clk : in std_logic; + WrEn : in std_logic; + WrAddr : in std_logic_vector(AddressWidth - 1 downto 0); + Din : in std_logic_vector(DataWidth - 1 downto 0); + ReAddr : in std_logic_vector(AddressWidth - 1 downto 0); + Dout : out std_logic_vector(DataWidth - 1 downto 0)); + end component; + + type Histo_fsm_type is (idle, WriteHisto, ReadHisto, WaitOnMem, Clear); + signal Histo_fsm : Histo_fsm_type := idle; + + signal MemWrAddr : std_logic_vector(HistogramRange - 1 downto 0); + signal MemRdAddr : std_logic_vector(HistogramRange - 1 downto 0); + signal MemWrEn : std_logic; + signal MemDIn : std_logic_vector(HistogramHeight - 1 downto 0); + signal MemDOut : std_logic_vector(HistogramHeight - 1 downto 0); + + signal bincounter : unsigned(HistogramRange - 1 downto 0); + signal delcounter : integer range 0 to 1 := 0; + signal Overflow : std_logic := '0'; + +begin + + BlockMemory_1 : BlockMemory + generic map ( + DataWidth => HistogramHeight, + AddressWidth => HistogramRange) + port map ( + clk => clk, + WrEn => MemWrEn, + WrAddr => MemWrAddr, + Din => MemDIn, + ReAddr => MemRdAddr, + Dout => MemDOut); + + Histogram : process(clk) + begin -- process Histogram + if rising_edge(clk) then + case Histo_fsm is + when idle => + bincounter <= (others => '0'); + MemRdAddr <= (others => '0'); + MemWrAddr <= (others => '0'); + MemDIn <= (others => '0'); + MemWrEn <= '0'; + DataValid <= '0'; + if (Wr = '1' and StartRun = '1' and Overflow = '0') then + Histo_fsm <= WriteHisto; + MemRdAddr <= BinSelect; + elsif StartRd = '1' then + Histo_fsm <= WaitOnMem; + MemRdAddr <= ReadAddr; + elsif Reset = '1' then + Histo_fsm <= Clear; + Overflow <= '0'; + else + Histo_fsm <= Idle; + end if; + + when WriteHisto => + if delcounter = 1 then + MemWrAddr <= MemRdAddr; + MemWrEn <= '1'; + delcounter <= 0; + Histo_fsm <= idle; + if to_integer(unsigned(MemDOut)) = 2**HistogramHeight - 1 then + --Overflow detected stop writing histogram data + MemDIn <= MemDOut; + Overflow <= '1'; + else + MemDIn <= std_logic_vector(unsigned(MemDOut) + 1); + Overflow <= '0'; + end if; + else + delcounter <= delcounter + 1; --one clk read delay of memory + end if; + + when WaitOnMem => + Histo_fsm <= ReadHisto; + + when ReadHisto => + BinHeight <= MemDOut; + DataValid <= '1'; + Histo_fsm <= idle; + + when Clear => + bincounter <= bincounter + 1; + MemWrAddr <= std_logic_vector(bincounter); + MemDIn <= (others => '0'); + MemWrEn <= '1'; + if to_integer(bincounter) = (2**HistogramRange - 1) then + Histo_fsm <= idle; + end if; + end case; + end if; + end process Histogram; + +end Behavioral; + diff --git a/mupix/Mupix8/sources/HitbusHistogram.vhd b/mupix/Mupix8/sources/HitbusHistogram.vhd new file mode 100644 index 0000000..191ddb1 --- /dev/null +++ b/mupix/Mupix8/sources/HitbusHistogram.vhd @@ -0,0 +1,300 @@ +------------------------------------------------------------------------------- +--Histogramming of Hitbus for Time over Threshold and Latency Measurement +--Tobias Weber +--Ruhr Universitaet Bochum +------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; + +entity HitbusHistogram is + generic ( + HistogramRange : integer := 8; --number of histogram bins 2**HistogramRange + PostOscillationWaitCycles : integer := 5);--number of clock cycles to wait after hit-bus signal went low + port ( + clk : in std_logic; --clock + hitbus : in std_logic; --hit-bus signal + trigger : in std_logic; --external trigger e.g. from scintillator + 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 HitbusHistogram; + +architecture Behavioral of HitbusHistogram is + + component Histogram + generic ( + HistogramHeight : integer; + HistogramRange : integer); + port ( + clk : in std_logic; + reset : in std_logic; + StartRun : in std_logic; + StartRd : in std_logic; + ReadAddr : in std_logic_vector(HistogramRange - 1 downto 0); + Wr : in std_logic; + BinSelect : in std_logic_vector(HistogramRange - 1 downto 0); + DataValid : out std_logic; + 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 trigger_i : std_logic_vector(1 downto 0); + + --ToT Histogram + type hithisto_fsm_type is (idle, hitbus_high, wait_for_postOscillation); + signal hithisto_fsm : hithisto_fsm_type := idle; + signal hitbus_counter : unsigned(HistogramRange - 1 downto 0); --duration of hitbus high + signal postOscillationCounter : unsigned(HistogramRange - 1 downto 0); + signal hitbus_HistoWrAddr : std_logic_vector(HistogramRange - 1 downto 0); + signal hitbus_WriteBin : std_logic; + signal hitbus_BinValue : std_logic_vector(15 downto 0); + + + --Latency Histogram + type latency_fsm_type is (idle, waitforhitbus); + signal latency_fsm : latency_fsm_type := idle; + 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 latency_BinValue : std_logic_vector(15 downto 0); + + + --Histogram Ctrl + signal histo_ctrl : std_logic_vector(31 downto 0) := (others => '0'); + signal histvalue : std_logic_vector(31 downto 0); + signal histvalue_valid : std_logic; + signal ReadAddr_i : std_logic_vector(HistogramRange - 1 downto 0); + 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 + + Histogram_1 : Histogram + generic map ( + HistogramHeight => 16, --change Max Height of Histogrambin here + HistogramRange => HistogramRange) + port map ( + clk => clk, + reset => histo_ctrl(2), + StartRun => histo_ctrl(1), + StartRd => ReadHisto, + ReadAddr => ReadAddr_i, + Wr => hitbus_WriteBin, + BinSelect => hitbus_HistoWrAddr, + DataValid => histvalue_valid, + BinHeight => hitbus_BinValue); + + Histogram_2 : Histogram + generic map ( + HistogramHeight => 16, + HistogramRange => HistogramRange) + port map ( + clk => clk, + reset => histo_ctrl(2), + StartRun => histo_ctrl(1), + StartRd => ReadHisto, + ReadAddr => ReadAddr_i, + Wr => latency_WriteBin, + 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 and trigger edge detect + hitbus_edge_proc: process (clk) is + begin -- process hitbus_edge_proc + if rising_edge(clk) then + hitbus_i <= hitbus_i(0) & hitbus_delayed; + trigger_i <= trigger_i(0) & trigger; + end if; + end process hitbus_edge_proc; + + ----------------------------------------------------------------------------- + --Time over Threshold histogram + ----------------------------------------------------------------------------- + HitBusHisto : process(clk) + begin -- process HitBusHisto + 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'); + 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) = PostOscillationWaitCycles) then --wait 5 clock cycles + hitbus_WriteBin <= '1'; + hitbus_HistoWrAddr <= std_logic_vector(hitbus_counter); + hithisto_fsm <= idle; + 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; + end process HitBusHisto; + + ----------------------------------------------------------------------------- + --Latency Histogram + ----------------------------------------------------------------------------- + LatencyHisto : process(clk) + begin -- process LatencyHisto + if rising_edge(clk) then + latency_histoWraddr <= (others => '0'); + latency_WriteBin <= '0'; + case latency_fsm is + when idle => + if trigger_i = "01" then + latency_fsm <= waitforhitbus; + latency_counter <= latency_counter + 1; + else + latency_fsm <= idle; + latency_counter <= (others => '0'); + end if; + + when waitforhitbus => + 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 = hitbus_wait then + latency_fsm <= idle; + else + latency_fsm <= waitforhitbus; + end if; + end case; + end if; + end process LatencyHisto; + + ----------------------------------------------------------------------------- + --TRB Slave Bus + --0x0070: Histogram Ctrl + --0x0071: Last ToT Value + --0x0072: Last Latency Value + --0x0073: Read Histograms + --0x0074: ReadCounter + --0x0075: snapshot of hitbus + --0x0076: max wait time for hitbus event after latency trigger has been seen + ----------------------------------------------------------------------------- + SLV_BUS_HANDLER : process(clk) + begin -- process SLV_BUS_HANDLER + if rising_edge(clk) then + SLV_DATA_OUT <= (others => '0'); + SLV_ACK_OUT <= '0'; + 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 + SLV_DATA_OUT <= histvalue; + SLV_ACK_OUT <= '1'; + reading_histo_mem <= '0'; + readcounter <= readcounter + 1; + else + reading_histo_mem <= '1'; + end if; + + elsif SLV_READ_IN = '1' then + case SLV_ADDR_IN is + when x"0800" => + SLV_DATA_OUT <= histo_ctrl; + SLV_ACK_OUT <= '1'; + when x"0801" => + SLV_DATA_OUT(31 downto 16) <= (others => '0'); + SLV_DATA_OUT(HistogramRange - 1 downto 0) <= hitbus_HistoWrAddr; + SLV_ACK_OUT <= '1'; + when x"0802" => + SLV_DATA_OUT(31 downto 16) <= (others => '0'); + SLV_DATA_OUT(HistogramRange - 1 downto 0) <= latency_histoWraddr; + SLV_ACK_OUT <= '1'; + when x"0803" => + ReadHisto <= '1'; + ReadAddr_i <= std_logic_vector(readcounter); + reading_histo_mem <= '1'; + when x"0804" => + SLV_DATA_OUT(HistogramRange - 1 downto 0) <= std_logic_vector(readcounter); + SLV_ACK_OUT <= '1'; + 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; + + elsif SLV_WRITE_IN = '1' then + case SLV_ADDR_IN is + when x"0800" => + histo_ctrl <= SLV_DATA_IN; + SLV_ACK_OUT <= '1'; + 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; + + end process SLV_BUS_HANDLER; + + + +end Behavioral; + diff --git a/mupix/Mupix8/sources/InputSynchronizer.vhd b/mupix/Mupix8/sources/InputSynchronizer.vhd new file mode 100644 index 0000000..e1eae6d --- /dev/null +++ b/mupix/Mupix8/sources/InputSynchronizer.vhd @@ -0,0 +1,39 @@ +---------------------------------------------------------------------------- +-- Synchronize input to signal to input clock domain +-- Tobias Weber +-- Ruhr Unversitaet Bochum +----------------------------------------------------------------------------- + library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + + entity InputSynchronizer is + generic(depth : integer := 2); + port( + clk : in std_logic; --input clock + rst : in std_logic; --reset + input : in std_logic; --asynchronous input signal + sync_output : out std_logic --synchronized signal + ); + end entity InputSynchronizer; + +architecture RTL of InputSynchronizer is + + signal syncstage : std_logic_vector(depth - 1 downto 0) := (others => '0'); + +begin + + sync_process : process (clk) is + begin + if rising_edge(clk) then + if rst = '1' then + syncstage <= (others => '0'); + else + syncstage <= syncstage(depth - 2 downto 0) & input; + end if; + end if; + end process sync_process; + + sync_output <= syncstage(depth - 1); + +end architecture RTL; diff --git a/mupix/Mupix8/sources/LTC1658SPI.vhd b/mupix/Mupix8/sources/LTC1658SPI.vhd new file mode 100644 index 0000000..20a6df9 --- /dev/null +++ b/mupix/Mupix8/sources/LTC1658SPI.vhd @@ -0,0 +1,128 @@ +---------------------------------------------------------------------------------- +-- SPI Interface for the LTC1658 DACs on the mupix 8 sensorboard +-- used for controlling threshold + injection voltage and temperature measurement +-- Tobias Weber +-- Ruhr Unversitaet Bochum +----------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity LTC1658SPI is + generic( + data_length : integer; -- bits in data word + fpga_clock_speed : integer;-- clock speed of FPGA + spi_clock_speed : integer);-- clock speed of SPI bus + port( + clk : in std_logic; --clock + reset : in std_logic; --reset + start_write : in std_logic; --start writing data to DAC + spi_data_in : in std_logic_vector(data_length - 1 downto 0); --data to write + spi_data_from_chip : in std_logic; --serial data from dac + spi_data_to_chip : out std_logic; --seral data to dac shift register + spi_data_out : out std_logic_vector(data_length - 1 downto 0); --data read from shift register + spi_clk : out std_logic; --SPI interface clock + spi_ld : out std_logic); --SPI load/chip select +end entity LTC1658SPI; + + +architecture rtl of LTC1658SPI is + + constant max_cycles : integer := fpga_clock_speed/spi_clock_speed; + + type state_type is (waiting, sendbit1, sendbit2, loading1, loading2); + signal state : state_type; + + signal shiftregister_out : std_logic_vector(data_length - 1 downto 0); + signal shiftregister_in : std_logic_vector(data_length - 1 downto 0); + signal clkdiv : integer range 0 to max_cycles - 1; + signal clk_enable : std_logic; + signal clkdiv_reset : std_logic; + signal wordcounter : integer range data_length - 1 downto 0; + + +begin + + clkdiv_reset <= reset or start_write; + + clk_div_proc : process(clk) is + begin + if rising_edge(clk) then + if clkdiv_reset = '1' then + clk_enable <= '0'; + clkdiv <= 0; + else + if clkdiv = max_cycles - 1 then + clk_enable <= '1'; + clkdiv <= 0; + else + clk_enable <= '0'; + clkdiv <= clkdiv + 1; + end if; + end if; + end if; + end process clk_div_proc; + + shift_out_proc : process(clk) + begin + if rising_edge(clk) then + if (reset = '1') then + wordcounter <= 0; + spi_data_to_chip <= '0'; + spi_clk <= '0'; + spi_ld <= '0'; + shiftregister_in <= (others => '0'); + state <= waiting; + else + case state is + when waiting => + wordcounter <= 0; + spi_data_to_chip <= '0'; + spi_clk <= '0'; + spi_ld <= '0'; + state <= waiting; + shiftregister_in <= (others => '0'); + if start_write = '1' then + shiftregister_out <= spi_data_in; + state <= sendbit1; + end if; + when sendbit1 => --pull clock low and shift out new bit + spi_clk <= '0'; + spi_data_to_chip <= shiftregister_out(data_length - 1); + if (clk_enable = '1') then + shiftregister_out(data_length - 1 downto 1) <= shiftregister_out(data_length - 2 downto 0); + shiftregister_out(0) <= '0'; + state <= sendbit2; + end if; + when sendbit2 => --pull clock high + spi_clk <= '1'; + if (clk_enable = '1') then + shiftregister_in <= shiftregister_in(data_length - 2 downto 0) & spi_data_from_chip; + if (wordcounter = data_length - 1) then -- we are done... + state <= loading1; + else + state <= sendbit1; + wordcounter <= wordcounter + 1; + end if; + end if; + when loading1 => + spi_clk <= '1'; + spi_ld <= '1'; + if (clk_enable = '1') then + state <= loading2; + end if; + when loading2 => + spi_clk <= '0'; + spi_ld <= '1'; + spi_data_to_chip <= '0'; + if (clk_enable = '1') then + state <= waiting; + spi_data_out <= shiftregister_in; + end if; + end case; + end if; + end if; + end process shift_out_proc; + + +end rtl; diff --git a/mupix/Mupix8/sources/MupixBoard.vhd b/mupix/Mupix8/sources/MupixBoard.vhd new file mode 100644 index 0000000..c6c44f8 --- /dev/null +++ b/mupix/Mupix8/sources/MupixBoard.vhd @@ -0,0 +1,362 @@ +------------------------------------------------------------------------------- +--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.trb_net_std.all; +use work.trb_net_components.all; +use work.trb3_components.all; + +use work.StdTypes.all; + +entity MupixBoard is + port( + --Clock signal + clk : in std_logic; + fast_clk : in std_logic; + reset : in std_logic; + + --slow control signals + testpulse : out std_logic; --generate injection pulse + ctrl_din : out std_logic; --serial data to mupix + ctrl_clk1 : out std_logic; --slow control clk1 + ctrl_clk2 : out std_logic; --slow control clk2 + ctrl_ld : out std_logic; --slow control load latched data + ctrl_dout : in std_logic; --serial data from mupix + ctrl_rb : out std_logic; --slow control readback?? + spi_dout_adc : in std_logic; --adc serial data from board + spi_dout_dac : in std_logic; --dac serial data from board + dac4_dout : in std_logic; --serial data in from threshold dac + spi_clk : out std_logic; --serial clock + spi_din : out std_logic; --serial data out + spi_ld_tmp_dac : out std_logic; --load temperature dac + spi_ld_adc : out std_logic; --load adc + spi_ld_thres : out std_logic; --load threshold and injection dac + --slow data signals + hitbus : in std_logic; --hitbus signal + hit : in std_logic; --hit signal (replacement for priout?) + ldcol : out std_logic; --load column + rdcol : out std_logic; --read column + pull_down : out std_logic; --pull down + ldpix : out std_logic; --load pixel + --fast data signals + clkref : out std_logic; --reference clock + clkext : out std_logic; --external clock (difference to first one?) + syncres : out std_logic; --sync something + trigger : in std_logic; --external trigger + --data + data1_P : in std_logic; --data 1 + data1_N : in std_logic; + data2_P : in std_logic; --data 2 + data2_N : in std_logic; + data3_P : in std_logic; --data 3 + data3_N : in std_logic; + data4_P : in std_logic; --this channel is muxed version of other three + data4_N : in std_logic; + + --resets + timestampreset_in : in std_logic; --time stamp reset + eventcounterreset_in : in std_logic; --event number reset + + --TRB trigger connections + TIMING_TRG_IN : in std_logic; + 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); + + --TRB data connections + 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; + + --TRB slow control connections + 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 MupixBoard; + + +architecture Behavioral of MupixBoard is + + component MupixBoardInterface + port( + clk_in : in std_logic; + fast_clk_in : in std_logic; + reset : in std_logic; + --input signals from mupix sensorboard + ctrl_dout : in std_logic; --serial data from mupix + spi_dout_adc : in std_logic; --adc serial data from board + spi_dout_dac : in std_logic; --dac serial data from board + dac4_dout : in std_logic; --serial data in from dac 4?? + hitbus : in std_logic; --hitbus signal + hit : in std_logic; --hit signal (replacement for priout?) + trigger : in std_logic; --external trigger + --synchronized signals to FPGA logic + ctrl_dout_sync : out std_logic; + spi_dout_adc_sync : out std_logic; + spi_dout_dac_sync : out std_logic; + dac4_dout_sync : out std_logic; + hitbus_sync : out std_logic; + trigger_sync : out std_logic; + hitbus_sync_fast : out std_logic; --sampled with 200 MHz clock + trigger_sync_fast : out std_logic; --sampled with 200 MHz clock + hit_sync : out std_logic); + end component MupixBoardInterface; + + signal ctrl_dout_sync : std_logic; + signal spi_dout_adc_sync : std_logic; + signal spi_dout_dac_sync : std_logic; + signal dac4_dout_sync : std_logic; + signal hitbus_sync : std_logic; + signal trigger_sync : std_logic; + signal hitbus_sync_fast : std_logic; --sampled with 200 MHz clock + signal trigger_sync_fast : std_logic; --sampled with 200 MHz clock + signal hit_sync : std_logic; + + component HitbusHistogram + generic( + HistogramRange : integer; + PostOscillationWaitCycles : integer); + 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; + + component PixelControl + generic( + fpga_clk_speed : integer; + spi_clk_speed : integer + ); + port( + clk : in std_logic; --clock + reset : in std_logic; --reset + --mupix control + ctrl_din : out std_logic; --serial data to mupix + ctrl_clk1 : out std_logic; --slow control clock 1 + ctrl_clk2 : out std_logic; --slow control clock 2 + ctrl_load : out std_logic; --slow control load + ctrl_dout : in std_logic; --serial data from mupix + --TRB slow control + 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 PixelControl; + + constant fpga_clk_speed : integer := 1e8; --100 MHz + constant mupix_spi_clk_speed : integer := 5e4;--50 kHz + + component MupixBoardDAC is + port( + clk : in std_logic; --clock + reset : in std_logic; --reset + --DAC signals + spi_dout_dac : in std_logic; --dac serial data from board + dac4_dout : in std_logic; --serial data in from threshold dac + spi_dout_adc : in std_logic; --adc serial data from board + spi_clk : out std_logic; --serial clock + spi_din : out std_logic; --serial data out + spi_ld_tmp_dac : out std_logic; --load temperature dac + spi_ld_thres : out std_logic; --load threshold and injection dac + spi_ld_adc : out std_logic; --load adc + --TRB slow control + 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 MupixBoardDAC; + +--signal declarations +-- Bus Handler + constant NUM_PORTS : integer := 3; + + signal slv_read : std_logic_vector(NUM_PORTS-1 downto 0); + signal slv_write : std_logic_vector(NUM_PORTS-1 downto 0); + signal slv_no_more_data : std_logic_vector(NUM_PORTS-1 downto 0); + signal slv_ack : std_logic_vector(NUM_PORTS-1 downto 0); + signal slv_addr : std_logic_vector(NUM_PORTS*16-1 downto 0); + signal slv_data_rd : std_logic_vector(NUM_PORTS*32-1 downto 0); + signal slv_data_wr : std_logic_vector(NUM_PORTS*32-1 downto 0); + signal slv_unknown_addr : std_logic_vector(NUM_PORTS-1 downto 0); + + + +begin -- Behavioral + +------------------------------------------------------------------------------- +-- Port Maps +------------------------------------------------------------------------------- + + THE_BUS_HANDLER : trb_net16_regio_bus_handler + generic map( + PORT_NUMBER => NUM_PORTS, + + PORT_ADDRESSES => ( + 0 => x"0070", -- Hitbus Histograms + 1 => x"0080", -- Mupix DAC and Pixel Control + 2 => x"0090", -- Board Control + others => x"0000"), + PORT_ADDR_MASK => ( + 0 => 4, -- HitBus Histograms + 1 => 4, -- Mupix DAC and Pixel Control + 2 => 4, -- Board Control + others => 0) + --PORT_MASK_ENABLE => 1 + ) + port map( + CLK => CLK, + RESET => RESET, + + DAT_ADDR_IN => REGIO_ADDR_IN, + DAT_DATA_IN => REGIO_DATA_IN, + DAT_DATA_OUT => REGIO_DATA_OUT, + DAT_READ_ENABLE_IN => REGIO_READ_ENABLE_IN, + DAT_WRITE_ENABLE_IN => REGIO_WRITE_ENABLE_IN, + DAT_TIMEOUT_IN => REGIO_TIMEOUT_IN, + DAT_DATAREADY_OUT => REGIO_DATAREADY_OUT, + DAT_WRITE_ACK_OUT => REGIO_WRITE_ACK_OUT, + DAT_NO_MORE_DATA_OUT => REGIO_NO_MORE_DATA_OUT, + DAT_UNKNOWN_ADDR_OUT => REGIO_UNKNOWN_ADDR_OUT, + + -- Control Registers + BUS_READ_ENABLE_OUT => slv_read, + BUS_WRITE_ENABLE_OUT => slv_write, + BUS_DATA_OUT => slv_data_wr, + BUS_DATA_IN => slv_data_rd, + BUS_ADDR_OUT => slv_addr, + BUS_TIMEOUT_OUT => open, + BUS_DATAREADY_IN => slv_ack, + BUS_WRITE_ACK_IN => slv_ack, + BUS_NO_MORE_DATA_IN => slv_no_more_data, + BUS_UNKNOWN_ADDR_IN => slv_unknown_addr, + + -- DEBUG + STAT_DEBUG => open + ); + + mupixboardinterface_1 : component MupixBoardInterface + port map( + clk_in => clk, + fast_clk_in => fast_clk, + reset => reset, + ctrl_dout => ctrl_dout, + spi_dout_adc => spi_dout_adc, + spi_dout_dac => spi_dout_dac, + dac4_dout => dac4_dout, + hitbus => hitbus, + hit => hit, + trigger => trigger, + ctrl_dout_sync => ctrl_dout_sync, + spi_dout_adc_sync => spi_dout_adc_sync, + spi_dout_dac_sync => spi_dout_dac_sync, + dac4_dout_sync => dac4_dout_sync, + hitbus_sync => hitbus_sync, + trigger_sync => trigger_sync, + hitbus_sync_fast => hitbus_sync_fast, + trigger_sync_fast => trigger_sync_fast, + hit_sync => hit_sync + ); + + hitbushistogram_1 : component HitbusHistogram + generic map( + HistogramRange => 10, + PostOscillationWaitCycles => 5 + ) + port map( + clk => clk, + hitbus => hitbus_sync, + trigger => trigger_sync, + SLV_READ_IN => slv_read(0), + SLV_WRITE_IN => slv_write(0), + SLV_DATA_OUT => slv_data_rd(0*32 + 31 downto 0*32), + SLV_DATA_IN => slv_data_wr(0*32 + 31 downto 0*32), + SLV_ADDR_IN => slv_addr(0*16 + 15 downto 0*16), + SLV_ACK_OUT => slv_ack(0), + SLV_NO_MORE_DATA_OUT => slv_no_more_data(0), + SLV_UNKNOWN_ADDR_OUT => slv_unknown_addr(0) + ); + + pixelcontrol_1 : component PixelControl + generic map( + fpga_clk_speed => fpga_clk_speed, + spi_clk_speed => mupix_spi_clk_speed + ) + port map( + clk => clk, + reset => reset, + ctrl_din => ctrl_din, + ctrl_clk1 => ctrl_clk1, + ctrl_clk2 => ctrl_clk2, + ctrl_load => ctrl_ld, + ctrl_dout => ctrl_dout_sync, + SLV_READ_IN => slv_read(1), + SLV_WRITE_IN => slv_write(1), + SLV_DATA_OUT => slv_data_rd(1*32 + 31 downto 1*32), + SLV_DATA_IN => slv_data_wr(1*32 + 31 downto 1*32), + SLV_ADDR_IN => slv_addr(1*16 + 15 downto 1*16), + SLV_ACK_OUT => slv_ack(1), + SLV_NO_MORE_DATA_OUT => slv_no_more_data(1), + SLV_UNKNOWN_ADDR_OUT => slv_unknown_addr(1) + ); + + boardcontrol_1 : component MupixBoardDAC + port map( + clk => clk, + reset => reset, + spi_dout_dac => spi_dout_dac_sync, + dac4_dout => dac4_dout_sync, + spi_dout_adc => spi_dout_adc_sync, + spi_clk => spi_clk, + spi_din => spi_din, + spi_ld_tmp_dac => spi_ld_tmp_dac, + spi_ld_thres => spi_ld_thres, + spi_ld_adc => spi_ld_adc, + SLV_READ_IN => slv_read(2), + SLV_WRITE_IN => slv_write(2), + SLV_DATA_OUT => slv_data_rd(2*32 + 31 downto 2*32), + SLV_DATA_IN => slv_data_wr(2*32 + 31 downto 2*32), + SLV_ADDR_IN => slv_addr(2*16 + 15 downto 2*16), + SLV_ACK_OUT => slv_ack(2), + SLV_NO_MORE_DATA_OUT => slv_no_more_data(2), + SLV_UNKNOWN_ADDR_OUT => slv_unknown_addr(2) + ); + +end Behavioral; diff --git a/mupix/Mupix8/sources/MupixBoardDAC.vhd b/mupix/Mupix8/sources/MupixBoardDAC.vhd new file mode 100644 index 0000000..7690f23 --- /dev/null +++ b/mupix/Mupix8/sources/MupixBoardDAC.vhd @@ -0,0 +1,219 @@ +----------------------------------------------------------------------------------- +-- Collection of all SPI interfaces controlling threshold, injection and other DACs +-- Tobias Weber +-- Ruhr Unversitaet Bochum +------------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity MupixBoardDAC is + port( + clk : in std_logic; --clock + reset : in std_logic; --reset + --DAC signals + spi_dout_dac : in std_logic; --dac serial data from board + dac4_dout : in std_logic; --serial data in from threshold dac + spi_dout_adc : in std_logic; --adc serial data from board + spi_clk : out std_logic; --serial clock + spi_din : out std_logic; --serial data out + spi_ld_tmp_dac : out std_logic; --load temperature dac + spi_ld_thres : out std_logic; --load threshold and injection dac + spi_ld_adc : out std_logic; --load adc + --TRB slow control + 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 entity MupixBoardDAC; + +architecture RTL of MupixBoardDAC is + + component LTC1658SPI + generic( + data_length : integer; + fpga_clock_speed : integer; + spi_clock_speed : integer + ); + port( + clk : in std_logic; + reset : in std_logic; + start_write : in std_logic; + spi_data_in : in std_logic_vector(data_length - 1 downto 0); + spi_data_from_chip : in std_logic; + spi_data_to_chip : out std_logic; + spi_data_out : out std_logic_vector(data_length - 1 downto 0); + spi_clk : out std_logic; + spi_ld : out std_logic + ); + end component LTC1658SPI; + + component ADS1018SPI + generic( + fpga_clock_speed : integer := 1e8; + spi_clock_speed : integer := 1e4 + ); + port( + clk : in std_logic; + reset : in std_logic; + start_write : in std_logic; + config_in : in std_logic_vector(15 downto 0); + spi_data_from_chip : in std_logic; + spi_data_to_chip : out std_logic; + spi_data_out : out std_logic_vector(31 downto 0); + spi_clk : out std_logic; + spi_ld : out std_logic + ); + end component ADS1018SPI; + + constant c_bits_threshold_dacs : integer := 64;--4*16 bit of the four DACs + signal start_write_threshold : std_logic; + signal spi_data_in_threshold : std_logic_vector(c_bits_threshold_dacs - 1 downto 0); + signal spi_data_to_chip_threshold : std_logic; + signal spi_data_out_threshold : std_logic_vector(c_bits_threshold_dacs - 1 downto 0); + signal spi_clk_threshold : std_logic; + + constant c_bits_temperature_dac : integer := 16; + signal start_write_temperature : std_logic; + signal spi_data_in_temperature : std_logic_vector(c_bits_temperature_dac - 1 downto 0); + signal spi_data_to_chip_temperature : std_logic; + signal spi_data_out_temperature : std_logic_vector(c_bits_temperature_dac - 1 downto 0); + signal spi_clk_temperature_temperature : std_logic; + + signal start_write_adc : std_logic; + signal config_adc : std_logic_vector(15 downto 0); + signal spi_data_to_chip_adc : std_logic; + signal spi_data_out_adc : std_logic_vector(31 downto 0); + signal spi_clk_adc : std_logic; + + + +begin + + spi_din <= spi_data_to_chip_threshold or spi_data_to_chip_temperature or spi_data_to_chip_adc; + spi_clk <= spi_clk_threshold or spi_clk_temperature_temperature or spi_clk_adc; + + threshold_injection_dac : entity work.LTC1658SPI + generic map( + data_length => c_bits_threshold_dacs, + fpga_clock_speed => 1e8, --100 MHz + spi_clock_speed => 5e4 --50 kHz + ) + port map( + clk => clk, + reset => reset, + start_write => start_write_threshold, + spi_data_in => spi_data_in_threshold, + spi_data_from_chip => dac4_dout, + spi_data_to_chip => spi_data_to_chip_threshold, + spi_data_out => spi_data_out_threshold, + spi_clk => spi_clk_threshold, + spi_ld => spi_ld_thres + ); + + temperature_dac : entity work.LTC1658SPI + generic map( + data_length => c_bits_temperature_dac, + fpga_clock_speed => 1e8, --100 MHz + spi_clock_speed => 5e4 --50 kHz + ) + port map( + clk => clk, + reset => reset, + start_write => start_write_temperature, + spi_data_in => spi_data_in_temperature, + spi_data_from_chip => spi_dout_dac, + spi_data_to_chip => spi_data_to_chip_temperature, + spi_data_out => spi_data_out_temperature, + spi_clk => spi_clk_temperature_temperature, + spi_ld => spi_ld_tmp_dac + ); + + + temperature_adc : component ADS1018SPI + generic map( + fpga_clock_speed => 1e8, + spi_clock_speed => 5e4 + ) + port map( + clk => clk, + reset => reset, + start_write => start_write_adc, + config_in => config_adc, + spi_data_from_chip => spi_dout_adc, + spi_data_to_chip => spi_data_to_chip_adc, + spi_data_out => spi_data_out_adc, + spi_clk => spi_clk_adc, + spi_ld => spi_ld_adc + ); + ----------------------------------------------------------------------------- + --TRB Slave Bus + --0x0090: threshold high and low dacs, 31:16 threshold high, 15:0 threshold low + --0x0091: threshold pix dac and injection dac, 31:16 pix dac, 15:0 injection dac + --0x0092: readback threshold high and low dacs, 31:16 threshold high, 15:0 threshold low + --0x0093: readback threshold pix dac and injection dac, 31:16 pix dac, 15:0 injection dac + --0x0094: temperature dac + --0x0095: readback temperature dac + --0x0096: start write threshold and injection dacs bit + ----------------------------------------------------------------------------- + SLV_BUS_HANDLER : process(clk) + begin -- process SLV_BUS_HANDLER + if rising_edge(clk) then + SLV_DATA_OUT <= (others => '0'); + SLV_ACK_OUT <= '0'; + SLV_UNKNOWN_ADDR_OUT <= '0'; + SLV_NO_MORE_DATA_OUT <= '0'; + start_write_threshold <= '0'; + + if SLV_READ_IN = '1' then + case SLV_ADDR_IN is + when x"0090" => + SLV_DATA_OUT <= spi_data_in_threshold(63 downto 32); + SLV_ACK_OUT <= '1'; + when x"0091" => + SLV_DATA_OUT <= spi_data_in_threshold(31 downto 0); + SLV_ACK_OUT <= '1'; + when x"0092" => + SLV_DATA_OUT <= spi_data_out_threshold(63 downto 32); + SLV_ACK_OUT <= '1'; + when x"0093" => + SLV_DATA_OUT <= spi_data_out_threshold(31 downto 0); + SLV_ACK_OUT <= '1'; + when x"0094" => + SLV_DATA_OUT(15 downto 0) <= spi_data_in_temperature; + SLV_ACK_OUT <= '1'; + when x"0095" => + SLV_DATA_OUT(15 downto 0) <= spi_data_out_temperature; + SLV_ACK_OUT <= '1'; + when others => + SLV_UNKNOWN_ADDR_OUT <= '1'; + end case; + + elsif SLV_WRITE_IN = '1' then + case SLV_ADDR_IN is + when x"0090" => + spi_data_in_threshold(63 downto 32) <= SLV_DATA_IN; + SLV_ACK_OUT <= '1'; + when x"0091" => + spi_data_in_threshold(31 downto 0) <= SLV_DATA_IN; + SLV_ACK_OUT <= '1'; + when x"0094" => + spi_data_in_temperature <= SLV_DATA_IN(15 downto 0); + start_write_temperature <= '1'; + SLV_ACK_OUT <= '1'; + when x"0096" => + start_write_threshold <= '1'; + SLV_ACK_OUT <= '1'; + when others => + SLV_UNKNOWN_ADDR_OUT <= '1'; + end case; + + end if; + end if; + end process SLV_BUS_HANDLER; + +end architecture RTL; diff --git a/mupix/Mupix8/sources/MupixBoardInterface.vhd b/mupix/Mupix8/sources/MupixBoardInterface.vhd new file mode 100644 index 0000000..9d2c70f --- /dev/null +++ b/mupix/Mupix8/sources/MupixBoardInterface.vhd @@ -0,0 +1,88 @@ +---------------------------------------------------------------------------- +-- Synchronize signals from mupix board +-- Tobias Weber +-- Ruhr Unversitaet Bochum +----------------------------------------------------------------------------- + +library ieee; +use ieee.numeric_std.all; +use ieee.std_logic_1164.all; + +entity MupixBoardInterface is + port( + clk_in : in std_logic; --slow clock + fast_clk_in : in std_logic; --fast clock + reset : in std_logic; --reset signal + --input signals from mupix sensorboard + ctrl_dout : in std_logic; --serial data from mupix + spi_dout_adc : in std_logic; --adc serial data from board + spi_dout_dac : in std_logic; --dac serial data from board + dac4_dout : in std_logic; --serial data in from dac 4?? + hitbus : in std_logic; --hitbus signal + hit : in std_logic; --hit signal (replacement for priout?) + trigger : in std_logic; --external trigger + --synchronized signals to FPGA logic + ctrl_dout_sync : out std_logic; + spi_dout_adc_sync : out std_logic; + spi_dout_dac_sync : out std_logic; + dac4_dout_sync : out std_logic; + hitbus_sync : out std_logic; + trigger_sync : out std_logic; + hitbus_sync_fast : out std_logic; --sampled with 200 MHz clock + trigger_sync_fast : out std_logic; --sampled with 200 MHz clock + hit_sync : out std_logic); +end entity MupixBoardInterface; + + +architecture rtl of MupixBoardInterface is + + + component InputSynchronizer + generic(depth : integer); + port( + clk : in std_logic; + rst : in std_logic; + input : in std_logic; + sync_output : out std_logic + ); + end component InputSynchronizer; + +begin + + sync_ctrl_dout : component InputSynchronizer + generic map(depth => 2) + port map(clk_in, reset, ctrl_dout, ctrl_dout_sync); + + sync_spi_dout_adc : component InputSynchronizer + generic map(depth => 2) + port map(clk_in, reset, spi_dout_adc, spi_dout_adc_sync); + + sync_spi_dout_dac : component InputSynchronizer + generic map(depth => 2) + port map(clk_in, reset, spi_dout_dac, spi_dout_dac_sync); + + sync_dac4_dout : component InputSynchronizer + generic map(depth => 2) + port map(clk_in, reset, dac4_dout, dac4_dout_sync); + + sync_hitbus : component InputSynchronizer + generic map(depth => 2) + port map(clk_in, reset, hitbus, hitbus_sync); + + sync_trigger : component InputSynchronizer + generic map(depth => 2) + port map(clk_in, reset, trigger, trigger_sync); + + sync_hit : component InputSynchronizer + generic map(depth => 2) + port map(clk_in, reset, hit, hit_sync); + + sync_fast_hitbus : component InputSynchronizer + generic map(depth => 2) + port map(fast_clk_in, reset, hitbus, hitbus_sync_fast); + + sync_fast_trigger : component InputSynchronizer + generic map(depth => 2) + port map(fast_clk_in, reset, trigger, trigger_sync_fast); + +end architecture rtl; diff --git a/mupix/Mupix8/sources/PixelControl.vhd b/mupix/Mupix8/sources/PixelControl.vhd new file mode 100644 index 0000000..75b4aac --- /dev/null +++ b/mupix/Mupix8/sources/PixelControl.vhd @@ -0,0 +1,378 @@ +------------------------------------------------------------------------------- +--Control of MuPix DACs and Pixel Tune DACs +--T. Weber, Mainz Univesity +------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.numeric_std.all; + +entity PixelControl is + generic( + fpga_clk_speed : integer := 1e8; + spi_clk_speed : integer := 1e4 + ); + port ( + clk : in std_logic; --clock + reset : in std_logic; --reset + --mupix control + ctrl_din : out std_logic; --serial data to mupix + ctrl_clk1 : out std_logic; --slow control clock 1 + ctrl_clk2 : out std_logic; --slow control clock 2 + ctrl_load : out std_logic; --slow control load + ctrl_dout : in std_logic; --serial data from mupix + --TRB slow control + 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 PixelControl; + +architecture Behavioral of PixelControl is + + constant fifo_word_width : integer := 32; + + signal bitcounter : unsigned(15 downto 0) := (others => '0');--number of transmitted configuration bits + signal bitstosend : unsigned(15 downto 0) := (others => '0');--number of bits which need to be send + signal bitcouner_word : integer range 0 to fifo_word_width - 1 := 0; --index to current bit in word from fifo + signal controlConfig : std_logic_vector(15 downto 0) := (others => '0');--configuration control + + --fifos storage of configuration bits + component STD_FIFO + generic( + DATA_WIDTH : positive := 8; + FIFO_DEPTH : positive := 256 + ); + port( + CLK : in std_logic; + RST : in std_logic; + WriteEn : in std_logic; + DataIn : in std_logic_vector(fifo_word_width - 1 downto 0); + ReadEn : in std_logic; + DataOut : out std_logic_vector(fifo_word_width - 1 downto 0); + Empty : out std_logic; + Full : out std_logic + ); + end component STD_FIFO; + + component CRC + generic( + detect_enable_edge : boolean := false + ); + port( + clk : in std_logic; + rst : in std_logic; + enable : in std_logic; + data_in : in std_logic; + crc_out : out std_logic_vector(4 downto 0) + ); + end component CRC; + + signal WriteEn : std_logic; + signal DataIn : std_logic_vector (fifo_word_width - 1 downto 0); + signal ReadEn : std_logic; + signal DataOut : std_logic_vector (fifo_word_width - 1 downto 0); + signal Empty : std_logic; + signal Full : std_logic; + + --clock enable signals + signal clk_enable : std_logic := '0'; + constant clk_div_max : integer := fpga_clk_speed/spi_clk_speed - 1; + signal clk_div_counter : integer range 0 to clk_div_max := clk_div_max; + + --send single configuration bit + type bit_send_fsm_type is (idle, sendbit1, sendbit2, sendbit3); + signal bit_send_fsm : bit_send_fsm_type := idle; + signal start_send, sending : std_logic; + + --configuration state machine + type config_fsm_type is (idle, config, readfifo, waitfifo, load); + signal config_fsm : config_fsm_type := idle; + + --check sum for data integrity + signal crc_correct : std_logic; + signal enable_crc_to_mupix : std_logic; + signal data_in_crc_to_mupix : std_logic; + signal crc_out_crc_to_mupix : std_logic_vector(4 downto 0); + signal reset_crc_to_mupix : std_logic; + signal enable_crc_from_mupix : std_logic; + signal data_in_crc_from_mupix : std_logic; + signal crc_out_crc_from_mupix : std_logic_vector(4 downto 0); + signal reset_crc_from_mupix : std_logic; + + --control signals to mupix + signal mupix_ctrl_i, mupix_ctrl_reg : MupixSlowControl := MuPixSlowControlInit; + + +begin -- Behavioral + + fifo_1 : entity work.STD_FIFO + generic map( + DATA_WIDTH => fifo_word_width, + FIFO_DEPTH => 32 + ) + port map( + CLK => CLK, + RST => reset, + WriteEn => WriteEn, + DataIn => DataIn, + ReadEn => ReadEn, + DataOut => DataOut, + Empty => Empty, + Full => Full + ); + + --TODO: CRC checking logic + crc_in : entity work.CRC + generic map(detect_enable_edge => true) + port map( + clk => clk, + rst => reset_crc_to_mupix, + enable => enable_crc_to_mupix, + data_in => data_in_crc_to_mupix, + crc_out => crc_out_crc_to_mupix + ); + + reset_crc_to_mupix <= reset or controlConfig(2); + + crc_out : entity work.CRC + generic map(detect_enable_edge => true) + port map( + clk => clk, + rst => reset_crc_from_mupix, + enable => enable_crc_from_mupix, + data_in => data_in_crc_from_mupix, + crc_out => crc_out_crc_from_mupix + ); + + reset_crc_from_mupix <= reset or controlConfig(3); + + spi_clk_div_proc : process (clk) is + begin + if rising_edge(clk) then + if reset = '1' then + clk_enable <= '0'; + clk_div_counter <= clk_div_max; + else + if clk_div_counter = 0 then + clk_div_counter <= clk_div_max; + clk_enable <= '1'; + else + clk_div_counter <= clk_div_counter - 1; + clk_enable <= '0'; + end if; + end if; + end if; + end process spi_clk_div_proc; + + + sendpixbit_proc : process (clk) is + begin + if rising_edge(clk) then + if reset = '1' then + mupix_ctrl_i.ck_c <= '0'; + mupix_ctrl_i.ck_d <= '0'; + mupix_ctrl_i.sin <= '0'; + sending <= '0'; + bit_send_fsm <= idle; + bitcounter <= (others => '0'); + bitcouner_word <= fifo_word_width - 1; + else + if clk_enable = '1' then + mupix_ctrl_i.ck_c <= '0'; + mupix_ctrl_i.ck_d <= '0'; + mupix_ctrl_i.sin <= '0'; + enable_crc_to_mupix <= '0'; + enable_crc_from_mupix <= '0'; + data_in_crc_from_mupix <= '0'; + data_in_crc_to_mupix <= '0'; + case bit_send_fsm is + when idle => + bitcouner_word <= fifo_word_width - 1; + if start_send = '1' then + bit_send_fsm <= sendbit1; + sending <= '1'; + else + bit_send_fsm <= idle; + sending <= '0'; + end if; + when sendbit1 => + mupix_ctrl_i.sin <= DataOut(bitcouner_word); + sending <= '1'; + bit_send_fsm <= sendbit2; + when sendbit2 => --rising clock edge + mupix_ctrl_i.sin <= DataOut(bitcouner_word); + if controlConfig(0) = '1' then + mupix_ctrl_i.ck_d <= '1'; + else + mupix_ctrl_i.ck_c <= '1'; + end if; + enable_crc_to_mupix <= '1'; + data_in_crc_to_mupix <= DataOut(bitcouner_word); + bit_send_fsm <= sendbit3; + sending <= '1'; + when sendbit3 => + sending <= '1'; + mupix_ctrl_i.sin <= DataOut(bitcouner_word); + enable_crc_from_mupix <= '1'; + if controlConfig(0) = '1' then + data_in_crc_from_mupix <= sout_d_from_mupix; + else + data_in_crc_from_mupix <= sout_c_from_mupix; + end if; + bitcouner_word <= bitcouner_word - 1; + bitcounter <= bitcounter + 1; + if bitcouner_word = 0 or bitcounter = bitstosend then + bit_send_fsm <= idle; + else + bit_send_fsm <= sendbit1; + end if; + end case; + end if; + end if; + end if; + end process sendpixbit_proc; + + + configure_proc : process (clk) is + variable hold_load_counter : integer range 0 to 7; + begin + if rising_edge(clk) then + if reset = '1' then + mupix_ctrl_i.ld_c <= '0'; + config_fsm <= idle; + hold_load_counter := 0; + else + mupix_ctrl_i.ld_c <= '0'; + ReadEn <= '0'; + start_send <= '0'; + case config_fsm is + when idle => + hold_load_counter := 0; + if Empty = '0' then + config_fsm <= readfifo; + else + config_fsm <= idle; + end if; + when readfifo => + if Empty = '0' then + ReadEn <= '1'; + config_fsm <= waitfifo; + else + ReadEn <= '0'; + config_fsm <= readfifo; + end if; + when waitfifo => + config_fsm <= config; + if sending = '0' then + start_send <= '1'; + config_fsm <= waitfifo; + else + start_send <= '0'; + config_fsm <= config; + end if; + when config => + if sending = '1' then + config_fsm <= config; + else + if bitcounter < bitstosend then + config_fsm <= readfifo; + else + if controlConfig(1) = '0' then + config_fsm <= load; + else + config_fsm <= idle; + end if; + end if; + end if; + when load => + hold_load_counter := hold_load_counter + 1; + mupix_ctrl_i.ld_c <= '1'; + if hold_load_counter = 7 then + mupix_ctrl_i.ld_c <= '0'; + config_fsm <= idle; + else + config_fsm <= load; + end if; + end case; + end if; + end if; + end process configure_proc; + + + ----------------------------------------------------------------------------- + --x0080: input to fifo (write)/current fifo output (read) + --x0081: current CRC check sum (read only) + --x0082: data fifo is full (read only) + --x0083: configure bit 0: configure chip dacs/pixel dacs, + -- bit 1: readback bit 32-16 number of config bits + -- bit 2: reset outgoing CRC sum + -- bit 3: reset incoming CRC sum + ----------------------------------------------------------------------------- + SLV_BUS : process (clk) + begin -- process SLV_BUS + if rising_edge(clk) then + + SLV_DATA_OUT <= (others => '0'); + SLV_UNKNOWN_ADDR_OUT <= '0'; + SLV_NO_MORE_DATA_OUT <= '0'; + SLV_ACK_OUT <= '0'; + DataIn <= (others => '0'); + WriteEn <= '0'; + if SLV_WRITE_IN = '1' then + case SLV_ADDR_IN is + when x"0080" => + DataIn <= SLV_DATA_IN; + WriteEn <= '1'; + SLV_ACK_OUT <= '1'; + when x"0083" => + controlConfig <= SLV_DATA_IN(15 downto 0); + bitstosend <= unsigned(SLV_DATA_IN(31 downto 16)); + SLV_ACK_OUT <= '1'; + when others => + SLV_UNKNOWN_ADDR_OUT <= '1'; + end case; + + elsif SLV_READ_IN = '1' then + case SLV_ADDR_IN is + when x"0080" => + SLV_DATA_OUT <= DataOut; + SLV_ACK_OUT <= '1'; + when x"0081" => + SLV_DATA_OUT(10 downto 0) <= crc_out_crc_from_mupix & crc_out_crc_to_mupix & crc_correct; + SLV_ACK_OUT <= '1'; + when x"0082" => + SLV_DATA_OUT(1 downto 0) <= Empty & Full; + SLV_ACK_OUT <= '1'; + when x"0083" => + SLV_DATA_OUT <= std_logic_vector(bitstosend) & controlConfig; + SLV_ACK_OUT <= '1'; + when others => + SLV_UNKNOWN_ADDR_OUT <= '1'; + end case; + end if; + end if; + end process SLV_BUS; + + crc_correct <= '1' when crc_out_crc_from_mupix = crc_out_crc_to_mupix else '0'; + + output_pipe : process (clk) is + begin + if rising_edge(clk) then + if reset = '1' then + mupix_ctrl_reg <= MuPixSlowControlInit; + else + mupix_ctrl_reg <= mupix_ctrl_i; + end if; + end if; + end process output_pipe; + + --matching to outputs + mupix_ctrl <= mupix_ctrl_reg; + +end Behavioral; + + diff --git a/mupix/Mupix8/sources/SignalDelay.vhd b/mupix/Mupix8/sources/SignalDelay.vhd new file mode 100644 index 0000000..808b003 --- /dev/null +++ b/mupix/Mupix8/sources/SignalDelay.vhd @@ -0,0 +1,44 @@ +------------------------------------------------------------ +--Delay Signal for number of clock cycles given by delay_in +--T. Weber +------------------------------------------------------------ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.numeric_std.all; + +entity SignalDelay is + generic( + Width : integer := 1; + Delay : integer := 4 -- 2**Delay-1 + ); + 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 entity; + +architecture arch of SignalDelay is + + signal writecounter : unsigned(Delay - 1 downto 0) := (others => '0'); + signal readcounter : unsigned(Delay - 1 downto 0) := (others => '0'); + + type memory_t is array((2**Delay) - 1 downto 0) of std_logic_vector(Width - 1 downto 0); + signal memory : memory_t; + +begin + + DelayProc : process(clk_in) + begin + if rising_edge(clk_in) then + if write_en_in = '1' then + memory(to_integer(writecounter)) <= sig_in; + writecounter <= writecounter + 1; + readcounter <= writecounter - unsigned(delay_in) + 2; + end if; + sig_out <= memory(to_integer(readcounter)); + end if; + end process DelayProc; + +end architecture; diff --git a/mupix/Mupix8/sources/TestpulseGenerator.vhd b/mupix/Mupix8/sources/TestpulseGenerator.vhd new file mode 100644 index 0000000..fab7a5d --- /dev/null +++ b/mupix/Mupix8/sources/TestpulseGenerator.vhd @@ -0,0 +1,118 @@ +----------------------------------------------------------------------------- +-- MUPIX3 injection generator +-- +-- Niklaus Berger, Heidelberg University +-- nberger@physi.uni-heidelberg.de +-- +-- Adepted to TRBv3 Readout: Tobias Weber, University Mainz +----------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity injection_generator is + port ( + rst : in std_logic; + clk : 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; + testpulse1 : out std_logic; + testpulse2 : out std_logic + ); +end injection_generator; + + +architecture rtl of injection_generator is + + signal counter1 : unsigned(15 downto 0) := (others => '0'); + signal counter2 : unsigned(15 downto 0) := (others => '0'); + + signal counter_from_slv : unsigned(31 downto 0); + signal slv_written : std_logic_vector(1 downto 0); + + + signal testpulse1_i : std_logic; + signal testpulse2_i : std_logic; + signal testpulse_busy : std_logic := '0'; + + +begin + + process(clk, rst) + begin + if(rst = '1') then + + testpulse1_i <= '0'; + testpulse2_i <= '0'; + + elsif rising_edge(clk) then + if slv_written = "10" then + counter1 <= counter_from_slv(15 downto 0); + counter2 <= counter_from_slv(31 downto 16); + end if; + + if(counter1 > x"0000") then + testpulse1_i <= '1'; + counter1 <= counter1 - 1; + else + testpulse1_i <= '0'; + end if; + + if(counter2 > x"0000") then + testpulse2_i <= '1'; + counter2 <= counter2 - 1; + else + testpulse2_i <= '0'; + end if; + + end if; + end process; + + testpulse_busy <= '1' when testpulse2_i = '1' or testpulse1_i = '1' else '0'; + + SLV_HANDLER : process(clk) + begin + if rising_edge(clk) then + SLV_DATA_OUT <= (others => '0'); + SLV_UNKNOWN_ADDR_OUT <= '0'; + SLV_NO_MORE_DATA_OUT <= '0'; + SLV_ACK_OUT <= '0'; + slv_written <= slv_written(0) & SLV_WRITE_IN; + + if SLV_READ_IN = '1' then + if SLV_ADDR_IN = x"0060" then + SLV_DATA_OUT(31 downto 16) <= std_logic_vector(counter2); + SLV_DATA_OUT(15 downto 0) <= std_logic_vector(counter1); + SLV_ACK_OUT <= '1'; + else + SLV_UNKNOWN_ADDR_OUT <= '1'; + end if; + end if; + + if SLV_WRITE_IN = '1' then + if SLV_ADDR_IN = x"0060" then + if testpulse_busy = '0' then + counter_from_slv <= unsigned(SLV_DATA_IN); + SLV_ACK_OUT <= '1'; + else + SLV_ACK_OUT <= '1'; + end if; + + else + SLV_UNKNOWN_ADDR_OUT <= '1'; + end if; + end if; + end if; + end process SLV_HANDLER; + +--Output Signals + testpulse2 <= testpulse2_i; + testpulse1 <= testpulse1_i; + +end rtl; diff --git a/mupix/Mupix8/sources/TriggerHandler.vhd b/mupix/Mupix8/sources/TriggerHandler.vhd new file mode 100644 index 0000000..dd260c5 --- /dev/null +++ b/mupix/Mupix8/sources/TriggerHandler.vhd @@ -0,0 +1,427 @@ +----------------------------------------------------------------------------- +-- Trigger Handler for TRBnet +-- Tobias Weber, University Mainz +----------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +--use work.trb_net_std.all; +--use work.trb_net_components.all; +--use work.trb3_components.all; + +entity TriggerHandler is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + + --Input Triggers + TIMING_TRIGGER_IN : in std_logic; -- The raw timing Trigger Signal + LVL1_TRG_DATA_VALID_IN : in std_logic; -- Data Trigger is valid + LVL1_VALID_TIMING_TRG_IN : in std_logic; -- Timin Trigger is valid + LVL1_VALID_NOTIMING_TRG_IN : in std_logic; -- calib trigger w/o ref time + 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); + + --Response from FEE + 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_TRG_RELEASE_OUT : out std_logic; + FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); + + FEE_DATA_0_IN : in std_logic_vector(31 downto 0); + FEE_DATA_WRITE_0_IN : in std_logic; + + -- Trigger FeedBack + TRIGGER_BUSY_MUPIX_READ_IN : in std_logic; + TRIGGER_BUSY_FIFO_READ_IN : in std_logic; + + -- OUT + VALID_TRIGGER_OUT : out std_logic; + TRIGGER_TIMING_OUT : out std_logic; + TRIGGER_STATUS_OUT : out std_logic; + FAST_CLEAR_OUT : out std_logic;--clear event buffer + FLUSH_BUFFER_OUT : out std_logic; + + -- Slave bus + 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 entity TriggerHandler; + + +architecture behavioral of TriggerHandler is + +--trigger + signal bypass_trigger : std_logic := '0'; + signal reset_trigger_state : std_logic := '0'; + signal reset_trigger_state_edge : std_logic_vector(1 downto 0) := "00"; + signal valid_trigger_int : std_logic := '0'; + signal timing_trigger_int : std_logic := '0'; + signal timing_trigger_edge : std_logic_vector(1 downto 0) := "00"; + signal status_trigger_int : std_logic := '0'; + signal fast_clear_int : std_logic := '0'; + signal flush_buffer_int : std_logic := '0'; + signal trigger_busy_int : std_logic := '0'; + signal mupix_readout_end_int : std_logic_vector(1 downto 0) := "00"; + signal fifo_readout_end_int : std_logic_vector(1 downto 0) := "00"; +--fee + signal fee_data_int : std_logic_vector(31 downto 0) := (others => '0'); + signal fee_data_write_int : std_logic := '0'; + signal fee_data_finished_int : std_logic := '0'; + signal fee_trg_release_int : std_logic := '0'; + signal fee_trg_statusbit_int : std_logic_vector(31 downto 0) := (others => '0'); +--event buffer + +--registers + signal reset_trigger_counters : std_logic := '0'; + signal reset_trigger_counters_edge : std_logic_vector(1 downto 0) := (others => '0'); + signal trigger_rate_acc : unsigned(31 downto 0) := (others => '0'); + signal trigger_rate_tot : unsigned(31 downto 0) := (others => '0'); + signal trigger_rate_time_counter : unsigned(31 downto 0) := (others => '0'); + signal invalid_trigger_counter : unsigned(31 downto 0) := (others => '0'); + signal valid_trigger_counter : unsigned(31 downto 0) := (others => '0'); + signal invalid_trigger_counter_t : unsigned(31 downto 0) := (others => '0'); + signal valid_trigger_counter_t : unsigned(31 downto 0) := (others => '0'); + signal trigger_handler_state : std_logic_vector(7 downto 0) := (others => '0'); + +--trigger types + constant trigger_physics_type : std_logic_vector(3 downto 0) := x"1"; + constant trigger_status_type : std_logic_vector(3 downto 0) := x"e"; + +--trigger handler + type trigger_handler_type is (idle, + timing_trigger, + no_timing_trigger, + check_trigger_type, + status_trigger, + write_data_to_eventbuffer, + write_data_to_ipu, + trigger_release_a, + trigger_release_b, + trigger_release_c, + wait_trigger_release, + ignore, + wait_trigger_data_valid_a, + wait_trigger_data_valid_b); + + type trigger_type_type is (t_timing, + t_physics, + t_status, + t_ignore, + t_unknown); + + signal trigger_handler_fsm : trigger_handler_type := idle; + signal trigger_type : trigger_type_type := t_unknown; + signal wr_header_int : std_logic := '0'; + signal wr_data_int : std_logic := '0'; + signal wr_status_int : std_logic := '0'; + signal wr_dummy_int : std_logic := '0'; + +begin + + Signal_Edge_Detect: process (CLK_IN) is + begin -- process Mupix_Readout_End_Detect + if rising_edge(CLK_IN) then + mupix_readout_end_int <= mupix_readout_end_int(0) & TRIGGER_BUSY_MUPIX_READ_IN; + fifo_readout_end_int <= fifo_readout_end_int(0) & TRIGGER_BUSY_FIFO_READ_IN; + timing_trigger_edge <= timing_trigger_edge(0) & TIMING_TRIGGER_IN; + reset_trigger_state_edge <= reset_trigger_state_edge(1) & reset_trigger_state; + end if; + end process Signal_Edge_Detect; + + ------------------------------------------------------------ + --Handling of LVL1 triggers + ------------------------------------------------------------ + trigger_handler_proc: process is + begin -- process trigger_handler_proc + wait until rising_edge(clk_in); + valid_trigger_int <= '0'; + timing_trigger_int <= '0'; + status_trigger_int <= '0'; + flush_buffer_int <= '0'; + fee_data_finished_int <= '0'; + fee_trg_release_int <= '0'; + fee_trg_statusbit_int <= (others => '0'); + fast_clear_int <= '0'; + trigger_busy_int <= '1'; + fast_clear_int <= '0'; + fee_trg_release_int <= '0'; + wr_header_int <= '0'; + wr_data_int <= '0'; + wr_status_int <= '0'; + wr_dummy_int <= '0'; + if LVL1_INVALID_TRG_IN = '1' or reset_trigger_state_edge = "01" then + fast_clear_int <= '1'; + fee_trg_release_int <= '1'; + trigger_handler_fsm <= idle; + else + case trigger_handler_fsm is + when idle => + trigger_busy_int <= '0'; + trigger_handler_state <= x"01"; + if LVL1_VALID_TIMING_TRG_IN = '1' then + wr_header_int <= '1'; + if bypass_trigger = '1' then + trigger_type <= t_ignore; + trigger_handler_fsm <= ignore; + else + trigger_type <= t_timing; + trigger_handler_fsm <= timing_trigger; + end if; + elsif(LVL1_VALID_NOTIMING_TRG_IN = '1') then + wr_header_int <= '1'; + if bypass_trigger = '1' then + trigger_type <= t_ignore; + trigger_handler_fsm <= ignore; + else + trigger_handler_fsm <= check_trigger_type; + end if; + end if; + + when check_trigger_type => + trigger_handler_state <= x"02"; + if(LVL1_TRG_DATA_VALID_IN = '1') then + if(LVL1_TRG_TYPE_IN = trigger_status_type) then + trigger_type <= t_status; + trigger_handler_fsm <= no_timing_trigger; + elsif(LVL1_TRG_TYPE_IN = trigger_physics_type) then + trigger_type <= t_physics; + trigger_handler_fsm <= no_timing_trigger; + else + --unknown trigger + trigger_type <= t_unknown; + trigger_handler_fsm <= no_timing_trigger; + end if; + else + trigger_handler_fsm <= check_trigger_type; + end if; + + when timing_trigger =>--starts mupix readout fsm + trigger_handler_state <= x"03"; + valid_trigger_int <= '1'; + timing_trigger_int <= '1'; + trigger_handler_fsm <= write_data_to_eventbuffer; + + when no_timing_trigger => + trigger_handler_state <= x"04"; + if trigger_type = t_physics then + trigger_handler_fsm <= timing_trigger; + elsif trigger_type = t_status then + trigger_handler_fsm <= status_trigger; + else + trigger_handler_fsm <= ignore; + end if; + + when ignore => + wr_dummy_int <= '1'; --write a dummy value to identify + --inactive FEE + trigger_handler_state <= x"05"; + trigger_handler_fsm <= wait_trigger_data_valid_b; + + when status_trigger => --dummy implementation + trigger_handler_state <= x"06"; + wr_status_int <= '1'; + trigger_handler_fsm <= wait_trigger_data_valid_b; + + when write_data_to_eventbuffer => + trigger_handler_state <= x"07"; + if mupix_readout_end_int = "10" then + trigger_handler_fsm <= write_data_to_ipu; + flush_buffer_int <= '1'; + else + trigger_handler_fsm <= write_data_to_eventbuffer; + end if; + + when write_data_to_ipu => + trigger_handler_state <= x"0A"; + wr_data_int <= '1'; + if fifo_readout_end_int = "10" then + wr_data_int <= '0'; + trigger_handler_fsm <= wait_trigger_data_valid_a; + else + trigger_handler_fsm <= write_data_to_ipu; + end if; + + when wait_trigger_data_valid_a => + trigger_handler_state <= x"0B"; + if LVL1_TRG_DATA_VALID_IN = '1' then + trigger_handler_fsm <= wait_trigger_data_valid_b; + end if; + + when wait_trigger_data_valid_b => + trigger_handler_state <= x"0C"; + trigger_handler_fsm <= trigger_release_a; + + when trigger_release_a => + trigger_handler_state <= x"0D"; + trigger_handler_fsm <= trigger_release_b; + + when trigger_release_b => + trigger_handler_state <= x"0E"; + fee_data_finished_int <= '1'; + trigger_handler_fsm <= trigger_release_c; + + when trigger_release_c => + trigger_handler_state <= x"0F"; + fee_trg_release_int <= '1'; + trigger_handler_fsm <= wait_trigger_release; + + when wait_trigger_release => + if(LVL1_TRG_DATA_VALID_IN = '1') then + trigger_handler_fsm <= wait_trigger_release; + else + trigger_handler_fsm <= idle; + end if; + end case; + end if; + end process trigger_handler_proc; + + ------------------------------------------------------------ + --Data Output Mux + ------------------------------------------------------------ + Data_Out_Mux: process (clk_in) is + begin -- process Data_Out_Mux + if rising_edge(clk_in) then + if wr_header_int = '1' then + fee_data_write_int <= '1';--header see Hades DAQ user guide + fee_data_int <= "001" & "0" & LVL1_TRG_TYPE_IN & LVL1_TRG_CODE_IN & LVL1_TRG_NUMBER_IN; + elsif wr_data_int = '1' then + fee_data_write_int <= FEE_DATA_WRITE_0_IN; + fee_data_int <= FEE_DATA_0_IN; + elsif wr_status_int = '1' then + fee_data_int <= x"deadbeef"; + fee_data_write_int <= '1'; + elsif wr_dummy_int = '1' then + fee_data_write_int <= '1' ; + fee_data_int <= x"fff00000"; + else + fee_data_write_int <= '0'; + fee_data_int <= (others => '1'); + end if; + end if; + end process Data_Out_Mux; + + + ------------------------------------------------------------ + --Trigger statistics + ------------------------------------------------------------ + Trigger_Statistics_Proc: process (clk_in) is + begin -- process Trigger_Statistics_Proc + if rising_edge(CLK_IN) then + reset_trigger_counters_edge <= reset_trigger_counters_edge(0) & reset_trigger_counters; + if reset_trigger_counters_edge = "01" then + trigger_rate_acc <= (others => '0'); + invalid_trigger_counter_t <= (others => '0'); + valid_trigger_counter_t <= (others => '0'); + trigger_rate_time_counter <= (others => '0'); + end if; + if trigger_rate_time_counter < x"5f5e100" then--1s at 10ns clock period + --if trigger_rate_time_counter < x"000007e" then + trigger_rate_time_counter <= trigger_rate_time_counter + 1; + if valid_trigger_int = '1' then + valid_trigger_counter_t <= valid_trigger_counter_t + 1; + elsif LVL1_INVALID_TRG_IN = '1' or (trigger_busy_int = '1' and timing_trigger_edge = "01") then + invalid_trigger_counter_t <= invalid_trigger_counter_t + 1; + end if; + else + valid_trigger_counter <= valid_trigger_counter + valid_trigger_counter_t; + invalid_trigger_counter <= invalid_trigger_counter + invalid_trigger_counter_t; + trigger_rate_acc <= valid_trigger_counter_t; + trigger_rate_tot <= valid_trigger_counter_t + invalid_trigger_counter_t; + trigger_rate_time_counter <= (others => '0'); + valid_trigger_counter_t <= (others => '0'); + invalid_trigger_counter_t <= (others => '0'); + end if; + end if; + end process Trigger_Statistics_Proc; + + ------------------------------------------------------------ + --TRB SLV-BUS Hanlder + ------------------------------------------------------------ + --0x100: accepted trigger_rate + --0x101: total trigger_rate + --0x102: invalid triggers + --0x103: valid triggers + --0x104: trigger_handler_state + --0x105: reset counters + --0x106: reset trigger state machine + --0x107: bypass trigger signals flag + + slv_bus_handler : process(CLK_IN) + begin + if rising_edge(CLK_IN) then + slv_data_out <= (others => '0'); + slv_ack_out <= '0'; + slv_no_more_data_out <= '0'; + slv_unknown_addr_out <= '0'; + + if slv_write_in = '1' then + case SLV_ADDR_IN is + when x"0105" => + reset_trigger_counters <= SLV_DATA_IN(0); + slv_ack_out <= '1'; + when x"0106" => + reset_trigger_state <= SLV_DATA_IN(0); + slv_ack_out <= '1'; + when x"0107"=> + bypass_trigger <= SLV_DATA_IN(0); + slv_ack_out <= '1'; + when others => + slv_unknown_addr_out <= '1'; + end case; + + elsif slv_read_in = '1' then + case slv_addr_in is + when x"0100" => + slv_data_out <= std_logic_vector(trigger_rate_acc); + slv_ack_out <= '1'; + when x"0101" => + slv_data_out <= std_logic_vector(trigger_rate_tot); + slv_ack_out <= '1'; + when x"0102" => + slv_data_out <= std_logic_vector(invalid_trigger_counter); + slv_ack_out <= '1'; + when x"0103" => + slv_data_out <= std_logic_vector(valid_trigger_counter); + slv_ack_out <= '1'; + when x"0104" => + slv_data_out <= x"000000" & trigger_handler_state; + slv_ack_out <= '1'; + when x"0107" => + slv_data_out(0) <= bypass_trigger; + slv_ack_out <= '1'; + when others => + slv_unknown_addr_out <= '1'; + end case; + + end if; + end if; + end process slv_bus_handler; + + --map output signals + valid_trigger_out <= valid_trigger_int; + trigger_timing_out <= timing_trigger_int; + trigger_status_out <= status_trigger_int; + fast_clear_out <= fast_clear_int; + flush_buffer_out <= flush_buffer_int; + fee_data_out <= fee_data_int; + fee_data_write_out <= fee_data_write_int; + fee_data_finished_out <= fee_data_finished_int; + fee_trg_release_out <= fee_trg_release_int; + fee_trg_statusbits_out <= fee_trg_statusbit_int; + +end architecture behavioral; diff --git a/mupix/Mupix8/tb/CRCTest.vhd b/mupix/Mupix8/tb/CRCTest.vhd new file mode 100644 index 0000000..46acdc1 --- /dev/null +++ b/mupix/Mupix8/tb/CRCTest.vhd @@ -0,0 +1,67 @@ +------------------------------------------------------------------------------- +--Test bench for cyclic redundancy check computation +--We use the CRC5 polynomial f(x) = 1 + x^2 + x^ 5 used by the USB2.0 protocol +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity CRCTest is +end entity CRCTest; + +architecture simulation of CRCTest is + + component CRC + port( + clk : in std_logic; + rst : in std_logic; + enable : in std_logic; + data_in : in std_logic; + crc_out : out std_logic_vector(4 downto 0) + ); + end component CRC; + + signal clk : std_logic; + signal rst : std_logic := '0'; + signal enable : std_logic := '0'; + signal data_in : std_logic := '0'; + signal crc_out : std_logic_vector(4 downto 0); + + constant clk_period : time := 10 ns; + constant message : std_logic_vector(10 downto 0) := "10100111010"; + +begin + + dut : entity work.CRC + port map( + clk => clk, + rst => rst, + enable => enable, + data_in => data_in, + crc_out => crc_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 50 ns; + for i in 10 downto 0 loop + enable <= '1'; + data_in <= message(i); + wait for clk_period; + end loop; + enable <= '0'; + assert crc_out = "11000" report "error during crc calculation" severity error; + + wait; + end process stimulus; + + +end architecture simulation; diff --git a/mupix/Mupix8/tb/HitbusHistogramTest.vhd b/mupix/Mupix8/tb/HitbusHistogramTest.vhd new file mode 100644 index 0000000..b788f08 --- /dev/null +++ b/mupix/Mupix8/tb/HitbusHistogramTest.vhd @@ -0,0 +1,120 @@ +------------------------------------------------------------ +--! @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; diff --git a/mupix/Mupix8/tb/LTC1658SPITest.vhd b/mupix/Mupix8/tb/LTC1658SPITest.vhd new file mode 100644 index 0000000..feb8703 --- /dev/null +++ b/mupix/Mupix8/tb/LTC1658SPITest.vhd @@ -0,0 +1,99 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity LTC1658SPITest is +end entity LTC1658SPITest; + +architecture simulation of LTC1658SPITest is + + component LTC1658SPI + generic( + data_length : integer; + fpga_clock_speed : integer; + spi_clock_speed : integer + ); + port( + clk : in std_logic; + reset : in std_logic; + start_write : in std_logic; + spi_data_in : in std_logic_vector(data_length - 1 downto 0); + spi_data_from_chip : in std_logic; + spi_data_to_chip : out std_logic; + spi_data_out : out std_logic_vector(data_length - 1 downto 0); + spi_clk : out std_logic; + spi_ld : out std_logic + ); + end component LTC1658SPI; + + + constant data_length : integer := 16; + constant clk_period : time := 10 ns; + + signal clk : std_logic; + signal reset : std_logic := '0'; + signal start_write : std_logic := '0'; + signal spi_data_in : std_logic_vector(data_length - 1 downto 0); + signal spi_data_from_chip : std_logic := '0'; + signal spi_data_to_chip : std_logic; + signal spi_data_out : std_logic_vector(data_length - 1 downto 0); + signal spi_clk : std_logic; + signal spi_ld : std_logic; + + signal shiftreg : std_logic_vector(data_length - 1 downto 0) := (others => '0'); + +begin + + dut : entity work.LTC1658SPI + generic map( + data_length => data_length, + fpga_clock_speed => 100, + spi_clock_speed => 10 + ) + port map( + clk => clk, + reset => reset, + start_write => start_write, + spi_data_in => spi_data_in, + spi_data_from_chip => spi_data_from_chip, + spi_data_to_chip => spi_data_to_chip, + spi_data_out => spi_data_out, + spi_clk => spi_clk, + spi_ld => spi_ld + ); + + clk_gen : process is + begin + clk <= '0'; + wait for clk_period/2; + clk <= '1'; + wait for clk_period/2; + end process clk_gen; + + ltcshiftreg : process(spi_clk) is + begin + if spi_clk'event and spi_clk = '1' then + spi_data_from_chip <= shiftreg(data_length - 1) after 5 ns; + shiftreg <= shiftreg(data_length - 2 downto 0) & spi_data_to_chip; + end if; + end process ltcshiftreg; + + + stimulus : process is + begin + wait for 100 ns; + spi_data_in <= x"AAAA"; + start_write <= '1'; + wait for clk_period; + start_write <= '0'; + wait for 5 us; + spi_data_in <= x"BBBB"; + start_write <= '1'; + wait for clk_period; + start_write <= '0'; + wait; + end process stimulus; + + + +end architecture simulation; diff --git a/mupix/Mupix8/tb/MupixShiftReg.vhd b/mupix/Mupix8/tb/MupixShiftReg.vhd new file mode 100644 index 0000000..687d67f --- /dev/null +++ b/mupix/Mupix8/tb/MupixShiftReg.vhd @@ -0,0 +1,46 @@ +------------------------------------------------------------ +--Simulation of mupix 6 shift register +------------------------------------------------------------ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity MupixShiftReg is + generic( + pixeldac_shift_length : integer := 64; + chipdac_shift_length : integer := 16 + ); + port( + ck_c : in std_logic; + ck_d : in std_logic; + sin : in std_logic; + sout_c : out std_logic; + sout_d : out std_logic); +end entity MupixShiftReg; + +architecture RTL of MupixShiftReg is + + signal pixeldac_shift_reg : std_logic_vector(pixeldac_shift_length - 1 downto 0) := (others => '0'); + signal chipdac_shift_reg : std_logic_vector(chipdac_shift_length - 1 downto 0) := (others => '0'); + +begin + + process(ck_c) + begin + if ck_c'event and ck_c = '1' then + pixeldac_shift_reg <= pixeldac_shift_reg(pixeldac_shift_length - 2 downto 0) & sin; + end if; + end process; + + process(ck_d) + begin + if ck_d'event and ck_d = '1' then + chipdac_shift_reg <= chipdac_shift_reg(chipdac_shift_length - 2 downto 0) & sin; + end if; + end process; + + sout_c <= pixeldac_shift_reg(pixeldac_shift_length - 1); + sout_d <= chipdac_shift_reg(chipdac_shift_length - 1); + +end architecture RTL; + diff --git a/mupix/Mupix8/tb/PixCtrlTest.vhd b/mupix/Mupix8/tb/PixCtrlTest.vhd new file mode 100644 index 0000000..798a27e --- /dev/null +++ b/mupix/Mupix8/tb/PixCtrlTest.vhd @@ -0,0 +1,121 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.numeric_std.all; + +use work.StdTypes.all; +use work.TRBSimulationPkg.all; + + +entity PixCtrlTest is +end entity PixCtrlTest; + +architecture simulation of PixCtrlTest is + + component PixCtr + generic( + fpga_clk_speed : integer := 1e8; + spi_clk_speed : integer := 1e4 + ); + port( + clk : in std_logic; + reset : in std_logic; + sout_c_from_mupix : in std_logic; + sout_d_from_mupix : in std_logic; + mupix_ctrl : out MupixSlowControl; + 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 PixCtr; + + component MupixShiftReg + generic( + pixeldac_shift_length : integer := 64; + chipdac_shift_length : integer := 16 + ); + port( + ck_c : in std_logic; + ck_d : in std_logic; + sin : in std_logic; + sout_c : out std_logic; + sout_d : out std_logic + ); + end component MupixShiftReg; + + signal clk : std_logic; + signal reset : std_logic := '0'; + signal sout_c_from_mupix : std_logic := '0'; + signal sout_d_from_mupix : std_logic := '0'; + signal mupix_ctrl : MupixSlowControl; + signal SLV_READ_IN : std_logic := '0'; + signal SLV_WRITE_IN : std_logic := '0'; + signal SLV_DATA_OUT : std_logic_vector(31 downto 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_ACK_OUT : std_logic; + signal SLV_NO_MORE_DATA_OUT : std_logic; + signal SLV_UNKNOWN_ADDR_OUT : std_logic; + + constant clk_period : time := 10 ns; + +begin + + dut : entity work.PixCtr + generic map( + fpga_clk_speed => 1e8, + spi_clk_speed => 5e7 + ) + port map( + clk => clk, + reset => reset, + sout_c_from_mupix => sout_c_from_mupix, + sout_d_from_mupix => sout_d_from_mupix, + mupix_ctrl => mupix_ctrl, + 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 + ); + + mupix : entity work.MupixShiftReg + generic map( + pixeldac_shift_length => 64, + chipdac_shift_length => 16 + ) + port map( + ck_c => mupix_ctrl.ck_c, + ck_d => mupix_ctrl.ck_d, + sin => mupix_ctrl.sin, + sout_c => sout_c_from_mupix, + sout_d => sout_d_from_mupix + ); + + clk_gen : process is + begin + clk <= '1'; + wait for clk_period/2; + clk <= '0'; + wait for clk_period/2; + end process clk_gen; + + stimulus_gen : process is + begin + wait for 100 ns; + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"004F0000",x"0083"); + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"BBBBBBBB",x"0080"); + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"AAAAAAAA",x"0080"); + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"CCCCCCCC",x"0080"); + wait; + end process stimulus_gen; + + +end architecture simulation; diff --git a/mupix/Mupix8/tb/TRBSimulation.vhd b/mupix/Mupix8/tb/TRBSimulation.vhd new file mode 100644 index 0000000..2e8dfce --- /dev/null +++ b/mupix/Mupix8/tb/TRBSimulation.vhd @@ -0,0 +1,66 @@ +------------------------------------------------------------ +--! @file +--! @brief Function and Procedures useful for TRB Simulation +--! @author Tobias Weber +--! @date August 2017 +------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package TRBSimulationPkg is + + procedure TRBRegisterWrite(signal SLV_Write : out std_logic; + signal SLV_Data : out std_logic_vector(31 downto 0); + signal SLV_Addr : out std_logic_vector(15 downto 0); + constant data : in std_logic_vector(31 downto 0); + constant addr : in std_logic_vector(15 downto 0); + constant clk_period : in time := 10 ns); + + procedure TRBRegisterRead(signal SLV_Read : out std_logic; + signal SLV_Data : out std_logic_vector(31 downto 0); + signal SLV_Addr : out std_logic_vector(15 downto 0); + constant data : in std_logic_vector(31 downto 0); + constant addr : in std_logic_vector(15 downto 0); + constant clk_period : in time := 10 ns); + +end package TRBSimulationPkg; + +package body TRBSimulationPkg is + + procedure TRBRegisterWrite(signal SLV_Write : out std_logic; + signal SLV_Data : out std_logic_vector(31 downto 0); + signal SLV_Addr : out std_logic_vector(15 downto 0); + constant data : in std_logic_vector(31 downto 0); + constant addr : in std_logic_vector(15 downto 0); + constant clk_period : in time := 10 ns) is + begin + SLV_Write <= '1'; + SLV_Data <= data; + SLV_Addr <= addr; + wait for clk_period; + SLV_Write <= '0'; + SLV_Data <= (others => '0'); + SLV_Addr <= (others => '0'); + wait for clk_period; + end TRBRegisterWrite; + + procedure TRBRegisterRead(signal SLV_Read : out std_logic; + signal SLV_Data : out std_logic_vector(31 downto 0); + signal SLV_Addr : out std_logic_vector(15 downto 0); + constant data : in std_logic_vector(31 downto 0); + constant addr : in std_logic_vector(15 downto 0); + constant clk_period : in time := 10 ns) is + begin + SLV_Read <= '1'; + SLV_Data <= data; + SLV_Addr <= addr; + wait for clk_period; + SLV_Read <= '0'; + SLV_Data <= (others => '0'); + SLV_Addr <= (others => '0'); + wait for clk_period; + end procedure TRBRegisterRead; + + +end TRBSimulationPkg; \ No newline at end of file diff --git a/mupix/Mupix8/trb3_periph.vhd b/mupix/Mupix8/trb3_periph.vhd new file mode 100644 index 0000000..ffe53db --- /dev/null +++ b/mupix/Mupix8/trb3_periph.vhd @@ -0,0 +1,691 @@ +------------------------------------------------------------------------------- +--trb3_periph for MuPix Version 8 +--Tobias Weber +--Ruhr Universitaet Bochum +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.trb3_components.all; +use work.version.all; + +library ecp3; +use ecp3.components.all; + + +entity trb3_periph is + port( + --Clocks + CLK_GPLL_RIGHT : in std_logic; --Clock Manager 2/(2468), 200 MHz <-- MAIN CLOCK for FPGA + CLK_GPLL_LEFT : in std_logic; --Clock Manager 1/(2468), 125 MHz + CLK_PCLK_LEFT : in std_logic; --Clock Fan-out, 200/400 MHz <-- For TDC. Same oscillator as GPLL left! + CLK_PCLK_RIGHT : in std_logic; --Clock Fan-out, 200/400 MHz <-- For TDC. Same oscillator as GPLL right! + --Trigger + TRIGGER_LEFT : in std_logic; --left side trigger input from fan-out + TRIGGER_RIGHT : in std_logic; --right side trigger input from fan-out + --Serdes + CLK_SERDES_INT_LEFT : in std_logic; --Clock Manager 1/(1357), off, 125 MHz possible + CLK_SERDES_INT_RIGHT : in std_logic; --Clock Manager 2/(1357), 200 MHz, only in case of problems + SERDES_INT_TX : out std_logic_vector(3 downto 0); + SERDES_INT_RX : in std_logic_vector(3 downto 0); + SERDES_ADDON_TX : out std_logic_vector(11 downto 0); + SERDES_ADDON_RX : in std_logic_vector(11 downto 0); + --Inter-FPGA Communication + FPGA5_COMM : inout std_logic_vector(11 downto 0); + --Bit 0/1 input, serial link RX active + --Bit 2/3 output, serial link TX active + + --------------------------------------------------------------------------- + -- BEGIN SenorBoard MuPix + --------------------------------------------------------------------------- + led_line : out std_logic_vector(3 downto 0); --leds on TRB addon board + spare_line : in std_logic_vector(5 downto 0); --spare lines + --slow control signals + testpulse : out std_logic; --generate injection pulse + ctrl_din : out std_logic; --serial data to mupix + ctrl_clk1 : out std_logic; --slow control clk1 + ctrl_clk2 : out std_logic; --slow control clk2 + ctrl_ld : out std_logic; --slow control load latched data + ctrl_dout : in std_logic; --serial data from mupix + ctrl_rb : out std_logic; --slow control readback?? + spi_dout_adc : in std_logic; --adc serial data from board + spi_dout_dac : in std_logic; --dac serial data from board + spi_ld : out std_logic; --serial data load + spi_clk : out std_logic; --serial clock + spi_din : out std_logic; --serial data out + spi_ld_tmp_dac : out std_logic; --load temperature dac ?? + spi_ld_adc : out std_logic; --load adc ?? + dac4_dout : in std_logic; --serial data in from dac 4?? + --slow data signals + hitbus : in std_logic; --hitbus signal + hit : in std_logic; --hit signal (replacement for priout?) + ldcol : out std_logic; --load column + rdcol : out std_logic; --read column + pull_down : out std_logic; --pull down + ldpix : out std_logic; --load pixel + --fast data signals + clkref : out std_logic; --reference clock + clkext : out std_logic; --external clock (difference to first one?) + syncres : out std_logic; --sync something + trigger : in std_logic; --external trigger + --fast data comes in via serdes addon (see above) + + --------------------------------------------------------------------------- + -- END SensorBoard MuPix + --------------------------------------------------------------------------- + not_connected : out std_logic_vector(25 downto 0); + + --Flash ROM & Reboot + FLASH_CLK : out std_logic; + FLASH_CS : out std_logic; + FLASH_DIN : out std_logic; + FLASH_DOUT : in std_logic; + PROGRAMN : out std_logic; --reboot FPGA + --Misc + TEMPSENS : inout std_logic; --Temperature Sensor + CODE_LINE : in std_logic_vector(1 downto 0); + LED_GREEN : out std_logic; + LED_ORANGE : out std_logic; + LED_RED : out std_logic; + LED_YELLOW : out std_logic; + SUPPL : in std_logic; --terminated diff pair, PCLK, Pads + --Test Connectors + TEST_LINE : out std_logic_vector(15 downto 0) + ); + + attribute syn_useioff : boolean; + --no IO-FF for LEDs relaxes timing constraints + attribute syn_useioff of LED_GREEN : signal is false; + attribute syn_useioff of LED_ORANGE : signal is false; + attribute syn_useioff of LED_RED : signal is false; + attribute syn_useioff of LED_YELLOW : signal is false; + attribute syn_useioff of TEMPSENS : signal is false; + attribute syn_useioff of PROGRAMN : signal is false; + attribute syn_useioff of CODE_LINE : signal is false; + attribute syn_useioff of TRIGGER_LEFT : signal is false; + attribute syn_useioff of TRIGGER_RIGHT : signal is false; + --important signals + attribute syn_useioff of FLASH_CLK : signal is true; + attribute syn_useioff of FLASH_CS : signal is true; + attribute syn_useioff of FLASH_DIN : signal is true; + attribute syn_useioff of FLASH_DOUT : signal is true; + attribute syn_useioff of FPGA5_COMM : signal is true; + attribute syn_useioff of TEST_LINE : signal is true; + --attribute syn_useioff of INP : signal is false; + --attribute syn_useioff of DAC_SDO : signal is true; + --attribute syn_useioff of DAC_SDI : signal is true; + --attribute syn_useioff of DAC_SCK : signal is true; + --attribute syn_useioff of DAC_CS : signal is true; + + +end entity; + + +architecture trb3_periph_arch of trb3_periph is + --Constants + constant REGIO_NUM_STAT_REGS : integer := 5; + constant REGIO_NUM_CTRL_REGS : integer := 3; + constant NumberFEECards : integer := 1; + + attribute syn_keep : boolean; + attribute syn_preserve : boolean; + + --Clock / Reset + signal clk_100_i : std_logic; --clock for main logic, 100 MHz, via Clock Manager and internal PLL + signal clk_200_i : std_logic; --clock for logic at 200 MHz, via Clock Manager and bypassed PLL + signal pll_lock : std_logic; --Internal PLL locked. E.g. used to reset all internal logic. + signal clear_i : std_logic; + signal reset_i : std_logic; + signal GSR_N : std_logic; + attribute syn_keep of GSR_N : signal is true; + attribute syn_preserve of GSR_N : signal is true; + + --Media Interface + signal med_stat_op : std_logic_vector (1*16-1 downto 0); + signal med_ctrl_op : std_logic_vector (1*16-1 downto 0); + signal med_stat_debug : std_logic_vector (1*64-1 downto 0); + signal med_ctrl_debug : std_logic_vector (1*64-1 downto 0); + signal med_data_out : std_logic_vector (1*16-1 downto 0); + signal med_packet_num_out : std_logic_vector (1*3-1 downto 0); + signal med_dataready_out : std_logic; + signal med_read_out : std_logic; + signal med_data_in : std_logic_vector (1*16-1 downto 0); + signal med_packet_num_in : std_logic_vector (1*3-1 downto 0); + signal med_dataready_in : std_logic; + signal med_read_in : std_logic; + + --LVL1 channel + signal timing_trg_received_i : std_logic; + signal trg_data_valid_i : std_logic; + signal trg_timing_valid_i : std_logic; + signal trg_notiming_valid_i : std_logic; + signal trg_invalid_i : std_logic; + signal trg_type_i : std_logic_vector(3 downto 0); + signal trg_number_i : std_logic_vector(15 downto 0); + signal trg_code_i : std_logic_vector(7 downto 0); + signal trg_information_i : std_logic_vector(23 downto 0); + signal trg_int_number_i : std_logic_vector(15 downto 0); + signal trg_multiple_trg_i : std_logic; + signal trg_timeout_detected_i : std_logic; + signal trg_spurious_trg_i : std_logic; + signal trg_missing_tmg_trg_i : std_logic; + signal trg_spike_detected_i : std_logic; + + --Data channel + signal fee_trg_release_i : std_logic_vector(NumberFEECards-1 downto 0); + signal fee_trg_statusbits_i : std_logic_vector(NumberFEECards*32-1 downto 0); + signal fee_data_i : std_logic_vector(NumberFEECards*32-1 downto 0); + signal fee_data_write_i : std_logic_vector(NumberFEECards-1 downto 0); + signal fee_data_finished_i : std_logic_vector(NumberFEECards-1 downto 0); + signal fee_almost_full_i : std_logic_vector(NumberFEECards-1 downto 0); + + --Slow Control channel + signal common_stat_reg : std_logic_vector(std_COMSTATREG*32-1 downto 0); + signal common_ctrl_reg : std_logic_vector(std_COMCTRLREG*32-1 downto 0); + signal stat_reg : std_logic_vector(32*2**REGIO_NUM_STAT_REGS-1 downto 0); + signal ctrl_reg : std_logic_vector(32*2**REGIO_NUM_CTRL_REGS-1 downto 0); + signal common_stat_reg_strobe : std_logic_vector(std_COMSTATREG-1 downto 0); + signal common_ctrl_reg_strobe : std_logic_vector(std_COMCTRLREG-1 downto 0); + signal stat_reg_strobe : std_logic_vector(2**REGIO_NUM_STAT_REGS-1 downto 0); + signal ctrl_reg_strobe : std_logic_vector(2**REGIO_NUM_CTRL_REGS-1 downto 0); + + --RegIO + signal my_address : std_logic_vector (15 downto 0); + signal regio_addr_out : std_logic_vector (15 downto 0); + signal regio_read_enable_out : std_logic; + signal regio_write_enable_out : std_logic; + signal regio_data_out : std_logic_vector (31 downto 0); + signal regio_data_in : std_logic_vector (31 downto 0); + signal regio_dataready_in : std_logic; + signal regio_no_more_data_in : std_logic; + signal regio_write_ack_in : std_logic; + signal regio_unknown_addr_in : std_logic; + signal regio_timeout_out : std_logic; + + --Timer + signal global_time : std_logic_vector(31 downto 0); + signal local_time : std_logic_vector(7 downto 0); + signal time_since_last_trg : std_logic_vector(31 downto 0); + signal timer_ticks : std_logic_vector(1 downto 0); + + --Flash + signal spictrl_read_en : std_logic; + signal spictrl_write_en : std_logic; + signal spictrl_data_in : std_logic_vector(31 downto 0); + signal spictrl_addr : std_logic; + signal spictrl_data_out : std_logic_vector(31 downto 0); + signal spictrl_ack : std_logic; + signal spictrl_busy : std_logic; + signal spimem_read_en : std_logic; + signal spimem_write_en : std_logic; + signal spimem_data_in : std_logic_vector(31 downto 0); + signal spimem_addr : std_logic_vector(5 downto 0); + signal spimem_data_out : std_logic_vector(31 downto 0); + signal spimem_ack : std_logic; + signal spidac_read_en : std_logic; + signal spidac_write_en : std_logic; + signal spidac_data_in : std_logic_vector(31 downto 0); + signal spidac_addr : std_logic_vector(4 downto 0); + signal spidac_data_out : std_logic_vector(31 downto 0); + signal spidac_ack : std_logic; + signal spidac_busy : std_logic; + + signal dac_cs_i : std_logic_vector(3 downto 0); + signal dac_sck_i : std_logic; + signal dac_sdi_i : std_logic; + + signal spi_bram_addr : std_logic_vector(7 downto 0); + signal spi_bram_wr_d : std_logic_vector(7 downto 0); + signal spi_bram_rd_d : std_logic_vector(7 downto 0); + signal spi_bram_we : std_logic; + + --FPGA Test + signal time_counter : unsigned(31 downto 0); + + -- MuPix Regio Bus + signal mu_regio_addr_in_0 : std_logic_vector (15 downto 0); + signal mu_regio_data_in_0 : std_logic_vector (31 downto 0); + signal mu_regio_data_out_0 : std_logic_vector (31 downto 0); + signal mu_regio_read_enable_in_0 : std_logic; + signal mu_regio_write_enable_in_0 : std_logic; + signal mu_regio_timeout_in_0 : std_logic; + signal mu_regio_dataready_out_0 : std_logic; + signal mu_regio_write_ack_out_0 : std_logic; + signal mu_regio_no_more_data_out_0 : std_logic; + signal mu_regio_unknown_addr_out_0 : std_logic; + + --common reset signals for mupix frontends + signal reset_timestamps_i : std_logic; + signal reset_eventcounters_i : std_logic; + signal resethandler_regio_addr_in_0 : std_logic_vector (15 downto 0); + signal resethandler_regio_data_in_0 : std_logic_vector (31 downto 0); + signal resethandler_regio_data_out_0 : std_logic_vector (31 downto 0); + signal resethandler_regio_read_enable_in_0 : std_logic; + signal resethandler_regio_write_enable_in_0 : std_logic; + signal resethandler_regio_timeout_in_0 : std_logic; + signal resethandler_regio_ack_out_0 : std_logic; + signal resethandler_regio_no_more_data_out_0 : std_logic; + signal resethandler_regio_unknown_addr_out_0 : std_logic; + + +begin + + --tie not connected outputs to 0 + --not_connected(25 downto 18) <= (others => '0'); + --not_connected(16 downto 0) <= (others => '0'); +--------------------------------------------------------------------------- +-- Reset Generation +--------------------------------------------------------------------------- + + GSR_N <= pll_lock; + + THE_RESET_HANDLER : trb_net_reset_handler + generic map( + RESET_DELAY => x"FEEE" + ) + port map( + CLEAR_IN => '0', -- reset input (high active, async) + CLEAR_N_IN => '1', -- reset input (low active, async) + CLK_IN => clk_200_i, -- raw master clock, NOT from PLL/DLL! + SYSCLK_IN => clk_100_i, -- PLL/DLL remastered clock + PLL_LOCKED_IN => pll_lock, -- master PLL lock signal (async) + RESET_IN => '0', -- general reset signal (SYSCLK) + TRB_RESET_IN => med_stat_op(13), -- TRBnet reset signal (SYSCLK) + CLEAR_OUT => clear_i, -- async reset out, USE WITH CARE! + RESET_OUT => reset_i, -- synchronous reset out (SYSCLK) + DEBUG_OUT => open + ); + + +--------------------------------------------------------------------------- +-- Clock Handling +--------------------------------------------------------------------------- + THE_MAIN_PLL : pll_in200_out100 + port map( + CLK => CLK_GPLL_RIGHT, + RESET => '0', + CLKOP => clk_100_i, + CLKOK => clk_200_i, + LOCK => pll_lock + ); + + +--------------------------------------------------------------------------- +-- The TrbNet media interface (to other FPGA) +--------------------------------------------------------------------------- + THE_MEDIA_UPLINK : trb_net16_med_ecp3_sfp + generic map( + SERDES_NUM => 1, --number of serdes in quad + EXT_CLOCK => c_NO, --use internal clock + USE_200_MHZ => c_YES, --run on 200 MHz clock + USE_125_MHZ => c_NO, + USE_CTC => c_NO + ) + port map( + CLK => clk_200_i, + SYSCLK => clk_100_i, + RESET => reset_i, + CLEAR => clear_i, + CLK_EN => '1', + --Internal Connection + MED_DATA_IN => med_data_out, + MED_PACKET_NUM_IN => med_packet_num_out, + MED_DATAREADY_IN => med_dataready_out, + MED_READ_OUT => med_read_in, + MED_DATA_OUT => med_data_in, + MED_PACKET_NUM_OUT => med_packet_num_in, + MED_DATAREADY_OUT => med_dataready_in, + MED_READ_IN => med_read_out, + REFCLK2CORE_OUT => open, + --SFP Connection + SD_RXD_P_IN => SERDES_INT_RX(2), + SD_RXD_N_IN => SERDES_INT_RX(3), + SD_TXD_P_OUT => SERDES_INT_TX(2), + SD_TXD_N_OUT => SERDES_INT_TX(3), + SD_REFCLK_P_IN => open, + SD_REFCLK_N_IN => open, + SD_PRSNT_N_IN => FPGA5_COMM(0), + SD_LOS_IN => FPGA5_COMM(0), + SD_TXDIS_OUT => FPGA5_COMM(2), + -- Status and control port + STAT_OP => med_stat_op, + CTRL_OP => med_ctrl_op, + STAT_DEBUG => med_stat_debug, + CTRL_DEBUG => (others => '0') + ); + +--------------------------------------------------------------------------- +-- Endpoint +--------------------------------------------------------------------------- + THE_ENDPOINT : trb_net16_endpoint_hades_full_handler + generic map( + REGIO_NUM_STAT_REGS => REGIO_NUM_STAT_REGS, --4, --16 stat reg + REGIO_NUM_CTRL_REGS => REGIO_NUM_CTRL_REGS, --3, --8 cotrol reg + ADDRESS_MASK => x"FFFF", + BROADCAST_BITMASK => x"FF", + BROADCAST_SPECIAL_ADDR => x"48", + REGIO_COMPILE_TIME => std_logic_vector(to_unsigned(VERSION_NUMBER_TIME, 32)), + REGIO_HARDWARE_VERSION => x"9100_6000", + REGIO_INIT_ADDRESS => x"1100", + REGIO_USE_VAR_ENDPOINT_ID => c_YES, + CLOCK_FREQUENCY => 125, + TIMING_TRIGGER_RAW => c_YES, + --Configure data handler + DATA_INTERFACE_NUMBER => NumberFEECards, --number of FEE Cards + DATA_BUFFER_DEPTH => 13, --13 + DATA_BUFFER_WIDTH => 32, + DATA_BUFFER_FULL_THRESH => 2**13-800, --2**13-1024 + TRG_RELEASE_AFTER_DATA => c_YES, + HEADER_BUFFER_DEPTH => 9, + HEADER_BUFFER_FULL_THRESH => 2**9-16 + ) + port map( + CLK => clk_100_i, + RESET => reset_i, + CLK_EN => '1', + MED_DATAREADY_OUT => med_dataready_out, -- open, -- + MED_DATA_OUT => med_data_out, -- open, -- + MED_PACKET_NUM_OUT => med_packet_num_out, -- open, -- + MED_READ_IN => med_read_in, + MED_DATAREADY_IN => med_dataready_in, + MED_DATA_IN => med_data_in, + MED_PACKET_NUM_IN => med_packet_num_in, + MED_READ_OUT => med_read_out, -- open, -- + MED_STAT_OP_IN => med_stat_op, + MED_CTRL_OP_OUT => med_ctrl_op, + + --Timing trigger in + TRG_TIMING_TRG_RECEIVED_IN => timing_trg_received_i, + --LVL1 trigger to FEE + LVL1_TRG_DATA_VALID_OUT => trg_data_valid_i, + LVL1_VALID_TIMING_TRG_OUT => trg_timing_valid_i, + LVL1_VALID_NOTIMING_TRG_OUT => trg_notiming_valid_i, + LVL1_INVALID_TRG_OUT => trg_invalid_i, + + LVL1_TRG_TYPE_OUT => trg_type_i, + LVL1_TRG_NUMBER_OUT => trg_number_i, + LVL1_TRG_CODE_OUT => trg_code_i, + LVL1_TRG_INFORMATION_OUT => trg_information_i, + LVL1_INT_TRG_NUMBER_OUT => trg_int_number_i, + + --Information about trigger handler errors + TRG_MULTIPLE_TRG_OUT => trg_multiple_trg_i, + TRG_TIMEOUT_DETECTED_OUT => trg_timeout_detected_i, + TRG_SPURIOUS_TRG_OUT => trg_spurious_trg_i, + TRG_MISSING_TMG_TRG_OUT => trg_missing_tmg_trg_i, + TRG_SPIKE_DETECTED_OUT => trg_spike_detected_i, + + --Response from FEE, i.e. MuPix + FEE_TRG_RELEASE_IN(0) => fee_trg_release_i(0), + FEE_TRG_STATUSBITS_IN(0*32+31 downto 0*32) => fee_trg_statusbits_i(0*32+31 downto 0*32), + FEE_DATA_IN(0*32+31 downto 0*32) => fee_data_i(0*32+31 downto 0*32), + FEE_DATA_WRITE_IN(0) => fee_data_write_i(0), + FEE_DATA_FINISHED_IN(0) => fee_data_finished_i(0), + FEE_DATA_ALMOST_FULL_OUT(0) => fee_almost_full_i(0), + + -- Slow Control Data Port + REGIO_COMMON_STAT_REG_IN => common_stat_reg, --0x00 + REGIO_COMMON_CTRL_REG_OUT => common_ctrl_reg, --0x20 + REGIO_COMMON_STAT_STROBE_OUT => common_stat_reg_strobe, + REGIO_COMMON_CTRL_STROBE_OUT => common_ctrl_reg_strobe, + REGIO_STAT_REG_IN => stat_reg, --start 0x80 + REGIO_CTRL_REG_OUT => ctrl_reg, --start 0xc0 + REGIO_STAT_STROBE_OUT => stat_reg_strobe, + REGIO_CTRL_STROBE_OUT => ctrl_reg_strobe, + REGIO_VAR_ENDPOINT_ID(1 downto 0) => CODE_LINE, + REGIO_VAR_ENDPOINT_ID(15 downto 2) => (others => '0'), + + BUS_ADDR_OUT => regio_addr_out, + BUS_READ_ENABLE_OUT => regio_read_enable_out, + BUS_WRITE_ENABLE_OUT => regio_write_enable_out, + BUS_DATA_OUT => regio_data_out, + BUS_DATA_IN => regio_data_in, + BUS_DATAREADY_IN => regio_dataready_in, + BUS_NO_MORE_DATA_IN => regio_no_more_data_in, + BUS_WRITE_ACK_IN => regio_write_ack_in, + BUS_UNKNOWN_ADDR_IN => regio_unknown_addr_in, + BUS_TIMEOUT_OUT => regio_timeout_out, + ONEWIRE_INOUT => TEMPSENS, + ONEWIRE_MONITOR_OUT => open, + + TIME_GLOBAL_OUT => global_time, + TIME_LOCAL_OUT => local_time, + TIME_SINCE_LAST_TRG_OUT => time_since_last_trg, + TIME_TICKS_OUT => timer_ticks, + + STAT_DEBUG_IPU => open, + STAT_DEBUG_1 => open, + STAT_DEBUG_2 => open, + STAT_DEBUG_DATA_HANDLER_OUT => open, + STAT_DEBUG_IPU_HANDLER_OUT => open, + STAT_TRIGGER_OUT => open, + CTRL_MPLEX => (others => '0'), + IOBUF_CTRL_GEN => (others => '0'), + STAT_ONEWIRE => open, + STAT_ADDR_DEBUG => open, + DEBUG_LVL1_HANDLER_OUT => open + ); + + timing_trg_received_i <= TRIGGER_LEFT; + +--------------------------------------------------------------------------- +-- AddOn +--------------------------------------------------------------------------- + +--------------------------------------------------------------------------- +-- Bus Handler +--------------------------------------------------------------------------- + THE_BUS_HANDLER : trb_net16_regio_bus_handler + generic map( + PORT_NUMBER => 4, + PORT_ADDRESSES => (0 => x"d000", + 1 => x"d100", + 2 => x"8000", --Mupix 0 + 3 => x"c000", --Reset + others => x"0000"), + PORT_ADDR_MASK => (0 => 1, + 1 => 6, + 2 => 12, + 3 => 12, + others => 0) + ) + port map( + CLK => clk_100_i, + RESET => reset_i, + + DAT_ADDR_IN => regio_addr_out, + DAT_DATA_IN => regio_data_out, + DAT_DATA_OUT => regio_data_in, + DAT_READ_ENABLE_IN => regio_read_enable_out, + DAT_WRITE_ENABLE_IN => regio_write_enable_out, + DAT_TIMEOUT_IN => regio_timeout_out, + DAT_DATAREADY_OUT => regio_dataready_in, + DAT_WRITE_ACK_OUT => regio_write_ack_in, + DAT_NO_MORE_DATA_OUT => regio_no_more_data_in, + DAT_UNKNOWN_ADDR_OUT => regio_unknown_addr_in, + + --Bus Handler (SPI CTRL) + BUS_READ_ENABLE_OUT(0) => spictrl_read_en, + BUS_WRITE_ENABLE_OUT(0) => spictrl_write_en, + BUS_DATA_OUT(0*32+31 downto 0*32) => spictrl_data_in, + BUS_ADDR_OUT(0*16) => spictrl_addr, + BUS_ADDR_OUT(0*16+15 downto 0*16+1) => open, + BUS_TIMEOUT_OUT(0) => open, + BUS_DATA_IN(0*32+31 downto 0*32) => spictrl_data_out, + BUS_DATAREADY_IN(0) => spictrl_ack, + BUS_WRITE_ACK_IN(0) => spictrl_ack, + BUS_NO_MORE_DATA_IN(0) => spictrl_busy, + BUS_UNKNOWN_ADDR_IN(0) => '0', + + --Bus Handler (SPI Memory) + BUS_READ_ENABLE_OUT(1) => spimem_read_en, + BUS_WRITE_ENABLE_OUT(1) => spimem_write_en, + BUS_DATA_OUT(1*32+31 downto 1*32) => spimem_data_in, + BUS_ADDR_OUT(1*16+5 downto 1*16) => spimem_addr, + BUS_ADDR_OUT(1*16+15 downto 1*16+6) => open, + BUS_TIMEOUT_OUT(1) => open, + BUS_DATA_IN(1*32+31 downto 1*32) => spimem_data_out, + BUS_DATAREADY_IN(1) => spimem_ack, + BUS_WRITE_ACK_IN(1) => spimem_ack, + BUS_NO_MORE_DATA_IN(1) => '0', + BUS_UNKNOWN_ADDR_IN(1) => '0', + + --Bus Handler (MuPix trb_net16_regio_bus_handler) + BUS_READ_ENABLE_OUT(2) => mu_regio_read_enable_in_0, + BUS_WRITE_ENABLE_OUT(2) => mu_regio_write_enable_in_0, + BUS_DATA_OUT(2*32+31 downto 2*32) => mu_regio_data_in_0, + BUS_ADDR_OUT(2*16+11 downto 2*16) => mu_regio_addr_in_0(11 downto 0), + BUS_ADDR_OUT(2*16+15 downto 2*16+12) => open, + BUS_TIMEOUT_OUT(2) => open, + BUS_DATA_IN(2*32+31 downto 2*32) => mu_regio_data_out_0, + BUS_DATAREADY_IN(2) => mu_regio_dataready_out_0, + BUS_WRITE_ACK_IN(2) => mu_regio_write_ack_out_0, + BUS_NO_MORE_DATA_IN(2) => mu_regio_no_more_data_out_0, + BUS_UNKNOWN_ADDR_IN(2) => mu_regio_unknown_addr_out_0, + + --Common Reset + BUS_READ_ENABLE_OUT(3) => resethandler_regio_read_enable_in_0, + BUS_WRITE_ENABLE_OUT(3) => resethandler_regio_write_enable_in_0, + BUS_DATA_OUT(3*32+31 downto 3*32) => resethandler_regio_data_in_0, + BUS_ADDR_OUT(3*16+11 downto 3*16) => resethandler_regio_addr_in_0(11 downto 0), + BUS_ADDR_OUT(3*16+15 downto 3*16+12) => open, + BUS_TIMEOUT_OUT(3) => open, + BUS_DATA_IN(3*32+31 downto 3*32) => resethandler_regio_data_out_0, + BUS_DATAREADY_IN(3) => resethandler_regio_ack_out_0, + BUS_WRITE_ACK_IN(3) => resethandler_regio_ack_out_0, + BUS_NO_MORE_DATA_IN(3) => resethandler_regio_no_more_data_out_0, + BUS_UNKNOWN_ADDR_IN(3) => resethandler_regio_unknown_addr_out_0, + + STAT_DEBUG => open + ); + +--------------------------------------------------------------------------- +-- SPI / Flash +--------------------------------------------------------------------------- + THE_SPI_MASTER : spi_master + port map( + CLK_IN => clk_100_i, + RESET_IN => reset_i, + -- Slave bus + BUS_READ_IN => spictrl_read_en, + BUS_WRITE_IN => spictrl_write_en, + BUS_BUSY_OUT => spictrl_busy, + BUS_ACK_OUT => spictrl_ack, + BUS_ADDR_IN(0) => spictrl_addr, + BUS_DATA_IN => spictrl_data_in, + BUS_DATA_OUT => spictrl_data_out, + -- SPI connections + SPI_CS_OUT => FLASH_CS, + SPI_SDI_IN => FLASH_DOUT, + SPI_SDO_OUT => FLASH_DIN, + SPI_SCK_OUT => FLASH_CLK, + -- BRAM for read/write data + BRAM_A_OUT => spi_bram_addr, + BRAM_WR_D_IN => spi_bram_wr_d, + BRAM_RD_D_OUT => spi_bram_rd_d, + BRAM_WE_OUT => spi_bram_we, + -- Status lines + STAT => open + ); + + -- data memory for SPI accesses + THE_SPI_MEMORY : spi_databus_memory + port map( + CLK_IN => clk_100_i, + RESET_IN => reset_i, + -- Slave bus + BUS_ADDR_IN => spimem_addr, + BUS_READ_IN => spimem_read_en, + BUS_WRITE_IN => spimem_write_en, + BUS_ACK_OUT => spimem_ack, + BUS_DATA_IN => spimem_data_in, + BUS_DATA_OUT => spimem_data_out, + -- state machine connections + BRAM_ADDR_IN => spi_bram_addr, + BRAM_WR_D_OUT => spi_bram_wr_d, + BRAM_RD_D_IN => spi_bram_rd_d, + BRAM_WE_IN => spi_bram_we, + -- Status lines + STAT => open + ); + +--------------------------------------------------------------------------- +-- Reboot FPGA +--------------------------------------------------------------------------- + THE_FPGA_REBOOT : fpga_reboot + port map( + CLK => clk_100_i, + RESET => reset_i, + DO_REBOOT => common_ctrl_reg(15), + PROGRAMN => PROGRAMN + ); + +--------------------------------------------------------------------------- +-- LED +--------------------------------------------------------------------------- + LED_GREEN <= not med_stat_op(9); + LED_ORANGE <= not med_stat_op(10); + LED_RED <= timing_trg_received_i; + LED_YELLOW <= not med_stat_op(11); + +----------------------------------------------------------------------------- +-- MuPix Frontend-Board +----------------------------------------------------------------------------- + MuPix3_Board_0 : MuPix3_Board + port map ( + clk => clk_100_i, + fast_clk => clk_200_i, + reset => reset_i, + + timestampreset_in => reset_timestamps_i, + eventcounterreset_in => reset_eventcounters_i, + + TIMING_TRG_IN => TRIGGER_RIGHT, + LVL1_TRG_DATA_VALID_IN => trg_data_valid_i, + LVL1_VALID_TIMING_TRG_IN => trg_timing_valid_i, + LVL1_VALID_NOTIMING_TRG_IN => trg_notiming_valid_i, + LVL1_INVALID_TRG_IN => trg_invalid_i, + LVL1_TRG_TYPE_IN => trg_type_i, + LVL1_TRG_NUMBER_IN => trg_number_i, + LVL1_TRG_CODE_IN => trg_code_i, + LVL1_TRG_INFORMATION_IN => trg_information_i, + LVL1_INT_TRG_NUMBER_IN => trg_int_number_i, + + FEE_TRG_RELEASE_OUT => fee_trg_release_i(0), + FEE_TRG_STATUSBITS_OUT => fee_trg_statusbits_i(0*32+31 downto 0*32), + FEE_DATA_OUT => fee_data_i(0*32+31 downto 0*32), + FEE_DATA_WRITE_OUT => fee_data_write_i(0), + FEE_DATA_FINISHED_OUT => fee_data_finished_i(0), + FEE_DATA_ALMOST_FULL_IN => fee_almost_full_i(0), + + REGIO_ADDR_IN => mu_regio_addr_in_0, + REGIO_DATA_IN => mu_regio_data_in_0, + REGIO_DATA_OUT => mu_regio_data_out_0, + REGIO_READ_ENABLE_IN => mu_regio_read_enable_in_0, + REGIO_WRITE_ENABLE_IN => mu_regio_write_enable_in_0, + REGIO_TIMEOUT_IN => mu_regio_timeout_in_0, + REGIO_DATAREADY_OUT => mu_regio_dataready_out_0, + REGIO_WRITE_ACK_OUT => mu_regio_write_ack_out_0, + REGIO_NO_MORE_DATA_OUT => mu_regio_no_more_data_out_0, + REGIO_UNKNOWN_ADDR_OUT => mu_regio_unknown_addr_out_0); + + resethandler_1 : entity work.resethandler + port map ( + CLK_IN => clk_100_i, + RESET_IN => reset_i, + TimestampReset_OUT => reset_timestamps_i, + EventCounterReset_OUT => reset_eventcounters_i, + SLV_READ_IN => resethandler_regio_read_enable_in_0, + SLV_WRITE_IN => resethandler_regio_write_enable_in_0, + SLV_DATA_OUT => resethandler_regio_data_out_0, + SLV_DATA_IN => resethandler_regio_data_in_0, + SLV_ADDR_IN => resethandler_regio_addr_in_0, + SLV_ACK_OUT => resethandler_regio_ack_out_0, + SLV_NO_MORE_DATA_OUT => resethandler_regio_no_more_data_out_0, + SLV_UNKNOWN_ADDR_OUT => resethandler_regio_unknown_addr_out_0); + +end architecture; -- 2.43.0