From: Tobias Weber Date: Tue, 10 Jul 2018 12:58:46 +0000 (+0200) Subject: readback of mupix 8 shift register. X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=b24d183c8381ad985478a3da560eca44fda65cf2;p=trb3.git readback of mupix 8 shift register. --- diff --git a/mupix/Mupix8/sources/PixelControl.vhd b/mupix/Mupix8/sources/PixelControl.vhd index 36db86c..47a21f9 100644 --- a/mupix/Mupix8/sources/PixelControl.vhd +++ b/mupix/Mupix8/sources/PixelControl.vhd @@ -10,14 +10,15 @@ use work.StdTypes.all; entity PixelControl is generic( - fpga_clk_speed : integer := 1e8; - spi_clk_speed : integer := 1e4 - ); + fpga_clk_speed : integer := 1e8; + spi_clk_speed : integer := 1e4; + config_bits : integer := 8096 + ); port ( - clk : in std_logic; --clock - reset : in std_logic; --reset + clk : in std_logic; --clock + reset : in std_logic; --reset mupixslctrl : out MupixSlowControl; - ctrl_dout : in std_logic; --serial data from mupix + ctrl_dout : in std_logic; --serial data from mupix --TRB slow control SLV_READ_IN : in std_logic; SLV_WRITE_IN : in std_logic; @@ -30,352 +31,450 @@ entity PixelControl is end PixelControl; architecture Behavioral of PixelControl is - - constant c_fifo_word_width : integer := 32; - constant c_clk_div_max : integer := fpga_clk_speed/spi_clk_speed - 1; - signal clk_div_cnt : integer range 0 to c_clk_div_max - 1 := 0; - - 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 c_fifo_word_width - 1 := c_fifo_word_width - 1; --index to current bit in word from fifo - - --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(c_fifo_word_width - 1 downto 0); - ReadEn : in std_logic; - DataOut : out std_logic_vector(c_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 (c_fifo_word_width - 1 downto 0); - signal ReadEn : std_logic; - signal DataOut : std_logic_vector (c_fifo_word_width - 1 downto 0); - signal Empty : std_logic; - signal Full : std_logic; - - --send single configuration bit - signal start_send, sending : std_logic; - signal reset_bitcounter : std_logic; - type t_send_bits_fsm is (idle, sendbit1, sendbit2, done); - signal send_bits_fsm : t_send_bits_fsm := idle; - - - --configuration state machine - type t_config_fsm is (idle, config, readfifo, waitfifo, load); - signal config_fsm : t_config_fsm := 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, reset_crc_to_mupix_ext: 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, reset_crc_from_mupix_ext : std_logic; - - --control signals to mupix - signal mupix_ctrcl_select : std_logic; - signal mupix_ctrl_i, mupix_ctrl_ext, mupix_ctrl_sel, mupix_ctrl_reg : MupixSlowControl := c_mupix_slctrl_init; - - + + constant c_fifo_word_width : integer := 32; + constant c_clk_div_max : integer := fpga_clk_speed/spi_clk_speed - 1; + signal clk_div_cnt : integer range 0 to c_clk_div_max - 1 := 0; + + 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 c_fifo_word_width - 1 := c_fifo_word_width - 1; --index to current bit in word from fifo + + --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(c_fifo_word_width - 1 downto 0); + ReadEn : in std_logic; + DataOut : out std_logic_vector(c_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; + + component BlockMemory is + generic ( + DataWidth : integer; + AddressWidth : integer); + port ( + clk : in std_logic; + reset : 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 BlockMemory; + + signal WriteEn : std_logic; + signal DataIn : std_logic_vector (c_fifo_word_width - 1 downto 0); + signal ReadEn : std_logic; + signal DataOut : std_logic_vector (c_fifo_word_width - 1 downto 0); + signal Empty : std_logic; + signal Full : std_logic; + + --send single configuration bit + signal start_send, sending : std_logic; + signal reset_bitcounter : std_logic; + type t_send_bits_fsm is (idle, sendbit1, sendbit2, done); + signal send_bits_fsm : t_send_bits_fsm := idle; + + + --configuration state machine + type t_config_fsm is (idle, config, readfifo, waitfifo, load); + signal config_fsm : t_config_fsm := idle; + + --readback of configuration data + constant c_config_words_max : integer := config_bits/32 + 1; + constant c_ram_address_width : integer := f_log2(c_config_words_max); + signal data_from_mupix_i : std_logic := '0'; + signal readback_wr_addr, readback_rd_addr : std_logic_vector(c_ram_address_width - 1 downto 0) := (others => '0'); + signal readback_wr_addr_new : std_logic_vector(c_ram_address_width - 1 downto 0) := (others => '0'); + signal readback_data_in, readback_data_out : std_logic_vector(31 downto 0) := (others => '0'); + signal readback_mem_wren_i : std_logic := '0'; + signal reset_readback_i : std_logic := '0'; + signal readback_cnt_i : integer range 0 to 32 := 0; + signal readback_shift_reg : std_logic_vector(31 downto 0) := (others => '0'); + signal mupix_clk1_edge : std_logic_vector(1 downto 0) := (others => '0'); + signal mupix_load_edge : std_logic_vector(1 downto 0) := (others => '0'); + + + --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, reset_crc_to_mupix_ext : std_logic; + signal enable_crc_from_mupix : std_logic; + signal crc_out_crc_from_mupix : std_logic_vector(4 downto 0); + signal reset_crc_from_mupix, reset_crc_from_mupix_ext : std_logic; + + --control signals to mupix + signal mupix_ctrcl_select : std_logic; + signal mupix_ctrl_i, mupix_ctrl_ext, mupix_ctrl_sel, mupix_ctrl_reg : MupixSlowControl := c_mupix_slctrl_init; + + begin -- Behavioral - - fifo_1 : entity work.STD_FIFO - generic map( - DATA_WIDTH => c_fifo_word_width, - FIFO_DEPTH => 32 - ) - port map( - CLK => CLK, - RST => reset, - WriteEn => WriteEn, - DataIn => DataIn, - ReadEn => ReadEn, - DataOut => DataOut, - Empty => Empty, - Full => Full - ); - - 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 reset_crc_to_mupix_ext; - - 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 reset_crc_from_mupix_ext; - - - sendpix_bits : process(clk) is - begin - if rising_edge(clk) then - if reset = '1' then - send_bits_fsm <= idle; - mupix_ctrl_i.clk1 <= '0'; - mupix_ctrl_i.clk2 <= '0'; - mupix_ctrl_i.sin <= '0'; - sending <= '0'; - else - case send_bits_fsm is - when idle => - bitcouner_word <= 31; - sending <= '0'; - clk_div_cnt <= 0; - send_bits_fsm <= idle; - mupix_ctrl_i.clk1 <= '0'; - mupix_ctrl_i.clk2 <= '0'; - mupix_ctrl_i.sin <= '0'; - if start_send = '1' then - sending <= '1'; - send_bits_fsm <= sendbit1; - end if; - if reset_bitcounter = '1' then - bitcounter <= (others => '0'); - end if; - when sendbit1 => - clk_div_cnt <= clk_div_cnt + 1; - send_bits_fsm <= sendbit1; - mupix_ctrl_i.sin <= DataOut(bitcouner_word); - enable_crc_from_mupix <= '0'; - enable_crc_to_mupix <= '0'; - data_in_crc_from_mupix <= '0'; - data_in_crc_to_mupix <= ctrl_dout; - if clk_div_cnt = (c_clk_div_max - 1)/2 then - send_bits_fsm <= sendbit2; - mupix_ctrl_i.clk1 <= '1'; -- clocking - mupix_ctrl_i.clk2 <= '0'; - data_in_crc_from_mupix <= ctrl_dout; --CRC checksum - data_in_crc_to_mupix <= DataOut(bitcouner_word); - enable_crc_from_mupix <= '1'; - enable_crc_to_mupix <= '1'; - bitcounter <= bitcounter + 1; - end if; - when sendbit2 => - clk_div_cnt <= clk_div_cnt + 1; - send_bits_fsm <= sendbit2; - if clk_div_cnt = c_clk_div_max - 1 then - mupix_ctrl_i.clk1 <= '0'; - mupix_ctrl_i.clk2 <= '1'; - clk_div_cnt <= 0; - if bitcouner_word = 0 or bitcounter = bitstosend then - send_bits_fsm <= done; - else - send_bits_fsm <= sendbit1; - bitcouner_word <= bitcouner_word -1; - end if; - end if; - when done => -- - clk_div_cnt <= clk_div_cnt + 1; - send_bits_fsm <= done; - if clk_div_cnt = (c_clk_div_max - 1)/2 then - send_bits_fsm <= idle; -- just hold clk2 high long enough before going back to idle - end if; - end case; - end if; - end if; - end process sendpix_bits; - - - - 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.load <= '0'; - config_fsm <= idle; - hold_load_counter := 0; - else - mupix_ctrl_i.load <= '0'; - ReadEn <= '0'; - start_send <= '0'; - reset_bitcounter <= '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'; - start_send <= '1'; - config_fsm <= waitfifo; - else - ReadEn <= '0'; - config_fsm <= readfifo; -- wait on next config word in fifo - end if; - when waitfifo => -- wait for fifo word to be valid - config_fsm <= config; - when config => - if sending = '1' then - config_fsm <= config; - else - if bitcounter < bitstosend then -- everything send or read other fifo word - config_fsm <= readfifo; - else - config_fsm <= load; - end if; - end if; - when load => -- load from shift register - hold_load_counter := hold_load_counter + 1; - mupix_ctrl_i.load <= '1'; - config_fsm <= load; - if hold_load_counter = 7 then - mupix_ctrl_i.load <= '0'; - reset_bitcounter <= '1'; - config_fsm <= idle; - end if; - end case; - end if; - end if; - end process configure_proc; - - + + fifo_1 : entity work.STD_FIFO + generic map( + DATA_WIDTH => c_fifo_word_width, + FIFO_DEPTH => 32 + ) + port map( + CLK => CLK, + RST => reset, + WriteEn => WriteEn, + DataIn => DataIn, + ReadEn => ReadEn, + DataOut => DataOut, + Empty => Empty, + Full => Full + ); + + crc_in : entity work.CRC + generic map(detect_enable_edge => false) + 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 reset_crc_to_mupix_ext; + + crc_out : entity work.CRC + generic map(detect_enable_edge => false) + port map( + clk => clk, + rst => reset_crc_from_mupix, + enable => enable_crc_from_mupix, + data_in => data_from_mupix_i, + crc_out => crc_out_crc_from_mupix + ); + + reset_crc_from_mupix <= reset or reset_crc_from_mupix_ext; + + BlockMemory_1 : entity work.BlockMemory + generic map ( + DataWidth => 32, + AddressWidth => c_ram_address_width) + port map ( + clk => clk, + reset => reset, + WrEn => readback_mem_wren_i, + WrAddr => readback_wr_addr, + Din => readback_data_in, + ReAddr => readback_rd_addr, + Dout => readback_data_out); + + + -- purpose: readback of configuration from dout of mupix and storing in bram + readback_proc : process (clk) is + begin -- process readback_proc + if rising_edge(clk) then -- rising clock edge + if reset = '1' or reset_readback_i = '1' then + mupix_clk1_edge <= (others => '0'); + mupix_load_edge <= (others => '0'); + readback_cnt_i <= 0; + readback_wr_addr <= (others => '0'); + readback_data_in <= (others => '0'); + readback_mem_wren_i <= '0'; + readback_shift_reg <= (others => '0'); + enable_crc_from_mupix <= '0'; + enable_crc_to_mupix <= '0'; + data_from_mupix_i <= '0'; + data_in_crc_to_mupix <= '0'; + readback_wr_addr_new <= (others => '0'); + else + enable_crc_from_mupix <= '0'; + enable_crc_to_mupix <= '0'; + data_from_mupix_i <= '0'; + data_in_crc_to_mupix <= '0'; + readback_mem_wren_i <= '0'; + mupix_clk1_edge <= mupix_clk1_edge(0) & mupix_ctrl_reg.clk1; + mupix_load_edge <= mupix_load_edge(0) & mupix_ctrl_reg.load; + if mupix_clk1_edge = "01" then -- use rising edge of clk1 as sampling point for mupix_dout and crc sums + readback_shift_reg <= readback_shift_reg(30 downto 0) & ctrl_dout; + readback_cnt_i <= readback_cnt_i + 1; + data_from_mupix_i <= ctrl_dout; --CRC checksum + enable_crc_from_mupix <= '1'; + data_in_crc_to_mupix <= mupix_ctrl_reg.sin; + enable_crc_to_mupix <= '1'; + readback_wr_addr <= readback_wr_addr_new; + end if; + if readback_cnt_i = 32 or mupix_load_edge = "01" then + readback_cnt_i <= 0; + readback_mem_wren_i <= '1'; + readback_data_in <= readback_shift_reg; + if to_integer(unsigned(readback_wr_addr_new)) < c_config_words_max - 1 then + readback_wr_addr_new <= std_logic_vector(unsigned(readback_wr_addr_new) + 1); + else + readback_wr_addr_new <= (others => '0'); + end if; + end if; + end if; + end if; + end process readback_proc; + + + sendpix_bits : process(clk) is + begin + if rising_edge(clk) then + if reset = '1' then + send_bits_fsm <= idle; + mupix_ctrl_i.clk1 <= '0'; + mupix_ctrl_i.clk2 <= '0'; + mupix_ctrl_i.sin <= '0'; + sending <= '0'; + else + case send_bits_fsm is + when idle => + bitcouner_word <= 31; + sending <= '0'; + clk_div_cnt <= 0; + send_bits_fsm <= idle; + mupix_ctrl_i.clk1 <= '0'; + mupix_ctrl_i.clk2 <= '0'; + mupix_ctrl_i.sin <= '0'; + if start_send = '1' then + sending <= '1'; + send_bits_fsm <= sendbit1; + end if; + if reset_bitcounter = '1' then + bitcounter <= (others => '0'); + end if; + when sendbit1 => + clk_div_cnt <= clk_div_cnt + 1; + send_bits_fsm <= sendbit1; + mupix_ctrl_i.sin <= DataOut(bitcouner_word); + if clk_div_cnt = (c_clk_div_max - 1)/2 then + send_bits_fsm <= sendbit2; + mupix_ctrl_i.clk1 <= '1'; -- clocking + mupix_ctrl_i.clk2 <= '0'; + bitcounter <= bitcounter + 1; + end if; + when sendbit2 => + clk_div_cnt <= clk_div_cnt + 1; + send_bits_fsm <= sendbit2; + if clk_div_cnt = c_clk_div_max - 1 then + mupix_ctrl_i.clk1 <= '0'; + mupix_ctrl_i.clk2 <= '1'; + clk_div_cnt <= 0; + if bitcouner_word = 0 or bitcounter = bitstosend then + send_bits_fsm <= done; + else + send_bits_fsm <= sendbit1; + bitcouner_word <= bitcouner_word -1; + end if; + end if; + when done => -- + clk_div_cnt <= clk_div_cnt + 1; + send_bits_fsm <= done; + if clk_div_cnt = (c_clk_div_max - 1)/2 then + send_bits_fsm <= idle; -- just hold clk2 high long enough before going back to idle + end if; + end case; + end if; + end if; + end process sendpix_bits; + + + + 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.load <= '0'; + config_fsm <= idle; + hold_load_counter := 0; + else + mupix_ctrl_i.load <= '0'; + ReadEn <= '0'; + start_send <= '0'; + reset_bitcounter <= '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'; + start_send <= '1'; + config_fsm <= waitfifo; + else + ReadEn <= '0'; + config_fsm <= readfifo; -- wait on next config word in fifo + end if; + when waitfifo => -- wait for fifo word to be valid + config_fsm <= config; + when config => + if sending = '1' then + config_fsm <= config; + else + if bitcounter < bitstosend then -- everything send or read other fifo word + config_fsm <= readfifo; + else + config_fsm <= load; + end if; + end if; + when load => -- load from shift register + hold_load_counter := hold_load_counter + 1; + mupix_ctrl_i.load <= '1'; + config_fsm <= load; + if hold_load_counter = 7 then + mupix_ctrl_i.load <= '0'; + reset_bitcounter <= '1'; + config_fsm <= idle; + 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: sin + -- bit 0: sin -- bit 1: clk1 -- bit 2: clk2 - -- bit 3: load - -- bit 4: select FPGA programming or software programming + -- bit 3: load + -- bit 4: select FPGA programming or software programming -- bit 5: reset outgoing CRC sum -- bit 6: reset incoming CRC sum -- bit 31-16: number of total bits for configuration + --x0084: reset readback process + --x0085: set readback address/data from readback memory ----------------------------------------------------------------------------- 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'; - reset_crc_to_mupix_ext <= '0'; - reset_crc_from_mupix_ext <= '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" => - mupix_ctrl_ext.sin <= SLV_DATA_IN(0); - mupix_ctrl_ext.clk1 <= SLV_DATA_IN(1); - mupix_ctrl_ext.clk2 <= SLV_DATA_IN(2); - mupix_ctrl_ext.load <= SLV_DATA_IN(3); - mupix_ctrcl_select <= SLV_DATA_IN(4); - reset_crc_to_mupix_ext <= SLV_DATA_IN(5); - reset_crc_from_mupix_ext <= SLV_DATA_IN(6); - mupix_ctrl_ext.rb <= SLV_DATA_IN(7); - 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(0) <= mupix_ctrl_ext.sin; - SLV_DATA_OUT(1) <= mupix_ctrl_ext.clk1; - SLV_DATA_OUT(2) <= mupix_ctrl_ext.clk2; - SLV_DATA_OUT(3) <= mupix_ctrl_ext.load; - SLV_DATA_OUT(4) <= mupix_ctrcl_select; - SLV_DATA_OUT(5) <= reset_crc_to_mupix_ext; - SLV_DATA_OUT(6) <= reset_crc_from_mupix_ext; - SLV_DATA_OUT(7) <= mupix_ctrl_ext.rb; - SLV_DATA_OUT(31 downto 16) <= std_logic_vector(bitstosend); - 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'; - - slow_control_mux : process(mupix_ctrcl_select, mupix_ctrl_ext, mupix_ctrl_i) is - begin - if mupix_ctrcl_select = '1' then - mupix_ctrl_sel <= mupix_ctrl_ext; - else - mupix_ctrl_sel <= mupix_ctrl_i; - end if; - end process slow_control_mux; - - output_pipe : process(clk) is - begin - if rising_edge(clk) then - if reset = '1' then - mupix_ctrl_reg <= c_mupix_slctrl_init; - else - mupix_ctrl_reg <= mupix_ctrl_sel; - end if; - end if; - end process output_pipe; - - --matching to outputs - mupixslctrl <= mupix_ctrl_reg; + 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'; + reset_crc_to_mupix_ext <= '0'; + reset_crc_from_mupix_ext <= '0'; + reset_readback_i <= '0'; + slv_data_out <= (others => '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" => + mupix_ctrl_ext.sin <= SLV_DATA_IN(0); + mupix_ctrl_ext.clk1 <= SLV_DATA_IN(1); + mupix_ctrl_ext.clk2 <= SLV_DATA_IN(2); + mupix_ctrl_ext.load <= SLV_DATA_IN(3); + mupix_ctrcl_select <= SLV_DATA_IN(4); + reset_crc_to_mupix_ext <= SLV_DATA_IN(5); + reset_crc_from_mupix_ext <= SLV_DATA_IN(6); + mupix_ctrl_ext.rb <= SLV_DATA_IN(7); + bitstosend <= unsigned(SLV_DATA_IN(31 downto 16)); + SLV_ACK_OUT <= '1'; + when x"0084" => + slv_ack_out <= '1'; + reset_readback_i <= '1'; + when x"0085" => + slv_ack_out <= '1'; + if to_integer(unsigned(slv_data_in)) < c_config_words_max then + readback_rd_addr <= slv_data_in(c_ram_address_width - 1 downto 0); + else + readback_rd_addr <= (others => '0'); + end if; + 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(0) <= mupix_ctrl_ext.sin; + SLV_DATA_OUT(1) <= mupix_ctrl_ext.clk1; + SLV_DATA_OUT(2) <= mupix_ctrl_ext.clk2; + SLV_DATA_OUT(3) <= mupix_ctrl_ext.load; + SLV_DATA_OUT(4) <= mupix_ctrcl_select; + SLV_DATA_OUT(5) <= reset_crc_to_mupix_ext; + SLV_DATA_OUT(6) <= reset_crc_from_mupix_ext; + SLV_DATA_OUT(7) <= mupix_ctrl_ext.rb; + SLV_DATA_OUT(31 downto 16) <= std_logic_vector(bitstosend); + SLV_ACK_OUT <= '1'; + when x"0085" => + slv_ack_out <= '1'; + slv_data_out <= readback_data_out; + 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'; + + slow_control_mux : process(mupix_ctrcl_select, mupix_ctrl_ext, mupix_ctrl_i) is + begin + if mupix_ctrcl_select = '1' then + mupix_ctrl_sel <= mupix_ctrl_ext; + else + mupix_ctrl_sel <= mupix_ctrl_i; + end if; + end process slow_control_mux; + + output_pipe : process(clk) is + begin + if rising_edge(clk) then + if reset = '1' then + mupix_ctrl_reg <= c_mupix_slctrl_init; + else + mupix_ctrl_reg <= mupix_ctrl_sel; + end if; + end if; + end process output_pipe; + + --matching to outputs + mupixslctrl <= mupix_ctrl_reg; end Behavioral; diff --git a/mupix/Mupix8/tb/PixCtrlTest.vhd b/mupix/Mupix8/tb/PixCtrlTest.vhd index d97f944..825f7dc 100644 --- a/mupix/Mupix8/tb/PixCtrlTest.vhd +++ b/mupix/Mupix8/tb/PixCtrlTest.vhd @@ -10,121 +10,199 @@ entity PixCtrlTest is end entity PixCtrlTest; architecture simulation of PixCtrlTest is - - component PixelControl - generic( - fpga_clk_speed : integer := 1e8; - spi_clk_speed : integer := 1e4 - ); - port( - clk : in std_logic; --clock - reset : in std_logic; --reset - mupixslctrl : out MupixSlowControl; - ctrl_dout : in std_logic; --serial data from mupix - 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; - - component MupixShiftReg - generic( - pixeldac_shift_length : integer := 64 - ); - port( - clk1 : in std_logic; - clk2 : in std_logic; - sin : in std_logic; - sout : out std_logic); - end component MupixShiftReg; - - signal clk : std_logic; - signal reset : std_logic := '0'; - signal sout : 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; - constant c_shiftregister_length : integer := 80; - constant c_time_per_word : time := 32*clk_period*1e8/1e7; - + + component PixelControl + generic( + fpga_clk_speed : integer := 1e8; + spi_clk_speed : integer := 1e4; + config_bits : integer := 3200 + ); + port( + clk : in std_logic; --clock + reset : in std_logic; --reset + mupixslctrl : out MupixSlowControl; + ctrl_dout : in std_logic; --serial data from mupix + 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; + + component MupixShiftReg + generic( + pixeldac_shift_length : integer := 64 + ); + port( + clk1 : in std_logic; + clk2 : in std_logic; + sin : in std_logic; + sout : out std_logic); + end component MupixShiftReg; + + signal clk : std_logic; + signal reset : std_logic := '0'; + signal sout : 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; + constant c_shiftregister_length : integer := 80; + constant c_time_per_word : time := 32*clk_period*1e8/1e7; + constant c_testdata : std_logic_vector(c_shiftregister_length - 1 downto 0) := x"AAAAAAAABBBBBBBBCCCC"; + + -- send load signal to mupix using external slow control + procedure MupixLoad( + signal slv_write_in : out std_logic; + signal slv_data_in : out std_logic_vector(31 downto 0); + signal slv_addr_in : out std_logic_vector(15 downto 0); + constant clk_period : in time := 10 ns) is + begin + TRBRegisterWrite(slv_write_in, slv_data_in, slv_addr_in, x"00000018", x"0083"); + wait for 5*clk_period; + TRBRegisterWrite(slv_write_in, slv_data_in, slv_addr_in, x"00000000", x"0083"); + end procedure MupixLoad; + + -- reset of crc checksums and readback + procedure MupixReset ( + signal slv_write_in : out std_logic; + signal slv_data_in : out std_logic_vector(31 downto 0); + signal slv_addr_in : out std_logic_vector(15 downto 0); + constant clk_period : in time := 10 ns) is + begin + TRBRegisterWrite(slv_write_in, slv_data_in, slv_addr_in, x"0000000f", x"0084"); + TRBRegisterWrite(slv_write_in, slv_data_in, slv_addr_in, x"00000060", x"0083"); + end procedure MupixReset; + + -- purpose: write bit to mupix 8 + procedure WriteMupixSlow ( + signal slv_write_in : out std_logic; + signal slv_data_in : out std_logic_vector(31 downto 0); + signal slv_addr_in : out std_logic_vector(15 downto 0); + constant sin : in std_logic; + constant clk_period : in time := 10 ns) is + begin -- procedure WriteMupixSlow + slv_write_in <= '1'; + slv_addr_in <= x"0083"; + slv_data_in(4 downto 0) <= "1000" & sin; + wait for clk_period; + slv_write_in <= '0'; + wait for 100 ns; + slv_write_in <= '1'; + slv_addr_in <= x"0083"; + slv_data_in(4 downto 0) <= "1001" & sin; + wait for clk_period; + slv_write_in <= '0'; + wait for 100 ns; + slv_write_in <= '1'; + slv_addr_in <= x"0083"; + slv_data_in(4 downto 0) <= "1010" & sin; + wait for clk_period; + slv_write_in <= '0'; + wait for 100 ns; + slv_write_in <= '1'; + slv_addr_in <= x"0083"; + slv_data_in(4 downto 0) <= "1000" & "0"; + wait for clk_period; + slv_write_in <= '0'; + slv_data_in <= (others => '0'); + slv_addr_in <= (others => '0'); + wait for clk_period; + end procedure WriteMupixSlow; + begin - - dut : entity work.PixelControl - generic map( - fpga_clk_speed => 1e8, - spi_clk_speed => 1e7 - ) - port map( - clk => clk, - reset => reset, - ctrl_dout => sout, - mupixslctrl => 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 => c_shiftregister_length - ) - port map( - clk1 => mupix_ctrl.clk1, - clk2 => mupix_ctrl.clk2, - sin => mupix_ctrl.sin, - sout => sout - ); - - 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; - --test control through trb slow control --- TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000011",x"0083"); --- TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000013",x"0083"); --- TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000014",x"0083"); --- TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000000",x"0083"); - --test programming with data from FIFO via FPGA state machine - TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, std_logic_vector(to_unsigned(c_shiftregister_length, 16)) & x"0000", x"0083"); - 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"BBBBBBBB",x"0080"); - wait for 3*c_time_per_word; - TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"CCCC0000",x"0080"); - --test of crc checksum computation - wait for 1.5*c_time_per_word; - TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, std_logic_vector(to_unsigned(c_shiftregister_length, 16)) & x"0060", x"0083"); - TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, std_logic_vector(to_unsigned(c_shiftregister_length, 16)) & x"0000", x"0083"); - 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"BBBBBBBB",x"0080"); - TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"CCCC0000",x"0080"); - - wait; - end process stimulus_gen; - - + + dut : entity work.PixelControl + generic map( + fpga_clk_speed => 1e8, + spi_clk_speed => 1e7, + config_bits => 80 + ) + port map( + clk => clk, + reset => reset, + ctrl_dout => sout, + mupixslctrl => 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 => c_shiftregister_length + ) + port map( + clk1 => mupix_ctrl.clk1, + clk2 => mupix_ctrl.clk2, + sin => mupix_ctrl.sin, + sout => sout + ); + + 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; + --test control through trb slow control + --first pass + for i in c_shiftregister_length - 1 downto 0 loop + WriteMupixSlow(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, c_testdata(i)); + end loop; + MupixLoad(slv_write_in, slv_data_in, slv_addr_in); + wait for 100 ns; + MupixReset(slv_write_in, slv_data_in, slv_addr_in); + wait for 1 us; + --second pass to test checksum and readback + for i in c_shiftregister_length - 1 downto 0 loop + WriteMupixSlow(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, c_testdata(i)); + end loop; -- send load and reset the readback + MupixLoad(slv_write_in, slv_data_in, slv_addr_in); + wait for 100 ns; + MupixReset(slv_write_in, slv_data_in, slv_addr_in); + wait for 1 us; + --read from readback memeory + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000002", x"0085"); + TRBRegisterRead(SLV_READ_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000000", x"0085"); + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"00000005", x"0085"); + --test programming with data from FIFO via FPGA state machine + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, std_logic_vector(to_unsigned(c_shiftregister_length, 16)) & x"0000", x"0083"); + 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"BBBBBBBB", x"0080"); + wait for 3*c_time_per_word; + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"CCCC0000", x"0080"); + --test of crc checksum computation + wait for 1.5*c_time_per_word; + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, std_logic_vector(to_unsigned(c_shiftregister_length, 16)) & x"0060", x"0083"); + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, std_logic_vector(to_unsigned(c_shiftregister_length, 16)) & x"0000", x"0083"); + 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"BBBBBBBB", x"0080"); + TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"CCCC0000", x"0080"); + + wait; + end process stimulus_gen; + + end architecture simulation;