use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
+use work.StdTypes.all;
+
entity PixelControl is
generic(
fpga_clk_speed : integer := 1e8;
port (
clk : in std_logic; --clock
reset : in std_logic; --reset
- --mupix control
- ctrl_din : out std_logic; --serial data to mupix
- ctrl_clk1 : out std_logic; --slow control clock 1
- ctrl_clk2 : out std_logic; --slow control clock 2
- ctrl_load : out std_logic; --slow control load
- ctrl_dout : in std_logic; --serial data from mupix
+ mupixslctrl : out MupixSlowControl;
+ ctrl_dout : in std_logic; --serial data from mupix
--TRB slow control
SLV_READ_IN : in std_logic;
SLV_WRITE_IN : in std_logic;
architecture Behavioral of PixelControl is
- constant fifo_word_width : integer := 32;
+ 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 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
+ 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
CLK : in std_logic;
RST : in std_logic;
WriteEn : in std_logic;
- DataIn : in std_logic_vector(fifo_word_width - 1 downto 0);
+ DataIn : in std_logic_vector(c_fifo_word_width - 1 downto 0);
ReadEn : in std_logic;
- DataOut : out std_logic_vector(fifo_word_width - 1 downto 0);
+ DataOut : out std_logic_vector(c_fifo_word_width - 1 downto 0);
Empty : out std_logic;
Full : out std_logic
);
end component CRC;
signal WriteEn : std_logic;
- signal DataIn : std_logic_vector (fifo_word_width - 1 downto 0);
+ signal DataIn : std_logic_vector (c_fifo_word_width - 1 downto 0);
signal ReadEn : std_logic;
- signal DataOut : std_logic_vector (fifo_word_width - 1 downto 0);
+ signal DataOut : std_logic_vector (c_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;
+ 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 config_fsm_type is (idle, config, readfifo, waitfifo, load);
- signal config_fsm : config_fsm_type := idle;
+ 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 : std_logic;
+ 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 : std_logic;
+ signal reset_crc_from_mupix, reset_crc_from_mupix_ext : std_logic;
--control signals to mupix
- signal mupix_ctrl_i, mupix_ctrl_reg : MupixSlowControl := MuPixSlowControlInit;
+ 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 => fifo_word_width,
+ DATA_WIDTH => c_fifo_word_width,
FIFO_DEPTH => 32
)
port map(
Full => Full
);
- --TODO: CRC checking logic
crc_in : entity work.CRC
generic map(detect_enable_edge => true)
port map(
crc_out => crc_out_crc_to_mupix
);
- reset_crc_to_mupix <= reset or controlConfig(2);
+ reset_crc_to_mupix <= reset or reset_crc_to_mupix_ext;
crc_out : entity work.CRC
generic map(detect_enable_edge => true)
crc_out => crc_out_crc_from_mupix
);
- reset_crc_from_mupix <= reset or controlConfig(3);
-
- spi_clk_div_proc : process (clk) is
- begin
- if rising_edge(clk) then
- if reset = '1' then
- clk_enable <= '0';
- clk_div_counter <= clk_div_max;
- else
- if clk_div_counter = 0 then
- clk_div_counter <= clk_div_max;
- clk_enable <= '1';
- else
- clk_div_counter <= clk_div_counter - 1;
- clk_enable <= '0';
- end if;
- end if;
- end if;
- end process spi_clk_div_proc;
+ reset_crc_from_mupix <= reset or reset_crc_from_mupix_ext;
- sendpixbit_proc : process (clk) is
+ sendpix_bits : 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;
+ send_bits_fsm <= idle;
+ mupix_ctrl_i.clk1 <= '0';
+ mupix_ctrl_i.clk2 <= '0';
+ mupix_ctrl_i.sin <= '0';
+ sending <= '0';
else
- if clk_enable = '1' then
- mupix_ctrl_i.ck_c <= '0';
- mupix_ctrl_i.ck_d <= '0';
- mupix_ctrl_i.sin <= '0';
- enable_crc_to_mupix <= '0';
- enable_crc_from_mupix <= '0';
- data_in_crc_from_mupix <= '0';
- data_in_crc_to_mupix <= '0';
- case bit_send_fsm is
- when idle =>
- bitcouner_word <= fifo_word_width - 1;
- if start_send = '1' then
- bit_send_fsm <= sendbit1;
- sending <= '1';
- else
- bit_send_fsm <= idle;
- sending <= '0';
- end if;
- when sendbit1 =>
- mupix_ctrl_i.sin <= DataOut(bitcouner_word);
- sending <= '1';
- bit_send_fsm <= sendbit2;
- when sendbit2 => --rising clock edge
- mupix_ctrl_i.sin <= DataOut(bitcouner_word);
- if controlConfig(0) = '1' then
- mupix_ctrl_i.ck_d <= '1';
- else
- mupix_ctrl_i.ck_c <= '1';
- end if;
- enable_crc_to_mupix <= '1';
- data_in_crc_to_mupix <= DataOut(bitcouner_word);
- bit_send_fsm <= sendbit3;
- sending <= '1';
- when sendbit3 =>
- sending <= '1';
- mupix_ctrl_i.sin <= DataOut(bitcouner_word);
- enable_crc_from_mupix <= '1';
- if controlConfig(0) = '1' then
- data_in_crc_from_mupix <= sout_d_from_mupix;
- else
- data_in_crc_from_mupix <= sout_c_from_mupix;
- end if;
- bitcouner_word <= bitcouner_word - 1;
- bitcounter <= bitcounter + 1;
+ 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
- bit_send_fsm <= idle;
+ send_bits_fsm <= done;
else
- bit_send_fsm <= sendbit1;
+ send_bits_fsm <= sendbit1;
+ bitcouner_word <= bitcouner_word -1;
end if;
- end case;
- 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 sendpixbit_proc;
+ end process sendpix_bits;
+
- configure_proc : process (clk) is
+ 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;
+ mupix_ctrl_i.load <= '0';
+ config_fsm <= idle;
hold_load_counter := 0;
else
- mupix_ctrl_i.ld_c <= '0';
- ReadEn <= '0';
- start_send <= '0';
- case config_fsm is
+ 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
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
+ ReadEn <= '1';
start_send <= '1';
config_fsm <= waitfifo;
else
- start_send <= '0';
- config_fsm <= config;
+ 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
+ if bitcounter < bitstosend then -- everything send or read other fifo word
config_fsm <= readfifo;
else
- if controlConfig(1) = '0' then
- config_fsm <= load;
- else
- config_fsm <= idle;
- end if;
+ config_fsm <= load;
end if;
- end if;
- when load =>
+ end if;
+ when load => -- load from shift register
hold_load_counter := hold_load_counter + 1;
- mupix_ctrl_i.ld_c <= '1';
+ mupix_ctrl_i.load <= '1';
+ config_fsm <= load;
if hold_load_counter = 7 then
- mupix_ctrl_i.ld_c <= '0';
- config_fsm <= idle;
- else
- config_fsm <= load;
+ mupix_ctrl_i.load <= '0';
+ reset_bitcounter <= '1';
+ config_fsm <= idle;
end if;
end case;
end if;
--x0080: input to fifo (write)/current fifo output (read)
--x0081: current CRC check sum (read only)
--x0082: data fifo is full (read only)
- --x0083: configure bit 0: configure chip dacs/pixel dacs,
- -- bit 1: readback bit 32-16 number of config bits
- -- bit 2: reset outgoing CRC sum
- -- bit 3: reset incoming CRC sum
+ --x0083: configure
+ -- bit 0: sin
+ -- bit 1: clk1
+ -- bit 2: clk2
+ -- 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
-----------------------------------------------------------------------------
- SLV_BUS : process (clk)
- begin -- process SLV_BUS
- if rising_edge(clk) then
-
- SLV_DATA_OUT <= (others => '0');
- SLV_UNKNOWN_ADDR_OUT <= '0';
- SLV_NO_MORE_DATA_OUT <= '0';
- SLV_ACK_OUT <= '0';
- DataIn <= (others => '0');
- WriteEn <= '0';
- if SLV_WRITE_IN = '1' then
- case SLV_ADDR_IN is
- when x"0080" =>
- DataIn <= SLV_DATA_IN;
- WriteEn <= '1';
- SLV_ACK_OUT <= '1';
- when x"0083" =>
- controlConfig <= SLV_DATA_IN(15 downto 0);
- bitstosend <= unsigned(SLV_DATA_IN(31 downto 16));
- SLV_ACK_OUT <= '1';
- when others =>
- SLV_UNKNOWN_ADDR_OUT <= '1';
- end case;
-
- elsif SLV_READ_IN = '1' then
- case SLV_ADDR_IN is
- when x"0080" =>
- SLV_DATA_OUT <= DataOut;
- SLV_ACK_OUT <= '1';
- when x"0081" =>
- SLV_DATA_OUT(10 downto 0) <= crc_out_crc_from_mupix & crc_out_crc_to_mupix & crc_correct;
- SLV_ACK_OUT <= '1';
- when x"0082" =>
- SLV_DATA_OUT(1 downto 0) <= Empty & Full;
- SLV_ACK_OUT <= '1';
- when x"0083" =>
- SLV_DATA_OUT <= std_logic_vector(bitstosend) & controlConfig;
- SLV_ACK_OUT <= '1';
- when others =>
- SLV_UNKNOWN_ADDR_OUT <= '1';
- end case;
- end if;
- end if;
- end process SLV_BUS;
+ 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';
- crc_correct <= '1' when crc_out_crc_from_mupix = crc_out_crc_to_mupix else '0';
-
- output_pipe : process (clk) is
- begin
- if rising_edge(clk) then
- if reset = '1' then
- mupix_ctrl_reg <= MuPixSlowControlInit;
- else
- mupix_ctrl_reg <= mupix_ctrl_i;
- end if;
- end if;
- end process output_pipe;
-
- --matching to outputs
- mupix_ctrl <= mupix_ctrl_reg;
+ 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);
+ 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(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;
end Behavioral;