------------------------------------------------------ -- Receive packet -- -- Ver 1.00 -- -- Dominique Gigi May 2015 ------------------------------------------------------ -- Version 1.00 -- -- -- ------------------------------------------------------ LIBRARY ieee; USE ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; entity rcv_pckt_s_XGMII 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(63 downto 0); --- data and K bit send from SERDES k_byte : in std_logic_vector( 7 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 MOL data : out std_logic_vector(31 downto 0); -- data from MOL 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_XGMII; architecture behavioral of rcv_pckt_s_XGMII is component crc_gen_32b IS PORT( clock : IN STD_LOGIC; reset : IN STD_LOGIC; data : IN STD_LOGIC_VECTOR(63 DOWNTO 0); data_valid : IN STD_LOGIC; eoc : IN STD_LOGIC; crc : OUT STD_LOGIC_VECTOR(31 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(63 downto 0); signal pipe_b : std_logic_vector(63 downto 0); signal pipe_c : std_logic_vector(63 downto 0); signal pipe_K : std_logic_vector( 7 downto 0); signal SOF : std_logic_vector(2 downto 0); signal EOF : std_logic_vector(0 downto 0); --attribute mark_debug : string; --attribute mark_debug of SOF, EOF : signal is "true"; signal stage : std_logic_vector(1 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(31 downto 0); signal crc_valid : std_logic; signal crc_to_be_check : std_logic_vector(31 downto 0); signal end_check : std_logic; signal cmd_pckt : std_logic; signal ack_pckt : std_logic; 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 SOF <= (others => '0'); elsif rising_edge(clock) then SOF(2 downto 1) <= SOF(1 downto 0); SOF(0) <= '0'; if k_byte(0) = '1' and datai(07 downto 00) = x"FB" then --start SOF(0) <= '1'; end if; end if; end process; -- realign the byte following on 64-bit word -- And Pipe data process(clock) begin if rising_edge(clock) then pipe_c <= pipe_b; pipe_a(63 downto 00) <= datai(63 downto 00); pipe_K <= k_byte; pipe_b(63 downto 00) <= pipe_a(63 downto 00); end if; end process; process(clock) begin if rising_edge(clock) then stage(1) <= stage(0); stage(0) <= SOF(0); 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(1) = '1' then cmp_crc <= '1'; elsif EOF(0) = '1' 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 EOF(0) = '1' then crc_to_be_check <= pipe_a(31 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(0) <= '0'; if (datai(39 downto 32) = x"FD" and k_byte(4) = '1') then --End of frame EOF(0) <= '1'; end if; end if; end process; EOC <= '1' when (datai(39 downto 32) = x"FD" and k_byte(4) = '1') else '0'; --******************************************************** -- instantiation to Compute the CRC CRC_generate:crc_gen_32b PORT MAP( clock => clock, reset => SOF(1), data => pipe_b, data_valid => cmp_crc, eoc => EOF(0), 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_a(62 downto 32); ack_pckt <= pipe_a(63); cmd_pckt <= not(pipe_a(63)); ID_reg <= pipe_a(31 downto 16); length_reg <= pipe_a(15 downto 00); elsif stage(1) = '1' then cmd_reg <= pipe_a(63 downto 32); status_reg(31 downto 00) <= pipe_a(63 downto 32); data_reg <= pipe_a(31 downto 00); 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;