@@ 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;
@@ 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;
@@ 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;