Commit 89ba64fb authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

wr_tbi_phy: uploaded missing module

parent 29c8157d
files = [ "dec_8b10b.vhd",
"enc_8b10b.vhd",
"wr_tbi_phy.vhd" ];
--! @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 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 dec_8b10b;
--=======================================================================================
--///////////////////////////////////////////////////////////////////////////////////////
--! Architecture Declaration rtl of dec_8b10b - 8b10b decoding
--=======================================================================================
architecture rtl of 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;
--! @file enc_8b10b.vhd
--! Standard library
library ieee;
--! Standard packages
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-------------------------------------------------------------------------------
-- --
-- GSI Darmstadt, Dept. BEL: 8b10b Encoder--
-- --
-------------------------------------------------------------------------------
--
-- unit name: enc_8b10b
--
--! @brief 8b/10b Encoder \n
--! This module provides 8bit-to-10bit encoding. \n
--! It accepts 8-bit parallel data input and generates 10-bit encoded data \n
--! output in accordance with the 8b/10b standard. IO latency is one clock
--! cycle. \n
--
--! @author Mathias Kreider\n
--! m.kreider@gsi.de
--
--! @date 18.02.2009
--
--! @version 1.0
--
--! @details This approach uses a mix of LUTs and stacked ifs, unlike the \n
--! suggested approach that only used gates. This uses more logic cells, but \n
--! also runs about twice as fast. \n
--! The reverse vector function is used because all code tables are provided \n
--! in literature as LSB first. This way, the sourcecode is easier to \n
--! compare. \n
--!
--! <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
--! 23.02.2009 mk cleanup\n
--! formatting, commenting
--! 16.06.2009 vc major rewrite with FSM \n
--! fixed disparity tables, formatting
-------------------------------------------------------------------------------
--! @todo Optimize, test in real design
--
-------------------------------------------------------------------------------
--=============================================================================
--/////////////////////////////////////////////////////////////////////////////
--! Entity declaration for enc_8b10b
--=============================================================================
entity enc_8b10b is port
(
clk_i : in std_logic; --! byte clock, trigger on rising edge
rst_n_i : in std_logic; --! reset, assert HI
ctrl_i : in std_logic; --! control char, assert HI
in_8b_i : in std_logic_vector(7 downto 0); --! 8bit input
err_o : out std_logic; --! HI if ctrl_i is HI and input is not a valid control byte
dispar_o : out std_logic; --! running disparity: HI = +1, LO = 0
out_10b_o : out std_logic_vector(9 downto 0) --! 10bit codeword output
);
end enc_8b10b;
--=============================================================================
--/////////////////////////////////////////////////////////////////////////////
--! Architecture Declaration rtl of enc_8b10b - 8b10b encoding
--=============================================================================
architecture rtl of enc_8b10b is
--=============================================================================
-- 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
--=============================================================================
-- LOOKUP TABLES
--=============================================================================
--! type for states of the FSM
type t_state_type is (RD_MINUS, RD_PLUS);
--! type for 5b/6b Code Table
type t_enc_5b_6b is array(integer range <>) of std_logic_vector(5 downto 0);
--! type for 5b/6b Code Table
type t_enc_3b_4b is array(integer range <>) of std_logic_vector(3 downto 0);
--! 5b/6b Code Table
constant c_enc_5b_6b_table : t_enc_5b_6b (0 to 31) :=
("100111", -- D00
"011101", -- D01
"101101", -- D02
"110001", -- D03
"110101", -- D04
"101001", -- D05
"011001", -- D06
"111000", -- D07
"111001", -- D08
"100101", -- D09
"010101", -- D10
"110100", -- D11
"001101", -- D12
"101100", -- D13
"011100", -- D14
"010111", -- D15
"011011", -- D16
"100011", -- D17
"010011", -- D18
"110010", -- D19
"001011", -- D20
"101010", -- D21
"011010", -- D22
"111010", -- D23
"110011", -- D24
"100110", -- D25
"010110", -- D26
"110110", -- D27
"001110", -- D28
"101110", -- D29
"011110", -- D30
"101011"); -- D31
--! 5b/6b Disparity Table
constant c_disPar_6b : std_logic_vector(0 to 31) :=
(
"11101000100000011000000110010111");
--! 3b/4b Code Table
constant c_enc_3b_4b_table : t_enc_3b_4b (0 to 7) :=
("1011", -- Dx0
"1001", -- Dx1
"0101", -- Dx2
"1100", -- Dx3
"1101", -- Dx4
"1010", -- Dx5
"0110", -- Dx6
"1110"); -- DxP7
--! 3b/4b Disparity Table
constant c_disPar_4b : std_logic_vector(0 to 7) :=
(
"10001001");
--=============================================================================
-- INTERNAL SIGNALS
--=============================================================================
signal s_ind5b : integer := 0; --! LUT 5b index
signal s_ind3b : integer := 0; --! LUT 3b index
signal s_val6bit : std_logic_vector(5 downto 0); --! 6bit code
signal s_val6bit_n : std_logic_vector(5 downto 0); --! 6bit code inverted
signal s_val4bit : std_logic_vector(3 downto 0); --! 4bit code
signal s_val4bit_n : std_logic_vector(3 downto 0); --! 4bit code inverted
--! code disparity 6b code: HI = uneven number of bits, LO = even, neutral disp
signal s_dP6bit : std_logic := '0';
--! code disparity 4b code: HI = uneven number of bits, LO = even, neutral disp
signal s_dP4bit : std_logic := '0';
signal s_in_8b_reg : std_logic_vector(7 downto 0); --! input 8b signal buffer
signal s_out_10b, s_out_10b_reg : std_logic_vector(9 downto 0) := (others => '0'); --! output 10b signal buffer
signal s_err, s_err_reg : std_logic; --! output err signal buffer
signal s_dispar_reg, s_ctrl_reg : std_logic; --! output dispar, ctrl signal buffers
signal s_dpTrack : std_logic := '0'; --! current disparity: Hi = +1, LO = 0
signal s_RunDisp : t_state_type; --! running disparity register
begin
--=============================================================================
-- CONCURRENT COMMANDS
--=============================================================================
-- use 3bit at 7-5 as index for 4bit code and disparity table \n
s_ind3b <= to_integer(unsigned(s_in_8b_reg(7 downto 5)));
s_val4bit <= c_enc_3b_4b_table(s_ind3b);
s_dP4bit <= c_disPar_4b(s_ind3b);
s_val4bit_n <= not (s_val4bit);
-- use 5bit at 4-0 as index for 6bit code and disparity table
s_ind5b <= to_integer(unsigned(s_in_8b_reg(4 downto 0)));
s_val6bit <= c_enc_5b_6b_table(s_ind5b);
s_dP6bit <= c_disPar_6b(s_ind5b);
s_val6bit_n <= not (s_val6bit);
-- output wires
dispar_o <= s_dispar_reg;
err_o <= s_err_reg;
out_10b_o <= s_out_10b_reg;
--=============================================================================
-- ENCODING
--=============================================================================
--=============================================================================
-- Begin of p_encoding
--! Process encodes 8bit value to 10bit codeword depending on current disparity
--=============================================================================
--! read: clk_i, reset_i, all signals
--! write: err_o,dispar_o,out_10b_o, s_dpTrack
p_encoding: PROCESS (s_RunDisp, s_in_8b_reg, s_dP4bit, s_dP6bit, s_val4bit,
s_val4bit_n, s_val6bit, s_val6bit_n, s_ctrl_reg)
--! buffers ctrl code during selection
variable v_ctrl_code : std_logic_vector(9 downto 0) := (others => '0');
begin
v_ctrl_code := (others => '0');
s_err <= '0';
s_dpTrack <= '0';
--========================================================================
-- TRANSMISSION CONTROL CODES
--========================================================================
if s_ctrl_reg = '1' then -- Control Char selected
--! control byte directly selects control code
case s_in_8b_reg is
when "00011100" => v_ctrl_code := f_reverse_vector("0011110100");
when "00111100" => v_ctrl_code := f_reverse_vector("0011111001");
when "01011100" => v_ctrl_code := f_reverse_vector("0011110101");
when "01111100" => v_ctrl_code := f_reverse_vector("0011110011");
when "10011100" => v_ctrl_code := f_reverse_vector("0011110010");
when "10111100" => v_ctrl_code := f_reverse_vector("0011111010");
when "11011100" => v_ctrl_code := f_reverse_vector("0011110110");
when "11111100" => v_ctrl_code := f_reverse_vector("0011111000");
when "11110111" => v_ctrl_code := f_reverse_vector("1110101000");
when "11111011" => v_ctrl_code := f_reverse_vector("1101101000");
when "11111101" => v_ctrl_code := f_reverse_vector("1011101000");
when "11111110" => v_ctrl_code := f_reverse_vector("0111101000");
when others => s_err <= '1';
end case;
--! select the right disparity and assign to output
if (s_RunDisp = RD_MINUS) then
s_out_10b <= v_ctrl_code;
else
s_out_10b <= not(v_ctrl_code);
s_dpTrack <= '1';
end if;
else
--====================================================================
-- DATA CODES
--====================================================================
--s_out_10b(5 downto 0) <= f_reverse_vector(s_val6bit);
--s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit);
s_out_10b <= f_reverse_vector(s_val6bit & s_val4bit);
case s_RunDisp is
when RD_MINUS =>
if s_dP4bit = s_dP6bit then
if s_dP6bit = '1' then
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
else
if s_dP4bit = '1' then
if ( (s_val6bit(2 downto 0) = "011") and
(s_val4bit(3 downto 1) = "111") ) then
s_out_10b(9 downto 6) <= "1110";
end if;
else
if (s_val4bit = "1100") then
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
end if;
end if;
when RD_PLUS =>
if s_dP6bit = '1' then
s_out_10b(5 downto 0) <= f_reverse_vector(s_val6bit_n);
else
if (s_val6bit = "111000") then
s_out_10b(5 downto 0) <= f_reverse_vector(s_val6bit_n);
end if;
if s_dP4bit = '1' then
if ( (s_val6bit(2 downto 0) = "100") and
(s_val4bit(3 downto 1) = "111") ) then
s_out_10b(9 downto 6) <= "0001";
else
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
else
if (s_val4bit = "1100") then
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
end if;
end if;
s_dpTrack <= '1';
when others => s_out_10b <= (others => '0'); -- never be executed
end case;
end if;
end PROCESS p_encoding;
disp_FSM_state: process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
--======================================================================
-- SYNC RESET
--======================================================================
if (rst_n_i = '0') then
s_RunDisp <= RD_MINUS;
else
case s_RunDisp is
when RD_MINUS =>
if ( s_ctrl_reg xor s_dP6bit xor s_dP4bit ) /= '0' then
s_RunDisp <= RD_PLUS;
end if;
when RD_PLUS =>
if ( s_ctrl_reg xor s_dP6bit xor s_dP4bit ) /= '0' then
s_RunDisp <= RD_MINUS;
end if;
when others =>
s_RunDisp <= RD_MINUS;
end case;
--! control codes K28.7-K30.7
if ( s_in_8b_reg(1 downto 0) /= "00" and s_ctrl_reg = '1') then
s_RunDisp <= s_RunDisp;
end if;
end if;
end if;
end process;
inout_buffers: process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
--======================================================================
-- SYNC RESET
--======================================================================
--! reset encoder
if(rst_n_i = '0') then
s_ctrl_reg <= '0';
s_in_8b_reg <= B"000_00000";
s_dispar_reg <= '0';
s_err_reg <= '0';
s_out_10b_reg <= B"0000_000000";
else
s_ctrl_reg <= ctrl_i;
s_in_8b_reg <= in_8b_i;
s_dispar_reg <= s_dpTrack;
s_err_reg <= s_err;
s_out_10b_reg <= s_out_10b;
end if;
end if;
end process;
end rtl;
-------------------------------------------------------------------------------
-- Title : TBI (Ten-bit-inteface) PHY adapter
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : wr_tbi_phy.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2011-05-27
-- Last update: 2011-05-28
-- Platform : FPGA-generics
-- Standard : VHDL
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-05-27 1.0 twlostow Imported from wrsw_endpoint
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
entity wr_tbi_phy is
port(
---------------------------------------------------------------------------
-- Endpoint interface (serdes)
---------------------------------------------------------------------------
serdes_rst_i : in std_logic;
serdes_loopen_i : in std_logic;
serdes_prbsen_i : in std_logic;
serdes_enable_i : in std_logic;
serdes_syncen_i : in std_logic;
serdes_tx_data_i : in std_logic_vector(7 downto 0);
serdes_tx_k_i : in std_logic;
serdes_tx_disparity_o : out std_logic;
serdes_tx_enc_err_o : out std_logic;
serdes_rx_data_o : out std_logic_vector(7 downto 0);
serdes_rx_k_o : out std_logic;
serdes_rx_enc_err_o : out std_logic;
serdes_rx_bitslide_o : out std_logic_vector(3 downto 0);
---------------------------------------------------------------------------
-- TBI PHY I/O pins
---------------------------------------------------------------------------
tbi_refclk_i : in std_logic;
tbi_rbclk_i : in std_logic;
tbi_td_o : out std_logic_vector(9 downto 0);
tbi_rd_i : in std_logic_vector(9 downto 0);
tbi_syncen_o : out std_logic;
tbi_loopen_o : out std_logic;
tbi_prbsen_o : out std_logic;
tbi_enable_o : out std_logic
);
end wr_tbi_phy;
architecture rtl of wr_tbi_phy is
component dec_8b10b
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
in_10b_i : in std_logic_vector(9 downto 0);
ctrl_o : out std_logic;
code_err_o : out std_logic;
rdisp_err_o : out std_logic;
out_8b_o : out std_logic_vector(7 downto 0));
end component;
component enc_8b10b
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
ctrl_i : in std_logic;
in_8b_i : in std_logic_vector(7 downto 0);
err_o : out std_logic;
dispar_o : out std_logic;
out_10b_o : out std_logic_vector(9 downto 0));
end component;
signal rx_reg : std_logic_vector(9 downto 0);
signal tx_reg : std_logic_vector(9 downto 0);
signal txdata_encoded : std_logic_vector(9 downto 0);
signal dec_err_enc : std_logic;
signal dec_err_rdisp : std_logic;
signal rst_synced_rbclk : std_logic;
signal rst_synced_rbclk_n : std_logic;
signal serdes_rst_n : std_logic;
begin -- rtl
-------------------------------------------------------------------------------
-- RX path
-------------------------------------------------------------------------------
U_sync_reset : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => tbi_refclk_i,
rst_n_i => '1',
data_i => serdes_rst_i,
synced_o => rst_synced_rbclk,
npulse_o => open,
ppulse_o => open);
rst_synced_rbclk_n <= not rst_synced_rbclk;
p_register_input : process(tbi_rbclk_i)
begin
if rising_edge(tbi_rbclk_i) then
rx_reg <= tbi_rd_i;
end if;
end process;
U_DEC : dec_8b10b
port map (
clk_i => tbi_rbclk_i,
rst_n_i => rst_synced_rbclk_n,
in_10b_i => rx_reg,
ctrl_o => serdes_rx_k_o,
out_8b_o => serdes_rx_data_o,
code_err_o => dec_err_enc,
rdisp_err_o => dec_err_rdisp);
serdes_rx_enc_err_o <= dec_err_rdisp or dec_err_rdisp;
serdes_rx_bitslide_o <= (others => '0');
-------------------------------------------------------------------------------
-- TX Path
-------------------------------------------------------------------------------
serdes_rst_n <= not serdes_rst_i;
U_ENC : enc_8b10b
port map (
clk_i => tbi_refclk_i,
rst_n_i => serdes_rst_n,
ctrl_i => serdes_tx_k_i,
in_8b_i => serdes_tx_data_i,
err_o => serdes_tx_enc_err_o,
dispar_o => serdes_tx_disparity_o,
out_10b_o => txdata_encoded);
p_register_output : process(tbi_refclk_i)
begin
if rising_edge(tbi_refclk_i) then
tx_reg <= txdata_encoded;
end if;
end process;
tbi_td_o <= tx_reg;
end rtl;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment