--- /dev/null
+library ieee;
+USE IEEE.std_logic_1164.ALL;
+use ieee.numeric_std.all;
+use work.trb_net_std.all;
+
+package config is
+
+
+------------------------------------------------------------------------------
+--Begin of design configuration
+------------------------------------------------------------------------------
+
+ constant USE_DUMMY_READOUT : integer := c_NO; --use slowcontrol for readout, no trigger logic
+
+--Run wih 125 MHz instead of 100 MHz
+ constant USE_125_MHZ : integer := c_NO; --not implemented yet!
+ constant USE_EXTERNALCLOCK : integer := c_NO; --not implemented yet!
+
+--Use sync mode, RX clock for all parts of the FPGA
+ constant USE_RXCLOCK : integer := c_NO; --not implemented yet!
+
+
+--Address settings
+ constant INIT_ADDRESS : std_logic_vector := x"F30a";
+ constant BROADCAST_SPECIAL_ADDR : std_logic_vector := x"4b";
+
+--ADC sampling frequency (only 40 MHz supported a.t.m.)
+ constant ADC_SAMPLING_RATE : integer := 40;
+
+--These are currently used for the included features table only
+ constant ADC_PROCESSING_TYPE : integer := 0;
+ constant ADC_BASELINE_LOGIC : integer := c_YES;
+ constant ADC_TRIGGER_LOGIC : integer := c_YES;
+ constant ADC_CHANNELS : integer := 48;
+
+------------------------------------------------------------------------------
+--End of design configuration
+------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+--Select settings by configuration
+------------------------------------------------------------------------------
+ type intlist_t is array(0 to 7) of integer;
+ type hw_info_t is array(0 to 7) of unsigned(31 downto 0);
+ constant HW_INFO_BASE : unsigned(31 downto 0) := x"91009000";
+
+ constant CLOCK_FREQUENCY_ARR : intlist_t := (100,125, others => 0);
+ constant MEDIA_FREQUENCY_ARR : intlist_t := (200,125, others => 0);
+
+ --declare constants, filled in body
+ constant HARDWARE_INFO : std_logic_vector(31 downto 0);
+ constant CLOCK_FREQUENCY : integer;
+ constant MEDIA_FREQUENCY : integer;
+ constant INCLUDED_FEATURES : std_logic_vector(63 downto 0);
+
+
+end;
+
+package body config is
+--compute correct configuration mode
+
+ constant HARDWARE_INFO : std_logic_vector(31 downto 0) := std_logic_vector(
+ HW_INFO_BASE );
+ constant CLOCK_FREQUENCY : integer := CLOCK_FREQUENCY_ARR(USE_125_MHZ);
+ constant MEDIA_FREQUENCY : integer := MEDIA_FREQUENCY_ARR(USE_125_MHZ);
+
+
+
+function generateIncludedFeatures return std_logic_vector is
+ variable t : std_logic_vector(63 downto 0);
+begin
+ t := (others => '0');
+ t(63 downto 56) := std_logic_vector(to_unsigned(4,8)); --table version 2
+ t(7 downto 0) := std_logic_vector(to_unsigned(ADC_SAMPLING_RATE,8));
+ t(11 downto 8) := std_logic_vector(to_unsigned(ADC_PROCESSING_TYPE,4)); --processing type
+ t(14 downto 14) := std_logic_vector(to_unsigned(ADC_BASELINE_LOGIC,1));
+ t(15 downto 15) := std_logic_vector(to_unsigned(ADC_TRIGGER_LOGIC,1));
+ t(23 downto 16) := std_logic_vector(to_unsigned(ADC_CHANNELS,8));
+ t(42 downto 42) := "1"; --std_logic_vector(to_unsigned(INCLUDE_SPI,1));
+ t(44 downto 44) := "0"; --std_logic_vector(to_unsigned(INCLUDE_STATISTICS,1));
+ t(51 downto 48) := x"0";--std_logic_vector(to_unsigned(INCLUDE_TRIGGER_LOGIC,4));
+ t(52 downto 52) := std_logic_vector(to_unsigned(USE_125_MHZ,1));
+ t(53 downto 53) := std_logic_vector(to_unsigned(USE_RXCLOCK,1));
+ t(54 downto 54) := std_logic_vector(to_unsigned(USE_EXTERNALCLOCK,1));
+ return t;
+end function;
+
+ constant INCLUDED_FEATURES : std_logic_vector(63 downto 0) := generateIncludedFeatures;
+
+end package body;
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--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
--- /dev/null
+-------------------------------------------------------------------------------
+--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;
--- /dev/null
+------------------------------------------------------------
+--!@brief Small implementation of a FIFO using shift register
+--!this implementation does not support seperate input and output clock
+--!and should be replaced with a FIFO from the manufacturer IP for production
+--!systems
+--!@author Tobias Weber
+--!@date March 2017
+------------------------------------------------------------
+library ieee;
+use ieee.numeric_std.all;
+use ieee.std_logic_1164.all;
+
+entity tiny_fifo is
+ generic(
+ fifo_depth : integer := 4; --! number words = fifo_depth**2
+ fifo_width : integer := 32); --! fifo data width
+ port(
+ clk_in : in std_logic;--! clock input
+ --fifo input channel
+ fifo_data_in : in std_logic_vector(fifo_width - 1 downto 0); --! fifo data input
+ fifo_valid_in : in std_logic; --! fifo input data is valid
+ fifo_ready_out : out std_logic; --! fifo is ready to accept data
+
+ --fifo output channel
+ fifo_data_out : out std_logic_vector(fifo_width - 1 downto 0); --! fifo data output
+ fifo_valid_out : out std_logic; --! fifo output data is valid
+ fifo_ready_in : in std_logic); --! fifo reader is ready for new word (pushes new word to fifo output0
+end entity;
+
+architecture behavior of tiny_fifo is
+
+ type memory_type is array((2**fifo_depth - 1) downto 0) of std_logic_vector(fifo_width - 1 downto 0);
+ signal fifo_memory : memory_type := (others => (others => '0'));
+ signal fifo_index : signed (fifo_depth downto 0) := to_signed(-1, fifo_depth + 1);
+ signal fifo_full : std_logic;
+ signal fifo_empty : std_logic;
+ signal fifo_in_enable : boolean;
+ signal fifo_out_enable : boolean;
+
+begin
+
+ fifo_full <= '1' when (fifo_index = 2**fifo_depth - 1) else '0';
+ fifo_empty <= '1' when (fifo_index = -1) else '0';
+
+ fifo_ready_out <= '1' when (fifo_full = '0') else '0';
+ fifo_valid_out <= '1' when (fifo_empty = '0') else '0';
+
+ fifo_in_enable <= (fifo_valid_in = '1') and (fifo_full = '0');
+ fifo_out_enable <= (fifo_ready_in = '1') and (fifo_empty = '0');
+
+ fifo_data_out <= fifo_memory(to_integer(unsigned(fifo_index(fifo_depth - 1 downto 0))));
+
+ fifo_proc : process(clk_in)
+ begin
+ if rising_edge(clk_in) then
+ if fifo_in_enable then
+ fifo_memory((2**fifo_depth - 1) downto 1) <= fifo_memory((2**fifo_depth - 2) downto 0);
+ fifo_memory(0) <= fifo_data_in;
+ if not fifo_out_enable then
+ fifo_index <= fifo_index + 1;
+ end if;
+ elsif fifo_out_enable then
+ fifo_index <= fifo_index - 1;
+ end if;
+ end if;
+ end process fifo_proc;
+
+end architecture;
+++ /dev/null
-------------------------------------------------------------
---VHDL description of very basic FIFO
---T.Weber, Mainz University
-------------------------------------------------------------
-
-library IEEE;
-use IEEE.STD_LOGIC_1164.all;
-use IEEE.NUMERIC_STD.all;
-
-entity fifo is
- generic(addr_wd : integer := 8;
- word_wd : integer := 8);
- port (Din : in std_logic_vector (word_wd - 1 downto 0);
- Wr : in std_logic;
- Dout : out std_logic_vector (word_wd - 1 downto 0);
- Rd : in std_logic;
- Empty : out std_logic;
- Full : out std_logic;
- WrCnt_o : out std_logic_vector(addr_wd - 1 downto 0);
- Reset : in std_logic;
- CLK : in std_logic
- );
-end fifo;
-
-
-architecture fifo_arch of fifo is
- -- decl
- signal wrcnt : unsigned (addr_wd-1 downto 0) := (others => '0');
- signal rdcnt : unsigned (addr_wd-1 downto 0) := (others => '0');
- signal din_int : unsigned (word_wd-1 downto 0) := (others => '0');
- type memory_type is array(0 to (2**addr_wd)-1) of unsigned(word_wd-1 downto 0);
- signal memory : memory_type;
- signal memory_address : unsigned(addr_wd-1 downto 0) := (others => '0');
-
- signal full_loc : std_logic;
- signal empty_loc : std_logic;
- signal write_int : std_logic;
-
-begin
-
- blockmemory: process(clk)
- begin
- if rising_edge(clk) then
- if (write_int = '1') then
- memory(to_integer(memory_address)) <= din_int;
- end if;
- dout <= std_logic_vector(memory(to_integer(memory_address)));
- end if;
- end process blockmemory;
-
- AddressMux: process (clk)
- begin -- process AddressMux
- if rising_edge(clk) then
- if Reset = '1' then
- rdcnt <= (others => '0');
- wrcnt <= (others => '0');
- else
- if Wr = '1' and full_loc = '0' then
- memory_address <= wrcnt;
- write_int <= '1';
- din_int <= unsigned(Din);
- wrcnt <= wrcnt + 1;
- elsif (Rd = '1' and empty_loc = '0') then
- memory_address <= rdcnt ;
- rdcnt <= rdcnt + 1;
- else
- write_int <= '0';
- memory_address <= (others => '0');
- end if;
- end if;
- end if;
- end process AddressMux;
-
- full_loc <= '1' when rdcnt = wrcnt+1 else '0';
- empty_loc <= '1' when rdcnt = wrcnt else '0';
- Full <= full_loc;
- Empty <= empty_loc;
- WrCnt_o <= std_logic_vector(wrcnt-rdcnt);
-
-end architecture fifo_arch;
-------------------------------------------------------------------------------
---Controll of MuPix DACs and Pixel Tune DACs
+--Control of MuPix DACs and Pixel Tune DACs
--T. Weber, Mainz Univesity
-------------------------------------------------------------------------------
library IEEE;
use work.StdTypes.all;
entity PixCtr is
-
+ 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;
end PixCtr;
architecture Behavioral of PixCtr is
-
-
- signal sout_from_mupix : std_logic_vector(31 downto 0);
- signal slowcontrol_reg_new : std_logic_vector(31 downto 0);
- signal slowcontrol_reg_old : std_logic_vector(31 downto 0);
- signal start_write_mupix : std_logic;
- signal done_write_mupix : std_logic;
- signal busy_write_mupix : std_logic := '0';
-
- type delay_type is (idle, delay1, done);
- signal delay_fsm : delay_type := idle;
+
+ 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_checksum_out, crc_checksum_in : std_logic_vector(4 downto 0) := (others => '0');
+ 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 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);
+
+ --control signals to mupix
+ signal mupix_ctrl_i, mupix_ctrl_reg : MupixSlowControl := MuPixSlowControlInit;
+
+
begin -- Behavioral
-
- Delay : process (clk)
- begin -- process Delay
- if rising_edge(clk) then
- done_write_mupix <= '0';
- case delay_fsm is
- when idle =>
- if start_write_mupix = '1' then
- delay_fsm <= delay1;
- end if;
- when delay1 =>
- delay_fsm <= done;
- when done =>
- done_write_mupix <= '1';
- sout_from_mupix <= sout_from_mupix(29 downto 0) & sout_c_from_mupix & sout_d_from_mupix;
- slowcontrol_reg_old <= slowcontrol_reg_new;
- delay_fsm <= idle;
- end case;
- end if;
- end process Delay;
-
- mupix_ctrl.sin <= slowcontrol_reg_old(0);
- mupix_ctrl.ck_c <= slowcontrol_reg_old(1);
- mupix_ctrl.ck_d <= slowcontrol_reg_old(2);
- mupix_ctrl.ld_c <= slowcontrol_reg_old(3);
-
+
+ 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,
+ enable => enable_crc_to_mupix,
+ data_in => data_in_crc_to_mupix,
+ crc_out => crc_out_crc_to_mupix
+ );
+
+ crc_out : entity work.CRC
+ generic map(detect_enable_edge => true)
+ port map(
+ clk => clk,
+ rst => reset,
+ enable => enable_crc_from_mupix,
+ data_in => data_in_crc_from_mupix,
+ crc_out => crc_out_crc_from_mupix
+ );
+
+ 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';
+ 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;
+ bit_send_fsm <= sendbit3;
+ sending <= '1';
+ when sendbit3 =>
+ sending <= '1';
+ mupix_ctrl_i.sin <= DataOut(bitcouner_word);
+ 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: Register for SlowControl
- --x0081: Output of MuPix SlowControl Pins
+ --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
-----------------------------------------------------------------------------
-
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';
- start_write_mupix <= '0';
-
-
- if busy_write_mupix = '1' then
- if done_write_mupix = '0'then
- busy_write_mupix <= '1';
- else
- busy_write_mupix <= '0';
- SLV_ACK_OUT <= '1';
- end if;
-
-
- elsif SLV_WRITE_IN = '1' then
+ SLV_ACK_OUT <= '0';
+ DataIn <= (others => '0');
+ WriteEn <= '0';
+ if SLV_WRITE_IN = '1' then
case SLV_ADDR_IN is
when x"0080" =>
- slowcontrol_reg_new <= SLV_DATA_IN;
- start_write_mupix <= '1';
- busy_write_mupix <= '1';
+ 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 <= slowcontrol_reg_old;
+ SLV_DATA_OUT <= DataOut;
SLV_ACK_OUT <= '1';
when x"0081" =>
- SLV_DATA_OUT <= sout_from_mupix;
+ SLV_DATA_OUT(10 downto 0) <= crc_checksum_in & crc_checksum_out & 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 if;
end if;
end process SLV_BUS;
+
+ crc_correct <= '1' when crc_checksum_out = crc_checksum_in 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;
sin : std_logic; --serial data in
end record MupixSlowControl;
+ constant MuPixSlowControlInit : MupixSlowControl := (ck_d => '0', ck_c => '0', ld_c => '0', sin => '0');
end package StdTypes;
--- /dev/null
+-------------------------------------------------------------------------------
+--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;
--- /dev/null
+------------------------------------------------------------
+--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;
+
--- /dev/null
+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;