From 27b552703118f7a38e72f49bc7e37265efb7c67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Mon, 7 Nov 2022 18:01:45 +0100 Subject: [PATCH] feat(link): add lane alignment --- src/data_link/data_link_pkg.vhd | 7 +++ src/data_link/lane_alignment.vhd | 86 ++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/data_link/lane_alignment.vhd diff --git a/src/data_link/data_link_pkg.vhd b/src/data_link/data_link_pkg.vhd index 0be8f83..f9abe5e 100644 --- a/src/data_link/data_link_pkg.vhd +++ b/src/data_link/data_link_pkg.vhd @@ -10,4 +10,11 @@ package data_link_pkg is d8b : std_logic_vector(7 downto 0); -- The decoded data end record character_vector; + type link_state is ( + INIT, + CGS, + ILAS, + DATA, + ERR); -- States of the link + end package data_link_pkg; diff --git a/src/data_link/lane_alignment.vhd b/src/data_link/lane_alignment.vhd new file mode 100644 index 0000000..3df6ae5 --- /dev/null +++ b/src/data_link/lane_alignment.vhd @@ -0,0 +1,86 @@ +library ieee; +use ieee.std_logic_1164.all; +use work.data_link_pkg.all; + +entity lane_alignment is + generic ( + buffer_size : integer := 256; + alignment_character : std_logic_vector(7 downto 0) := "01111100"; + dummy_character : character_vector := ('1', '0', '0', "10111100")); + + port ( + ci_char_clk : in std_logic; + ci_reset : in std_logic; + ci_start : in std_logic; + ci_state : in link_state; + ci_F : in integer range 0 to 256; + ci_K : in integer range 0 to 32; + di_char : in character_vector; + co_ready : out std_logic; + co_aligned : out std_logic; + co_error : out std_logic; + do_char : out character_vector); + +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")); + + signal reg_ready : std_logic := '0'; + signal reg_started : std_logic := '0'; + signal reg_error : std_logic := '0'; + + signal reg_write_index : integer := 0; + signal reg_read_index : integer := 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")); + 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) <= di_char; + 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 = alignment_character and (ci_state = CGS or ci_state = ILAS)) else + '0'; + next_started <= '0' when reg_ready = '0' else + '1' when reg_ready = '1' and (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_ready = '1' and reg_started = '0' and (reg_write_index = 0) else + '1' when reg_error = '1' else + '0'; + + do_char <= dummy_character when ci_state = INIT or reg_started = '0' else + buff(reg_read_index); + +end architecture a1; -- 2.48.1