~ruther/jesd204b-vhdl

ref: ff129f4671170a9b2c0388596fc0af71760a185d jesd204b-vhdl/src/data_link/char_alignment.vhd -rw-r--r-- 4.2 KiB
ff129f46 — František Boháček chore: update quartus project 1 year, 10 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
-------------------------------------------------------------------------------
-- Title      : Synchronize with character start
-- Project    : JESD204B Receiver
-------------------------------------------------------------------------------
-- File       : char_alignment.vhd
-- Description: Tries to align the beginning of the character from 8b/10b encoding.
-- Accepting 10 bits, outputting 10 bits. Will try to sync to /K/ character when
-- ci_synced is false.
-------------------------------------------------------------------------------

-- input d_in[9:0], ci_synced
-- output co_aligned, d_out[9:0]

library ieee;
use ieee.std_logic_1164.all;

entity char_alignment is

  generic (
    K_CHAR : std_logic_vector(9 downto 0) := "0011111010"  -- The character used for synchronization (positive RD)
    );
  port (
    ci_char_clk: in std_logic;          -- The character clock
    ci_reset   : in std_logic;          -- The reset, active high.
    di_10b     : in  std_logic_vector(9 downto 0);  -- The 8b/10b encoded input data from physical layer
    ci_synced  : in  std_logic;  -- Whether the receiver is currently synchronized
    do_10b     : out std_logic_vector(9 downto 0);  -- The 8b/10b encoded data aligned with a character (if co_aligned is true, otherwise unknown)
    co_aligned : out std_logic);  -- Whether the output is currently aligned

end entity char_alignment;

architecture a1 of char_alignment is
  signal next_cache_10b : std_logic_vector(19 downto 0) := (others => '0');  -- The next value of cache_10b
  signal next_do_10b : std_logic_vector(9 downto 0) := (others => '0');  -- The next value of do_10b
  signal next_co_aligned : std_logic := '0';

  signal reg_found_sync_char : std_logic := '0';  -- Whether sync char was found
  signal reg_cache_10b : std_logic_vector(19 downto 0) := (others => '0');  -- The cache of 10b characters.
  signal reg_do_10b : std_logic_vector(9 downto 0) := (others => '0');
  signal reg_alignment_index : integer range 0 to 16 := 0;  -- Where the character starts in the cache, if aligned.
  signal reg_last_synced : std_logic := '0';  -- The last value of ci_synced
  signal reg_co_aligned : std_logic := '0';  -- Whether aligned
begin  -- architecture a1

  -- purpose: Set next signals
  -- type   : combinational
  -- inputs : clk, reset
  -- outputs: alignment_index, cache_10b, do_10b, co_aligned
  set_next: process (ci_char_clk, ci_reset) is
  begin  -- process set_next
    if ci_reset = '0' then
      reg_last_synced <= '0';
      reg_co_aligned <= '0';
      reg_cache_10b <= (others => '0');
      reg_do_10b <= (others => '0');
    elsif rising_edge(ci_char_clk) then
      reg_last_synced <= ci_synced;
      reg_co_aligned <= next_co_aligned;
      reg_cache_10b <= next_cache_10b;
      reg_do_10b <= next_do_10b;
    end if;
  end process set_next;

  -- purpose: Tries to find the sync character if synced is false
  -- type   : sequential
  -- inputs : ci_char_clk, ci_reset, di_10b, ci_synced
  -- outputs: reg_found_sync_char, reg_alignment_index
  find_sync_char: process (ci_char_clk, ci_reset) is
  begin  -- process find_sync_char
    if ci_reset = '0' then              -- asynchronous reset (active low)
      reg_alignment_index <= 0;
      reg_found_sync_char <= '0';
    elsif rising_edge(ci_char_clk) then  -- rising clock edge
      if reg_found_sync_char = '1' then
        reg_found_sync_char <= '0';
      end if;
      -- Try to find /K/ character again and again until ci_synced is one (that
      -- will be set by 8b10b_decoder)
      if ci_synced = '0' then
        -- Try to find /K/ (K_CHAR) in either RD (either K_CHAR or not K_CHAR).
        for i in 0 to 9 loop
          if reg_cache_10b(i+9 downto i) = K_CHAR or reg_cache_10b(i+9 downto i) = not K_CHAR then
            reg_found_sync_char <= '1';
            reg_alignment_index <= i;
          end if;
        end loop;  -- i
      end if;
    end if;
  end process find_sync_char;

  co_aligned <= reg_co_aligned;
  do_10b <= reg_do_10b;

  next_co_aligned <= (reg_found_sync_char or reg_co_aligned) and not (reg_last_synced and not ci_synced);
  next_do_10b(9 downto 0) <= reg_cache_10b(reg_alignment_index+9 downto reg_alignment_index);
  next_cache_10b(19 downto 0) <= reg_cache_10b(9 downto 0) & di_10b(9 downto 0);
end architecture a1;
Do not follow this link