---------------------------------------------------------------------------------- -- Institute: DESY -- Engineer: Ozgur Sahin -- Create Date: 11:31:17 01/21/2014 -- Design Name: -- Module Name: buffer_ngccm_com - Behavioral -- Project Name: -- Target Devices: ngCCM -- Tool versions: -- Description: --This module generates wb packets (ipbus) and send commands to ngCCM_gbt module. -- Dependencies: -- -- Revision: -- Revision 0.01 - Moved from ngFEC_module -- Revision 0.50 - Protocol btw i2c and FE modules (described in Specification of ngCCM - CCMServer Communication) is implemented. -- Revision 0.51 - Small fix to accomodate redundant path (described in Specification of ngCCM - CCMServer Communication) is implemented. (FC) -- Additional Comments: -- needs to be tested (especially the fringe cases) ---------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.ALL; --use work.ipbus.all; use work.ngFEC_pack.all; use IEEE.numeric_std.all; Library UNISIM; use UNISIM.vcomponents.all; entity buffer_ngccm_com is port( ipb_clk_i : in std_logic; ipb_reset_i : in std_logic; ngccm_addr : out std_logic_vector (BRAM_WORD_SIZE downto 0); ngccm_din : out std_logic_vector (31 downto 0); ngccm_wr : out std_logic_vector (0 downto 0); ngccm_dout : in std_logic_vector (31 downto 0); input_size : in std_logic_vector (31 downto 0); status_reg : out std_logic_vector (31 downto 0); ngccm_state : in state; ngccm_miso : in ipb_rbus; ngccm_mosi : out ipb_wbus; output_size : out std_logic_vector (31 downto 0); partition : in std_logic_vector (4 downto 0) ); end buffer_ngccm_com; architecture Behavioral of buffer_ngccm_com is signal data_length : unsigned(10 downto 0); signal data_address : unsigned(BRAM_WORD_SIZE downto 0); signal ngccm_addr_i : unsigned(BRAM_WORD_SIZE downto 0); signal ngccm_aout : unsigned(BRAM_WORD_SIZE downto 0); signal ngccm_wr_i : std_logic_vector(0 downto 0); signal ngccm_address : std_logic_vector(31 downto 0); signal error : std_logic := '0'; -- variable moved to signal type status is (write_s, response_s, idle_s, repeat_s, wait_s); type command_type is (cr_txr, sr_rxr, prer, sleep_c,fast_c); begin ngccm_addr <= std_logic_vector(ngccm_addr_i); ngccm_wr <= ngccm_wr_i; data_pro_test:process (ipb_clk_i,ipb_reset_i) variable response_length : unsigned(10 downto 0) := (others=>'0'); variable w_address : unsigned(BRAM_WORD_SIZE downto 0) := (others=>'0'); variable timeout_cyc : integer; variable sleep_cyc : integer := 0; variable fe_status : status; variable server_c : command_type; variable w_tobram : std_logic := '0'; variable data_r : std_logic_vector(7 downto 0) := (others=>'0'); variable SR : std_logic_vector(7 downto 0) := (others=>'0'); variable status_mask : std_logic_vector(7 downto 0) := (others=>'0'); variable status_rep : std_logic_vector(7 downto 0) := (others=>'0'); begin if(ipb_reset_i = '1') then data_length <= (others=>'0'); response_length := (others=>'0'); w_address := x"4E2"; data_address <= (others=> '0'); ngccm_aout <= (others=> '0'); ngccm_address <= word0; timeout_cyc := 1000; sleep_cyc := 0; error <= '0'; w_toBRAM := '0'; data_r := (others=>'0'); SR := (others=>'0'); status_rep := (others=>'0'); status_reg <= word1; output_size <= (others=>'0'); ngccm_wr_i <= "0"; ngccm_addr_i <= (others=>'0'); ngccm_din <= (others=>'0'); ngccm_mosi <= init_ipb_wbus; elsif rising_edge(ipb_clk_i) then if(ngccm_wr_i = "0")then ngccm_aout <= ngccm_addr_i; end if; if ngccm_state= refresh_s then data_length <= (others=>'0'); data_address <= x"000"; w_address := x"4E2"; sleep_cyc := 0; w_toBRAM := '0'; response_length := (others=>'0'); output_size <= (others=>'0'); SR := (others=>'0'); status_rep := (others=>'0'); status_mask := (others=>'0'); status_reg <= word1; fe_status := idle_s; ngccm_mosi.ipb_strobe<= '0'; elsif ngccm_state= process_s then status_reg <= word0; sleep_cyc := sleep_cyc - 1; if unsigned(input_size(12 downto 2)) > data_length and sleep_cyc < 1 then ngccm_addr_i <= data_address; ngccm_wr_i <= "0"; if (ngccm_aout = data_address) then w_tobram := ngccm_dout(24); if (ngccm_dout(29) = '1') then status_rep := (others=>'0'); SR := (others=>'0'); end if; if (ngccm_dout(31 downto 30) = "01" and status_rep /= x"00") or (ngccm_dout(31 downto 30) = "10" and status_rep = x"00") or ngccm_dout(31 downto 30) = "00" then if fe_status = idle_s or fe_status = repeat_s then case ngccm_dout(28 downto 25) is -- when "1000" => server_c := cr_txr; ngccm_mosi.ipb_strobe <= '1'; ngccm_mosi.ipb_write <= '1'; fe_status := write_s; ngccm_mosi.ipb_wdata <= x"0000"&ngccm_dout(15 downto 0); ngccm_mosi.ipb_addr <= "01101"&partition(4)&"000000"&partition(3 downto 0)&x"11"&partition(3 downto 0)&x"1"; when "0100" => server_c := sr_rxr; fe_status := response_s; ngccm_mosi.ipb_strobe <= '1'; ngccm_mosi.ipb_write <= '0'; status_mask := ngccm_dout(23 downto 16); timeout_cyc := to_integer(unsigned(ngccm_dout(15 downto 0))); ngccm_mosi.ipb_addr <= "01101"&partition(4)&"000000"&partition(3 downto 0)&x"11"&partition(3 downto 0)&x"1"; when "0010" => server_c := sleep_c; sleep_cyc := to_integer(unsigned(ngccm_dout(23 downto 0))); fe_status := idle_s; ngccm_mosi.ipb_strobe<= '0'; --timeout_cyc := timeout_cyc + sleep_cyc; --wait 8 more cycles in addition to the sleep cycles indicated by the s/w in case of unreponsive f/w slave when "0001" => server_c := fast_c; ngccm_mosi.ipb_strobe<= '1'; ngccm_mosi.ipb_write <= '1'; fe_status := write_s; ngccm_mosi.ipb_wdata <= x"00"&ngccm_dout(23 downto 0); ngccm_mosi.ipb_addr <= "01101"&partition(4)&"000000"&partition(3 downto 0)&x"000a"; when others => fe_status := idle_s; error <= '1'; --!! need to find a better way to deal with error signal end case; end if; end if; --write to the I2C bridge if (fe_status = write_s) then if (ngccm_miso.ipb_ack = '1') then -- wait for the ack of the write, then start read case server_c is when cr_txr => fe_status := idle_s; when fast_c => fe_status := idle_s; when prer => fe_status := wait_s; ngccm_mosi.ipb_write <= '0'; when others => error <= '1'; fe_status := idle_s; end case; end if; --pull the response from I2C bridge elsif fe_status = response_s and timeout_cyc /= 0 then if (ngccm_miso.ipb_ack = '1' ) then -- wait for the read SR := ngccm_miso.ipb_rdata(15 downto 8); data_r := ngccm_miso.ipb_rdata(7 downto 0); if SR(1 downto 0) = "01" then status_rep := status_rep or (status_mask and SR); fe_status := idle_s; error <= '0'; elsif SR(1) = '1' then timeout_cyc := timeout_cyc - 1; error <= '0'; else fe_status := idle_s; error <= '1'; end if; end if; elsif fe_status = response_s and timeout_cyc = 0 then status_rep(1) := '1'; fe_status := idle_s; elsif fe_status = wait_s and ngccm_miso.ipb_ack = '1' then if ngccm_dout(15 downto 0) = ngccm_miso.ipb_rdata(15 downto 0) then fe_status := idle_s; end if; end if; if fe_status = idle_s and data_address < 1250 then status_rep(2) := error; error <= '0'; data_address <= data_address + 1; data_length <= data_length+1; ngccm_mosi.ipb_strobe<= '0'; end if; if w_tobram = '1' and fe_status = idle_s and w_address < 2500 then --write to bram ngccm_din(31 downto 24) <= ngccm_dout(31 downto 24); ngccm_din(7 downto 0) <= data_r; ngccm_din(15 downto 8) <= status_rep; ngccm_wr_i <= "1"; ngccm_addr_i <= w_address; --handle the ouput size and write address increment w_address := w_address+1; response_length := response_length+1; output_size(12 downto 2) <= std_logic_vector(response_length); end if; end if; elsif input_size(12 downto 2) /= "00000000000" and input_size(12 downto 2) = std_logic_vector(data_length) then ngccm_wr_i <= "0"; status_reg <= word2;-- process finished, letting know the ngccm... end if; end if; end if; end process; end Behavioral;