~ruther/jesd204b-vhdl

ref: ff129f4671170a9b2c0388596fc0af71760a185d jesd204b-vhdl/src/transport/transport_layer.vhd -rw-r--r-- 7.3 KiB
ff129f46 — František Boháček chore: update quartus project 1 year, 11 months 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
-------------------------------------------------------------------------------
-- Title      : transport layer
-------------------------------------------------------------------------------
-- File       : transport_layer.vhd
-------------------------------------------------------------------------------
-- Description: Takes aligned frame characters from multiple lanes
-- Outputs samples from one frame by converter.
-------------------------------------------------------------------------------

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

entity transport_layer 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
    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
                                        -- =0
  port (
    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
    ci_frame_states : in  frame_state_array(0 to L-1);
    co_frame_state  : out frame_state;
    do_samples      : out samples_array(0 to M - 1, 0 to S - 1)(N - 1 downto 0);
    do_ctrl_bits    : out ctrl_bits_array(0 to M - 1, 0 to S - 1)(CS - 1 downto 0));
end entity transport_layer;

architecture a1 of transport_layer is
  signal samples             : samples_array(0 to M - 1, 0 to S - 1)(N - 1 downto 0);
  signal prev_samples        : samples_array(0 to M - 1, 0 to S - 1)(N - 1 downto 0);
  signal next_samples        : samples_array(0 to M - 1, 0 to S - 1)(N - 1 downto 0);
  signal ctrl_bits           : ctrl_bits_array(0 to M - 1, 0 to S - 1)(CS - 1 downto 0);
  signal prev_ctrl_bits      : ctrl_bits_array(0 to M - 1, 0 to S - 1)(CS - 1 downto 0);
  signal next_ctrl_bits      : ctrl_bits_array(0 to M - 1, 0 to S - 1)(CS - 1 downto 0);
  signal reg_error           : std_logic;  -- if err, repeat last samples.
  signal current_frame_state : frame_state;

  signal reg_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 a1
  set_data: process (ci_frame_clk, ci_reset) is
  begin  -- process set_data
    if ci_reset = '0' then              -- asynchronous reset (active low)
      reg_error <= '0';
      reg_buffered_data <= (others => '0');
    elsif ci_frame_clk'event and ci_frame_clk = '1' then  -- rising clock edge
      do_samples <= next_samples;
      do_ctrl_bits <= next_ctrl_bits;
      co_frame_state <= current_frame_state;

      if any_error = '0' then
        prev_samples <= samples;
        prev_ctrl_bits <= ctrl_bits;
      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;

  -- 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';

  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 <= samples when any_error = '0' else prev_samples;
  next_ctrl_bits <= ctrl_bits when any_error = '0' else prev_ctrl_bits;

  -- for one or multiple lanes if CF = 0
  -- (no control words)
  -- (control chars are right after sample)
  multi_lane_no_cf: if CF = 0 generate
    converters: for ci in 0 to M - 1 generate
      assign_samples: for si in 0 to S - 1 generate
        samples(ci, si) <= 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
          ctrl_bits(ci, si) <= 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 assign_samples;
    end generate converters;
  end generate multi_lane_no_cf;

  -- for one or mutliple lanes if CF != 0
  -- (control words are present)
  multi_lane_cf: if CF > 0 generate
    cf_groups: for cfi in 0 to CF-1 generate
      converters: for ci in 0 to M/CF-1 generate
        assign_samples: for si in 0 to S - 1 generate
          samples(ci + cfi*M/CF, si) <= 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
            ctrl_bits(ci + cfi*M/CF, si) <= 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 assign_samples;
      end generate converters;
    end generate cf_groups;
  end generate multi_lane_cf;

end architecture a1;
Do not follow this link