M src/data_link/an8b10b_decoder.vhd => src/data_link/an8b10b_decoder.vhd +20 -4
@@ 16,6 16,9 @@ use ieee.numeric_std.all;
use work.data_link_pkg.all;
entity an8b10b_decoder is
+ generic (
+ REVERSE : std_logic := '1' -- Whether to expect characters reversed
+ );
port (
ci_char_clk : in std_logic; -- The character clock
ci_reset : in std_logic; -- The reset (asynchronous active low)
@@ 77,6 80,10 @@ architecture a1 of an8b10b_decoder is
signal data_4b_int_neg : integer range 0 to 15 := 0;
signal data_6b_int_neg : integer range 0 to 63 := 0;
+ signal di_10b_reversed : std_logic_vector(9 downto 0);
+
+ signal di_10b_actual : std_logic_vector(9 downto 0);
+
function IsMissingCharacter(
cdata_4b_int : integer range 0 to 15;
cdata_6b_int : integer range 0 to 63
@@ 171,6 178,8 @@ architecture a1 of an8b10b_decoder is
end function IsDisparityCorrect;
begin -- architecture a1
+ di_10b_reversed <= di_10b(0) & di_10b(1) & di_10b(2) & di_10b(3) & di_10b(4) & di_10b(5) & di_10b(6) & di_10b(7) & di_10b(8) & di_10b(9);
+
-- purpose: Set next states
-- type : sequential
-- inputs : ci_char_clk, ci_reset
@@ 196,8 205,15 @@ begin -- architecture a1
reg_rd <= next_rd;
end if;
end process set_next;
- data_4b <= di_10b(3 downto 0);
- data_6b <= di_10b(9 downto 4);
+
+ WITHOUT_REVERSE: if REVERSE = '0' generate
+ di_10b_actual <= di_10b;
+ end generate;
+ REVERSED: if REVERSE = '1' generate
+ di_10b_actual <= di_10b_reversed;
+ end generate;
+ data_4b <= di_10b_actual(3 downto 0);
+ data_6b <= di_10b_actual(9 downto 4);
data_4b_int <= to_integer(unsigned(data_4b));
data_6b_int <= to_integer(unsigned(data_6b));
data_4b_int_neg <= to_integer(unsigned(not data_4b));
@@ 208,11 224,11 @@ begin -- architecture a1
-- will output 1 ... it's basically an odd parity)
-- synchronize in case of disparity error (can be either at the beginning of
-- communication or the last character was loaded incorrectly)
- change_rd <= (not xor_reduce(di_10b) or next_disparity_error) and not (not xor_reduce(di_10b) and next_disparity_error);
+ change_rd <= (not xor_reduce(di_10b_actual) or next_disparity_error) and not (not xor_reduce(di_10b_actual) and next_disparity_error);
next_rd <= (not reg_rd and change_rd) or (reg_rd and not change_rd);
-- control characters
- next_kout <= IsControlCharacter(di_10b);
+ next_kout <= IsControlCharacter(di_10b_actual);
-- errors
next_missing_error <= IsMissingCharacter(data_4b_int, data_6b_int) and not next_kout;
M src/data_link/char_alignment.vhd => src/data_link/char_alignment.vhd +15 -4
@@ 17,7 17,10 @@ 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)
+ K_CHAR : std_logic_vector(9 downto 0) := "0011111010"; -- The character used for synchronization (positive RD)
+ REVERSE : std_logic := '1' -- Whether to expect the K character in
+ -- reverse, most probably will be reversed in a
+ -- real FPGA situation
);
port (
ci_char_clk: in std_logic; -- The character clock
@@ 30,6 33,7 @@ entity char_alignment is
end entity char_alignment;
architecture a1 of char_alignment is
+ constant K_CHAR_REVERSED : std_logic_vector(9 downto 0) := K_CHAR(0) & K_CHAR(1) & K_CHAR(2) & K_CHAR(3) & K_CHAR(4) & K_CHAR(5) & K_CHAR(6) & K_CHAR(7) & K_CHAR(8) & K_CHAR(9);
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';
@@ 79,9 83,16 @@ begin -- architecture a1
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;
+ if REVERSE = '1' then
+ if reg_cache_10b(i+9 downto i) = K_CHAR_REVERSED or reg_cache_10b(i+9 downto i) = not K_CHAR_REVERSED then
+ reg_found_sync_char <= '1';
+ reg_alignment_index <= i;
+ end if;
+ else
+ 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 if;
end loop; -- i
end if;
M src/data_link/data_link_layer.vhd => src/data_link/data_link_layer.vhd +7 -0
@@ 27,6 27,7 @@ entity data_link_layer is
-- multiframe start
A_CHAR : std_logic_vector(7 downto 0) := "01111100"; -- multiframe end
Q_CHAR : std_logic_vector(7 downto 0) := "10011100"; -- 2nd ILAS frame
+ REVERSE : std_logic := '0'; -- Whether to expect 10b characters reversed
-- 2nd character
ALIGN_BUFFER_SIZE : integer := 255; -- Size of a
-- buffer that is
@@ 145,6 146,9 @@ begin -- architecture a1
-- char alignment
char_alignment: entity work.char_alignment
+ generic map (
+ REVERSE => REVERSE
+ )
port map (
ci_char_clk => ci_char_clk,
ci_reset => ci_reset,
@@ 154,6 158,9 @@ begin -- architecture a1
-- 8b10b decoder
an8b10b_decoder: entity work.an8b10b_decoder
+ generic map (
+ REVERSE => REVERSE
+ )
port map (
ci_char_clk => ci_char_clk,
ci_reset => ci_reset,
M src/jesd204b_link_rx.vhd => src/jesd204b_link_rx.vhd +3 -0
@@ 22,6 22,8 @@ entity jesd204b_link_rx is
-- alignment character
Q_CHAR : std_logic_vector(7 downto 0) := "10011100"; -- ILAS 2nd
-- frame 2nd character
+ REVERSE_LANE_INPUT : std_logic := '0'; -- Whether to reverse data going in
+ -- the lane
ADJCNT : integer range 0 to 15 := 0;
ADJDIR : std_logic := '0';
BID : integer range 0 to 15 := 0;
@@ 194,6 196,7 @@ begin -- architecture a1
data_links : for i in 0 to L-1 generate
data_link_layer : entity work.data_link_layer
generic map (
+ REVERSE => REVERSE_LANE_INPUT,
ALIGN_BUFFER_SIZE => ALIGN_BUFFER_SIZE,
K_CHAR => K_CHAR,
R_CHAR => R_CHAR,