------------------------------------------------------ -- Receive packet -- -- Ver 1.00 -- -- Dominique Gigi Feb 2012 ------------------------------------------------------ -- -- -- -- ------------------------------------------------------ LIBRARY ieee; -- LIBRARY altera_mf; -- LIBRARY altera; USE ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; -- LIBRARY lpm; -- USE lpm.lpm_components.all; -- USE altera_mf.altera_mf_components.all; -- USE altera.altera_primitives_components.all; entity rcv_pckt_s is port ( reset_clk : in std_logic; reset_clkT : in std_logic; Greset_clk : in std_logic; Greset_clkT : in std_logic; clock : in std_logic; clock_t : in std_logic; datai : in std_logic_vector(31 downto 0); -- data and K bit send from SERDES k_byte : in std_logic_vector( 3 downto 0); error_gen : in std_logic; -- 1 will emulate an error in one ack packet cmd : out std_logic_vector(31 downto 0); -- command from DAQ data : out std_logic_vector(31 downto 0); -- data from DAQ ena_cmd : out std_logic; -- validate command status : out std_logic_vector(63 downto 0); -- value return from read command request seqnb : out std_logic_vector(30 downto 0); -- seq numb from ack (received an ack) ena_ack : out std_logic; card_ID : out std_logic_vector(15 downto 0); cnt_pckt_rcv : out std_logic_vector(31 downto 0) ); end rcv_pckt_s; architecture behavioral of rcv_pckt_s is component crc_gen_usb_32to16 PORT( clock : IN STD_LOGIC; reset : IN STD_LOGIC; data : IN STD_LOGIC_VECTOR(31 DOWNTO 0); data_valid : IN STD_LOGIC; eoc : IN STD_LOGIC; crc : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); crc_valid : OUT STD_LOGIC ); end component; component resync port ( reset : in std_logic; Free_clki : in std_logic; clocki : in std_logic; clocko : in std_logic; input : in std_logic; output : out std_logic ); end component; signal pipe_a : std_logic_vector(31 downto 0); signal pipe_b : std_logic_vector(31 downto 0); signal pipe_c : std_logic_vector(31 downto 0); signal pipe_K : std_logic_vector(3 downto 0); signal align : std_logic_vector(3 downto 0); signal SOF : std_logic_vector(2 downto 0); signal EOF : std_logic_vector(2 downto 0); signal stage : std_logic_vector(4 downto 0); signal cmd_reg : std_logic_vector(31 downto 0); signal data_reg : std_logic_vector(31 downto 0); signal ena_cmd_reg : std_logic; signal status_reg : std_logic_vector(63 downto 0); signal ena_ack_reg : std_logic; signal seqnb_reg : std_logic_vector(30 downto 0); signal ID_reg : std_logic_vector(15 downto 0); signal length_reg : std_logic_vector(15 downto 0); signal cmp_crc : std_logic; signal eoc : std_logic; signal crc_val : std_logic_vector(15 downto 0); signal crc_valid : std_logic; signal crc_to_be_check : std_logic_vector(15 downto 0); signal end_check : std_logic; signal cmd_pckt : std_logic; signal ack_pckt : std_logic; signal latch_crc_in : std_logic_vector(1 downto 0); signal mem_error_gen : std_logic_vector(1 downto 0); signal pack_counter : std_logic_vector(31 downto 0); --******************************************************* --************** BEGIN ******************************** --******************************************************* begin --****** error gen ******** process(reset_clk,clock) begin if reset_clk = '0' then mem_error_gen <= (others => '0'); elsif rising_edge(clock) then if SOF(0) = '1' then mem_error_gen(1) <= mem_error_gen(0); elsif crc_valid = '1' then mem_error_gen(1) <= '0'; end if; if error_gen = '1' then mem_error_gen(0) <= '1'; elsif SOF(0) = '1' then mem_error_gen(0) <= '0'; end if; end if; end process; --************************* process(reset_clk,clock) -- alignment on the start of frame begin if reset_clk = '0' then align <= (others => '0'); elsif rising_edge(clock) then SOF(0) <= '0'; SOF(2 downto 1) <= SOF(1 downto 0); if align /= "0000" and end_check = '1' then align <= "0000"; elsif datai(23 downto 16) = x"FB" and k_byte(2) = '1' and align = "0000" then align <= "1000"; SOF(0) <= '1'; elsif datai(07 downto 00) = x"FB" and k_byte(0) = '1' and align = "0000" then align <= "0010"; SOF(0) <= '1'; end if; end if; end process; -- Swapp bytes in case of alignement need -- And Pipe data process(clock) begin if rising_edge(clock) then pipe_c <= pipe_b; if align(1) = '1' then pipe_b(31 downto 24) <= pipe_a(31 downto 24);-- normal pipe_b(23 downto 16) <= pipe_a(23 downto 16); pipe_b(15 downto 08) <= pipe_a(15 downto 08); pipe_b(07 downto 00) <= pipe_a(07 downto 00); elsif align(3) = '1' then pipe_b(31 downto 24) <= datai (15 downto 08);-- half_word swapped pipe_b(23 downto 16) <= datai (07 downto 00); pipe_b(15 downto 08) <= pipe_a(31 downto 24); pipe_b(07 downto 00) <= pipe_a(23 downto 16); end if; pipe_a <= datai; pipe_K <= k_byte; end if; end process; process(clock) begin if rising_edge(clock) then stage(4 downto 1) <= stage(3 downto 0); stage(0) <= SOF(1); end if; end process; -- Envelop the data to be used to compute the CRC process(reset_clk,clock) begin if reset_clk = '0' then cmp_crc <= '0'; elsif rising_edge(clock) then if SOF(2) = '1' then cmp_crc <= '1'; elsif EOF(1) = '1' or (EOF(0) = '1' and latch_crc_in = "11" ) then cmp_crc <= '0'; end if; end if; end process; -- latch the CRC received in the packet process(reset_clk,clock) begin if rising_edge(clock) then if latch_crc_in = "01" then crc_to_be_check(15 downto 8) <= pipe_a(31 downto 24); crc_to_be_check(07) <= pipe_a(23) xor mem_error_gen(1); crc_to_be_check(06 downto 0) <= pipe_a(22 downto 16); elsif latch_crc_in = "11" then crc_to_be_check(15 downto 8) <= pipe_a(15 downto 08); crc_to_be_check(07) <= pipe_a(07) xor mem_error_gen(1); crc_to_be_check(06 downto 0) <= pipe_a(06 downto 00); end if; end if; end process; -- check where is the CRC in the packet -- according the alignment of the data process(reset_clk,clock) begin if reset_clk = '0' then EOF <= (others => '0'); elsif rising_edge(clock) then EOF(2 downto 1) <= EOF(1 downto 0); EOF(0) <= '0'; latch_crc_in <= "00"; if (datai(15 downto 08) = x"FD" and k_byte(1) = '1') then --normal wait EOF(0) <= '1'; latch_crc_in <= "01"; elsif (pipe_a(31 downto 24) = x"FD" and pipe_K(3) = '1') then -- met half_word swapped EOF(0) <= '1'; latch_crc_in <= "11"; elsif k_byte = "1111" and cmp_crc = '1' then -- in case of we lost the synchronization EOF(0) <= '1'; end if; end if; end process; EOC <= '1' when EOF(1) = '1' or (EOF(0) = '1' and latch_crc_in = "11" ) else '0'; --******************************************************** -- instantiation to Compute the CRC CRC_generate:crc_gen_usb_32to16 PORT MAP( clock => clock, reset => SOF(1), data => pipe_c, data_valid => cmp_crc, eoc => EOC, crc => crc_val, crc_valid => crc_valid ); --******************************************************** -- recover the values from the packet -- Sequence#, -- Ack nit, --Status,.... process(reset_clk,clock) begin if reset_clk = '0' then cmd_pckt <= '0'; ack_pckt <= '0'; elsif rising_edge(clock) then if stage(0) = '1' then seqnb_reg <= pipe_b(30 downto 0); ack_pckt <= pipe_b(31); cmd_pckt <= not(pipe_b(31)); elsif stage(1) = '1' then ID_reg <= pipe_b(31 downto 16); length_reg <= pipe_b(15 downto 00); elsif stage(2) = '1' and ack_pckt = '0' then status_reg(63 downto 32) <= pipe_b; cmd_reg <= pipe_b; elsif stage(3) = '1' then status_reg(31 downto 00) <= pipe_b; data_reg <= pipe_b; elsif end_check = '1' then cmd_pckt <= '0'; ack_pckt <= '0'; end if; end if; end process; -- validate or unvalidate the packet according the CRC check process(reset_clk,clock) begin if reset_clk = '0' then ena_cmd_reg <= '0'; ena_ack_reg <= '0'; end_check <= '0'; elsif rising_edge(clock) then ena_cmd_reg <= '0'; ena_ack_reg <= '0'; end_check <= '0'; if crc_valid = '1' then end_check <= '1'; if crc_val = crc_to_be_check then if ack_pckt = '1' then ena_ack_reg <= '1'; elsif cmd_pckt = '1' then ena_cmd_reg <= '1'; end if; end if; end if; end if; end process; process(Greset_clk,clock) begin if Greset_clk = '0' then pack_counter <= (others => '0'); elsif rising_edge(clock) then if crc_valid = '1' then if crc_val = crc_to_be_check then if ack_pckt = '1' then pack_counter <= pack_counter + '1'; end if; end if; end if; end if; end process; -- resynchronisation between clock domains resync_ena_ack:resync port map( reset => reset_clk, Free_clki => '1', clocki => clock, clocko => clock_t, input => ena_ack_reg, output => ena_ack ); resync_ena_cmd:resync port map( reset => reset_clk, Free_clki => '1', clocki => clock, clocko => clock_t, input => ena_cmd_reg, output => ena_cmd ); cmd <= cmd_reg; data <= data_reg; status <= status_reg; seqnb <= seqnb_reg; card_ID <= ID_reg; cnt_pckt_rcv <= pack_counter; -- count only the ack (not the command received end behavioral;