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;
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;
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;