From 99b0946252fc5f69082672317ab0affefdd5d515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Wed, 16 Nov 2022 20:50:18 +0100 Subject: [PATCH] feat(link): output frame_character from data link, add user_data to character --- src/data_link/8b10b_decoder.vhd | 2 + src/data_link/data_link_pkg.vhd | 11 +++ src/data_link/frame_alignment.vhd | 37 ++++++---- src/data_link/lane_alignment.vhd | 9 +-- testbench/data_link/frame_alignment_tb.vhd | 78 ++++++++++------------ 5 files changed, 78 insertions(+), 59 deletions(-) diff --git a/src/data_link/8b10b_decoder.vhd b/src/data_link/8b10b_decoder.vhd index 8208a0c..546d68f 100644 --- a/src/data_link/8b10b_decoder.vhd +++ b/src/data_link/8b10b_decoder.vhd @@ -172,6 +172,7 @@ begin -- architecture a1 do_char.disparity_error <= '0'; do_char.missing_error <= '0'; do_char.kout <= '0'; + do_char.user_data <= '0'; reg_do_8b <= (others => '0'); reg_rd <= '0'; elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge @@ -179,6 +180,7 @@ begin -- architecture a1 do_char.disparity_error <= next_disparity_error; do_char.missing_error <= next_missing_error; do_char.kout <= next_kout; + do_char.user_data <= '0'; reg_do_8b <= next_do_8b; reg_rd <= next_rd; end if; diff --git a/src/data_link/data_link_pkg.vhd b/src/data_link/data_link_pkg.vhd index d9d5cb8..1df96f1 100644 --- a/src/data_link/data_link_pkg.vhd +++ b/src/data_link/data_link_pkg.vhd @@ -8,8 +8,19 @@ package data_link_pkg is disparity_error : std_logic; -- Whether there was a disparity error (if this is true, the character will still be correct) missing_error : std_logic; -- Whether the character was not found in the table d8b : std_logic_vector(7 downto 0); -- The decoded data + user_data : std_logic; end record character_vector; + type frame_character is record + kout : std_logic; -- Whether the character is a control character + disparity_error : std_logic; -- Whether there was a disparity error (if this is true, the character will still be correct) + missing_error : std_logic; -- Whether the character was not found in the table + d8b : std_logic_vector(7 downto 0); -- The decoded data + octet_index : integer range 0 to 256; + frame_index : integer range 0 to 32; + user_data : std_logic; + end record frame_character; + type link_state is ( INIT, CGS, diff --git a/src/data_link/frame_alignment.vhd b/src/data_link/frame_alignment.vhd index 50641f5..a0cd3d7 100644 --- a/src/data_link/frame_alignment.vhd +++ b/src/data_link/frame_alignment.vhd @@ -20,9 +20,7 @@ entity frame_alignment is di_char : in character_vector; -- The received character co_aligned : out std_logic; co_misaligned : out std_logic; - co_octet_index : out integer range 0 to 256; -- The index of the octet in current frame - co_frame_index : out integer range 0 to 32; -- The index of the frame in current multiframe - do_char : out character_vector); -- The output character + do_char : out frame_character); -- The output character end entity frame_alignment; architecture a1 of frame_alignment is @@ -47,17 +45,22 @@ architecture a1 of frame_alignment is signal next_octet_index : integer range 0 to 256 := 0; signal next_frame_index : integer range 0 to 32 := 0; - signal next_char : character_vector := ('0', '0', '0', "00000000"); + signal next_char : character_vector := ('0', '0', '0', "00000000", '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_frame_index <= 0; reg_octet_index <= 0; - do_char <= ('0', '0', '0', "00000000"); + do_char <= ('0', '0', '0', "00000000", 0, 0, '0'); reg_state <= INIT; elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge - do_char <= next_char; + do_char.kout <= next_char.kout; + do_char.d8b <= next_char.d8b; + do_char.disparity_error <= next_char.disparity_error; + do_char.missing_error <= next_char.missing_error; + do_char.user_data <= next_char.user_data; + do_char.frame_index <= reg_frame_index; -- set last_frame_data if this is the last frame and not /F/ or /A/ if next_is_last_octet = '1' and not (is_f = '1' or is_a = '1') then @@ -68,16 +71,24 @@ begin -- architecture a1 reg_state <= INIT; reg_frame_index <= 0; reg_octet_index <= 0; + do_char.octet_index <= 0; + do_char.frame_index <= 0; elsif di_char.kout = '1' and di_char.d8b = sync_char then reg_state <= RECEIVED_K; reg_frame_index <= 0; reg_octet_index <= 0; + do_char.octet_index <= 0; + do_char.frame_index <= 0; elsif reg_state = INIT then reg_frame_index <= 0; reg_octet_index <= 0; + do_char.octet_index <= 0; + do_char.frame_index <= 0; elsif reg_state = RECEIVED_K then reg_frame_index <= 0; reg_octet_index <= 0; + do_char.octet_index <= 0; + do_char.frame_index <= 0; if di_char.d8b /= sync_char or di_char.kout = '0' then reg_state <= ALIGNED; @@ -85,6 +96,8 @@ begin -- architecture a1 else reg_frame_index <= next_frame_index; reg_octet_index <= next_octet_index; + do_char.octet_index <= next_octet_index; + do_char.frame_index <= next_frame_index; if reg_state = ALIGNED then if is_wrong_char = '1' then reg_state <= MISALIGNED; @@ -94,6 +107,7 @@ begin -- architecture a1 if ci_enable_realign = '1' then reg_octet_index <= ci_F - 1; + do_char.octet_index <= ci_F - 1; else reg_state <= WRONG_ALIGNMENT; end if; @@ -104,7 +118,8 @@ begin -- architecture a1 if is_wrong_char = '0' and (is_f = '1' or is_a = '1') then reg_state <= MISALIGNED; elsif ci_enable_realign = '1' and (is_f = '1' or is_a = '1') then - reg_frame_index <= ci_F - 1; + do_char.octet_index <= ci_F - 1; + reg_octet_index <= ci_F - 1; end if; end if; end if; -- in RECEIVED_K @@ -119,6 +134,7 @@ begin -- architecture a1 A_replace_data; next_char.disparity_error <= di_char.disparity_error; next_char.missing_error <= di_char.missing_error; + next_char.user_data <= di_char.user_data; next_is_last_octet <= '1' when next_octet_index = ci_F - 1 else '0'; next_is_last_frame <= '1' when next_frame_index = ci_K - 1 else '0'; @@ -127,12 +143,9 @@ begin -- architecture a1 is_a <= '1' when di_char.d8b = A_char and di_char.kout = '1' else '0'; next_frame_index <= reg_frame_index when reg_octet_index < (ci_F - 1) else - reg_frame_index + 1 when reg_frame_index < (ci_K - 1) else - 0; - next_octet_index <= reg_octet_index + 1 when reg_octet_index < (ci_F - 1) else 0; + (reg_frame_index + 1) mod ci_K; + next_octet_index <= (reg_octet_index + 1) mod ci_F; co_misaligned <= '1' when reg_state = WRONG_ALIGNMENT else '0'; co_aligned <= '1' when reg_state = ALIGNED or reg_state = MISALIGNED else '0'; - co_octet_index <= reg_octet_index; - co_frame_index <= reg_frame_index; end architecture a1; diff --git a/src/data_link/lane_alignment.vhd b/src/data_link/lane_alignment.vhd index 3df6ae5..f4cb8da 100644 --- a/src/data_link/lane_alignment.vhd +++ b/src/data_link/lane_alignment.vhd @@ -6,7 +6,7 @@ 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")); + dummy_character : character_vector := ('1', '0', '0', "10111100", '0')); port ( ci_char_clk : in std_logic; @@ -25,7 +25,7 @@ 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 buff : buffer_array := (others => ('0', '0', '0', "00000000", '0')); signal reg_ready : std_logic := '0'; signal reg_started : std_logic := '0'; @@ -48,7 +48,7 @@ begin -- architecture a1 reg_ready <= '0'; reg_started <= '0'; reg_error <= '0'; - buff <= (others => ('0', '0', '0', "00000000")); + 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; @@ -69,7 +69,7 @@ begin -- architecture a1 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 + '1' when reg_ready = '1' or (di_char.kout = '1' and di_char.d8b = alignment_character and (ci_state = CGS or ci_state = ILS)) else '0'; next_started <= '0' when reg_ready = '0' else '1' when reg_ready = '1' and (ci_start = '1' or reg_started = '1') else @@ -82,5 +82,6 @@ begin -- architecture a1 do_char <= dummy_character when ci_state = INIT or reg_started = '0' else buff(reg_read_index); + do_char.user_data <= '1' when ci_state = DATA and reg_started = '1' else '0'; end architecture a1; diff --git a/testbench/data_link/frame_alignment_tb.vhd b/testbench/data_link/frame_alignment_tb.vhd index 4a5cc98..145f2db 100644 --- a/testbench/data_link/frame_alignment_tb.vhd +++ b/testbench/data_link/frame_alignment_tb.vhd @@ -13,11 +13,9 @@ architecture a1 of frame_alignment_tb is ci_enable_realign : std_logic; di_char : character_vector; - expected_char : character_vector; + expected_char : frame_character; expected_aligned : std_logic; expected_misaligned : std_logic; - expected_octet_index : integer range 0 to 256; - expected_frame_index : integer range 0 to 32; end record test_vector; @@ -25,39 +23,39 @@ architecture a1 of frame_alignment_tb is constant test_vectors : test_vector_array := ( -- rq scra real kout der mer data expec kout der mer data almisal oct fram - ('0', '0', '0', ('1', '0', '0', "10111100"), ('1', '0', '0', "10111100"), '0', '0', 0, 0), - ('0', '0', '0', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 0, 0), - ('0', '0', '0', ('0', '0', '0', "10101010"), ('0', '0', '0', "10101010"), '1', '0', 1, 0), - ('0', '0', '0', ('0', '0', '0', "01010101"), ('0', '0', '0', "01010101"), '1', '0', 2, 0), - ('0', '0', '0', ('0', '0', '0', "01010101"), ('0', '0', '0', "01010101"), '1', '0', 3, 0), - ('0', '0', '0', ('0', '0', '0', "01010101"), ('0', '0', '0', "01010101"), '1', '0', 4, 0), - ('0', '0', '0', ('0', '0', '0', "11111111"), ('0', '0', '0', "11111111"), '1', '0', 0, 1), - ('0', '0', '0', ('0', '0', '0', "11111111"), ('0', '0', '0', "11111111"), '1', '0', 1, 1), - ('0', '0', '0', ('0', '0', '0', "11111111"), ('0', '0', '0', "11111111"), '1', '0', 2, 1), - ('0', '0', '0', ('0', '0', '0', "11111111"), ('0', '0', '0', "11111111"), '1', '0', 3, 1), - ('0', '0', '0', ('1', '0', '0', "11111100"), ('0', '0', '0', "01010101"), '1', '0', 4, 1), - ('0', '0', '0', ('1', '0', '0', "11111100"), ('0', '0', '0', "01010101"), '1', '0', 0, 2), - ('0', '0', '0', ('1', '0', '0', "11111100"), ('0', '0', '0', "01010101"), '0', '1', 1, 2), - ('0', '0', '0', ('0', '0', '0', "11110000"), ('0', '0', '0', "11110000"), '0', '1', 2, 2), - ('0', '0', '0', ('0', '0', '0', "11110000"), ('0', '0', '0', "11110000"), '0', '1', 3, 2), - ('0', '0', '0', ('1', '0', '0', "11111100"), ('0', '0', '0', "01010101"), '1', '0', 4, 2), - ('1', '1', '1', ('0', '0', '0', "11111100"), ('0', '0', '0', "11111100"), '0', '0', 0, 0), - ('0', '1', '1', ('1', '0', '0', "10111100"), ('1', '0', '0', "10111100"), '0', '0', 0, 0), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 0, 0), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 1, 0), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 2, 0), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 3, 0), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 4, 0), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 0, 1), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 1, 1), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 2, 1), - ('0', '1', '1', ('0', '0', '0', "00000000"), ('0', '0', '0', "00000000"), '1', '0', 3, 1), - ('0', '1', '1', ('1', '0', '0', "11111100"), ('0', '0', '0', "11111100"), '1', '0', 4, 1), - ('0', '1', '1', ('1', '0', '0', "01111100"), ('0', '0', '0', "01111100"), '1', '0', 0, 2), - ('0', '1', '1', ('1', '0', '0', "01111100"), ('0', '0', '0', "01111100"), '1', '0', 4, 2), - ('0', '1', '1', ('0', '0', '0', "11111111"), ('0', '0', '0', "11111111"), '1', '0', 0, 3), - ('0', '1', '1', ('0', '0', '0', "11111111"), ('0', '0', '0', "11111111"), '1', '0', 1, 3), - ('0', '1', '1', ('0', '0', '0', "11111111"), ('0', '0', '0', "11111111"), '1', '0', 2, 3) + ('0', '0', '0', ('1', '0', '0', "10111100", '0'), ('1', '0', '0', "10111100", 0, 0, '0'), '0', '0'), + ('0', '0', '0', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 0, 0, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "10101010", '0'), ('0', '0', '0', "10101010", 1, 0, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "01010101", '0'), ('0', '0', '0', "01010101", 2, 0, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "01010101", '0'), ('0', '0', '0', "01010101", 3, 0, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "01010101", '0'), ('0', '0', '0', "01010101", 4, 0, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 0, 1, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 1, 1, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 2, 1, '0'), '1', '0'), + ('0', '0', '0', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 3, 1, '0'), '1', '0'), + ('0', '0', '0', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "01010101", 4, 1, '0'), '1', '0'), + ('0', '0', '0', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "01010101", 0, 2, '0'), '1', '0'), + ('0', '0', '0', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "01010101", 1, 2, '0'), '0', '1'), + ('0', '0', '0', ('0', '0', '0', "11110000", '0'), ('0', '0', '0', "11110000", 2, 2, '0'), '0', '1'), + ('0', '0', '0', ('0', '0', '0', "11110000", '0'), ('0', '0', '0', "11110000", 3, 2, '0'), '0', '1'), + ('0', '0', '0', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "01010101", 4, 2, '0'), '1', '0'), + ('1', '1', '1', ('0', '0', '0', "11111100", '0'), ('0', '0', '0', "11111100", 0, 0, '0'), '0', '0'), + ('0', '1', '1', ('1', '0', '0', "10111100", '0'), ('1', '0', '0', "10111100", 0, 0, '0'), '0', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 0, 0, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 1, 0, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 2, 0, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 3, 0, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 4, 0, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 0, 1, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 1, 1, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 2, 1, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 3, 1, '0'), '1', '0'), + ('0', '1', '1', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "11111100", 4, 1, '0'), '1', '0'), + ('0', '1', '1', ('1', '0', '0', "01111100", '0'), ('0', '0', '0', "01111100", 0, 2, '0'), '1', '0'), + ('0', '1', '1', ('1', '0', '0', "01111100", '0'), ('0', '0', '0', "01111100", 4, 2, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 0, 3, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 1, 3, '0'), '1', '0'), + ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 2, 3, '0'), '1', '0') ); constant clk_period : time := 1 ns; @@ -69,15 +67,13 @@ architecture a1 of frame_alignment_tb is signal reset : std_logic := '0'; signal di_char : character_vector; - signal do_char : character_vector; + signal do_char : frame_character; signal ci_request_sync : std_logic; signal ci_enable_realign : std_logic; signal ci_scrambled : std_logic; signal co_aligned : std_logic; signal co_misaligned : std_logic; - signal co_octet_index : integer range 0 to 256; - signal co_frame_index : integer range 0 to 32; signal test_data_index : integer := 0; @@ -94,8 +90,6 @@ begin -- architecture a1 di_char => di_char, co_aligned => co_aligned, co_misaligned => co_misaligned, - co_octet_index => co_octet_index, - co_frame_index => co_frame_index, do_char => do_char); clk <= not clk after clk_period/2; @@ -120,8 +114,6 @@ begin -- architecture a1 assert co_aligned = prev_test_vec.expected_aligned report "The aligned does not match. Expected: " & std_logic'image(prev_test_vec.expected_aligned) &", Index: " & integer'image(i-1) severity error; assert co_misaligned = prev_test_vec.expected_misaligned report "The misaligned does not match. Index: " & integer'image(i-1) severity error; - assert co_octet_index = prev_test_vec.expected_octet_index report "The octet index does not match. Expected: " & integer'image(prev_test_vec.expected_octet_index) & ", got: " & integer'image(co_octet_index) & ", index: " & integer'image(i-1) severity error; - assert co_frame_index = prev_test_vec.expected_frame_index report "The frame index does not match. Expected: " & integer'image(prev_test_vec.expected_frame_index) & ", got: " & integer'image(co_frame_index) & ", index: " & integer'image(i-1) severity error; assert do_char = prev_test_vec.expected_char report "The character does not match. Index: " & integer'image(i-1) severity error; end if; -- 2.48.1