M src/data_link/char_alignment.vhd => src/data_link/char_alignment.vhd +35 -34
@@ 17,47 17,48 @@ use ieee.std_logic_1164.all;
entity char_alignment is
generic (
- sync_char : std_logic_vector(9 downto 0) := "0011111010" -- The character used for synchronization (positive RD)
+ CHANNEL_WIDTH : integer := 1;
+ sync_char : std_logic_vector(9 downto 0) := "0011111010" -- The character used for synchronization (positive RD)
);
port (
- ci_char_clk: in std_logic; -- The character clock
- ci_reset : in std_logic; -- The reset, active high.
- di_10b : in std_logic_vector(9 downto 0); -- The 8b/10b encoded input data from physical layer
- ci_synced : in std_logic; -- Whether the receiver is currently synchronized
- do_10b : out std_logic_vector(9 downto 0); -- The 8b/10b encoded data aligned with a character (if co_aligned is true, otherwise unknown)
- co_aligned : out std_logic); -- Whether the output is currently aligned
+ ci_link_clk : in std_logic; -- The character clock
+ ci_reset : in std_logic; -- The reset, active high.
+ di_chars : in std_logic_vector(10*CHANNEL_WIDTH-1 downto 0); -- The 8b/10b encoded input data from physical layer
+ ci_synced : in std_logic; -- Whether the receiver is currently synchronized
+ do_chars : out std_logic_vector(10*CHANNEL_WIDTH-1 downto 0); -- The 8b/10b encoded data aligned with a character (if co_aligned is true, otherwise unknown)
+ co_aligned : out std_logic); -- Whether the output is currently aligned
end entity char_alignment;
architecture a1 of char_alignment is
- signal next_cache_10b : std_logic_vector(19 downto 0) := (others => '0'); -- The next value of cache_10b
- signal next_do_10b : std_logic_vector(9 downto 0) := (others => '0'); -- The next value of do_10b
- signal next_co_aligned : std_logic := '0';
+ signal next_cache_chars : std_logic_vector(2*10*CHANNEL_WIDTH-1 downto 0) := (others => '0'); -- The next value of cache_10b
+ signal next_do_chars : std_logic_vector(10*CHANNEL_WIDTH-1 downto 0) := (others => '0'); -- The next value of do_10b
+ signal next_co_aligned : std_logic := '0';
- signal reg_found_sync_char : std_logic := '0'; -- Whether sync char was found
- signal reg_cache_10b : std_logic_vector(19 downto 0) := (others => '0'); -- The cache of 10b characters.
- signal reg_do_10b : std_logic_vector(9 downto 0) := (others => '0');
- signal reg_alignment_index : integer range 0 to 16 := 0; -- Where the character starts in the cache, if aligned.
- signal reg_last_synced : std_logic := '0'; -- The last value of ci_synced
- signal reg_co_aligned : std_logic := '0'; -- Whether aligned
+ signal reg_found_sync_char : std_logic := '0'; -- Whether sync char was found
+ signal reg_cache_chars : std_logic_vector(2*10*CHANNEL_WIDTH-1 downto 0) := (others => '0'); -- The cache of 10b characters.
+ signal reg_do_chars : std_logic_vector(10*CHANNEL_WIDTH-1 downto 0) := (others => '0');
+ signal reg_alignment_index : integer range 0 to 16 := 0; -- Where the character starts in the cache, if aligned.
+ signal reg_last_synced : std_logic := '0'; -- The last value of ci_synced
+ signal reg_co_aligned : std_logic := '0'; -- Whether aligned
begin -- architecture a1
-- purpose: Set next signals
- -- type : combinational
+ -- type : sequential
-- inputs : clk, reset
-- outputs: alignment_index, cache_10b, do_10b, co_aligned
- set_next: process (ci_char_clk, ci_reset) is
+ set_next : process (ci_link_clk, ci_reset) is
begin -- process set_next
if ci_reset = '0' then
reg_last_synced <= '0';
- reg_co_aligned <= '0';
- reg_cache_10b <= (others => '0');
- reg_do_10b <= (others => '0');
- elsif rising_edge(ci_char_clk) then
+ reg_co_aligned <= '0';
+ reg_cache_chars <= (others => '0');
+ reg_do_chars <= (others => '0');
+ elsif rising_edge(ci_link_clk) then
reg_last_synced <= ci_synced;
- reg_co_aligned <= next_co_aligned;
- reg_cache_10b <= next_cache_10b;
- reg_do_10b <= next_do_10b;
+ reg_co_aligned <= next_co_aligned;
+ reg_cache_chars <= next_cache_chars;
+ reg_do_chars <= next_do_chars;
end if;
end process set_next;
@@ 65,12 66,12 @@ begin -- architecture a1
-- type : sequential
-- inputs : ci_char_clk, ci_reset, di_10b, ci_synced
-- outputs: reg_found_sync_char, reg_alignment_index
- find_sync_char: process (ci_char_clk, ci_reset) is
+ find_sync_char: process (ci_link_clk, ci_reset) is
begin -- process find_sync_char
if ci_reset = '0' then -- asynchronous reset (active low)
reg_alignment_index <= 0;
reg_found_sync_char <= '0';
- elsif rising_edge(ci_char_clk) then -- rising clock edge
+ elsif rising_edge(ci_link_clk) then -- rising clock edge
if reg_found_sync_char = '1' then
reg_found_sync_char <= '0';
end if;
@@ 78,10 79,10 @@ begin -- architecture a1
-- will be set by 8b10b_decoder)
if ci_synced = '0' then
-- Try to find /K/ (sync_char) in either RD (either sync_char or not sync_char).
- for i in 0 to 9 loop
- if reg_cache_10b(i+9 downto i) = sync_char or reg_cache_10b(i+9 downto i) = not sync_char then
+ for i in 0 to (2*CHANNEL_WIDTH-1)*10-1 loop
+ if reg_cache_chars(i+9 downto i) = sync_char or reg_cache_chars(i+9 downto i) = not sync_char then
reg_found_sync_char <= '1';
- reg_alignment_index <= i;
+ reg_alignment_index <= i mod 10;
end if;
end loop; -- i
end if;
@@ 89,9 90,9 @@ begin -- architecture a1
end process find_sync_char;
co_aligned <= reg_co_aligned;
- do_10b <= reg_do_10b;
+ do_chars <= reg_do_chars;
- next_co_aligned <= (reg_found_sync_char or reg_co_aligned) and not (reg_last_synced and not ci_synced);
- next_do_10b(9 downto 0) <= reg_cache_10b(reg_alignment_index+9 downto reg_alignment_index);
- next_cache_10b(19 downto 0) <= reg_cache_10b(9 downto 0) & di_10b(9 downto 0);
+ next_co_aligned <= (reg_found_sync_char or reg_co_aligned) and not (reg_last_synced and not ci_synced);
+ next_do_chars(CHANNEL_WIDTH*10-1 downto 0) <= reg_cache_chars(reg_alignment_index+CHANNEL_WIDTH*10-1 downto reg_alignment_index);
+ next_cache_chars(2*CHANNEL_WIDTH*10-1 downto 0) <= reg_cache_chars(CHANNEL_WIDTH*10-1 downto 0) & di_chars(CHANNEL_WIDTH*10-1 downto 0);
end architecture a1;
M src/data_link/data_link_layer.vhd => src/data_link/data_link_layer.vhd +43 -30
@@ 28,6 28,10 @@ entity data_link_layer is
A_character : std_logic_vector(7 downto 0) := "01111100"; -- multiframe end
Q_character : std_logic_vector(7 downto 0) := "10011100"; -- 2nd ILAS frame
-- 2nd character
+ CHANNEL_WIDTH : integer := 1; -- How many
+ -- characters are on
+ -- the input of the
+ -- layer
ALIGN_BUFFER_SIZE : integer := 255; -- Size of a
-- buffer that is
-- used for
@@ 39,7 43,7 @@ entity data_link_layer is
F : integer range 1 to 256 := 2; -- Number of octets in a frame
K : integer range 1 to 32 := 1); -- Number of frames in a mutliframe
port (
- ci_char_clk : in std_logic; -- Character clock
+ ci_link_clk : in std_logic; -- Link clk (character clk divided by CHANNEL_WIDTH)
ci_frame_clk : in std_logic; -- Frame clock
ci_reset : in std_logic; -- Reset (asynchronous, active low)
@@ 53,15 57,15 @@ entity data_link_layer is
-- input, output
co_synced : out std_logic; -- Whether the lane is synced
- di_10b : in std_logic_vector(9 downto 0); -- The 10b input character
+ di_chars : in std_logic_vector(10*CHANNEL_WIDTH-1 downto 0); -- The 10b input characters
do_aligned_chars : out std_logic_vector(8*F - 1 downto 0);
co_frame_state : out frame_state); -- The aligned frame output character
end entity data_link_layer;
architecture a1 of data_link_layer is
- signal char_alignment_do_10b : std_logic_vector(9 downto 0);
+ signal char_alignment_do_chars : std_logic_vector(10*CHANNEL_WIDTH-1 downto 0);
- signal decoder_do_char : character_vector;
+ signal decoder_do_chars : character_array(0 to CHANNEL_WIDTH-1);
signal error_handler_co_request_sync : std_logic;
@@ 69,7 73,7 @@ architecture a1 of data_link_layer is
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_do_char : character_array(0 to CHANNEL_WIDTH-1);
signal lane_alignment_co_correct_sync_chars : integer;
signal frame_alignment_ci_request_sync : std_logic;
@@ 123,12 127,13 @@ begin -- architecture a1
link_controller_ci_resync <= error_handler_co_request_sync or ci_request_sync;
link_controller : entity work.link_controller
generic map (
- SUBCLASSV => SUBCLASSV,
- F => F,
- K => K)
+ CHANNEL_WIDTH => CHANNEL_WIDTH,
+ SUBCLASSV => SUBCLASSV,
+ F => F,
+ K => K)
port map (
ci_frame_clk => ci_frame_clk,
- ci_char_clk => ci_char_clk,
+ ci_link_clk => ci_link_clk,
ci_reset => ci_reset,
ci_resync => link_controller_ci_resync,
ci_lane_alignment_error => lane_alignment_co_error,
@@ 136,36 141,43 @@ begin -- architecture a1
ci_lane_alignment_ready => lane_alignment_co_ready,
ci_frame_alignment_error => frame_alignment_co_error,
ci_frame_alignment_aligned => frame_alignment_co_aligned,
- di_char => decoder_do_char,
+ di_chars => decoder_do_chars,
co_synced => link_controller_co_synced,
co_state => link_controller_co_state,
do_config => link_controller_do_config);
-- char alignment
- char_alignment: entity work.char_alignment
+ char_alignment : entity work.char_alignment
+ generic map (
+ CHANNEL_WIDTH => CHANNEL_WIDTH)
port map (
- ci_char_clk => ci_char_clk,
+ ci_link_clk => ci_link_clk,
ci_reset => ci_reset,
ci_synced => link_controller_co_synced,
- di_10b => di_10b,
- do_10b => char_alignment_do_10b);
-
- -- 8b10b decoder
- an8b10b_decoder: entity work.an8b10b_decoder
- port map (
- ci_char_clk => ci_char_clk,
- ci_reset => ci_reset,
- di_10b => char_alignment_do_10b,
- do_char => decoder_do_char);
+ di_chars => di_chars,
+ do_chars => char_alignment_do_chars);
+
+ -- 8b10b decoders (for each character)
+ decode : for i in 0 to CHANNEL_WIDTH - 1 generate
+ constant lower_bit_position : integer := CHANNEL_WIDTH*10 - (i + 1)*10;
+ begin
+ an8b10b_decoder : entity work.an8b10b_decoder
+ port map (
+ ci_link_clk => ci_link_clk,
+ ci_reset => ci_reset,
+ di_chars => char_alignment_do_chars(lower_bit_position + 9 downto lower_bit_position),
+ do_chars => decoder_do_chars(i));
+ end generate decode;
-- lane alignment
lane_alignment : entity work.lane_alignment
generic map (
- BUFFER_SIZE => ALIGN_BUFFER_SIZE,
- F => F,
- K => K)
+ CHANNEL_WIDTH => CHANNEL_WIDTH,
+ BUFFER_SIZE => ALIGN_BUFFER_SIZE,
+ F => F,
+ K => K)
port map (
- ci_char_clk => ci_char_clk,
+ ci_link_clk => ci_link_clk,
ci_reset => ci_reset,
ci_state => link_controller_co_state,
ci_realign => lane_alignment_ci_realign,
@@ 178,11 190,12 @@ begin -- architecture a1
-- frame alignment
frame_alignment : entity work.frame_alignment
generic map (
- SCRAMBLING => SCRAMBLING,
- F => F,
- K => K)
+ CHANNEL_WIDTH => CHANNEL_WIDTH,
+ SCRAMBLING => SCRAMBLING,
+ F => F,
+ K => K)
port map (
- ci_char_clk => ci_char_clk,
+ ci_link_clk => ci_link_clk,
ci_frame_clk => ci_frame_clk,
ci_reset => ci_reset,
co_frame_state => frame_alignment_co_frame_state,
M src/data_link/data_link_pkg.vhd => src/data_link/data_link_pkg.vhd +1 -12
@@ 11,18 11,7 @@ package data_link_pkg is
user_data : std_logic; -- Whether the data is user data (in
-- DATA state, false otherwise)
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; -- The position of the octet in a
- -- frame
- frame_index : integer range 0 to 32; -- The position of the frame in multiframe
- user_data : std_logic; -- Whether the data is user data (in
- -- DATA state, false otherwise)
- end record frame_character;
+ type character_array is array (natural range <>) of character_vector;
type link_state is (
INIT, -- Initial state, waiting for /K/ characters
M src/data_link/frame_alignment.vhd => src/data_link/frame_alignment.vhd +21 -18
@@ 19,22 19,24 @@ use work.transport_pkg.all;
entity frame_alignment is
generic (
- SCRAMBLING : std_logic; -- 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
+ CHANNEL_WIDTH : integer := 1;
+ SCRAMBLING : std_logic; -- 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
+ BUFFER_SIZE : integer := 2*F;
sync_char : std_logic_vector(7 downto 0) := "10111100"; -- K
-- character
- -- for syncing
+ -- for syncing
A_char : std_logic_vector(7 downto 0) := "01111100"; -- Last
-- character
- -- in multiframe
+ -- in multiframe
F_char : std_logic_vector(7 downto 0) := "11111100"; -- Last
-- character
-- in frame
F_replace_data : std_logic_vector(7 downto 0) := "11111100"; -- The character to replace with upon receiving /F/ with scrambled data
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_link_clk : in std_logic; -- Character clock
ci_frame_clk : in std_logic; -- Frame clock
ci_reset : in std_logic; -- Reset (asynchronous, active low)
ci_request_sync : in std_logic; -- Whether sync is requested
@@ 78,24 80,25 @@ architecture a1 of frame_alignment is
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 F := 0;
+ signal next_octet_index : integer range 0 to F := 0;
signal next_adjusted_octet_index : integer range 0 to F := 0;
begin -- architecture a1
- data_buffer: entity work.ring_buffer
+ data_buffer : entity work.ring_buffer
generic map (
- BUFFER_SIZE => F*2,
+ BUFFER_SIZE => BUFFER_SIZE,
READ_SIZE => F,
+ WRITE_SIZE => CHANNEL_WIDTH,
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);
+ ci_clk => ci_link_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
M src/data_link/ilas_parser.vhd => src/data_link/ilas_parser.vhd +9 -5
@@ 14,6 14,7 @@ use ieee.numeric_std.all;
entity ilas_parser is
generic (
+ CHANNEL_WIDTH : integer := 1;
F : integer range 1 to 256; -- Number of octets in a frame
K : integer range 1 to 32; -- Number of frames in a multiframe
K_character : std_logic_vector(7 downto 0) := "10111100"; -- Character
@@ 30,7 31,7 @@ entity ilas_parser is
multiframes_count : integer range 1 to 32 := 4);
port (
- ci_char_clk : in std_logic; -- Character clock
+ ci_link_clk : in std_logic; -- Link clock
ci_reset : in std_logic; -- Reset (asynchonous, active low)
ci_state : in link_state; -- State of the lane
di_char : in character_vector; -- Character from 8b10b decoder
@@ 58,7 59,6 @@ architecture a1 of ilas_parser is
signal finished : std_logic := '0';
signal err : std_logic := '0';
-
function getOctetUpIndex (
octet_index : integer range 0 to F*K+5)
return integer is
@@ 104,7 104,7 @@ begin -- architecture a1
-- and co_wrong_chksum or co_unexpected_char. Stop processing.
-- The controller will then request new synchronization try.
- set_next: process (ci_char_clk, ci_reset) is
+ set_next: process (ci_link_clk, ci_reset) is
begin -- process set_next
if ci_reset = '0' then -- asynchronous reset (active low)
reg_octet_index <= 0;
@@ 117,10 117,14 @@ begin -- architecture a1
end if;
end process set_next;
- check_chars: process (ci_char_clk, ci_reset) is
+ check_chars: process (ci_link_clk, ci_reset) is
variable up_index : integer range 7 to link_config_length-1;
variable processing_ilas : std_logic;
begin -- process check_chars
+ -- if in CGS, find first non /K/ character after 4 /K/ characters,
+ -- then move to ILS
+ -- take care that /R/ may be at any position, not just the first one.
+ -- store some kind of position information of the next link dta
processing_ilas := next_processing_ilas or reg_processing_ilas;
if ci_reset = '0' then -- asynchronous reset (active low)
err <= '0';
@@ 128,7 132,7 @@ begin -- architecture a1
co_wrong_chksum <= '0';
finished <= '0';
link_config_data <= (others => '0');
- elsif ci_char_clk'event and ci_char_clk = '1' and (processing_ilas = '0' or ci_state = INIT) then
+ elsif ci_link_clk'event and ci_link_clk = '1' and (processing_ilas = '0' or ci_state = INIT) then
err <= '0';
co_unexpected_char <= '0';
co_wrong_chksum <= '0';
M src/data_link/lane_alignment.vhd => src/data_link/lane_alignment.vhd +33 -18
@@ 15,6 15,7 @@ use work.data_link_pkg.all;
entity lane_alignment is
generic (
+ CHANNEL_WIDTH : integer := 1;
F : integer range 1 to 256; -- Number of octets in a frame
K : integer range 1 to 32; -- Number of frames in a multiframe
BUFFER_SIZE : integer := 256; -- How many octets to keep
@@ 23,21 24,21 @@ entity lane_alignment is
-- Character to send before the buffer is ready and started
port (
- ci_char_clk : in std_logic; -- Character clock
+ ci_link_clk : in std_logic; -- Link clock
ci_reset : in std_logic; -- Reset (asynchronous, active low)
ci_start : in std_logic; -- Start sending the data from the
-- buffer.
- ci_state : in link_state; -- State of the lane
+ ci_state : in link_state; -- State of the lane
ci_realign : in std_logic; -- Whether to realign to the last
-- found alignment character
- di_char : in character_vector; -- Character from 8b10b decoder
+ di_chars : in character_array; -- Character from 8b10b decoder
co_ready : out std_logic; -- Whether /A/ was received and
-- waiting for start
co_aligned : out std_logic; -- Whether the alignment is still correct
- co_correct_sync_chars : out integer; -- How many alignment characters on
- -- correct place were found in a row
+ co_correct_sync_chars : out integer; -- How many alignment characters on
+ -- correct place were found in a row
co_error : out std_logic; -- Whether there is an error
- do_char : out character_vector); -- The aligned output character
+ do_chars : out character_array); -- The aligned output character
end entity lane_alignment;
@@ 59,6 60,7 @@ architecture a1 of lane_alignment is
signal next_error : std_logic := '0';
begin -- architecture a1
set_next : process (ci_char_clk, ci_reset) is
+ variable ready : std_logic := '0';
begin -- process set_next
if ci_reset = '0' then -- asynchronous reset (active low)
reg_write_index <= 0;
@@ 68,16 70,29 @@ begin -- architecture a1
reg_error <= '0';
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;
- reg_ready <= next_ready;
- reg_started <= next_started;
- reg_error <= next_error;
- buff(reg_write_index).d8b <= di_char.d8b;
- buff(reg_write_index).kout <= di_char.kout;
- buff(reg_write_index).disparity_error <= di_char.disparity_error;
- buff(reg_write_index).missing_error <= di_char.missing_error;
- buff(reg_write_index).user_data <= '1' when ci_state = DATA else '0';
+ ready := reg_ready;
+ if ci_state = INIT or reg_ready = '0' then
+ ready := '0';
+ reg_read_index <= 0;
+ reg_write_index <= 0;
+ end if;
+
+ reg_write_index <= reg_write_index + CHANNEL_WIDTH;
+ reg_read_index <= reg_read_index + CHANNEL_WIDTH;
+ reg_ready <= ready;
+ reg_started <= next_started;
+ reg_error <= next_error;
+ for i in 0 to CHANNEL_WIDTH - 1 loop
+ -- if CGS, look for /R/, if /R/, set that as starting index
+ if ci_state = CGS then
+
+ end if;
+ buff((reg_write_index + i) mod BUFFER_SIZE).d8b <= di_chars(i).d8b;
+ buff((reg_write_index + i) mod BUFFER_SIZE).kout <= di_chars(i).kout;
+ buff((reg_write_index + i) mod BUFFER_SIZE).disparity_error <= di_chars(i).disparity_error;
+ buff((reg_write_index + i) mod BUFFER_SIZE).missing_error <= di_chars(i).missing_error;
+ buff((reg_write_index + i) mod BUFFER_SIZE).user_data <= '1' when ci_state = DATA else '0';
+ end loop; -- i
end if;
end process set_next;
@@ 102,7 117,7 @@ begin -- architecture a1
'1' when reg_ready = '1' and reg_started = '0' and (reg_write_index = 0) else
'0';
- do_char <= dummy_character when ci_state = INIT or reg_started = '0' else
- buff(reg_read_index);
+ do_chars <= dummy_characters when ci_state = INIT or reg_started = '0' else
+ buff(reg_read_index to reg_read_index + CHANNEL);
end architecture a1;
M src/data_link/link_controller.vhd => src/data_link/link_controller.vhd +53 -28
@@ 20,15 20,15 @@ use work.data_link_pkg.all;
entity link_controller is
generic (
- SUBCLASSV : integer range 0 to 1 := 0;
- F : integer range 1 to 256; -- Number of octets in a frame
- K : integer range 1 to 32; -- Number of frames in a multiframe
- K_character : std_logic_vector(7 downto 0) := "10111100"); -- Sync character
+ CHANNEL_WIDTH : integer := 1; -- Number of characters going in at once
+ F : integer range 1 to 256; -- Number of octets in a frame
+ K : integer range 1 to 32; -- Number of frames in a multiframe
+ K_character : std_logic_vector(7 downto 0) := "10111100"); -- Sync character
port (
- ci_frame_clk : in std_logic; -- Frame clock
- ci_char_clk : in std_logic; -- Character clock
- ci_reset : in std_logic; -- Reset (asynchronous, active low)
- di_char : in character_vector; -- Output character from 8b10b decoder
+ ci_frame_clk : in std_logic; -- Frame clock
+ ci_link_clk : in std_logic; -- Link clock
+ ci_reset : in std_logic; -- Reset (asynchronous, active low)
+ di_chars : in character_array(0 to CHANNEL_WIDTH-1); -- Output character from 8b10b decoder
do_config : out link_config; -- Config found in ILAS
@@ 71,36 71,64 @@ architecture a1 of link_controller is
signal reg_state : link_state := INIT;
signal reg_k_counter : integer range 0 to 15 := 0;
- signal ilas_finished : std_logic := '0';
- signal ilas_error : std_logic := '0';
- signal ilas_wrong_chksum : std_logic := '0';
+ signal ilas_finished : std_logic := '0';
+ signal ilas_error : std_logic := '0';
+ signal ilas_wrong_chksum : std_logic := '0';
signal ilas_unexpected_char : std_logic := '0';
+
+ signal any_missing_error : std_logic;
+ signal any_disparity_error : std_logic;
begin -- architecture a1
- ilas: entity work.ilas_parser
+ ilas : entity work.ilas_parser
generic map (
- F => F,
- K => K)
+ CHANNEL_WIDTH => CHANNEL_WIDTH,
+ F => F,
+ K => K)
port map (
ci_char_clk => ci_char_clk,
ci_reset => ci_reset,
ci_state => reg_state,
- di_char => di_char,
+ di_chars => di_chars,
do_config => do_config,
co_finished => ilas_finished,
co_error => ilas_error,
co_wrong_chksum => ilas_wrong_chksum,
co_unexpected_char => ilas_unexpected_char);
- set_state: process (ci_char_clk, ci_reset) is
- variable char_error : std_logic;
+ set_state: process (ci_link_clk, ci_reset) is
+ variable chars_error : std_logic := '0';
+ variable chars_missing_error : std_logic := '0';
+ variable chars_disparity_error : std_logic := '0';
+ variable k_count : integer := 0;
begin -- process set_state
if ci_reset = '0' then -- asynchronous reset (active low)
reg_state <= INIT;
- elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge
- char_error := di_char.disparity_error or di_char.missing_error;
+ reg_k_counter <= '0';
+ correct_8b10b_characters <= 0;
+ elsif ci_link_clk'event and ci_link_clk = '1' then -- rising clock edge
+ k_count := reg_k_counter;
+ for i in 0 to CHANNEL_WIDTH - 1 loop
+ if di_chars(i).disparity_error = '1' then
+ chars_disparity_error := '1';
+ end if;
+ if di_chars(i).missing_error = '1' then
+ chars_missing_error := '1';
+ end if;
+
+ if di_chars(i).d8b = K_character and di_chars(i).kout = '1' then
+ k_count := k_count + 1;
+ else
+ k_count := 0;
+ end if;
+ end loop; -- i
+ chars_error := chars_missing_error or chars_disparity_error;
if correct_8b10b_characters < FULL_SYNCHRONIZATION_AFTER and char_error = '0' then
- correct_8b10b_characters <= correct_8b10b_characters + 1;
+ if correct_8b10b_characters + CHANNEL_WIDTH > FULL_SYNCHRONIZATION_AFTER then
+ correct_8b10b_characters <= FULL_SYNCHRONIZATION_AFTER;
+ else
+ correct_8b10b_characters <= correct_8b10b_characters + CHANNEL_WIDTH;
+ end if;
end if;
if ci_resync = '1' or (full_synchronization = '0' and char_error = '1') then
@@ 109,15 137,11 @@ begin -- architecture a1
elsif reg_state = CGS then
if reg_k_counter < SYNC_COUNT then
correct_8b10b_characters <= 1;
- if di_char.d8b = K_character and di_char.kout = '1' then
- reg_k_counter <= reg_k_counter + 1;
- else
- reg_k_counter <= 0;
- end if;
- elsif di_char.d8b /= K_character or di_char.kout = '0' then
+ reg_k_counter <= k_count;
+ elsif k_count = 0 then
reg_state <= ILS;
end if;
- elsif di_char.d8b = K_character and di_char.kout = '1' then
+ elsif k_count > 0 then
reg_state <= CGS;
reg_k_counter <= 0;
elsif reg_state = ILS then
@@ 137,9 161,10 @@ begin -- architecture a1
co_synced <= synced;
co_state <= reg_state;
+
-- TODO: add ILAS errors, add CGS error in case sync does not happen for long
-- time
- co_error <= ci_lane_alignment_error or ci_frame_alignment_error or di_char.missing_error or di_char.disparity_error;
+ co_error <= ci_lane_alignment_error or ci_frame_alignment_error or any_missing_error or any_disparity_error;
co_uncorrectable_error <= ilas_error;
end architecture a1;
M src/data_link/ring_buffer.vhd => src/data_link/ring_buffer.vhd +3 -2
@@ 7,6 7,7 @@ entity ring_buffer is
generic (
CHARACTER_SIZE : integer := 8;
BUFFER_SIZE : integer;
+ WRITE_SIZE : integer := 1;
READ_SIZE : integer); -- The size of the buffer
port (
@@ 15,7 16,7 @@ entity ring_buffer is
ci_adjust_position : in integer range -READ_SIZE/2-1 to READ_SIZE/2+1;
ci_read : in std_logic; -- One to read in current cycle, Zero
-- to stay on current reading position
- di_character : in std_logic_vector(CHARACTER_SIZE-1 downto 0); -- The character to save on next clock
+ di_character : in std_logic_vector(CHARACTER_SIZE*WRITE_SIZE-1 downto 0); -- The character to save on next clock
co_read : out std_logic_vector(CHARACTER_SIZE*READ_SIZE - 1 downto 0); -- The output characters read from the buffer
co_size : out integer; -- The current count of filled data
co_read_position : out integer; -- The current read position inside of
@@ 68,7 69,7 @@ begin -- architecture a1
end if;
adjusted_read_position <= read_position + ci_adjust_position;
- buff(CHARACTER_SIZE*BUFFER_SIZE-1 - CHARACTER_SIZE*write_position downto CHARACTER_SIZE*BUFFER_SIZE - CHARACTER_SIZE*(write_position + 1)) <= di_character;
+ buff(CHARACTER_SIZE*BUFFER_SIZE-1 - CHARACTER_SIZE*WRITE_SIZE*write_position downto CHARACTER_SIZE*BUFFER_SIZE - CHARACTER_SIZE*WRITE_SIZE*(write_position + 1)) <= di_character;
write_position <= (write_position + 1) mod BUFFER_SIZE;
end if;
end process read;
M testbench/data_link/char_alignment_tb.vhd => testbench/data_link/char_alignment_tb.vhd +9 -9
@@ 31,9 31,9 @@ architecture a1 of char_alignment_tb is
data_count => 10,
synced_after => 4,
expected_aligned_after => 4,
- expected_alignment_index => 2,
- data => (0 => "1111101000", 1 => "0000010100", 2 => "1010101011", 3 => "0101010110", 4 => "1110000001", 5 => "0001111111", 6 => "0000000000", others => "0000000000"),
- expected_data => (0 => "0011111010", 1 => "1100000101", 2 => "1010101010", 3 => "0101010101", 4 => "1111100000", 5 => "0000011111", others => "0000000000")
+ expected_alignment_index => 1,
+ data => (0 => "0111110100", 1 => "0000010100", 2 => "1010101011", 3 => "0101010101", 4 => "1111000000", 5 => "0000111110", 6 => "0000000000", others => "0000000000"),
+ expected_data => (0 => "0011111010", 1 => "0000001010", 2 => "0101010101", 3 => "1010101010", 4 => "1111100000", 5 => "0000011111", others => "0000000000")
)
);
@@ 51,14 51,14 @@ architecture a1 of char_alignment_tb is
signal cycle_num : integer := 0;
begin -- architecture a1
- uut: entity work.char_alignment
+ uut : entity work.char_alignment
port map (
- ci_char_clk => clk,
+ ci_link_clk => clk,
ci_reset => reset,
- di_10b => di_10b,
- do_10b => do_10b,
+ di_chars => di_10b,
+ do_chars => do_10b,
ci_synced => ci_synced,
- co_aligned => co_aligned);
+ co_aligned => co_aligned);
clk_gen: process is
begin -- process clk_gen
@@ 94,7 94,7 @@ begin -- architecture a1
end if;
if cycle >= test_vec.synced_after then
- assert (do_10b = test_vec.expected_data(cycle - 3)) report "The data does not match, data index: " & integer'image(i) & ", expected: " & vec2str(test_vec.expected_data(cycle - 2)) & ", got: " & vec2str(do_10b) severity error;
+ assert (do_10b = test_vec.expected_data(cycle - 2)) report "The data does not match, data index: " & integer'image(i) & ", expected: " & vec2str(test_vec.expected_data(cycle - 2)) & ", got: " & vec2str(do_10b) severity error;
end if;
wait for clk_period;