From 1103c72652ca7d2a3647fb3ac0709a7f57b3787a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Mon, 21 Nov 2022 20:36:42 +0100 Subject: [PATCH] feat(link): add error handler entity for managing data link errors (lane misalignment, frame misalignment, not in table error, disparity error, unexpected character error) --- src/data_link/data_link_layer.vhd | 49 +++++++++++++----- src/data_link/data_link_pkg.vhd | 16 ++++++ src/data_link/error_handler.vhd | 82 +++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 12 deletions(-) create mode 100644 src/data_link/error_handler.vhd diff --git a/src/data_link/data_link_layer.vhd b/src/data_link/data_link_layer.vhd index e019e04..fed4424 100644 --- a/src/data_link/data_link_layer.vhd +++ b/src/data_link/data_link_layer.vhd @@ -22,6 +22,9 @@ entity data_link_layer is co_lane_ready : out std_logic; -- Received /A/, waiting for lane sync ci_lane_start : in std_logic; -- Start sending data from lane buffer + -- errors + ci_error_config : in error_handling_config; + -- input, output co_synced : out std_logic; di_10b : in std_logic_vector(9 downto 0); @@ -33,21 +36,25 @@ architecture a1 of data_link_layer is signal decoder_do_char : character_vector; + signal lane_alignment_ci_realign : std_logic := '0'; signal lane_alignment_co_aligned : std_logic; signal lane_alignment_co_error : std_logic; signal lane_alignment_co_ready : std_logic; signal lane_alignment_do_char : character_vector; + signal lane_alignment_co_correct_sync_chars : integer; signal frame_alignment_ci_request_sync : std_logic; - signal frame_alignment_ci_enable_realign : std_logic := '0'; + signal frame_alignment_ci_realign : std_logic := '0'; signal frame_alignment_co_aligned : std_logic; signal frame_alignment_co_error : std_logic; signal frame_alignment_do_char : frame_character; + signal frame_alignment_co_correct_sync_chars : integer; signal link_controller_co_synced : std_logic; signal link_controller_co_state : link_state; signal link_controller_do_config : link_config; - signal link_controller_ci_resync : std_logic := '0'; + signal link_controller_ci_resync : std_logic; + begin -- architecture a1 do_lane_config <= link_controller_do_config; co_lane_ready <= lane_alignment_co_ready; @@ -61,6 +68,23 @@ begin -- architecture a1 -- | | | | -- FRAME ALIGNMENT <= LANE ALIGNMENT <= 8b10b DECODER <= CHAR ALIGNMENT + -- error handling + error_handling : entity work.error_handler + port map ( + ci_char_clk => ci_char_clk, + ci_reset => ci_reset, + ci_state => link_controller_co_state, + ci_F => ci_F, + di_char => decoder_do_char, + ci_config => ci_error_config, + ci_lane_alignment_error => lane_alignment_co_error, + ci_frame_alignment_error => frame_alignment_co_error, + ci_lane_alignment_correct_count => lane_alignment_co_correct_sync_chars, + ci_frame_alignment_correct_count => frame_alignment_co_correct_sync_chars, + co_frame_alignment_realign => frame_alignment_ci_realign, + co_lane_alignment_realign => lane_alignment_ci_realign, + co_request_sync => link_controller_ci_resync); + -- link controller link_controller : entity work.link_controller port map ( @@ -110,15 +134,16 @@ begin -- architecture a1 -- frame alignment frame_alignment : entity work.frame_alignment port map ( - ci_char_clk => ci_char_clk, - ci_reset => ci_reset, - ci_scrambled => ci_scrambled, - ci_F => ci_F, - ci_K => ci_K, - ci_request_sync => frame_alignment_ci_request_sync, - ci_enable_realign => frame_alignment_ci_enable_realign, - co_aligned => frame_alignment_co_aligned, - co_misaligned => frame_alignment_co_error, - di_char => lane_alignment_do_char); + ci_char_clk => ci_char_clk, + ci_reset => ci_reset, + ci_scrambled => ci_scrambled, + ci_F => ci_F, + ci_K => ci_K, + co_correct_sync_chars => frame_alignment_co_correct_sync_chars, + ci_request_sync => frame_alignment_ci_request_sync, + ci_realign => frame_alignment_ci_realign, + co_aligned => frame_alignment_co_aligned, + co_error => frame_alignment_co_error, + di_char => lane_alignment_do_char); end architecture a1; diff --git a/src/data_link/data_link_pkg.vhd b/src/data_link/data_link_pkg.vhd index 1df96f1..d3a4321 100644 --- a/src/data_link/data_link_pkg.vhd +++ b/src/data_link/data_link_pkg.vhd @@ -53,4 +53,20 @@ package data_link_pkg is CHKSUM : integer range 0 to 255; end record link_config; + type error_handling_config is record + lane_alignment_realign_after : integer; -- realign after correctly + -- received X alignment + -- characters (0 to disable) + frame_alignment_realign_after : integer; -- realign after correctly + -- received X alignment + -- characters (0 to disable) + tolerate_missing_in_frame : integer; -- How many missing errors to + -- tolerate in a frame (0 to disable) + tolerate_disparity_in_frame : integer; -- How many disparity errors to + -- tolerate in a frame (0 to disable) + tolerate_unexpected_characters_in_frame : integer; -- How many unexpected + -- characters to + -- tolerate in a frame + end record error_handling_config; + end package data_link_pkg; diff --git a/src/data_link/error_handler.vhd b/src/data_link/error_handler.vhd new file mode 100644 index 0000000..8c0407f --- /dev/null +++ b/src/data_link/error_handler.vhd @@ -0,0 +1,82 @@ +library ieee; +use ieee.std_logic_1164.all; +use work.data_link_pkg.all; + +entity error_handler is + port ( + ci_char_clk : in std_logic; + ci_reset : in std_logic; + ci_state : in link_state; + + ci_F : in integer range 0 to 256; + + di_char : in character_vector; + + ci_config : in error_handling_config; + ci_lane_alignment_error : in std_logic; + ci_lane_alignment_correct_count : in integer; + ci_frame_alignment_error : in std_logic; + ci_frame_alignment_correct_count : in integer; + + co_frame_alignment_realign : out std_logic; + co_lane_alignment_realign : out std_logic; + co_request_sync : out std_logic); +end entity error_handler; + +architecture a1 of error_handler is + signal active : std_logic; + + signal reg_index : integer range 0 to 256 := 0; + signal reg_request_sync : std_logic; + signal reg_missing_count : integer range 0 to 256 := 0; + signal reg_disparity_count : integer range 0 to 256 := 0; + signal reg_unexpected_count : integer range 0 to 256 := 0; + + signal next_index : integer range 0 to 256 := 0; + signal next_request_sync : std_logic; + signal next_missing_count : integer range 0 to 256 := 0; + signal next_disparity_count : integer range 0 to 256 := 0; + signal next_unexpected_count : integer range 0 to 256 := 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_index <= 0; + reg_request_sync <= '0'; + reg_missing_count <= 0; + reg_disparity_count <= 0; + reg_unexpected_count <= 0; + elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge + reg_index <= next_index; + reg_request_sync <= next_request_sync; + reg_missing_count <= next_missing_count; + reg_disparity_count <= next_disparity_count; + reg_unexpected_count <= next_unexpected_count; + end if; + end process set_next; + + co_request_sync <= reg_request_sync; + active <= '1' when di_char.user_data = '1' and ci_state /= INIT else '0'; + next_index <= 0 when active = '0' else + (reg_index + 1) mod ci_F; + + next_request_sync <= '0' when active = '0' else + '1' when reg_request_sync = '1' else + '1' when ci_lane_alignment_correct_count >= ci_config.lane_alignment_realign_after else + '1' when ci_frame_alignment_correct_count >= ci_config.frame_alignment_realign_after else + '1' when reg_missing_count > ci_config.tolerate_missing_in_frame else + '1' when reg_disparity_count > ci_config.tolerate_disparity_in_frame else + '1' when reg_unexpected_count > ci_config.tolerate_unexpected_characters_in_frame else + '0'; + + next_missing_count <= 0 when next_index = 0 else + next_missing_count when di_char.missing_error = '0' else + next_missing_count + 1; + next_disparity_count <= 0 when next_index = 0 else + next_disparity_count when di_char.disparity_error = '0' else + next_disparity_count + 1; + next_unexpected_count <= 0 when next_index = 0 else + next_unexpected_count when ci_state = DATA and di_char.kout = '1' and not (di_char.d8b = "11111100" or di_char.d8b = "01111100") else + next_unexpected_count + 1; + +end architecture a1; -- 2.48.1