~ruther/jesd204b-vhdl

ref: ce19c85c740b00215122da8c2311b31421204db6 jesd204b-vhdl/src/data_link/link_controller.vhd -rw-r--r-- 7.2 KiB
ce19c85c — František Boháček feat: partially implement channel widths 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
-------------------------------------------------------------------------------
-- Title      : controller of data link layer
-------------------------------------------------------------------------------
-- File       : link_controller.vhd
-------------------------------------------------------------------------------
-- Description: Controller for link layer, handling CGS and ILAS.
-- 
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.data_link_pkg.all;

-- What does it do?
-- Well, it manages the states (init, cgs, ilas, data)
-- It sends sync if needed (irecoverrable error detected). It holds? ILAS data.
-- It should get all the control outputs from lane_alignment,
-- frame_alignment, an8b10bdecoder, char_alignment.
-- It should get the current data from an8b10bdecoder

entity link_controller is
  generic (
    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_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

    ci_lane_alignment_error   : in std_logic;  -- Signals a problem with lane
                                             -- alignment in this data link
                                             -- (see lane alighnment component)
    ci_lane_alignment_aligned : in std_logic;  -- Signals that lane is
                                               -- correctly aligned (see
                                               -- lane_alignment component)
    ci_lane_alignment_ready   : in std_logic;  -- Signals that the lane received
                                             -- /A/ and is waiting to start
                                             -- sending data (see
                                             -- lane_alignment component)

    ci_frame_alignment_error   : in std_logic;  -- Signals that the frame was misaligned.
    ci_frame_alignment_aligned : in std_logic;  -- Signals that the frame end
                                                -- was found and did not change.

    ci_resync : in std_logic;  -- Whether to start syncing again.

    co_synced              : out std_logic;  -- Whether the lane is synced (received
                                        -- 4 /K/ characters and proceeds correctly)
    co_state               : out link_state;  -- The state of the lane.
    co_uncorrectable_error : out std_logic;  -- Detected an uncorrectable
                                             -- error, has to resync (ilas
                                             -- parsing error)
    co_error               : out std_logic);          -- Detected any error, processing may
                                        -- differ
end entity link_controller;

architecture a1 of link_controller is
  constant SYNC_COUNT : integer range 0 to 4 := 4;
  constant FULL_SYNCHRONIZATION_AFTER : integer range 0 to 4 := 4;
  signal synced : std_logic := '0';
  signal full_synchronization : std_logic := '0'; -- Assumed after 4 /K/
                                                  -- characters + 4 more 8b10b
                                                  -- correct characters
  signal correct_8b10b_characters : integer range 0 to FULL_SYNCHRONIZATION_AFTER;

  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_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
    generic map (
      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_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_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;
      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
        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
        reg_state <= INIT;
        reg_k_counter <= 0;
      elsif reg_state = CGS then
        if reg_k_counter < SYNC_COUNT then
          correct_8b10b_characters <= 1;
          reg_k_counter <= k_count;
        elsif k_count = 0 then
          reg_state <= ILS;
        end if;
      elsif k_count > 0 then
        reg_state <= CGS;
        reg_k_counter <= 0;
      elsif reg_state = ILS then
        if ilas_finished = '1' then
          reg_state <= DATA;
        elsif ilas_error = '1' then
          reg_state <= INIT;
        end if;
      elsif reg_state = DATA then
        -- uncorrectable error? resync.
      end if;
    end if;
  end process set_state;

  synced <= '0' when reg_state = INIT or (reg_state = CGS and reg_k_counter < SYNC_COUNT) else '1';
  full_synchronization <= '0' when synced = '0' or correct_8b10b_characters < FULL_SYNCHRONIZATION_AFTER else '1';

  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 any_missing_error or any_disparity_error;
  co_uncorrectable_error <= ilas_error;

end architecture a1;
Do not follow this link