~ruther/jesd204b-vhdl

ref: f83380237147be4aa6f79a29a0e251e54f631a76 jesd204b-vhdl/src/data_link/lane_alignment.vhd -rw-r--r-- 5.2 KiB
f8338023 — František Boháček feat: add lmfc counter clock generator 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
-------------------------------------------------------------------------------
-- Title      : Lane alignment
-------------------------------------------------------------------------------
-- File       : lane_alignment.vhd
-------------------------------------------------------------------------------
-- Description: Ensures all lanes are aligned to the same character.
-- Buffers after receiving first /A/ character until ci_start is set.
-- Then starts sending the data from the buffer.
-- That ensures all the lanes start at the same position.
-------------------------------------------------------------------------------

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

entity lane_alignment is
  generic (
    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
    R_character     : std_logic_vector(7 downto 0) := "00011100";  -- The /R/ character
    dummy_character : character_vector             := ('1', '0', '0', "10111100", '0'));
-- Character to send before the buffer is ready and started

  port (
    ci_char_clk           : in  std_logic;  -- Character 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_realign            : in  std_logic;  -- Whether to realign to the last
                                            -- found alignment character
    di_char               : in  character_vector;  -- 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_error              : out std_logic;  -- Whether there is an error
    do_char               : out character_vector);  -- The aligned output character

end entity lane_alignment;

architecture a1 of lane_alignment is
  type buffer_array is array (0 to buffer_size) of character_vector;
  signal buff : buffer_array := (others => ('0', '0', '0', "00000000", '0'));

  signal reg_ready : std_logic := '0';
  signal reg_started : std_logic := '0';
  signal reg_error : std_logic := '0';

  signal reg_write_index : integer range 0 to buffer_size := 0;
  signal reg_read_index  : integer range 0 to buffer_size := 0;

  signal next_write_index : integer range 0 to buffer_size-1 := 0;
  signal next_read_index  : integer range 0 to buffer_size-1 := 0;
  signal next_ready       : std_logic                        := '0';
  signal next_started     : std_logic                        := '0';
  signal next_error       : std_logic                        := '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_write_index <= 0;
      reg_read_index  <= 0;
      reg_ready       <= '0';
      reg_started     <= '0';
      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';
    end if;
  end process set_next;

  co_ready <= reg_ready;
  co_error <= reg_error;
  -- TODO handle realignment ?

  next_write_index <= ((reg_write_index + 1) mod buffer_size) when reg_ready = '1' or next_ready = '1' else
                      0;
  next_read_index <= ((reg_read_index + 1) mod buffer_size) when reg_started = '1' else
                     0;

  next_ready <= '0' when ci_state = INIT else
                '1' when reg_ready = '1' or (di_char.kout = '1' and di_char.d8b = R_character and (ci_state = CGS or ci_state = ILS)) else
                '0';
  next_started <= '0' when reg_ready = '0' else
                  '1' when (ci_start = '1' or reg_started = '1') else
                  '0';
  co_aligned <= reg_started;            -- TODO: check for misalignment
  next_error <= '0' when ci_state = INIT else
                '1' when reg_error = '1' else
                '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);

end architecture a1;
Do not follow this link