--! @file dec_8b10b.vhd --! Standard library library ieee; --! Standard packages use ieee.std_logic_1164.all; use ieee.numeric_std.all; ------------------------------------------------------------------------------- -- -- -- GSI Darmstadt, Dept. BEL: 8b10b Decoder-- -- -- ------------------------------------------------------------------------------- -- -- unit name: dec_8b10b -- --! @brief 8b/10b Decoder \n --! This module provides 10bit-to-8bit decoding. \n --! It accepts 10-bit encoded data input and generates 8-bit parallel data \n --! output in accordance with the 8b/10b standard. IO latency is 2 clock cycles. \n -- --! @author Vladimir Cherkashyn\n --! v.cherkashyn@gsi.de -- --! @date 11.05.2009 -- --! @version 1.0 -- --! @details This approach uses a mix of LUTs and stacked ifs, unlike the suggested \n --! approach that only used gates. This uses more logic cells, but also runs about \n --! twice as fast (420 opposed to 240MHz). \n --! The reverse vector function is used because all code tables are provided in \n --! literature as LSB first. This way, the sourcecode is easier to compare. --! 99 LUTs in Cyclone3 --! --! <b>Dependencies:</b>\n --! - --! --! <b>References:</b>\n --! - --! --! <b>Modified by:</b>\n --! Author: Vladimir Cherkashyn\n --! v.cherkashyn@gsi.de ------------------------------------------------------------------------------- --! \n\n<b>Last changes:</b>\n --! 11.05.2009 initial code\n ------------------------------------------------------------------------------- --! @todo Test -- ------------------------------------------------------------------------------- --======================================================================================= --/////////////////////////////////////////////////////////////////////////////////////// --! Entity declaration for dec_8b10b --======================================================================================= entity gc_dec_8b10b is port ( clk_i : in std_logic; --! byte clock, trigger on rising edge rst_n_i : in std_logic; --! reset, assert HI in_10b_i : in std_logic_vector(9 downto 0); --! 10bit input to be decoded ctrl_o : out std_logic; --! control char, assert HI code_err_o : out std_logic; --! HI if invalid 10bit group has been recieved rdisp_err_o : out std_logic; --! HI if running disparity error has occured out_8b_o : out std_logic_vector(7 downto 0) --! 8bit data output ); end gc_dec_8b10b; --======================================================================================= --/////////////////////////////////////////////////////////////////////////////////////// --! Architecture Declaration rtl of dec_8b10b - 8b10b decoding --======================================================================================= architecture rtl of gc_dec_8b10b is -- LUT and CTRL components component dec_8b10b_lut is port ( in_10b_i : in std_logic_vector(9 downto 0); out_8b_o : out std_logic_vector(7 downto 0) ); end component; component dec_8b10b_ctrl is port ( in_10b_i : in std_logic_vector(9 downto 0); --! 10bit input to be decoded ctrl_o : out std_logic; --! control char, assert HI code_err_o : out std_logic --! HI if invalid 10bit group has been recieved ); end component; component dec_8b10b_disp is port( clk_i : in std_logic; --! byte clock, trigger on rising edge rst_n_i : in std_logic; --! reset, assert HI in_10b_i : in std_logic_vector(9 downto 0); --! 10bit input to be decoded disp_err_o : out std_logic; --! HI if running disparity error has occured rdisp_err_o : out std_logic --! HI if running disparity error has occured ); end component; --======================================================================================= -- FUNCTIONS --======================================================================================= --! function f_reverse_vector - bit reversal function f_reverse_vector (a : in std_logic_vector) return std_logic_vector is variable v_result : std_logic_vector(a'reverse_range); begin for i in a'range loop v_result(i) := a(i); end loop; return v_result; end; -- function f_reverse_vector --======================================================================================= -- INTERNAL SIGNALS --======================================================================================= -- input clocked buffer signal s_in10b : std_logic_vector(9 downto 0); -- output clocked buffers signal s_out8b : std_logic_vector(7 downto 0); signal s_ctrl : std_logic; signal s_code_err : std_logic; signal s_disp_err : std_logic; -- LUT & CTRL wires signal s_out8b_lut : std_logic_vector(7 downto 0); signal s_ctrl_ctrl : std_logic; signal s_code_err_ctrl : std_logic; signal s_code_err_disp : std_logic; signal s_rdisp_err : std_logic; begin -- LUT and CTRL instances LUT : dec_8b10b_lut port map ( in_10b_i => s_in10b, out_8b_o => s_out8b_lut ); CTRL : dec_8b10b_ctrl port map ( in_10b_i => s_in10b, ctrl_o => s_ctrl_ctrl, code_err_o => s_code_err_ctrl ); DISP : dec_8b10b_disp port map ( clk_i => clk_i, rst_n_i => rst_n_i, in_10b_i => s_in10b, disp_err_o => s_code_err_disp, rdisp_err_o => s_rdisp_err ); --======================================================================================= -- CONCURRENT COMMANDS --======================================================================================= -- Wires from buffers to module I/O out_8b_o <= s_out8b; ctrl_o <= s_ctrl; code_err_o <= s_code_err; rdisp_err_o <= s_disp_err; --============================================================================ -- Begin of p_decoding --! Process decodes 10bit codeword to 8 bit value using LUT --============================================================================ p_decoding : process (clk_i, rst_n_i) begin if rising_edge(clk_i) then --========================================================================== -- SYNC RESET --========================================================================== if (rst_n_i = '0') then -- reset buffer triggers s_in10b <= B"111010_1000"; -- reset input buffer s_out8b <= B"111_10111"; -- reset output buffer s_ctrl <= '1'; -- reset control output buffer s_code_err <= '0'; -- reset code error output buffer s_disp_err <= '0'; -- reset disparity error output buffer else -- save input in clocked buffer in the inverse bit order s_in10b <= f_reverse_vector(in_10b_i); -- lut unit output to clocked buffers s_out8b <= s_out8b_lut; -- control and error signals from ctrl unit to clocked buffers s_ctrl <= s_ctrl_ctrl; s_code_err <= s_code_err_ctrl or s_code_err_disp; s_disp_err <= s_rdisp_err; end if; end if; end process; end rtl; --! Standard library library ieee; --! Standard packages use ieee.std_logic_1164.all; use ieee.numeric_std.all; --! @brief CTRL module for 10b/8b Decoder \n --! This module sets command code flag if the 10 bit recieved code was a \n --! command character. It also checks for invalid code violations. \n --! It accepts 10-bit encoded data input. Combinational logic only. \n --======================================================================================= --/////////////////////////////////////////////////////////////////////////////////////// --! Entity declaration for dec_8b10b_ctrl --======================================================================================= entity dec_8b10b_ctrl is port ( in_10b_i : in std_logic_vector(9 downto 0); --! 10bit input to be decoded ctrl_o : out std_logic; --! control char, assert HI code_err_o : out std_logic --! HI if invalid 10bit group has been recieved ); end dec_8b10b_ctrl; architecture rtl of dec_8b10b_ctrl is --======================================================================================= -- INTERNAL SIGNALS AND ALIASES --======================================================================================= alias a_abcd : std_logic_vector(3 downto 0) is in_10b_i(9 downto 6); alias a_ei : std_logic_vector(1 downto 0) is in_10b_i(5 downto 4); alias a_fghj : std_logic_vector(3 downto 0) is in_10b_i(3 downto 0); alias a_fgh : std_logic_vector(2 downto 0) is in_10b_i(3 downto 1); alias a_fg : std_logic_vector(1 downto 0) is in_10b_i(3 downto 2); alias a_cde : std_logic_vector(2 downto 0) is in_10b_i(7 downto 5); alias a_cdei : std_logic_vector(3 downto 0) is in_10b_i(7 downto 4); alias a_dei : std_logic_vector(2 downto 0) is in_10b_i(6 downto 4); alias a_eifgh : std_logic_vector(4 downto 0) is in_10b_i(5 downto 1); alias a_eifghj : std_logic_vector(5 downto 0) is in_10b_i(5 downto 0); alias a_in6b : std_logic_vector(5 downto 0) is in_10b_i(9 downto 4); alias a_in4b : std_logic_vector(3 downto 0) is in_10b_i(3 downto 0); signal s_eighj : std_logic_vector(4 downto 0); signal s_p13, s_p31 : std_logic; signal s_err1, s_err2, s_err3, s_err4, s_err5, s_err6 : std_logic; signal s_err7a, s_err7b, s_err8, s_err9, s_err10 : std_logic; signal s_err11, s_err12, s_err13, s_err14 : std_logic; signal s_ctrl_1, s_ctrl_2, s_ctrl_3 : std_logic; begin --======================================================================================= -- CONCURRENT COMMANDS --======================================================================================= s_eighj <= in_10b_i(5 downto 4) & in_10b_i(2 downto 0); -- invalid code checking s_err1 <= '1' when ((a_abcd = "0000") or (a_abcd = "1111")) else '0'; s_err2 <= '1' when ((a_ei = "00") and (s_p13 = '1')) else '0'; s_err3 <= '1' when ((a_ei = "11") and (s_p31 = '1')) else '0'; s_err4 <= '1' when ((a_fghj = "0000") or (a_fghj = "1111")) else '0'; s_err5 <= '1' when ((a_eifgh = "00000") or (a_eifgh = "11111")) else '0'; s_err6 <= '1' when ((s_eighj = "10111") or (s_eighj = "01000")) else '0'; s_err7a <= '1' when ((s_eighj = "00111") and (a_cde /= "000") and (a_cde /= "111")) else '0'; s_err7b <= '1' when ((s_eighj = "11000") and (a_cde /= "000") and (a_cde /= "111")) else '0'; s_err8 <= '1' when ((s_eighj = "10000") and (s_p31 = '0')) else '0'; s_err9 <= '1' when ((s_eighj = "01111") and (s_p13 = '0')) else '0'; s_err10 <= '1' when ((in_10b_i = "0011110001") or (in_10b_i = "1100001110")) else '0'; s_err11 <= '1' when ((a_cdei = "0000") and (a_fg = "00")) else '0'; s_err12 <= '1' when ((a_cdei = "1111") and (a_fg = "11")) else '0'; s_err13 <= '1' when ((a_dei = "000") and (a_fgh = "000")) else '0'; s_err14 <= '1' when ((a_dei = "111") and (a_fgh = "111")) else '0'; code_err_o <= s_err1 or s_err2 or s_err3 or s_err4 or s_err5 or s_err6 or s_err7a or s_err7b or s_err8 or s_err9 or s_err10 or s_err11 or s_err12 or s_err13 or s_err14; -- command code checking -- K28.x s_ctrl_1 <= '1' when ((a_cdei = "0000") or (a_cdei = "1111")) else '0'; -- K23,27,29,30, positive disparity s_ctrl_2 <= '1' when ((a_eifghj = "010111") and (s_p13 = '1')) else '0'; -- K23,27,29,30, negative disparity s_ctrl_3 <= '1' when ((a_eifghj = "101000") and (s_p31 = '1')) else '0'; ctrl_o <= s_ctrl_1 or s_ctrl_2 or s_ctrl_3; p_p13_p31_func : process(a_abcd) begin s_p13 <= '0'; s_p31 <= '0'; case a_abcd is when "0001" | "0010" | "0100" | "1000" => s_p13 <= '1'; s_p31 <= '0'; when "1110" | "1101" | "1011" | "0111" => s_p13 <= '0'; s_p31 <= '1'; when others => s_p13 <= '0'; s_p31 <= '0'; end case; end process; end rtl; --! @file dec_8b10b_disp.vhd --! Standard library library ieee; --! Standard packages use ieee.std_logic_1164.all; use ieee.numeric_std.all; ------------------------------------------------------------------------------- -- -- -- GSI Darmstadt, Dept. BEL: 8b10b Decoder-- -- -- ------------------------------------------------------------------------------- -- -- unit name: dec_8b10b_disp -- --! @brief 8b/10b Decoder \n --! This module provides 10bit-to-8bit decoding. \n --! It accepts 10-bit encoded data input and generates 8-bit parallel data \n --! output in accordance with the 8b/10b standard. IO latency is 2 clock cycles. \n -- --! @author Vladimir Cherkashyn\n --! v.cherkashyn@gsi.de -- --! @date 11.05.2009 -- --! @version 1.0 -- --! @details This approach uses a mix of LUTs and stacked ifs, unlike the suggested \n --! approach that only used gates. This uses more logic cells, but also runs about \n --! twice as fast (420 opposed to 240MHz). \n --! The reverse vector function is used because all code tables are provided in \n --! literature as LSB first. This way, the sourcecode is easier to compare. --! --! <b>Dependencies:</b>\n --! - --! --! <b>References:</b>\n --! - --! --! <b>Modified by:</b>\n --! Author: Vladimir Cherkashyn\n --! v.cherkashyn@gsi.de ------------------------------------------------------------------------------- --! \n\n<b>Last changes:</b>\n --! 11.05.2009 initial code\n ------------------------------------------------------------------------------- --! @todo Test -- ------------------------------------------------------------------------------- --======================================================================================= --/////////////////////////////////////////////////////////////////////////////////////// --! Entity declaration for dec_8b10b_disp --======================================================================================= entity dec_8b10b_disp is port ( clk_i : in std_logic; --! byte clock, trigger on rising edge rst_n_i : in std_logic; --! reset, assert HI in_10b_i : in std_logic_vector(9 downto 0); --! 10bit input to be decoded disp_err_o : out std_logic; --! HI if 10bit code disparity violated rdisp_err_o : out std_logic --! HI if running disparity error has occured ); end dec_8b10b_disp; --======================================================================================= --/////////////////////////////////////////////////////////////////////////////////////// --! Architecture Declaration rtl of dec_8b10b_disp - 8b10b_disp decoding --======================================================================================= architecture rtl of dec_8b10b_disp is --======================================================================================= -- FUNCTIONS --======================================================================================= --! function f_cnt4bit - counts ones in a bit vector function f_cnt4bit (vec : in std_logic_vector) return std_logic_vector is variable v_cnt : std_logic_vector(3 downto 0) := "0000"; begin for i in vec'range loop if (vec(i) = '1') then v_cnt := std_logic_vector(unsigned(v_cnt) + 1); end if; end loop; return v_cnt; end; -- function f_cnt4bit --======================================================================================= -- INTERNAL SIGNALS --======================================================================================= type t_state_type is (RD_MINUS, RD_PLUS); signal s_RunDisp : t_state_type; signal s_disp : std_logic_vector(3 downto 0); signal s_disp_err1, s_disp_err2 : std_logic; --signal s_disp_err3 : std_logic; alias a_in6b : std_logic_vector(5 downto 0) is in_10b_i(9 downto 4); alias a_in4b : std_logic_vector(3 downto 0) is in_10b_i(3 downto 0); begin s_disp <= f_cnt4bit(in_10b_i); -- disparity of 10bit input --s_disp_err3 <= '0' when ( (s_disp = "0100") or -- (s_disp = "0110") or -- (s_disp = "0101") ) -- else '1'; -- disparity of 4bit part (2,0,-2) s_disp_err2 <= '1' when ((a_in4b = "0000") or (a_in4b = "1111")) else '0'; disp_err_o <= s_disp_err1 or s_disp_err2; -- or s_disp_err3; -- disparity of 6bit part (2,0,-2) p_6bit_disp_err : process(a_in6b) begin s_disp_err1 <= '0'; case a_in6b is when "000001" | "000010" | "000100" | "001000" | "010000" | "100000" => s_disp_err1 <= '1'; when "011111" | "101111" | "110111" | "111011" | "111101" | "111110" => s_disp_err1 <= '1'; when "111111" | "000000" => s_disp_err1 <= '1'; when others => s_disp_err1 <= '0'; end case; end process; p_state_out : process (s_RunDisp, s_disp) begin rdisp_err_o <= '1'; case s_RunDisp is when RD_MINUS => if (s_disp = "0110") or (s_disp = "0101") then rdisp_err_o <= '0'; end if; when RD_PLUS => if (s_disp = "0100") or (s_disp = "0101") then rdisp_err_o <= '0'; end if; when others => null; end case; end process; --============================================================================ -- Begin of p_state_disp --! --============================================================================ p_state_disp : process (clk_i, rst_n_i) begin if rising_edge(clk_i) then --========================================================================== -- SYNC RESET --========================================================================== if (rst_n_i = '0') then s_RunDisp <= RD_PLUS; else case s_RunDisp is when RD_MINUS => if (s_disp = "0110") then s_RunDisp <= RD_PLUS; end if; when RD_PLUS => if (s_disp = "0100") then s_RunDisp <= RD_MINUS; end if; when others => s_RunDisp <= RD_MINUS; end case; end if; end if; end process; end rtl; --! @brief LUT module for 10b/8b Decoder \n --! This module provides 10bit-to-8bit decoding tables. \n --! It accepts 10-bit encoded data input and generates 8-bit parallel data \n --! output in accordance with the 8b/10b standard. Combinational logic only. \n -- --! Standard library library ieee; --! Standard packages use ieee.std_logic_1164.all; use ieee.numeric_std.all; --======================================================================================= --/////////////////////////////////////////////////////////////////////////////////////// --! Entity declaration for dec_8b10b_lut --======================================================================================= entity dec_8b10b_lut is port ( in_10b_i : in std_logic_vector(9 downto 0); --! 10bit input to be decoded out_8b_o : out std_logic_vector(7 downto 0) --! 8bit data output ); end dec_8b10b_lut; architecture rtl of dec_8b10b_lut is --======================================================================================= -- INTERNAL SIGNALS --======================================================================================= -- aliases to input vector alias a_in6b : std_logic_vector(5 downto 0) is in_10b_i(9 downto 4); alias a_in4b : std_logic_vector(3 downto 0) is in_10b_i(3 downto 0); -- aliases to output vector alias a_out5b : std_logic_vector(4 downto 0) is out_8b_o(4 downto 0); alias a_out3b : std_logic_vector(2 downto 0) is out_8b_o(7 downto 5); begin dec_4b_lut : process(a_in4b, a_in6b) begin -- 4 bits of data code (MSB) B4 : case a_in4b is when "1011" | "0100" => a_out3b <= "000"; -- Dx.0 when "1001" => if (a_in6b = "110000") then a_out3b <= "110"; -- D28.6 else a_out3b <= "001"; -- Dx.1 end if; when "0101" => if (a_in6b = "110000") then a_out3b <= "101"; -- K28.5 else a_out3b <= "010"; -- Dx.2 end if; when "1100" | "0011" => a_out3b <= "011"; -- Dx.3 when "1101" | "0010" => a_out3b <= "100"; -- Dx.4 when "1010" => if (a_in6b = "110000") then a_out3b <= "010"; -- K28.2 else a_out3b <= "101"; -- Dx.5 end if; when "0110" => if (a_in6b = "110000") then a_out3b <= "001"; -- K28.1 else a_out3b <= "110"; -- Dx.6 end if; when "1110" | "0001" => a_out3b <= "111"; -- Dx.7 when "1000" | "0111" => a_out3b <= "111"; -- Kx.7 when others => a_out3b <= (others => '0'); end case B4; end process; dec_6b_lut : process(a_in6b) begin -- 6 bits of data code (LSB) B6 : case a_in6b is when "100111" | "011000" => a_out5b <= "00000"; -- D0.x when "011101" | "100010" => a_out5b <= "00001"; when "101101" | "010010" => a_out5b <= "00010"; when "110001" => a_out5b <= "00011"; when "110101" | "001010" => a_out5b <= "00100"; when "101001" => a_out5b <= "00101"; when "011001" => a_out5b <= "00110"; when "111000" | "000111" => a_out5b <= "00111"; when "111001" | "000110" => a_out5b <= "01000"; when "100101" => a_out5b <= "01001"; when "010101" => a_out5b <= "01010"; when "110100" => a_out5b <= "01011"; when "001101" => a_out5b <= "01100"; when "101100" => a_out5b <= "01101"; when "011100" => a_out5b <= "01110"; when "010111" | "101000" => a_out5b <= "01111"; when "011011" | "100100" => a_out5b <= "10000"; when "100011" => a_out5b <= "10001"; when "010011" => a_out5b <= "10010"; when "110010" => a_out5b <= "10011"; when "001011" => a_out5b <= "10100"; when "101010" => a_out5b <= "10101"; when "011010" => a_out5b <= "10110"; when "111010" | "000101" => a_out5b <= "10111"; when "110011" | "001100" => a_out5b <= "11000"; when "100110" => a_out5b <= "11001"; when "010110" => a_out5b <= "11010"; when "110110" | "001001" => a_out5b <= "11011"; when "001110" => a_out5b <= "11100"; when "101110" | "010001" => a_out5b <= "11101"; when "011110" | "100001" => a_out5b <= "11110"; when "101011" | "010100" => a_out5b <= "11111"; -- D31.x when "001111" | "110000" => a_out5b <= "11100"; -- K28.x when others => a_out5b <= (others => '0'); end case B6; end process; end rtl;