A src/data_link/char_alignment.vhd => src/data_link/char_alignment.vhd +97 -0
@@ 0,0 1,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 8 bits. Will try to sync to /K/ character when
+-- 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 (
+ sync_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 := 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/ (sync_char) in either RD (either sync_char or not sync_char).
+ for i in 0 to 9 loop
+ if reg_cache_10b((9-i)+9 downto (9-i)) = sync_char or reg_cache_10b((9-i)+9 downto (9-i)) = not sync_char then
+ reg_found_sync_char <= '1';
+ reg_alignment_index <= 9 - 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) <= di_10b(9 downto 0) & reg_cache_10b(19 downto 10);
+end architecture a1;
A testbench/char_alignment_tb.vhd => testbench/char_alignment_tb.vhd +31 -0
@@ 0,0 1,31 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity char_alignment_tb is
+end entity char_alignment_tb;
+
+architecture a1 of char_alignment_tb is
+ constant clk_period : time := 1 ns; -- The clock period
+ constant buffer_positions : integer := 2;
+
+ signal clk : std_logic := '0'; -- The clock
+ signal reset : std_logic := '0'; -- The reset
+
+ signal synced : std_logic := '0'; -- Whether synced
+ signal data_10b : std_logic_vector(9 downto 0) := (others => '0'); -- The 10b data input
+
+ signal buffer_position : integer := 0;
+ signal data_10b_buffer : std_logic_vector(10*2-1 downto 0) := "00111100110011110011"; -- The 10b data input
+begin -- architecture a1
+ uut: entity work.char_alignment
+ port map (
+ ci_char_clk => clk,
+ ci_reset => reset,
+ di_10b => data_10b,
+ ci_synced => synced);
+
+ data_10b <= data_10b_buffer(buffer_position*10+9 downto buffer_position*10);
+ buffer_position <= (buffer_position + 1) mod buffer_positions after clk_period;
+ clk <= not clk after clk_period/2;
+ reset <= '1' after clk_period*2;
+end architecture a1;