library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library xpm; use xpm.vcomponents.all; entity combpm_protocol_electron is port( rst_n : in std_logic; clk : in std_logic; -- GT interface gt_datarx : in std_logic_vector(15 downto 0); gt_datatx : out std_logic_vector(15 downto 0); gt_powergood : in std_logic; gt_qplllock : in std_logic; gt_txclkactive : in std_logic; gt_rxclkactive : in std_logic; gt_txresetdone : in std_logic; gt_rxresetdone : in std_logic; gt_rxcdrlock : in std_logic; gt_rxbyteisaligned : in std_logic; gt_rxbyterealign : in std_logic; gt_rxcommadet : in std_logic; gt_txfault : in std_logic; gt_rxlos : in std_logic; gt_modabs : in std_logic; gt_rstall : out std_logic; gt_rxcommadeten : out std_logic; gt_txdisable : out std_logic; -- AXIS interface m_axi_tid : out std_logic_vector(0 downto 0); m_axi_tdest : out std_logic_vector(9 downto 0); m_axi_tdata : out std_logic_vector(127 downto 0); m_axi_tstrb : out std_logic_vector(15 downto 0); m_axi_tkeep : out std_logic_vector(15 downto 0); m_axi_tlast : out std_logic; m_axi_tuser : out std_logic_vector(0 downto 0); m_axi_tvalid : out std_logic; m_axi_tready : in std_logic; -- Status and control interface tx_disable_i : in std_logic; rx_commadeten_i : in std_logic; srst_gt_i : in std_logic; frame_counter_o : out std_logic_vector(15 downto 0); frame_error_o : out std_logic ); end entity combpm_protocol_electron; architecture rtl of combpm_protocol_electron is -------------------------- -- INTERFACE ATTRIBUTES -- -------------------------- ATTRIBUTE X_INTERFACE_INFO : STRING; ATTRIBUTE X_INTERFACE_PARAMETER : STRING; ATTRIBUTE X_INTERFACE_INFO of m_axi_tid : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TID"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tdest : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TDEST"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tdata : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TDATA"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tstrb : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TSTRB"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tkeep : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TKEEP"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tlast : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TLAST"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tuser : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TUSER"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tvalid : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TVALID"; ATTRIBUTE X_INTERFACE_INFO of m_axi_tready : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TREADY"; ATTRIBUTE X_INTERFACE_INFO of gt_datarx : SIGNAL is "soleil:user:gtsfp:1.0 GT datarx"; ATTRIBUTE X_INTERFACE_INFO of gt_datatx : SIGNAL is "soleil:user:gtsfp:1.0 GT datatx"; ATTRIBUTE X_INTERFACE_INFO of gt_powergood : SIGNAL is "soleil:user:gtsfp:1.0 GT powergood"; ATTRIBUTE X_INTERFACE_INFO of gt_qplllock : SIGNAL is "soleil:user:gtsfp:1.0 GT qplllock"; ATTRIBUTE X_INTERFACE_INFO of gt_txclkactive : SIGNAL is "soleil:user:gtsfp:1.0 GT txclkactive"; ATTRIBUTE X_INTERFACE_INFO of gt_rxclkactive : SIGNAL is "soleil:user:gtsfp:1.0 GT rxclkactive"; ATTRIBUTE X_INTERFACE_INFO of gt_txresetdone : SIGNAL is "soleil:user:gtsfp:1.0 GT txresetdone"; ATTRIBUTE X_INTERFACE_INFO of gt_rxresetdone : SIGNAL is "soleil:user:gtsfp:1.0 GT rxresetdone"; ATTRIBUTE X_INTERFACE_INFO of gt_rxcdrlock : SIGNAL is "soleil:user:gtsfp:1.0 GT rxcdrlock"; ATTRIBUTE X_INTERFACE_INFO of gt_rxbyteisaligned : SIGNAL is "soleil:user:gtsfp:1.0 GT rxbyteisaligned"; ATTRIBUTE X_INTERFACE_INFO of gt_rxbyterealign : SIGNAL is "soleil:user:gtsfp:1.0 GT rxbyterealign"; ATTRIBUTE X_INTERFACE_INFO of gt_rxcommadet : SIGNAL is "soleil:user:gtsfp:1.0 GT rxcommadet"; ATTRIBUTE X_INTERFACE_INFO of gt_txfault : SIGNAL is "soleil:user:gtsfp:1.0 GT txfault"; ATTRIBUTE X_INTERFACE_INFO of gt_rxlos : SIGNAL is "soleil:user:gtsfp:1.0 GT rxlos"; ATTRIBUTE X_INTERFACE_INFO of gt_modabs : SIGNAL is "soleil:user:gtsfp:1.0 GT modabs"; ATTRIBUTE X_INTERFACE_INFO of rst_n : SIGNAL is "xilinx.com:signal:reset:1.0 rst_n RST"; ATTRIBUTE X_INTERFACE_PARAMETER of rst_n : SIGNAL is "POLARITY ACTIVE_LOW"; -------------------------- -- CONSTANT DECLARATION -- -------------------------- constant C_SOP : std_logic_vector(15 downto 0) := x"5CFB"; constant C_EOP : std_logic_vector(15 downto 0) := x"FDFE"; constant C_DUMMY : std_logic_vector(31 downto 0) := x"12345678"; constant C_RSVD : std_logic_vector(31 downto 0) := x"00000000"; constant C_CRCINIT : std_logic_vector(31 downto 0) := x"FFFFFFFF"; ------------------------ -- SIGNAL DECLARATION -- ------------------------ signal S_AXI_RESET : std_logic; signal packet_reg : std_logic_vector(14*16-1 downto 0); -- Register to hold one packet signal flag_sop_inc : std_logic; signal flag_sop : std_logic; signal flag_eop : std_logic; signal flag_dummy : std_logic; signal flag_rsvd : std_logic; signal flag_crc : std_logic; signal flag_all : std_logic; signal flag_any : std_logic; signal packet_bpmid : std_logic_vector(9 downto 0); signal packet_startframe : std_logic; signal packet_timestamp : std_logic_vector(15 downto 0); signal packet_xpos : std_logic_vector(31 downto 0); signal packet_ypos : std_logic_vector(31 downto 0); signal packet_crc : std_logic_vector(31 downto 0); signal crc_result : std_logic_vector(31 downto 0); signal xorinv_crc_reg : std_logic_vector(31 downto 0); signal inv_crc_reg : std_logic_vector(31 downto 0); signal crc_reg : std_logic_vector(31 downto 0); signal lfsr_c : std_logic_vector(31 downto 0); signal crc_cnt : unsigned(3 downto 0); signal d : std_logic_vector(15 downto 0); signal frame_counter : unsigned(15 downto 0); signal gt_rxcommadeten_s : std_logic; signal itf_ready : std_logic; begin --------------------- -- PACKET REGISTER -- --------------------- p_packetreg:process(clk, rst_n) begin if rst_n = '0' then packet_reg <= (others => '0'); elsif rising_edge(clk) then -- Simple shift register, 16 bits width, 14 word long for I in 2 to 14 loop packet_reg(I*16-1 downto (I-1)*16) <= packet_reg((I-1)*16-1 downto (I-2)*16); end loop; -- swap bytes in input (first byte is LSB) packet_reg(15 downto 0) <= gt_datarx(7 downto 0) & gt_datarx(15 downto 8); end if; end process; ------------------------ -- PACKET CHECK FLAGS -- ------------------------ flag_sop <= '1' when packet_reg(14*16-1 downto 13*16) = C_SOP else '0'; flag_sop_inc <= '1' when packet_reg(15 downto 0) = C_SOP else '0'; flag_eop <= '1' when packet_reg(15 downto 0) = C_EOP else '0'; flag_dummy <= '1' when packet_reg(7*16-1 downto 5*16) = C_DUMMY else '0'; flag_rsvd <= '1' when packet_reg(5*16-1 downto 3*16) = C_RSVD else '0'; flag_crc <= '1' when packet_crc = crc_result else '0'; -- Any and all flag flag_all <= flag_sop and flag_eop and flag_dummy and flag_rsvd and flag_crc and itf_ready; flag_any <= flag_sop or flag_eop or flag_crc; ---------------------------- -- FRAME FIELD EXTRACTION -- ---------------------------- packet_bpmid <= packet_reg(185 downto 176); packet_startframe <= packet_reg(191); packet_timestamp <= packet_reg(13*16-1 downto 12*16); packet_xpos <= packet_reg(11*16-1 downto 9*16); packet_ypos <= packet_reg(9*16-1 downto 7*16); packet_crc <= packet_reg(3*16-1 downto 16); ----------------- -- CRC CHECKER -- ----------------- -- RefIn gen_invert: for I in 0 to 7 generate d(I) <= packet_reg(7-I); d(I+8) <= packet_reg(7-I+8); end generate; -- RefOut xorinv_crc_reg <= inv_crc_reg xor x"FFFFFFFF"; gen: for I in 0 to 31 generate inv_crc_reg(I) <= crc_reg(31-I); end generate; -- Byte reorder crc_result(7 downto 0) <= xorinv_crc_reg(31 downto 24); crc_result(15 downto 8) <= xorinv_crc_reg(23 downto 16); crc_result(23 downto 16) <= xorinv_crc_reg(15 downto 8); crc_result(31 downto 24) <= xorinv_crc_reg(7 downto 0); -- Register p_crc:process(clk, rst_n) begin if rst_n = '0' then crc_reg <= C_CRCINIT; crc_cnt <= (others => '0'); elsif rising_edge(clk) then if crc_cnt = 0 then if flag_sop_inc = '1' then crc_cnt <= crc_cnt+1; crc_reg <= C_CRCINIT; else crc_cnt <= (others => '0'); end if; else if crc_cnt = 10 then crc_cnt <= (others => '0'); else crc_cnt <= crc_cnt +1; end if; crc_reg <= lfsr_c; end if; end if; end process p_crc; -- Combinatorial, 16 turns unrolled lfsr_c(0) <= crc_reg(16) xor crc_reg(22) xor crc_reg(25) xor crc_reg(26) xor crc_reg(28) xor d(0) xor d(6) xor d(9) xor d(10) xor d(12); lfsr_c(1) <= crc_reg(16) xor crc_reg(17) xor crc_reg(22) xor crc_reg(23) xor crc_reg(25) xor crc_reg(27) xor crc_reg(28) xor crc_reg(29) xor d(0) xor d(1) xor d(6) xor d(7) xor d(9) xor d(11) xor d(12) xor d(13); lfsr_c(2) <= crc_reg(16) xor crc_reg(17) xor crc_reg(18) xor crc_reg(22) xor crc_reg(23) xor crc_reg(24) xor crc_reg(25) xor crc_reg(29) xor crc_reg(30) xor d(0) xor d(1) xor d(2) xor d(6) xor d(7) xor d(8) xor d(9) xor d(13) xor d(14); lfsr_c(3) <= crc_reg(17) xor crc_reg(18) xor crc_reg(19) xor crc_reg(23) xor crc_reg(24) xor crc_reg(25) xor crc_reg(26) xor crc_reg(30) xor crc_reg(31) xor d(1) xor d(2) xor d(3) xor d(7) xor d(8) xor d(9) xor d(10) xor d(14) xor d(15); lfsr_c(4) <= crc_reg(16) xor crc_reg(18) xor crc_reg(19) xor crc_reg(20) xor crc_reg(22) xor crc_reg(24) xor crc_reg(27) xor crc_reg(28) xor crc_reg(31) xor d(0) xor d(2) xor d(3) xor d(4) xor d(6) xor d(8) xor d(11) xor d(12) xor d(15); lfsr_c(5) <= crc_reg(16) xor crc_reg(17) xor crc_reg(19) xor crc_reg(20) xor crc_reg(21) xor crc_reg(22) xor crc_reg(23) xor crc_reg(26) xor crc_reg(29) xor d(0) xor d(1) xor d(3) xor d(4) xor d(5) xor d(6) xor d(7) xor d(10) xor d(13); lfsr_c(6) <= crc_reg(17) xor crc_reg(18) xor crc_reg(20) xor crc_reg(21) xor crc_reg(22) xor crc_reg(23) xor crc_reg(24) xor crc_reg(27) xor crc_reg(30) xor d(1) xor d(2) xor d(4) xor d(5) xor d(6) xor d(7) xor d(8) xor d(11) xor d(14); lfsr_c(7) <= crc_reg(16) xor crc_reg(18) xor crc_reg(19) xor crc_reg(21) xor crc_reg(23) xor crc_reg(24) xor crc_reg(26) xor crc_reg(31) xor d(0) xor d(2) xor d(3) xor d(5) xor d(7) xor d(8) xor d(10) xor d(15); lfsr_c(8) <= crc_reg(16) xor crc_reg(17) xor crc_reg(19) xor crc_reg(20) xor crc_reg(24) xor crc_reg(26) xor crc_reg(27) xor crc_reg(28) xor d(0) xor d(1) xor d(3) xor d(4) xor d(8) xor d(10) xor d(11) xor d(12); lfsr_c(9) <= crc_reg(17) xor crc_reg(18) xor crc_reg(20) xor crc_reg(21) xor crc_reg(25) xor crc_reg(27) xor crc_reg(28) xor crc_reg(29) xor d(1) xor d(2) xor d(4) xor d(5) xor d(9) xor d(11) xor d(12) xor d(13); lfsr_c(10) <= crc_reg(16) xor crc_reg(18) xor crc_reg(19) xor crc_reg(21) xor crc_reg(25) xor crc_reg(29) xor crc_reg(30) xor d(0) xor d(2) xor d(3) xor d(5) xor d(9) xor d(13) xor d(14); lfsr_c(11) <= crc_reg(16) xor crc_reg(17) xor crc_reg(19) xor crc_reg(20) xor crc_reg(25) xor crc_reg(28) xor crc_reg(30) xor crc_reg(31) xor d(0) xor d(1) xor d(3) xor d(4) xor d(9) xor d(12) xor d(14) xor d(15); lfsr_c(12) <= crc_reg(16) xor crc_reg(17) xor crc_reg(18) xor crc_reg(20) xor crc_reg(21) xor crc_reg(22) xor crc_reg(25) xor crc_reg(28) xor crc_reg(29) xor crc_reg(31) xor d(0) xor d(1) xor d(2) xor d(4) xor d(5) xor d(6) xor d(9) xor d(12) xor d(13) xor d(15); lfsr_c(13) <= crc_reg(17) xor crc_reg(18) xor crc_reg(19) xor crc_reg(21) xor crc_reg(22) xor crc_reg(23) xor crc_reg(26) xor crc_reg(29) xor crc_reg(30) xor d(1) xor d(2) xor d(3) xor d(5) xor d(6) xor d(7) xor d(10) xor d(13) xor d(14); lfsr_c(14) <= crc_reg(18) xor crc_reg(19) xor crc_reg(20) xor crc_reg(22) xor crc_reg(23) xor crc_reg(24) xor crc_reg(27) xor crc_reg(30) xor crc_reg(31) xor d(2) xor d(3) xor d(4) xor d(6) xor d(7) xor d(8) xor d(11) xor d(14) xor d(15); lfsr_c(15) <= crc_reg(19) xor crc_reg(20) xor crc_reg(21) xor crc_reg(23) xor crc_reg(24) xor crc_reg(25) xor crc_reg(28) xor crc_reg(31) xor d(3) xor d(4) xor d(5) xor d(7) xor d(8) xor d(9) xor d(12) xor d(15); lfsr_c(16) <= crc_reg(0) xor crc_reg(16) xor crc_reg(20) xor crc_reg(21) xor crc_reg(24) xor crc_reg(28) xor crc_reg(29) xor d(0) xor d(4) xor d(5) xor d(8) xor d(12) xor d(13); lfsr_c(17) <= crc_reg(1) xor crc_reg(17) xor crc_reg(21) xor crc_reg(22) xor crc_reg(25) xor crc_reg(29) xor crc_reg(30) xor d(1) xor d(5) xor d(6) xor d(9) xor d(13) xor d(14); lfsr_c(18) <= crc_reg(2) xor crc_reg(18) xor crc_reg(22) xor crc_reg(23) xor crc_reg(26) xor crc_reg(30) xor crc_reg(31) xor d(2) xor d(6) xor d(7) xor d(10) xor d(14) xor d(15); lfsr_c(19) <= crc_reg(3) xor crc_reg(19) xor crc_reg(23) xor crc_reg(24) xor crc_reg(27) xor crc_reg(31) xor d(3) xor d(7) xor d(8) xor d(11) xor d(15); lfsr_c(20) <= crc_reg(4) xor crc_reg(20) xor crc_reg(24) xor crc_reg(25) xor crc_reg(28) xor d(4) xor d(8) xor d(9) xor d(12); lfsr_c(21) <= crc_reg(5) xor crc_reg(21) xor crc_reg(25) xor crc_reg(26) xor crc_reg(29) xor d(5) xor d(9) xor d(10) xor d(13); lfsr_c(22) <= crc_reg(6) xor crc_reg(16) xor crc_reg(25) xor crc_reg(27) xor crc_reg(28) xor crc_reg(30) xor d(0) xor d(9) xor d(11) xor d(12) xor d(14); lfsr_c(23) <= crc_reg(7) xor crc_reg(16) xor crc_reg(17) xor crc_reg(22) xor crc_reg(25) xor crc_reg(29) xor crc_reg(31) xor d(0) xor d(1) xor d(6) xor d(9) xor d(13) xor d(15); lfsr_c(24) <= crc_reg(8) xor crc_reg(17) xor crc_reg(18) xor crc_reg(23) xor crc_reg(26) xor crc_reg(30) xor d(1) xor d(2) xor d(7) xor d(10) xor d(14); lfsr_c(25) <= crc_reg(9) xor crc_reg(18) xor crc_reg(19) xor crc_reg(24) xor crc_reg(27) xor crc_reg(31) xor d(2) xor d(3) xor d(8) xor d(11) xor d(15); lfsr_c(26) <= crc_reg(10) xor crc_reg(16) xor crc_reg(19) xor crc_reg(20) xor crc_reg(22) xor crc_reg(26) xor d(0) xor d(3) xor d(4) xor d(6) xor d(10); lfsr_c(27) <= crc_reg(11) xor crc_reg(17) xor crc_reg(20) xor crc_reg(21) xor crc_reg(23) xor crc_reg(27) xor d(1) xor d(4) xor d(5) xor d(7) xor d(11); lfsr_c(28) <= crc_reg(12) xor crc_reg(18) xor crc_reg(21) xor crc_reg(22) xor crc_reg(24) xor crc_reg(28) xor d(2) xor d(5) xor d(6) xor d(8) xor d(12); lfsr_c(29) <= crc_reg(13) xor crc_reg(19) xor crc_reg(22) xor crc_reg(23) xor crc_reg(25) xor crc_reg(29) xor d(3) xor d(6) xor d(7) xor d(9) xor d(13); lfsr_c(30) <= crc_reg(14) xor crc_reg(20) xor crc_reg(23) xor crc_reg(24) xor crc_reg(26) xor crc_reg(30) xor d(4) xor d(7) xor d(8) xor d(10) xor d(14); lfsr_c(31) <= crc_reg(15) xor crc_reg(21) xor crc_reg(24) xor crc_reg(25) xor crc_reg(27) xor crc_reg(31) xor d(5) xor d(8) xor d(9) xor d(11) xor d(15); -------------- -- AXIS OUT -- -------------- -- Static data m_axi_tstrb <= (others => '1'); m_axi_tkeep <= (others => '1'); m_axi_tid <= "0"; m_axi_tuser <= "0"; m_axi_tlast <= '1'; -- One transfer is One packet. p_axis:process(clk, rst_n) begin if rst_n = '0' then m_axi_tdata <= (others => '0'); m_axi_tvalid <= '0'; m_axi_tdest <= (others => '0'); elsif rising_edge(clk) then if flag_all = '1' then -- Make AXIS packet m_axi_tdata(31 downto 0) <= packet_ypos; m_axi_tdata(63 downto 32) <= packet_xpos; m_axi_tdata(95 downto 64) <= x"0000" & packet_timestamp; m_axi_tdata(111 downto 96) <= (others => '0'); m_axi_tdata(127 downto 112) <= "000000" & packet_bpmid; -- AXIS ancillary data m_axi_tdest <= packet_bpmid; -- AXIS TVALID m_axi_tvalid <= '1'; else -- Acknowledge transfer if m_axi_tready = '1' then m_axi_tvalid <= '0'; end if; end if; end if; end process p_axis; ------------------------ -- CONTROL AND STATUS -- ------------------------ frame_error_o <= flag_any xor flag_all; frame_counter_o <= std_logic_vector(frame_counter); itf_ready <= gt_txresetdone and gt_rxresetdone and gt_powergood and gt_qplllock and gt_rxbyteisaligned and (not srst_gt_i); -- frame counter p_framecnt:process(clk, rst_n) begin if rst_n = '0' then frame_counter <= (others => '0'); elsif rising_edge(clk) then if flag_all = '1' then frame_counter <= frame_counter+1; end if; end if; end process p_framecnt; -- Direct connexion to GT/SFP gt_txdisable <= tx_disable_i; gt_rstall <= srst_gt_i; gt_rxcommadeten <= rx_commadeten_i; end architecture rtl;