~ruther/jesd204b-vhdl

ref: 504ad614f5e439d4771f61332357b393d906ed48 jesd204b-vhdl/src/data_link/frame_alignment.vhd -rw-r--r-- 6.3 KiB
504ad614 — František Boháček feat(link): add data link layer component connecting all data link components 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
library ieee;
use ieee.std_logic_1164.all;
use work.data_link_pkg.all;

entity frame_alignment is
  generic (
    sync_char      : std_logic_vector(7 downto 0) := "10111100";
    A_char         : std_logic_vector(7 downto 0) := "01111100";
    F_char         : std_logic_vector(7 downto 0) := "11111100";
    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
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.
  signal reg_state : alignment_state := INIT;

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

  signal next_is_last_octet : std_logic := '0';
  signal next_is_last_frame : std_logic := '0';

  signal is_f : std_logic := '0';
  signal is_a : std_logic := '0';

  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 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');
begin  -- architecture a1
  set_next: process (ci_char_clk, ci_reset) is
  begin  -- process set_next
    if ci_reset = '0' then              -- asynchronous reset (active low)
      reg_frame_index <= 0;
      reg_octet_index <= 0;
      do_char <= ('0', '0', '0', "00000000", 0, 0, '0');
      reg_state <= INIT;
    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;
      end if;

      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;
      elsif reg_state = INIT then
        reg_frame_index <= 0;
        reg_octet_index <= 0;
        do_char.octet_index <= 0;
        do_char.frame_index <= 0;
      elsif reg_state = RECEIVED_K then
        reg_frame_index <= 0;
        reg_octet_index <= 0;
        do_char.octet_index <= 0;
        do_char.frame_index <= 0;

        if di_char.d8b /= sync_char or di_char.kout = '0' then
          reg_state <= ALIGNED;
        end if; -- switch to aligned
      else
        reg_frame_index <= next_frame_index;
        reg_octet_index <= next_octet_index;
        do_char.octet_index <= next_octet_index;
        do_char.frame_index <= next_frame_index;
        if reg_state = ALIGNED then
          if is_wrong_char = '1' then
            reg_state <= MISALIGNED;
          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;
            else
              reg_state <= WRONG_ALIGNMENT;
            end if;
          elsif is_wrong_char = '0' and (is_f = '1' or is_a = '1') then
            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
    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
                 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';

  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_misaligned <= '1' when reg_state = WRONG_ALIGNMENT else '0';
  co_aligned <= '1' when reg_state = ALIGNED or reg_state = MISALIGNED else '0';
end architecture a1;
Do not follow this link