@@ 15,9 15,13 @@
library ieee;
use ieee.std_logic_1164.all;
use work.data_link_pkg.all;
+use work.transport_pkg.all;
entity frame_alignment is
generic (
+ SCRAMBLED : boolean; -- Whether data are scrambled
+ F : integer range 0 to 256 := 8; -- Number of octets in a frame
+ K : integer range 0 to 32 := 1; -- Number of frames in a multiframe
sync_char : std_logic_vector(7 downto 0) := "10111100"; -- K
-- character
-- for syncing
@@ 31,11 35,9 @@ entity frame_alignment is
A_replace_data : std_logic_vector(7 downto 0) := "01111100"); -- The character to replace with upon receiving /A/ with scrambled data
port (
ci_char_clk : in std_logic; -- Character clock
+ ci_frame_clk : in std_logic; -- Frame clock
ci_reset : in std_logic; -- Reset (asynchronous, active low)
- ci_F : in integer range 0 to 256; -- The number of octets in a frame
- ci_K : in integer range 0 to 32; -- The number of frames in a multiframe
ci_request_sync : in std_logic; -- Whether sync is requested
- ci_scrambled : in std_logic; -- Whether the data is scrambled
ci_realign : in std_logic; -- Whether to realign to last
-- alignment character
di_char : in character_vector; -- The received character
@@ 44,14 46,25 @@ entity frame_alignment is
-- the alignment
co_correct_sync_chars : out integer; -- Number of alignment characters on
-- same position in a row
- do_char : out frame_character); -- The output character
- -- (going to transport layer)
+ do_aligned_chars : out std_logic_vector(8*F - 1 downto 0);
+ co_frame_state : out frame_state); -- Errors for current or next frame
+ -- a characters in a frame
end entity frame_alignment;
architecture a1 of frame_alignment is
- type alignment_state is (INIT, RECEIVED_K, ALIGNED, MISALIGNED);
+ type alignment_state is (INIT, ALIGNED, MISALIGNED);
signal reg_state : alignment_state := INIT;
+ signal next_frame_state : frame_state;
+
+ signal buffer_character : std_logic_vector(7 downto 0) := "00000000";
+ signal buffer_raw_adjust_position : integer := 0;
+ signal buffer_adjust_position : integer := 0;
+ signal buffer_align_to : integer := 0;
+ signal buffer_read_position : integer := 0;
+ signal buffer_write_position : integer := 0;
+ signal buffer_filled : std_logic := '0';
+
signal reg_last_frame_data : std_logic_vector(7 downto 0) := "00000000";
signal next_is_last_octet : std_logic := '0';
@@ 62,31 75,49 @@ architecture a1 of frame_alignment is
signal is_wrong_char : std_logic := '0';
- signal reg_octet_index : integer range 0 to 256 := 0;
- signal reg_frame_index : integer range 0 to 32 := 0;
signal reg_correct_sync_chars : integer := 0;
signal reg_known_sync_char_position : integer range 0 to 256;
- 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", '0');
+ signal next_octet_index : integer := 0;
begin -- architecture a1
- set_next: process (ci_char_clk, ci_reset) is
+ data_buffer: entity work.ring_buffer
+ generic map (
+ BUFFER_SIZE => F*2,
+ READ_SIZE => F,
+ CHARACTER_SIZE => 8)
+ port map (
+ ci_clk => ci_char_clk,
+ ci_reset => ci_reset,
+ ci_adjust_position => buffer_adjust_position,
+ ci_read => ci_frame_clk,
+ di_character => buffer_character,
+ co_read => do_aligned_chars,
+ co_read_position => buffer_read_position,
+ co_write_position => buffer_write_position,
+ co_filled => buffer_filled);
+
+ next_frame: process (ci_frame_clk) is
+ begin -- process next_frame
+ if ci_reset = '0' then
+ co_frame_state <= ('0', '0', '0', '0', '0', '0', '0', '0');
+ elsif ci_frame_clk'event and ci_frame_clk = '1' then -- rising clock edge
+ co_frame_state <= next_frame_state;
+ end if;
+ end process next_frame;
+
+ set_next: process (ci_char_clk, ci_frame_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", 0, 0, '0');
+ if ci_reset = '1' and ci_frame_clk'event and ci_frame_clk = '1' then
+ if reg_state /= INIT then
+ next_frame_state <= ('1', '0', '0', '0', '0', '0', '0', '0');
+ end if;
+ end if;
+
+ if ci_reset = '0' then -- asynchronous reset (active
reg_state <= INIT;
- reg_correct_sync_chars <= 0;
+ reg_last_frame_data <= (others => '0');
+ next_frame_state <= ('0', '0', '0', '0', '0', '0', '0', '0');
elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge
- 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
reg_last_frame_data <= di_char.d8b;
@@ 94,87 125,75 @@ begin -- architecture a1
if ci_request_sync = '1' then
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;
+ next_frame_state <= ('0', '0', '0', '0', '0', '0', '0', '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
+ next_frame_state <= ('0', '0', '0', '0', '0', '0', '0', '0');
+ -- if a or f, align to it and move to aligned
+ if is_a = '1' or is_f = '1' then
+ -- align to current character.
+ buffer_align_to <= next_octet_index;
+ next_frame_state <= ('1', '0', '0', '0', '0', '0', '0', '0');
reg_state <= ALIGNED;
- end if; -- switch to aligned
+ end if;
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 di_char.kout = '1' and not (is_a = '1' or is_f = '1') then
+ next_frame_state.invalid_characters <= '1';
+ end if;
+ if di_char.disparity_error = '1' then
+ next_frame_state.disparity_error <= '1';
+ end if;
+ if di_char.missing_error then
+ next_frame_state.not_in_table_error <= '1';
+ end if;
+ if di_char.user_data = '0' then
+ next_frame_state.user_data <= '0';
+ end if;
if reg_state = ALIGNED then
if is_wrong_char = '1' then
+ next_frame_state.wrong_alignment <= '1';
reg_state <= MISALIGNED;
reg_correct_sync_chars <= 1;
- reg_known_sync_char_position <= reg_octet_index;
+ reg_known_sync_char_position <= next_octet_index;
end if;
elsif reg_state = MISALIGNED then
+ next_frame_state.wrong_alignment <= '1';
if is_wrong_char = '1' then
- if reg_known_sync_char_position = reg_octet_index then
+ if reg_known_sync_char_position = next_octet_index then
reg_correct_sync_chars <= reg_correct_sync_chars + 1;
else
- reg_known_sync_char_position <= reg_octet_index;
+ reg_known_sync_char_position <= next_octet_index;
reg_correct_sync_chars <= 1;
end if;
elsif is_wrong_char = '0' and (is_f = '1' or is_a = '1') then
reg_correct_sync_chars <= 0;
reg_state <= ALIGNED;
elsif ci_realign = '1' then
- reg_correct_sync_chars <= 0;
- reg_octet_index <= (reg_octet_index + ((ci_F - 1) - reg_known_sync_char_position)) mod ci_F;
- do_char.octet_index <= (reg_octet_index + ((ci_F - 1) - reg_known_sync_char_position)) mod ci_F;
-
- reg_frame_index <= reg_frame_index + 1;
- do_char.frame_index <= reg_frame_index + 1;
+ -- align to last known sync char position
+ buffer_align_to <= reg_known_sync_char_position;
reg_state <= ALIGNED;
end if;
end if;
- end if; -- in RECEIVED_K
+ end if;
end if; -- clk, reset
end process set_next;
- is_wrong_char <= (is_f and not next_is_last_octet) or (is_a and not (next_is_last_octet and next_is_last_frame));
- next_char.kout <= di_char.kout when is_f = '0' and is_a = '0' else '0';
- next_char.d8b <= di_char.d8b when is_f = '0' and is_a = '0' else
- reg_last_frame_data when ci_scrambled = '0' else
+ co_correct_sync_chars <= reg_correct_sync_chars;
+ buffer_raw_adjust_position <= (buffer_align_to + 1 - buffer_read_position) mod F;
+ buffer_adjust_position <= buffer_raw_adjust_position when buffer_raw_adjust_position < F/2 + 1
+ else buffer_raw_adjust_position - F;
+
+ is_wrong_char <= (is_f and not next_is_last_octet) or (is_a and not next_is_last_octet);
+ buffer_character <= di_char.d8b when is_f = '0' and is_a = '0' else
+ reg_last_frame_data when SCRAMBLED else
F_replace_data when is_f = '1' else
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';
+ next_octet_index <= buffer_write_position mod F;
+ next_is_last_octet <= '1' when F = 1 or next_octet_index = F - 2 else '0';
is_f <= '1' when di_char.d8b = F_char and di_char.kout = '1' else '0';
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) mod ci_K;
- next_octet_index <= (reg_octet_index + 1) mod ci_F;
-
- co_correct_sync_chars <= reg_correct_sync_chars;
co_error <= '1' when reg_state = MISALIGNED else '0';
co_aligned <= '1' when reg_state = ALIGNED else '0';
end architecture a1;