M src/data_link/frame_alignment.vhd => src/data_link/frame_alignment.vhd +96 -74
@@ 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,51 @@ 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;
+ signal next_adjusted_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');
+ buffer_align_to <= -1;
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 127,76 @@ 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 + buffer_read_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 not 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_adjusted_octet_index <= (buffer_write_position - buffer_read_position - buffer_adjust_position) mod F;
+ next_octet_index <= (buffer_write_position - buffer_read_position) mod F;
+ next_is_last_octet <= '1' when next_adjusted_octet_index = F - 1 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;
A src/data_link/ring_buffer.vhd => src/data_link/ring_buffer.vhd +78 -0
@@ 0,0 1,78 @@
+library ieee;
+use work.data_link_pkg.all;
+use ieee.std_logic_1164.all;
+
+entity ring_buffer is
+
+ generic (
+ CHARACTER_SIZE : integer := 8;
+ BUFFER_SIZE : integer;
+ READ_SIZE : integer); -- The size of the buffer
+
+ port (
+ ci_clk : in std_logic; -- The clock
+ ci_reset : in std_logic; -- The reset (active low)
+ 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
+ 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
+ -- the buffer
+ co_write_position : out integer; -- The current write position
+ -- next character will be written to
+ co_filled : out std_logic); -- Whether the buffer is full
+
+end entity ring_buffer;
+
+architecture a1 of ring_buffer is
+ signal buff : std_logic_vector(CHARACTER_SIZE*BUFFER_SIZE-1 downto 0);
+ signal buff_triple : std_logic_vector(3*CHARACTER_SIZE*BUFFER_SIZE-1 downto 0);
+ signal next_read : std_logic_vector(CHARACTER_SIZE*BUFFER_SIZE-1 downto 0);
+ signal read_position : integer := 0;
+ signal adjusted_read_position : integer := 0;
+ signal write_position : integer := 0;
+ signal reg_size : integer := 0;
+ signal size : integer := 0;
+begin -- architecture a1
+ -- purpose: Adjust read position and read next character
+ -- type : sequential
+ -- inputs : ci_clk, ci_reset
+ -- outputs: read_position, write_position, buff
+ read: process (ci_clk, ci_reset) is
+ begin -- process read
+ if ci_reset = '0' then -- asynchronous reset (active low)
+ buff <= (others => '0');
+ read_position <= 0;
+ write_position <= 0;
+ reg_size <= 0;
+ co_read_position <= 0;
+ elsif ci_clk'event and ci_clk = '1' then -- rising clock edge
+ if ci_read = '1' and size >= READ_SIZE + ci_adjust_position then
+ read_position <= (read_position + ci_adjust_position + READ_SIZE) mod BUFFER_SIZE;
+ co_read_position <= read_position + ci_adjust_position;
+ reg_size <= size - READ_SIZE - ci_adjust_position + 1;
+ co_read <= buff_triple(2*CHARACTER_SIZE*BUFFER_SIZE - 1 - (read_position + ci_adjust_position)*CHARACTER_SIZE downto 2*CHARACTER_SIZE*BUFFER_SIZE - (read_position + ci_adjust_position + READ_SIZE)*CHARACTER_SIZE);
+ else
+ reg_size <= reg_size + 1;
+ 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;
+ write_position <= (write_position + 1) mod BUFFER_SIZE;
+ end if;
+ end process read;
+
+ co_write_position <= write_position;
+ co_size <= size;
+ size <= BUFFER_SIZE when reg_size > BUFFER_SIZE else
+ reg_size;
+ buff_triple(3*CHARACTER_SIZE*BUFFER_SIZE - 1 downto 2*CHARACTER_SIZE*BUFFER_SIZE) <= buff;
+ buff_triple(2*CHARACTER_SIZE*BUFFER_SIZE - 1 downto CHARACTER_SIZE*BUFFER_SIZE) <= buff;
+ buff_triple(CHARACTER_SIZE*BUFFER_SIZE - 1 downto 0) <= buff;
+
+ co_filled <= '1' when reg_size > BUFFER_SIZE else
+ '0';
+
+end architecture a1;
M src/transport/octets_to_sample.vhd => src/transport/octets_to_sample.vhd +64 -58
@@ 16,23 16,23 @@ use work.transport_pkg.all;
entity octets_to_samples is
generic (
CS : integer := 1; -- Number of control bits per sample
- M : integer := 1; -- Number of converters
- S : integer := 1; -- Number of samples
- L : integer := 1; -- Number of lanes
- F : integer := 2; -- Number of octets in a frame
+ M : integer := 1; -- Number of converters
+ S : integer := 1; -- Number of samples
+ L : integer := 1; -- Number of lanes
+ F : integer := 2; -- Number of octets in a frame
CF : integer := 0; -- Number of control words
- N : integer := 12; -- Size of a sample
- Nn : integer := 16); -- Size of a word (sample + ctrl if CF
+ N : integer := 12; -- Size of a sample
+ Nn : integer := 16); -- Size of a word (sample + ctrl if CF
-- =0
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)
- di_lanes_data : in frame_character_array(0 to L-1); -- Data from the lanes
- -- bits
- co_correct_data : out std_logic; -- Whether output is correct
- do_samples_data : out samples_array(0 to M - 1, 0 to S - 1)); -- The
- -- output samples
+ ci_frame_clk : in std_logic; -- Frame clock
+ ci_reset : in std_logic; -- Reset (asynchronous, active low)
+ di_lanes_data : in lane_character_array(0 to L-1)(F*8-1 downto 0); -- Data from the lanes
+ -- bits
+ ci_frame_states : in frame_state_array(0 to L-1);
+ co_frame_state : out frame_state;
+ do_samples_data : out samples_array(0 to M - 1, 0 to S - 1)); -- The
+ -- output samples
end entity octets_to_samples;
architecture a1 of octets_to_samples is
@@ 45,62 45,68 @@ architecture a1 of octets_to_samples is
signal next_samples_data : samples_array
(0 to M - 1, 0 to S - 1)
(data(N - 1 downto 0), ctrl_bits(CS - 1 downto 0));
-
- signal reg_all_user_data : std_logic; -- if '0', set correct_data to '0'.
- signal next_correct_data : std_logic; -- if '0', set correct_data to '0'.
signal reg_error : std_logic; -- if err, repeat last samples.
- signal new_frame : std_logic; -- Whether current frame is new frame
+ signal current_frame_state : frame_state;
signal reg_buffered_data : std_logic_vector(L*F*8-1 downto 0) := (others => '0');
- signal current_buffered_data : std_logic_vector(L*F*8-1 downto 0) := (others => '0');
- signal buffered_data : std_logic_vector(L*F*8-1 downto 0) := (others => '0');
+ signal reg_state_user_data : std_logic_vector(L-1 downto 0);
+ signal reg_state_invalid_character : std_logic_vector(L-1 downto 0);
+ signal reg_state_not_enough_data : std_logic_vector(L-1 downto 0);
+ signal reg_state_ring_buffer_overflow : std_logic_vector(L-1 downto 0);
+ signal reg_state_disparity_error : std_logic_vector(L-1 downto 0);
+ signal reg_state_not_in_table_error : std_logic_vector(L-1 downto 0);
+ signal reg_state_wrong_alignment : std_logic_vector(L-1 downto 0);
+ signal reg_state_last_frame_repeated : std_logic_vector(L-1 downto 0);
+
+ signal any_error : std_logic := '0';
+ constant all_ones : std_logic_vector(L-1 downto 0) := (others => '1');
+ constant all_zeros : std_logic_vector(L-1 downto 0) := (others => '0');
begin -- architecture a
- set_data: process (ci_char_clk, ci_reset) is
+ set_data: process (ci_frame_clk, ci_reset) is
begin -- process set_data
if ci_reset = '0' then -- asynchronous reset (active low)
- co_correct_data <= '0';
- reg_all_user_data <= '1';
reg_error <= '0';
reg_buffered_data <= (others => '0');
- next_correct_data <= '0';
- elsif ci_char_clk'event and ci_char_clk = '1' then -- rising clock edge
- if di_lanes_data(0).octet_index = 0 then
- reg_all_user_data <= '1';
- end if;
+ elsif ci_frame_clk'event and ci_frame_clk = '1' then -- rising clock edge
do_samples_data <= next_samples_data;
- co_correct_data <= next_correct_data;
- if new_frame = '1' then
- if reg_error = '1' then
- next_samples_data <= prev_samples_data;
- else
- next_samples_data <= samples_data;
- prev_samples_data <= samples_data;
- end if;
+ co_frame_state <= current_frame_state;
- reg_buffered_data <= (others => '0');
- next_correct_data <= reg_all_user_data;
- reg_all_user_data <= '1';
- reg_error <= '0';
- else
- for i in 0 to L-1 loop
- reg_buffered_data(L*F*8 - 1 - i*F*8 - 8*di_lanes_data(i).octet_index downto L*F*8 - 1 - i*F*8 - 8*di_lanes_data(i).octet_index - 7) <= di_lanes_data(i).d8b;
-
- if di_lanes_data(i).user_data = '0' or di_lanes_data(i).disparity_error = '1' or di_lanes_data(i).missing_error = '1' then
- reg_all_user_data <= '0';
- end if;
- end loop; -- i
+ if any_error = '0' then
+ prev_samples_data <= samples_data;
end if;
+
+ for i in 0 to L-1 loop
+ reg_buffered_data(L*F*8 - 1 - i*F*8 downto L*F*8 - (i + 1)*F*8) <= di_lanes_data(i);
+ reg_state_user_data(i) <= ci_frame_states(i).user_data;
+ reg_state_invalid_character(i) <= ci_frame_states(i).invalid_characters;
+ reg_state_not_enough_data(i) <= ci_frame_states(i).not_enough_data;
+ reg_state_ring_buffer_overflow(i) <= ci_frame_states(i).ring_buffer_overflow;
+ reg_state_disparity_error(i) <= ci_frame_states(i).disparity_error;
+ reg_state_not_in_table_error(i) <= ci_frame_states(i).not_in_table_error;
+ reg_state_wrong_alignment(i) <= ci_frame_states(i).wrong_alignment;
+ reg_state_last_frame_repeated(i) <= ci_frame_states(i).last_frame_repeated;
+ end loop; -- i
end if;
end process set_data;
- new_frame <= '1' when di_lanes_data(0).octet_index = F - 1 else '0';
-
- last_octet_data: for i in 0 to L-1 generate
- current_buffered_data(L*F*8 - 1 - i*F*8 - (F - 1)*8 downto L*F*8 - 1 - i*F*8 - (F - 1)*8 - 7) <= di_lanes_data(i).d8b;
- end generate last_octet_data;
+ -- set output error in case any lane has an error
+ current_frame_state.user_data <= '1' when reg_state_user_data = all_ones else '0';
+ current_frame_state.invalid_characters <= '0' when reg_state_invalid_character = all_zeros else '1';
+ current_frame_state.not_enough_data <= '0' when reg_state_not_enough_data = all_zeros else '1';
+ current_frame_state.ring_buffer_overflow <= '0' when reg_state_ring_buffer_overflow = all_zeros else '1';
+ current_frame_state.disparity_error <= '0' when reg_state_disparity_error = all_zeros else '1';
+ current_frame_state.not_in_table_error <= '0' when reg_state_not_in_table_error = all_zeros else '1';
+ current_frame_state.wrong_alignment <= '0' when reg_state_wrong_alignment = all_zeros else '1';
+ current_frame_state.last_frame_repeated <= '1' when any_error = '1' else '0';
- buffered_data <= current_buffered_data or reg_buffered_data;
+ any_error <= '1' when current_frame_state.invalid_characters = '1' or
+ current_frame_state.not_enough_data = '1' or
+ current_frame_state.ring_buffer_overflow = '1' or
+ current_frame_state.disparity_error = '1' or
+ current_frame_state.not_in_table_error = '1' or
+ current_frame_state.wrong_alignment = '1' else '0';
+ next_samples_data <= samples_data when any_error = '0' else prev_samples_data;
-- for one or multiple lanes if CF = 0
-- (no control words)
@@ 108,10 114,10 @@ begin -- architecture a
multi_lane_no_cf: if CF = 0 generate
converters: for ci in 0 to M - 1 generate
samples: for si in 0 to S - 1 generate
- samples_data(ci, si).data <= buffered_data(L*F*8 - 1 - ci*Nn*S - si*Nn downto L*F*8 - 1 - ci*Nn*S - si*Nn - N + 1);
+ samples_data(ci, si).data <= reg_buffered_data(L*F*8 - 1 - ci*Nn*S - si*Nn downto L*F*8 - 1 - ci*Nn*S - si*Nn - N + 1);
control_bits: if CS > 0 generate
- samples_data(ci, si).ctrl_bits <= buffered_data(L*F*8 - 1 - ci*Nn*S - si*Nn - N downto L*F*8 - 1 - ci*Nn*S - si*Nn - N - CS + 1);
+ samples_data(ci, si).ctrl_bits <= reg_buffered_data(L*F*8 - 1 - ci*Nn*S - si*Nn - N downto L*F*8 - 1 - ci*Nn*S - si*Nn - N - CS + 1);
end generate control_bits;
end generate samples;
end generate converters;
@@ 123,10 129,10 @@ begin -- architecture a
cf_groups: for cfi in 0 to CF-1 generate
converters: for ci in 0 to M/CF-1 generate
samples: for si in 0 to S - 1 generate
- samples_data(ci + cfi*M/CF, si).data <= buffered_data(L*F*8 - 1 - cfi*F*8*L/CF - ci*Nn*S - si*Nn downto L*F*8 - 1 - cfi*F*8*L/CF - ci*Nn*S - si*Nn - N + 1);
+ samples_data(ci + cfi*M/CF, si).data <= reg_buffered_data(L*F*8 - 1 - cfi*F*8*L/CF - ci*Nn*S - si*Nn downto L*F*8 - 1 - cfi*F*8*L/CF - ci*Nn*S - si*Nn - N + 1);
control_bits: if CS > 0 generate
- samples_data(ci + cfi*M/CF, si).ctrl_bits <= buffered_data(L*F*8 - 1 - cfi*F*8*L/CF - (M/CF)*S*Nn - ci*S*CS - si*CS downto L*F*8 - 1 - cfi*F*8*L/CF - (M/CF)*Nn*S - ci*S*CS - si*CS - CS + 1);
+ samples_data(ci + cfi*M/CF, si).ctrl_bits <= reg_buffered_data(L*F*8 - 1 - cfi*F*8*L/CF - (M/CF)*S*Nn - ci*S*CS - si*CS downto L*F*8 - 1 - cfi*F*8*L/CF - (M/CF)*Nn*S - ci*S*CS - si*CS - CS + 1);
end generate control_bits;
end generate samples;
end generate converters;
M src/transport/transport_layer.vhd => src/transport/transport_layer.vhd +6 -8
@@ 27,13 27,10 @@ entity transport_layer is
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)
- di_lanes_data : in frame_character_array(0 to L - 1); -- Data from the lanes
-
- co_correct_data : out std_logic; -- Whether the current data are correct
- -- user data
- do_samples_data : out samples_array(0 to M - 1, 0 to S - 1)); -- Samples
- -- in the
- -- given frame
+ ci_frame_states : in frame_state_array(0 to L-1);
+ co_frame_state : out frame_state;
+ do_samples_data : out samples_array(0 to M - 1, 0 to S - 1)); -- The
+ -- output samples
end entity transport_layer;
architecture a1 of transport_layer is
@@ 54,8 51,9 @@ begin -- architecture a1
ci_char_clk => ci_char_clk,
ci_frame_clk => ci_frame_clk,
ci_reset => ci_reset,
+ ci_frame_states => ci_frame_states,
di_lanes_data => di_lanes_data,
- co_correct_data => co_correct_data,
+ co_frame_state => co_frame_staet,
do_samples_data => do_samples_data);
end architecture a1;
M src/transport/transport_pkg.vhd => src/transport/transport_pkg.vhd +20 -1
@@ 11,8 11,27 @@ package transport_pkg is
ctrl_bits : std_logic_vector;
end record sample;
+ type frame_state is record -- An errors passed from data_link to transport
+ user_data : std_logic; -- All characters are user_data
+ invalid_characters : std_logic; -- Any of the charachers should not be
+ -- there (ie. there is a control)
+ not_enough_data : std_logic; -- There is not enough data in the
+ -- buffer, data will be sent on next
+ -- frame clock
+ ring_buffer_overflow : std_logic; -- Buffer storing characters has overflowed,
+ -- meaning frame clock is too slow
+ disparity_error : std_logic; -- Any character had disparity error
+ not_in_table_error : std_logic; -- Any character not in table
+ wrong_alignment : std_logic; -- Alignment character was detected to
+ -- be on wrong position, possible misalignment
+ last_frame_repeated : std_logic; -- Whether last frame was repeated
+ -- instead of new frame
+ end record frame_state;
+
+ type frame_state_array is array (natural range <>) of frame_state;
+
-- Array of frame characters (characters in one frame)
- type frame_character_array is array (natural range <>) of frame_character;
+ type lane_character_array is array (natural range <>) of std_logic_vector;
-- Array of samples in one frame by converter and by sample (used with oversampling)
type samples_array is array (natural range <>, natural range <>) of sample;
M testbench/data_link/frame_alignment_tb.vhd => testbench/data_link/frame_alignment_tb.vhd +72 -60
@@ 2,18 2,20 @@ library ieee;
use ieee.std_logic_1164.all;
use work.testing_functions.all;
use work.data_link_pkg.all;
+use work.transport_pkg.all;
entity frame_alignment_tb is
end entity frame_alignment_tb;
architecture a1 of frame_alignment_tb is
+ constant F : integer range 0 to 256 := 5;
+ constant K : integer range 0 to 32 := 4;
+
type test_vector is record
ci_request_sync : std_logic;
- ci_scrambled : std_logic;
ci_realign : std_logic;
di_char : character_vector;
- expected_char : frame_character;
expected_aligned : std_logic;
expected_error : std_logic;
@@ 23,55 25,58 @@ 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 aler oct fram
- ('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'), '0', '1'),
- ('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'), '0', '1'),
- ('0', '1', '1', ('0', '0', '0', "01111100", '0'), ('0', '0', '0', "01111100", 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'),
- ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 3, 3, '0'), '1', '0')
+ ('1', '0', ('1', '0', '0', "10111100", '0'), '0', '0'),
+ ('1', '0', ('1', '0', '0', "10111100", '0'), '0', '0'),
+ ('0', '0', ('1', '0', '0', "10111100", '0'), '0', '0'),
+ ('0', '0', ('1', '0', '0', "10111100", '0'), '0', '0'),
+ ('0', '0', ('0', '0', '0', "11000001", '1'), '0', '0'), -- frame begins
+ ('0', '0', ('0', '0', '0', "11000010", '1'), '0', '0'),
+ ('0', '0', ('0', '0', '0', "11000011", '1'), '0', '0'),
+ ('0', '0', ('0', '0', '0', "11000100", '1'), '0', '0'),
+ ('0', '0', ('1', '0', '0', "11111100", '1'), '0', '0'), -- frame ends
+ ('0', '0', ('0', '0', '0', "00000001", '1'), '1', '0'),
+ ('0', '0', ('1', '0', '0', "00000010", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00000011", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00000100", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00000000", '1'), '1', '0'), -- frame ends
+ ('0', '0', ('1', '0', '0', "11111100", '1'), '0', '1'), -- frame begins, /A/
+ ('0', '0', ('1', '0', '0', "11111100", '1'), '0', '1'), -- frame begins, /A/
+ ('0', '0', ('0', '0', '0', "01000001", '1'), '0', '1'),
+ ('0', '0', ('0', '0', '0', "01000010", '1'), '0', '1'),
+ ('0', '0', ('0', '0', '0', "01000011", '1'), '0', '1'),
+ ('0', '0', ('0', '0', '0', "01000100", '1'), '0', '1'),
+ ('0', '0', ('1', '0', '0', "11111100", '1'), '0', '1'),
+ ('0', '1', ('0', '0', '0', "00100001", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00100010", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00100011", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00100100", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "10000101", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "01000001", '1'), '1', '0'), -- frame begins
+ ('0', '0', ('0', '0', '0', "01000010", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "01000011", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "01000100", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "01000101", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00100001", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00100010", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00100011", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00100100", '1'), '1', '0'),
+ ('0', '0', ('1', '0', '0', "11111100", '1'), '1', '0'),
+ ('0', '0', ('0', '0', '0', "00000000", '1'), '1', '0')
);
- constant clk_period : time := 1 ns;
-
- constant F : integer range 0 to 256 := 5;
- constant K : integer range 0 to 32 := 4;
+ constant char_clk_period : time := 1 ns;
+ constant frame_clk_period : time := 1 ns * F;
- signal clk : std_logic := '0';
+ signal char_clk : std_logic := '0';
+ signal frame_clk : std_logic := '0';
signal reset : std_logic := '0';
signal di_char : character_vector;
- signal do_char : frame_character;
+ signal do_aligned_chars : std_logic_vector(8*F - 1 downto 0);
+ signal co_frame_state : frame_state;
signal ci_request_sync : std_logic;
signal ci_realign : std_logic;
- signal ci_scrambled : std_logic;
signal co_aligned : std_logic;
signal co_error : std_logic;
@@ 79,28 84,37 @@ architecture a1 of frame_alignment_tb is
begin -- architecture a1
uut : entity work.frame_alignment
+ generic map (
+ SCRAMBLED => false,
+ F => F,
+ K => K)
port map (
- ci_char_clk => clk,
- ci_reset => reset,
- ci_F => F,
- ci_K => K,
- ci_scrambled => ci_scrambled,
- ci_request_sync => ci_request_sync,
- ci_realign => ci_realign,
- di_char => di_char,
- co_aligned => co_aligned,
- co_error => co_error,
- do_char => do_char);
+ ci_frame_clk => frame_clk,
+ ci_char_clk => char_clk,
+ ci_reset => reset,
+ ci_request_sync => ci_request_sync,
+ ci_realign => ci_realign,
+ di_char => di_char,
+ co_aligned => co_aligned,
+ co_error => co_error,
+ do_aligned_chars => do_aligned_chars,
+ co_frame_state => co_frame_state);
clk_gen: process is
begin -- process clk_gen
- wait for clk_period/2;
- clk <= not clk;
+ wait for char_clk_period/2;
+ char_clk <= not char_clk;
end process clk_gen;
+
+ frame_clk_gen: process is
+ begin -- process clk_gen
+ wait for frame_clk_period/2;
+ frame_clk <= not frame_clk;
+ end process frame_clk_gen;
reset_gen: process is
begin -- process reset_gen
- wait for clk_period*2;
+ wait for char_clk_period*2;
reset <= '1';
end process reset_gen;
@@ 108,13 122,12 @@ begin -- architecture a1
variable test_vec : test_vector;
variable prev_test_vec : test_vector;
begin -- process test
- wait for clk_period*2;
+ wait for char_clk_period*2;
for i in test_vectors'range loop
test_data_index <= i;
test_vec := test_vectors(i);
di_char <= test_vec.di_char;
- ci_scrambled <= test_vec.ci_scrambled;
ci_realign <= test_vec.ci_realign;
ci_request_sync <= test_vec.ci_request_sync;
@@ 123,10 136,9 @@ 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_error = prev_test_vec.expected_error report "The error does not match. 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;
- wait for clk_period;
+ wait for char_clk_period;
end loop; -- i
wait for 100 ms;
end process test;
A testbench/data_link/ring_buffer_tb.vhd => testbench/data_link/ring_buffer_tb.vhd +99 -0
@@ 0,0 1,99 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use work.testing_functions.all;
+use work.data_link_pkg.all;
+
+entity ring_buffer_tb is
+
+end entity ring_buffer_tb;
+
+architecture a1 of ring_buffer_tb is
+ type test_vector is record
+ di_character : std_logic_vector(7 downto 0);
+ ci_read : std_logic;
+ ci_adjust_position : integer;
+ end record test_vector;
+
+ type test_vector_array is array (natural range <>) of test_vector;
+
+ constant test_vectors : test_vector_array :=
+ (
+ ("00000000", '0', 0),
+ ("00000001", '0', 0),
+ ("00000010", '0', 0),
+ ("00000011", '0', 0),
+ ("00000100", '0', 0),
+ ("11111111", '0', 0),
+ ("00000110", '0', 0),
+ ("00000111", '1', 2),
+ ("00001000", '0', 0),
+ ("00001001", '0', 0),
+ ("11111111", '0', 0),
+ ("00000001", '0', 0),
+ ("00000010", '1', 0),
+ ("00000011", '0', 0),
+ ("00000100", '0', 0),
+ ("11111111", '0', 0),
+ ("00000000", '0', 0),
+ ("00000000", '1', 0),
+ ("01000000", '0', 0),
+ ("01000000", '0', 0),
+ ("11111111", '0', 0),
+ ("01000000", '0', 0),
+ ("01000000", '0', 0),
+ ("01000000", '0', 0),
+ ("01000000", '0', 0),
+ ("11111111", '1', 0),
+ ("01000000", '0', 0),
+ ("01000000", '1', 0),
+ ("01000000", '0', 0)
+ );
+ signal F : integer := 5;
+
+ constant clk_period : time := 1 ns;
+ signal clk : std_logic := '0';
+ signal reset : std_logic := '0';
+ signal ci_read : std_logic;
+ signal ci_adjust_position : integer;
+ signal di_character : std_logic_vector(7 downto 0);
+ signal co_read : std_logic_vector(F*8-1 downto 0);
+ signal co_size : integer;
+ signal co_filled : std_logic;
+
+ signal test_data_index : integer := 0;
+begin -- architecture a1
+ uut : entity work.ring_buffer
+ generic map (
+ READ_SIZE => F,
+ BUFFER_SIZE => 2*F
+ )
+ port map (
+ ci_clk => clk,
+ ci_reset => reset,
+ di_character => di_character,
+ ci_adjust_position => ci_adjust_position,
+ ci_read => ci_read,
+ co_read => co_read,
+ co_size => co_size,
+ co_filled => co_filled);
+
+ clk <= not clk after clk_period/2;
+ reset <= '1' after clk_period*2;
+
+ test: process is
+ begin -- process test
+ wait for clk_period*2;
+
+ for i in test_vectors'range loop
+ test_data_index <= i;
+ di_character <= test_vectors(i).di_character;
+ ci_read <= test_vectors(i).ci_read;
+ ci_adjust_position <= test_vectors(i).ci_adjust_position;
+
+ wait for clk_period;
+ end loop; -- i
+
+ wait for 100 ms;
+ end process test;
+
+end architecture a1;
M testbench/transport/octets_to_samples_fc_tb.vhd => testbench/transport/octets_to_samples_fc_tb.vhd +25 -34
@@ 16,83 16,74 @@ architecture a1 of octets_to_samples_fc_tb is
constant CF : integer := 1; -- Count of control word bits
constant N : integer := 4; -- Sample size
constant Nn : integer := 4;
- constant CLK_PERIOD : time := 1 ns;
+ constant CLK_PERIOD : time := 5 ns;
- constant DUMMY_FC : frame_character := ('1', '1', '1', "11111111", 0, 0, '1');
constant DUMMY_S : sample := ("0000", "0");
type test_vector is record
- di_lanes_data : frame_character_array (0 to L - 1);
+ di_lanes_data : lane_character_array (0 to L - 1) (F*8-1 downto 0);
+ ci_frame_states : frame_state_array (0 to L - 1);
expected_result : integer;
end record test_vector;
type result_vector is record
- co_correct_data : std_logic;
do_samples_data : samples_array (0 to M - 1, 0 to S - 1)(data(M - 1 downto 0), ctrl_bits(CONTROL_SIZE - 1 downto 0));
+ co_frame_state : frame_state;
end record result_vector;
+ constant dummy_frame_state : frame_state := ('0', '0', '0', '0', '0', '0', '0', '0');
+
type test_vector_array is array (natural range<>) of test_vector;
constant test_vectors : test_vector_array :=
(
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "10111110", 0, 0, '1'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "00010100", 1, 0, '1'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "10100000", 2, 0, '1'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "00010001", 0, 1, '1'), others => DUMMY_FC), 0),
- ((('0', '0', '0', "00010001", 1, 1, '1'), others => DUMMY_FC), 0),
- ((('0', '0', '0', "11110000", 2, 1, '1'), others => DUMMY_FC), 0),
- ((('0', '0', '0', "11101110", 0, 2, '1'), others => DUMMY_FC), 1),
- ((('0', '0', '0', "11101110", 1, 2, '1'), others => DUMMY_FC), 1),
- ((('0', '0', '0', "00000000", 2, 2, '1'), others => DUMMY_FC), 1),
- ((('0', '0', '0', "00000000", 0, 3, '1'), others => DUMMY_FC), 2),
- ((('0', '0', '0', "11100000", 1, 3, '1'), others => DUMMY_FC), 2),
- ((('0', '0', '0', "11100000", 2, 3, '1'), others => DUMMY_FC), 2)
+ (("000000000000000000000000", others => (others => '0')), (('0', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), -1),
+ (("101111100001010010100000", others => (others => '0')), (('1', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), -1),
+ (("000100010001000111110000", others => (others => '0')), (('1', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), 0),
+ (("111011101110111000000000", others => (others => '0')), (('1', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), 1),
+ (("000000001110000011100000", others => (others => '0')), (('1', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), 2)
);
type result_vector_array is array (natural range<>) of result_vector;
constant result_vectors : result_vector_array :=
(
(
- '1',
(
(("1011", "1"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S),
(("0100", "0"), others => DUMMY_S)
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
),
(
- '1',
(
(("0001", "1"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S)
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
),
(
- '1',
(
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S)
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
)
);
- signal ci_char_clk : std_logic := '0';
signal ci_frame_clk : std_logic := '0';
signal ci_reset : std_logic := '0';
- signal di_lanes_data : frame_character_array(0 to L - 1);
+ signal di_lanes_data : lane_character_array (0 to L - 1)(F*8-1 downto 0);
+ signal ci_frame_states : frame_state_array (0 to L - 1);
signal do_samples_data : samples_array
(0 to M - 1, 0 to S - 1)
(data(N - 1 downto 0), ctrl_bits(CONTROL_SIZE - 1 downto 0));
- signal co_correct_data : std_logic;
+ signal co_frame_state : frame_state;
signal test_data_index : integer := 0;
begin -- architecture a1
@@ 107,14 98,14 @@ begin -- architecture a1
N => N,
Nn => Nn)
port map (
- ci_char_clk => ci_char_clk,
ci_reset => ci_reset,
ci_frame_clk => ci_frame_clk,
di_lanes_data => di_lanes_data,
- co_correct_data => co_correct_data,
+ ci_frame_states => ci_frame_states,
+ co_frame_state => co_frame_state,
do_samples_data => do_samples_data);
- ci_char_clk <= not ci_char_clk after CLK_PERIOD/2;
+ ci_frame_clk <= not ci_frame_clk after CLK_PERIOD/2;
ci_reset <= '1' after CLK_PERIOD*2;
test: process is
@@ 128,13 119,13 @@ begin -- architecture a1
test_data_index <= i;
test_vec := test_vectors(i);
di_lanes_data <= test_vec.di_lanes_data;
+ ci_frame_states <= test_vec.ci_frame_states;
if i > 0 then
prev_test_vec := test_vectors(i - 1);
if prev_test_vec.expected_result /= -1 then
- assert co_correct_data = result_vectors(prev_test_vec.expected_result).co_correct_data report "The correct data does not match, Index: " & integer'image(i-1) severity error;
-
+ assert co_frame_state = result_vectors(prev_test_vec.expected_result).co_frame_state report "The frame state does not match, index: " & integer'image(prev_test_vec.expected_result) severity error;
for ci in 0 to M - 1 loop
for si in 0 to S - 1 loop
assert do_samples_data(ci, si).data = result_vectors(prev_test_vec.expected_result).do_samples_data(ci, si).data report "The samples data do not match, expected: " & vec2str(result_vectors(prev_test_vec.expected_result).do_samples_data(ci, si).data) & ", got: " & vec2str(dummy) & ", index: " & integer'image(i-1) & ", ci: " & integer'image(ci) & ", si: " & integer'image(si) severity error;
M testbench/transport/octets_to_samples_multi_cf_tb.vhd => testbench/transport/octets_to_samples_multi_cf_tb.vhd +23 -33
@@ 18,83 18,73 @@ architecture a1 of octets_to_samples_multi_fc_tb is
constant Nn : integer := 4;
constant CLK_PERIOD : time := 1 ns;
- constant DUMMY_FC : frame_character := ('1', '1', '1', "11111111", 0, 0, '1');
- constant DUMMY_S : sample := ("0000", "0");
type test_vector is record
- di_lanes_data : frame_character_array (0 to L - 1);
+ di_lanes_data : lane_character_array (0 to L - 1) (F*8-1 downto 0);
+ ci_frame_states : frame_state_array (0 to L - 1);
expected_result : integer;
end record test_vector;
type result_vector is record
- co_correct_data : std_logic;
do_samples_data : samples_array (0 to M - 1, 0 to S - 1)(data(M - 1 downto 0), ctrl_bits(CONTROL_SIZE - 1 downto 0));
+ co_frame_state : frame_state;
end record result_vector;
type test_vector_array is array (natural range<>) of test_vector;
constant test_vectors : test_vector_array :=
(
- ((('1', '0', '0', "00000000", 0, 0, '0'), ('1', '0', '0', "00000000", 0, 0, '0')), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), ('1', '0', '0', "00000000", 0, 0, '0')), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), ('1', '0', '0', "00000000", 0, 0, '0')), -1),
- ((('0', '0', '0', "00010101", 0, 0, '1'), ('0', '0', '0', "00110111", 0, 0, '1')), -1),
- ((('0', '0', '0', "00100110", 1, 0, '1'), ('0', '0', '0', "01001000", 1, 0, '1')), -1),
- ((('0', '0', '0', "01011010", 2, 0, '1'), ('0', '0', '0', "11110000", 2, 0, '1')), -1),
- ((('0', '0', '0', "00111111", 0, 1, '1'), ('0', '0', '0', "00001010", 0, 1, '1')), 0),
- ((('0', '0', '0', "11000101", 1, 1, '1'), ('0', '0', '0', "11110000", 1, 1, '1')), 0),
- ((('0', '0', '0', "00101101", 2, 1, '1'), ('0', '0', '0', "00101101", 2, 1, '1')), 0),
- ((('0', '0', '0', "00010101", 0, 1, '1'), ('0', '0', '0', "00110111", 0, 1, '1')), 1),
- ((('0', '0', '0', "00100110", 1, 1, '1'), ('0', '0', '0', "01001000", 1, 1, '1')), 1),
- ((('0', '0', '0', "01011010", 2, 1, '1'), ('0', '0', '0', "11110000", 2, 1, '1')), 1),
- ((('0', '0', '0', "00010101", 0, 1, '1'), ('0', '0', '0', "00110111", 0, 1, '1')), 2),
- ((('0', '0', '0', "00100110", 1, 1, '1'), ('0', '0', '0', "01001000", 1, 1, '1')), 2),
- ((('0', '0', '0', "01011010", 2, 1, '1'), ('0', '0', '0', "11110000", 2, 1, '1')), 2)
+ (("000000000000000000000000", "000000000000000000000000"), (('0', '0', '0', '0', '0', '0', '0', '0'), ('0', '0', '0', '0', '0', '0', '0', '0')), -1),
+ (("000101010010011001011010", "001101110100100011110000"), (('1', '0', '0', '0', '0', '0', '0', '0'), ('1', '0', '0', '0', '0', '0', '0', '0')), -1),
+ (("001111111100010100101101", "000010101111000000101101"), (('1', '0', '0', '0', '0', '0', '0', '0'), ('1', '0', '0', '0', '0', '0', '0', '0')), 0),
+ (("000101010010011001011010", "001101110100100011110000"), (('1', '0', '0', '0', '0', '0', '0', '0'), ('1', '0', '0', '0', '0', '0', '0', '0')), 1),
+ (("000101010010011001011010", "001101110100100011110000"), (('1', '0', '0', '0', '0', '0', '0', '0'), ('1', '0', '0', '0', '0', '0', '0', '0')), 2)
);
type result_vector_array is array (natural range<>) of result_vector;
constant result_vectors : result_vector_array :=
(
(
- '1',
(
(("0001", "01"), ("0101", "01")),
(("0010", "10"), ("0110", "10")),
(("0011", "11"), ("0111", "11")),
(("0100", "00"), ("1000", "00"))
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
),
(
- '1',
(
(("0011", "00"), ("1111", "10")),
(("1100", "11"), ("0101", "01")),
(("0000", "00"), ("1010", "10")),
(("1111", "11"), ("0000", "01"))
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
),
(
- '1',
(
(("0001", "01"), ("0101", "01")),
(("0010", "10"), ("0110", "10")),
(("0011", "11"), ("0111", "11")),
(("0100", "00"), ("1000", "00"))
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
)
);
- signal ci_char_clk : std_logic := '0';
signal ci_frame_clk : std_logic := '0';
signal ci_reset : std_logic := '0';
- signal di_lanes_data : frame_character_array(0 to L - 1);
+ signal di_lanes_data : lane_character_array (0 to L - 1)(F*8-1 downto 0);
+ signal ci_frame_states : frame_state_array (0 to L - 1);
signal do_samples_data : samples_array
(0 to M - 1, 0 to S - 1)
(data(N - 1 downto 0), ctrl_bits(CONTROL_SIZE - 1 downto 0));
- signal co_correct_data : std_logic;
+ signal co_frame_state : frame_state;
signal test_data_index : integer := 0;
begin -- architecture a1
+
uut : entity work.octets_to_samples
generic map (
CS => CONTROL_SIZE,
@@ 106,14 96,14 @@ begin -- architecture a1
N => N,
Nn => Nn)
port map (
- ci_char_clk => ci_char_clk,
ci_reset => ci_reset,
ci_frame_clk => ci_frame_clk,
di_lanes_data => di_lanes_data,
- co_correct_data => co_correct_data,
+ ci_frame_states => ci_frame_states,
+ co_frame_state => co_frame_state,
do_samples_data => do_samples_data);
- ci_char_clk <= not ci_char_clk after CLK_PERIOD/2;
+ ci_frame_clk <= not ci_frame_clk after CLK_PERIOD/2;
ci_reset <= '1' after CLK_PERIOD*2;
test: process is
@@ 127,13 117,13 @@ begin -- architecture a1
test_data_index <= i;
test_vec := test_vectors(i);
di_lanes_data <= test_vec.di_lanes_data;
+ ci_frame_states <= test_vec.ci_frame_states;
if i > 0 then
prev_test_vec := test_vectors(i - 1);
if prev_test_vec.expected_result /= -1 then
- assert co_correct_data = result_vectors(prev_test_vec.expected_result).co_correct_data report "The correct data does not match, Index: " & integer'image(i-1) severity error;
-
+ assert co_frame_state = result_vectors(prev_test_vec.expected_result).co_frame_state report "The frame state does not match, index: " & integer'image(prev_test_vec.expected_result) severity error;
for ci in 0 to M - 1 loop
for si in 0 to S - 1 loop
assert do_samples_data(ci, si).data = result_vectors(prev_test_vec.expected_result).do_samples_data(ci, si).data report "The samples data do not match, expected: " & vec2str(result_vectors(prev_test_vec.expected_result).do_samples_data(ci, si).data) & ", got: " & vec2str(dummy) & ", index: " & integer'image(i-1) & ", ci: " & integer'image(ci) & ", si: " & integer'image(si) severity error;
M testbench/transport/octets_to_samples_simp_tb.vhd => testbench/transport/octets_to_samples_simp_tb.vhd +29 -43
@@ 18,98 18,83 @@ architecture a1 of octets_to_samples_simp_tb is
constant Nn : integer := 8;
constant CLK_PERIOD : time := 1 ns;
- constant DUMMY_FC : frame_character := ('1', '1', '1', "11111111", 0, 0, '1');
constant DUMMY_S : sample := ("0000", "0");
type test_vector is record
- di_lanes_data : frame_character_array (0 to L - 1);
+ di_lanes_data : lane_character_array (0 to L - 1) (F*8-1 downto 0);
+ ci_frame_states : frame_state_array (0 to L - 1);
expected_result : integer;
end record test_vector;
type result_vector is record
- co_correct_data : std_logic;
do_samples_data : samples_array (0 to M - 1, 0 to S - 1)(data(M - 1 downto 0), ctrl_bits(CONTROL_SIZE - 1 downto 0));
+ co_frame_state : frame_state;
end record result_vector;
+ constant dummy_frame_state : frame_state := ('0', '0', '0', '0', '0', '0', '0', '0');
+
type test_vector_array is array (natural range<>) of test_vector;
constant test_vectors : test_vector_array :=
(
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('1', '0', '0', "00000000", 0, 0, '0'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "10111000", 0, 0, '1'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "11100000", 1, 0, '1'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "00011000", 2, 0, '1'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "01000000", 3, 0, '1'), others => DUMMY_FC), -1),
- ((('0', '0', '0', "00011000", 0, 1, '1'), others => DUMMY_FC), 0),
- ((('0', '0', '0', "00011000", 1, 1, '1'), others => DUMMY_FC), 0),
- ((('0', '0', '0', "00011000", 2, 1, '1'), others => DUMMY_FC), 0),
- ((('0', '0', '0', "00011000", 3, 1, '1'), others => DUMMY_FC), 0),
- ((('0', '0', '0', "11100000", 0, 2, '1'), others => DUMMY_FC), 1),
- ((('0', '0', '0', "11100000", 1, 2, '1'), others => DUMMY_FC), 1),
- ((('0', '0', '0', "11100000", 2, 2, '1'), others => DUMMY_FC), 1),
- ((('0', '0', '0', "11100000", 3, 2, '1'), others => DUMMY_FC), 1),
- ((('0', '0', '0', "11100000", 0, 3, '0'), others => DUMMY_FC), 2),
- ((('0', '0', '0', "11100000", 1, 3, '1'), others => DUMMY_FC), 2),
- ((('0', '0', '0', "11100000", 2, 3, '1'), others => DUMMY_FC), 2),
- ((('0', '0', '0', "11100000", 3, 3, '1'), others => DUMMY_FC), 2),
- ((('0', '0', '0', "11100000", 0, 3, '0'), others => DUMMY_FC), 3),
- ((('0', '0', '0', "11100000", 1, 3, '1'), others => DUMMY_FC), 3),
- ((('0', '0', '0', "11100000", 2, 3, '1'), others => DUMMY_FC), 3),
- ((('0', '0', '0', "11100000", 3, 3, '1'), others => DUMMY_FC), 3)
+ (("00000000000000000000000000000000", others => (others => '0')), (('0', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), -1),
+ (("10111000111000000001100001000000", others => (others => '0')), (('1', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), -1),
+ (("00011000000110000001100000011000", others => (others => '0')), (('1', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), 0),
+ (("11100000111000001110000011100000", others => (others => '0')), (('1', '0', '0', '0', '0', '0', '0', '0'), others => dummy_frame_state), 1),
+ (("00000000000000000000000000000000", others => (others => '0')), (('1', '1', '0', '0', '0', '1', '0', '0'), others => dummy_frame_state), 2),
+ (("11100000111000001110000011100000", others => (others => '0')), (('1', '1', '0', '0', '0', '1', '0', '0'), others => dummy_frame_state), 3),
+ (("00000000000000000000000000000000", others => (others => '0')), (('1', '1', '0', '0', '0', '1', '0', '0'), others => dummy_frame_state), -1)
);
type result_vector_array is array (natural range<>) of result_vector;
constant result_vectors : result_vector_array :=
(
(
- '1',
(
(("1011", "1"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S),
(("0100", "0"), others => DUMMY_S)
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
),
(
- '1',
(
(("0001", "1"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S),
(("0001", "1"), others => DUMMY_S)
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
),
(
- '1',
(
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S)
- )
+ ),
+ ('1', '0', '0', '0', '0', '0', '0', '0')
),
(
- '0',
(
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S),
(("1110", "0"), others => DUMMY_S)
- )
+ ),
+ ('1', '1', '0', '0', '0', '1', '0', '1')
)
);
- signal ci_char_clk : std_logic := '0';
signal ci_frame_clk : std_logic := '0';
signal ci_reset : std_logic := '0';
- signal di_lanes_data : frame_character_array(0 to L - 1);
+ signal di_lanes_data : lane_character_array (0 to L - 1)(F*8-1 downto 0);
+ signal ci_frame_states : frame_state_array (0 to L - 1);
signal do_samples_data : samples_array
(0 to M - 1, 0 to S - 1)
(data(N - 1 downto 0), ctrl_bits(CONTROL_SIZE - 1 downto 0));
- signal co_correct_data : std_logic;
+ signal co_frame_state : frame_state;
signal test_data_index : integer := 0;
begin -- architecture a1
@@ 124,16 109,17 @@ begin -- architecture a1
N => N,
Nn => Nn)
port map (
- ci_char_clk => ci_char_clk,
ci_reset => ci_reset,
ci_frame_clk => ci_frame_clk,
di_lanes_data => di_lanes_data,
- co_correct_data => co_correct_data,
+ ci_frame_states => ci_frame_states,
+ co_frame_state => co_frame_state,
do_samples_data => do_samples_data);
- ci_char_clk <= not ci_char_clk after CLK_PERIOD/2;
+ ci_frame_clk <= not ci_frame_clk after CLK_PERIOD/2;
ci_reset <= '1' after CLK_PERIOD*2;
+
test: process is
variable test_vec : test_vector;
variable prev_test_vec : test_vector;
@@ 145,13 131,13 @@ begin -- architecture a1
test_data_index <= i;
test_vec := test_vectors(i);
di_lanes_data <= test_vec.di_lanes_data;
+ ci_frame_states <= test_vec.ci_frame_states;
if i > 0 then
prev_test_vec := test_vectors(i - 1);
if prev_test_vec.expected_result /= -1 then
- assert co_correct_data = result_vectors(prev_test_vec.expected_result).co_correct_data report "The correct data does not match, Index: " & integer'image(i-1) severity error;
-
+ assert co_frame_state = result_vectors(prev_test_vec.expected_result).co_frame_state report "The frame state does not match, index: " & integer'image(prev_test_vec.expected_result) severity error;
for ci in 0 to M - 1 loop
for si in 0 to S - 1 loop
assert do_samples_data(ci, si).data = result_vectors(prev_test_vec.expected_result).do_samples_data(ci, si).data report "The samples data do not match, expected: " & vec2str(result_vectors(prev_test_vec.expected_result).do_samples_data(ci, si).data) & ", got: " & vec2str(dummy) & ", index: " & integer'image(i-1) & ", ci: " & integer'image(ci) & ", si: " & integer'image(si) severity error;