~ruther/jesd204b-vhdl

3f3f62d543b8d0d5dac9eb2f0c286b19a5c2c01f — František Boháček 2 years ago f776e82
feat(link): add counting of wrong sync characters on the same place in frame alignment
2 files changed, 58 insertions(+), 53 deletions(-)

M src/data_link/frame_alignment.vhd
M testbench/data_link/frame_alignment_tb.vhd
M src/data_link/frame_alignment.vhd => src/data_link/frame_alignment.vhd +34 -29
@@ 10,24 10,22 @@ entity frame_alignment is
    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;
    ci_reset          : in  std_logic;
    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_enable_realign : in  std_logic;  -- Whether to enable automatic realignment
    di_char           : in  character_vector;       -- The received character
    co_aligned        : out std_logic;
    co_misaligned     : out std_logic;
    do_char           : out frame_character);      -- The output character
    ci_char_clk           : in  std_logic;
    ci_reset              : in  std_logic;
    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;
    di_char               : in  character_vector;  -- The received character
    co_aligned            : out std_logic;
    co_error              : out std_logic;
    co_correct_sync_chars : out integer;
    do_char               : out frame_character);  -- The output character
end entity frame_alignment;

architecture a1 of frame_alignment is
  type alignment_state is (INIT, RECEIVED_K, ALIGNED, MISALIGNED, WRONG_ALIGNMENT);
  -- The states of alignment. MISALIGNED means first alignment error.
  -- WRONG_ALIGNMENT is for second alignment error. won't be set if
  -- ci_enable_realigned is set. Thnen realignment will be processed.
  type alignment_state is (INIT, RECEIVED_K, ALIGNED, MISALIGNED);
  signal reg_state : alignment_state := INIT;

  signal reg_last_frame_data : std_logic_vector(7 downto 0) := "00000000";


@@ 42,6 40,8 @@ architecture a1 of frame_alignment is

  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;


@@ 54,6 54,7 @@ begin  -- architecture a1
      reg_octet_index <= 0;
      do_char <= ('0', '0', '0', "00000000", 0, 0, '0');
      reg_state <= INIT;
      reg_correct_sync_chars <= 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;


@@ 101,25 102,28 @@ begin  -- architecture a1
        if reg_state = ALIGNED then
          if is_wrong_char = '1' then
            reg_state <= MISALIGNED;
            reg_correct_sync_chars <= 1;
            reg_known_sync_char_position <= reg_octet_index;
          end if;
        elsif reg_state = MISALIGNED then
          if is_wrong_char = '1' then

            if ci_enable_realign = '1' then
              reg_octet_index <= ci_F - 1;
              do_char.octet_index <= ci_F - 1;
            if reg_known_sync_char_position = reg_octet_index then
              reg_correct_sync_chars <= reg_correct_sync_chars + 1;
            else
              reg_state <= WRONG_ALIGNMENT;
              reg_known_sync_char_position <= reg_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;
            reg_state <= ALIGNED;
          end if;
        elsif reg_state = WRONG_ALIGNMENT then
          if is_wrong_char = '0' and (is_f = '1' or is_a = '1') then
            reg_state <= MISALIGNED;
          elsif ci_enable_realign = '1' and (is_f = '1' or is_a = '1') then
            do_char.octet_index <= ci_F - 1;
            reg_octet_index <= ci_F - 1;
          end if;
        end if;
      end if; -- in RECEIVED_K


@@ 146,6 150,7 @@ begin  -- architecture a1
                      (reg_frame_index + 1) mod ci_K;
  next_octet_index <= (reg_octet_index + 1) mod ci_F;

  co_misaligned <= '1' when reg_state = WRONG_ALIGNMENT else '0';
  co_aligned <= '1' when reg_state = ALIGNED or reg_state = MISALIGNED else '0';
  co_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;

M testbench/data_link/frame_alignment_tb.vhd => testbench/data_link/frame_alignment_tb.vhd +24 -24
@@ 10,19 10,19 @@ architecture a1 of frame_alignment_tb is
  type test_vector is record
    ci_request_sync : std_logic;
    ci_scrambled : std_logic;
    ci_enable_realign : std_logic;
    ci_realign : std_logic;
    di_char : character_vector;

    expected_char : frame_character;
    expected_aligned : std_logic;
    expected_misaligned : std_logic;
    expected_error : std_logic;

  end record test_vector;

  type test_vector_array is array (natural range<>) of test_vector;
  constant test_vectors : test_vector_array :=
  (
  -- rq  scra real  kout  der mer   data   expec kout  der  mer  data       almisal oct fram
  -- 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'),


@@ 34,7 34,7 @@ architecture a1 of frame_alignment_tb is
    ('0', '0', '0', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 2, 1, '0'), '1', '0'),
    ('0', '0', '0', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 3, 1, '0'), '1', '0'),
    ('0', '0', '0', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "01010101", 4, 1, '0'), '1', '0'),
    ('0', '0', '0', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "01010101", 0, 2, '0'), '1', '0'),
    ('0', '0', '0', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "01010101", 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'),


@@ 51,11 51,11 @@ architecture a1 of frame_alignment_tb is
    ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 2, 1, '0'), '1', '0'),
    ('0', '1', '1', ('0', '0', '0', "00000000", '0'), ('0', '0', '0', "00000000", 3, 1, '0'), '1', '0'),
    ('0', '1', '1', ('1', '0', '0', "11111100", '0'), ('0', '0', '0', "11111100", 4, 1, '0'), '1', '0'),
    ('0', '1', '1', ('1', '0', '0', "01111100", '0'), ('0', '0', '0', "01111100", 0, 2, '0'), '1', '0'),
    ('0', '1', '1', ('1', '0', '0', "01111100", '0'), ('0', '0', '0', "01111100", 4, 2, '0'), '1', '0'),
    ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 0, 3, '0'), '1', '0'),
    ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 1, 3, '0'), '1', '0'),
    ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 2, 3, '0'), '1', '0')
    ('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'), '0', '1'),
    ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 1, 3, '0'), '0', '1'),
    ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 2, 3, '0'), '0', '1'),
    ('0', '1', '1', ('0', '0', '0', "11111111", '0'), ('0', '0', '0', "11111111", 3, 3, '0'), '0', '1')
  );

  constant clk_period : time := 1 ns;


@@ 70,27 70,27 @@ architecture a1 of frame_alignment_tb is
  signal do_char : frame_character;

  signal ci_request_sync : std_logic;
  signal ci_enable_realign : std_logic;
  signal ci_realign : std_logic;
  signal ci_scrambled : std_logic;
  signal co_aligned : std_logic;
  signal co_misaligned : std_logic;
  signal co_error : std_logic;

  signal test_data_index : integer := 0;

begin  -- architecture a1
  uut : entity work.frame_alignment
    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_enable_realign => ci_enable_realign,
      di_char           => di_char,
      co_aligned        => co_aligned,
      co_misaligned     => co_misaligned,
      do_char           => do_char);
      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);

  clk <= not clk after clk_period/2;
  reset <= '1' after clk_period*2;


@@ 106,14 106,14 @@ begin  -- architecture a1
      test_vec := test_vectors(i);
      di_char <= test_vec.di_char;
      ci_scrambled <= test_vec.ci_scrambled;
      ci_enable_realign <= test_vec.ci_enable_realign;
      ci_realign <= test_vec.ci_realign;
      ci_request_sync <= test_vec.ci_request_sync;

      if i > 0 then
        prev_test_vec := test_vectors(i - 1);

        assert co_aligned = prev_test_vec.expected_aligned report "The aligned does not match. Expected: " & std_logic'image(prev_test_vec.expected_aligned) &", Index: " & integer'image(i-1) severity error;
        assert co_misaligned = prev_test_vec.expected_misaligned report "The misaligned does not match. Index: " & integer'image(i-1) severity error;
        assert co_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;


Do not follow this link