------------------------------------------------------------------------------- -- Title : Lane alignment ------------------------------------------------------------------------------- -- File : lane_alignment.vhd ------------------------------------------------------------------------------- -- Description: Ensures all lanes are aligned to the same character. -- Buffers after receiving first /A/ character until ci_start is set. -- Then starts sending the data from the buffer. -- That ensures all the lanes start at the same position. ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use work.data_link_pkg.all; entity lane_alignment is generic ( F : integer range 1 to 256; -- Number of octets in a frame K : integer range 1 to 32; -- Number of frames in a multiframe buffer_size : integer := 256; -- How many octets to keep R_character : std_logic_vector(7 downto 0) := "00011100"; -- The /R/ character dummy_character : character_vector := ('1', '0', '0', "10111100", '0')); -- Character to send before the buffer is ready and started port ( ci_char_clk : in std_logic; -- Character clock ci_reset : in std_logic; -- Reset (asynchronous, active low) ci_start : in std_logic; -- Start sending the data from the -- buffer. ci_state : in link_state; -- State of the lane ci_realign : in std_logic; -- Whether to realign to the last -- found alignment character di_char : in character_vector; -- Character from 8b10b decoder co_ready : out std_logic; -- Whether /A/ was received and -- waiting for start co_aligned : out std_logic; -- Whether the alignment is still correct co_correct_sync_chars : out integer; -- How many alignment characters on -- correct place were found in a row co_error : out std_logic; -- Whether there is an error do_char : out character_vector); -- The aligned output character end entity lane_alignment; architecture a1 of lane_alignment is type buffer_array is array (0 to buffer_size) of character_vector; signal buff : buffer_array := (others => ('0', '0', '0', "00000000", '0')); signal reg_ready : std_logic := '0'; signal reg_started : std_logic := '0'; signal reg_error : std_logic := '0'; signal reg_write_index : integer range 0 to buffer_size := 0; signal reg_read_index : integer range 0 to buffer_size := 0; signal next_write_index : integer range 0 to buffer_size-1 := 0; signal next_read_index : integer range 0 to buffer_size-1 := 0; signal next_ready : std_logic := '0'; signal next_started : std_logic := '0'; signal next_error : std_logic := '0'; begin -- architecture a1 set_next : process (ci_char_clk, ci_reset) is begin -- process set_next if ci_reset = '0' then -- asynchronous reset (active low) reg_write_index <= 0; reg_read_index <= 0; reg_ready <= '0'; reg_started <= '0'; reg_error <= '0'; buff <= (others => ('0', '0', '0', "00000000", '0')); elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge reg_write_index <= next_write_index; reg_read_index <= next_read_index; reg_ready <= next_ready; reg_started <= next_started; reg_error <= next_error; buff(reg_write_index).d8b <= di_char.d8b; buff(reg_write_index).kout <= di_char.kout; buff(reg_write_index).disparity_error <= di_char.disparity_error; buff(reg_write_index).missing_error <= di_char.missing_error; buff(reg_write_index).user_data <= '1' when ci_state = DATA else '0'; end if; end process set_next; co_ready <= reg_ready; co_error <= reg_error; -- TODO handle realignment ? next_write_index <= ((reg_write_index + 1) mod buffer_size) when reg_ready = '1' or next_ready = '1' else 0; next_read_index <= ((reg_read_index + 1) mod buffer_size) when reg_started = '1' else 0; next_ready <= '0' when ci_state = INIT else '1' when reg_ready = '1' or (di_char.kout = '1' and di_char.d8b = R_character and (ci_state = CGS or ci_state = ILS)) else '0'; next_started <= '0' when reg_ready = '0' else '1' when (ci_start = '1' or reg_started = '1') else '0'; co_aligned <= reg_started; -- TODO: check for misalignment next_error <= '0' when ci_state = INIT else '1' when reg_error = '1' else '1' when reg_ready = '1' and reg_started = '0' and (reg_write_index = 0) else '0'; do_char <= dummy_character when ci_state = INIT or reg_started = '0' else buff(reg_read_index); end architecture a1;