From: Tobias Weber Date: Thu, 31 Aug 2017 07:24:24 +0000 (+0200) Subject: Speed up slow control configuration of chip. X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=58d347708e1c69c19b428f8439dfbdfd6da30679;p=trb3.git Speed up slow control configuration of chip. --- diff --git a/mupix/config.vhd b/mupix/config.vhd new file mode 100644 index 0000000..1108620 --- /dev/null +++ b/mupix/config.vhd @@ -0,0 +1,91 @@ +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 diff --git a/mupix/sources/CRC.vhd b/mupix/sources/CRC.vhd new file mode 100644 index 0000000..9803375 --- /dev/null +++ b/mupix/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/sources/FIFO.vhd b/mupix/sources/FIFO.vhd new file mode 100644 index 0000000..2d286aa --- /dev/null +++ b/mupix/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/sources/FIFO_FWFT.vhd b/mupix/sources/FIFO_FWFT.vhd new file mode 100644 index 0000000..6f9d910 --- /dev/null +++ b/mupix/sources/FIFO_FWFT.vhd @@ -0,0 +1,68 @@ +------------------------------------------------------------ +--!@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; diff --git a/mupix/sources/FiFo.vhd b/mupix/sources/FiFo.vhd deleted file mode 100644 index a4b00a5..0000000 --- a/mupix/sources/FiFo.vhd +++ /dev/null @@ -1,80 +0,0 @@ ------------------------------------------------------------- ---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; diff --git a/mupix/sources/MuPix3_PixCtr.vhd b/mupix/sources/MuPix3_PixCtr.vhd index d1b6b80..119cc47 100644 --- a/mupix/sources/MuPix3_PixCtr.vhd +++ b/mupix/sources/MuPix3_PixCtr.vhd @@ -1,5 +1,5 @@ ------------------------------------------------------------------------------- ---Controll of MuPix DACs and Pixel Tune DACs +--Control of MuPix DACs and Pixel Tune DACs --T. Weber, Mainz Univesity ------------------------------------------------------------------------------- library IEEE; @@ -9,9 +9,13 @@ use IEEE.numeric_std.all; 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; @@ -26,50 +30,266 @@ entity PixCtr is 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 @@ -77,25 +297,19 @@ begin -- Behavioral 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; @@ -103,10 +317,16 @@ begin -- Behavioral 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'; @@ -114,7 +334,23 @@ begin -- Behavioral 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; diff --git a/mupix/sources/StdTypes.vhd b/mupix/sources/StdTypes.vhd index 1fddd75..a0914ca 100644 --- a/mupix/sources/StdTypes.vhd +++ b/mupix/sources/StdTypes.vhd @@ -31,5 +31,6 @@ package StdTypes is 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; diff --git a/mupix/tb/CRCTest.vhd b/mupix/tb/CRCTest.vhd new file mode 100644 index 0000000..46acdc1 --- /dev/null +++ b/mupix/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/tb/MupixShiftReg.vhd b/mupix/tb/MupixShiftReg.vhd new file mode 100644 index 0000000..687d67f --- /dev/null +++ b/mupix/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/tb/PixCtrlTest.vhd b/mupix/tb/PixCtrlTest.vhd new file mode 100644 index 0000000..798a27e --- /dev/null +++ b/mupix/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;