From: Michael Boehmer Date: Fri, 28 Oct 2022 22:29:58 +0000 (+0200) Subject: code cleanup in transition X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=2bcc03ef611730293a909d46881beb2fe824ed9d;p=trbnet.git code cleanup in transition --- diff --git a/gbe_trb/base/gbe_frame_constr.vhd b/gbe_trb/base/gbe_frame_constr.vhd new file mode 100644 index 0000000..e2a1414 --- /dev/null +++ b/gbe_trb/base/gbe_frame_constr.vhd @@ -0,0 +1,450 @@ +library IEEE; +use IEEE.std_logic_1164.ALL; +use IEEE.numeric_std.ALL; +use IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; + +entity gbe_frame_constr is + port( + -- ports for user logic + RESET : in std_logic; + CLK : in std_logic; -- 125MHz clock + LINK_OK_IN : in std_logic; + -- frame stuff + WR_EN_IN : in std_logic; + DATA_IN : in std_logic_vector(7 downto 0); + START_OF_DATA_IN : in std_logic; + END_OF_DATA_IN : in std_logic; + IP_F_SIZE_IN : in std_logic_vector(15 downto 0); + UDP_P_SIZE_IN : in std_logic_vector(15 downto 0); -- needed for fragmentation + HEADERS_READY_OUT : out std_logic; + READY_OUT : out std_logic; + DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); + SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + FRAME_TYPE_IN : in std_logic_vector(15 downto 0); + IHL_VERSION_IN : in std_logic_vector(7 downto 0); + TOS_IN : in std_logic_vector(7 downto 0); + IDENTIFICATION_IN : in std_logic_vector(15 downto 0); + FLAGS_OFFSET_IN : in std_logic_vector(15 downto 0); + TTL_IN : in std_logic_vector(7 downto 0); + PROTOCOL_IN : in std_logic_vector(7 downto 0); + FRAME_DELAY_IN : in std_logic_vector(31 downto 0); + -- port for "RX ringbuffer" + FT_TX_DATA_OUT : out std_logic_vector(8 downto 0); + FT_TX_WR_OUT : out std_logic; + FT_TX_FIFOFULL_IN : in std_logic; + -- monitoring + MONITOR_TX_BYTES_OUT : out std_logic_vector(31 downto 0); + MONITOR_TX_FRAMES_OUT : out std_logic_vector(31 downto 0) + ); +end entity gbe_frame_constr; + +architecture gbe_frame_constr_arch of gbe_frame_constr is + +attribute syn_encoding : string; + +type constructStates is (IDLE, DEST_MAC_ADDR, SRC_MAC_ADDR, FRAME_TYPE_S, VERSION, + TOS_S, IP_LENGTH, IDENT, FLAGS, TTL_S, PROTO, HEADER_CS, + SRC_IP_ADDR, DEST_IP_ADDR, SRC_PORT, DEST_PORT, UDP_LENGTH, + UDP_CS, SAVE_DATA, CLEANUP, DELAY); +signal constructCurrentState, constructNextState : constructStates; +attribute syn_encoding of constructCurrentState: signal is "onehot"; + +signal headers_int_counter : integer range 0 to 6; +signal fpf_data : std_logic_vector(7 downto 0); +signal fpf_wr_en : std_logic; +signal fpf_rd_en : std_logic; +signal fpf_rd_en_q : std_logic; +signal fpf_q : std_logic_vector(8 downto 0); +signal ip_size : std_logic_vector(15 downto 0); +signal ip_checksum : std_logic_vector(31 downto 0); +signal udp_size : std_logic_vector(15 downto 0); +signal udp_checksum : std_logic_vector(15 downto 0); +signal put_udp_headers : std_logic; +signal ready : std_logic; +signal headers_ready : std_logic; + +signal cur_max : integer range 0 to 10; + +signal ip_cs_temp_right : std_logic_vector(15 downto 0); + +signal delay_ctr : std_logic_vector(31 downto 0); +signal frame_delay_reg : std_logic_vector(31 downto 0); +signal fpf_data_q : std_logic_vector(7 downto 0); +signal fpf_wr_en_q : std_logic; +signal fpf_eod_q : std_logic; + +signal mon_sent_frames : unsigned(31 downto 0); +signal mon_sent_bytes : unsigned(31 downto 0); + +begin + +-- No checksum test needed +udp_checksum <= x"0000"; + +-- frame constructor ready +THE_READY_PROC: process( CLK ) +begin +if( rising_edge(CLK) )then + if( constructCurrentState = IDLE ) then + ready <= '1'; + else + ready <= '0'; + end if; + + if( constructCurrentState = SAVE_DATA ) then + headers_ready <= '1'; + else + headers_ready <= '0'; + end if; +end if; +end process; + +-- Calculate UDP and IP sizes +THE_SIZE_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( (put_udp_headers = '1') and (DEST_UDP_PORT_IN /= x"0000") ) then + ip_size <= IP_F_SIZE_IN + x"14" + x"8"; + udp_size <= UDP_P_SIZE_IN + x"8"; + else + ip_size <= IP_F_SIZE_IN + x"14"; + udp_size <= UDP_P_SIZE_IN; + end if; + end if; +end process THE_SIZE_PROC; + +THE_IP_CS_PROC : process( CLK ) +begin + if( rising_edge(CLK) ) then + if( constructCurrentState = IDLE ) then + ip_checksum <= x"00000000"; + else + case constructCurrentState is + when DEST_MAC_ADDR => + case headers_int_counter is + when 0 => + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + SRC_IP_ADDRESS_IN(7 downto 0); + when 1 => + ip_checksum <= ip_checksum + SRC_IP_ADDRESS_IN(15 downto 8); + when 2 => + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + SRC_IP_ADDRESS_IN(23 downto 16); + when 3 => + ip_checksum <= ip_checksum + SRC_IP_ADDRESS_IN(31 downto 24); + when 4 => + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + DEST_IP_ADDRESS_IN(7 downto 0); + when 5 => + ip_checksum <= ip_checksum + DEST_IP_ADDRESS_IN(15 downto 8); + when others => null; + end case; + when SRC_MAC_ADDR => + case headers_int_counter is + when 0 => + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + DEST_IP_ADDRESS_IN(23 downto 16); + when 1 => + ip_checksum <= ip_checksum + DEST_IP_ADDRESS_IN(31 downto 24); + when 2 => + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + IHL_VERSION_IN; + when 3 => + ip_checksum <= ip_checksum + TOS_IN; + when 4 => + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + ip_size(15 downto 8); + when 5 => + ip_checksum <= ip_checksum + ip_size(7 downto 0); + when others => null; + end case; + when VERSION => + if( headers_int_counter = 0 ) then + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + IDENTIFICATION_IN(7 downto 0); + end if; + when TOS_S => + if( headers_int_counter = 0 ) then + ip_checksum <= ip_checksum + IDENTIFICATION_IN(15 downto 8); + end if; + when IP_LENGTH => + if( headers_int_counter = 0 ) then + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + FLAGS_OFFSET_IN(15 downto 8); + elsif headers_int_counter = 1 then + ip_checksum <= ip_checksum + FLAGS_OFFSET_IN(7 downto 0); + end if; + when IDENT => + if headers_int_counter = 0 then + ip_checksum(31 downto 8) <= ip_checksum(31 downto 8) + TTL_IN; + elsif headers_int_counter = 1 then + ip_checksum <= ip_checksum + PROTOCOL_IN; + end if; + -- gk 29.03.10 corrected the bug with bad checksums when sum larger than 16b + when FLAGS => + if ( headers_int_counter = 0 ) then + ip_cs_temp_right <= ip_checksum(31 downto 16); + elsif( headers_int_counter = 1 ) then + ip_checksum(31 downto 16) <= (others => '0'); + end if; + when TTL_S => + if( headers_int_counter = 0 ) then + ip_checksum <= ip_checksum + ip_cs_temp_right; + end if; + when PROTO => + if( headers_int_counter = 0 ) then + ip_checksum(15 downto 0) <= ip_checksum(15 downto 0) + ip_checksum(31 downto 16); + end if; + when others => null; + end case; + end if; + end if; +end process THE_IP_CS_PROC; + + +THE_CONSTRUCT_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( RESET = '1' ) then + constructCurrentState <= IDLE; + else + constructCurrentState <= constructNextState; + end if; + end if; +end process THE_CONSTRUCT_PROC; + +--find next state of construct machine +constructMachine: process( constructCurrentState, delay_ctr, FRAME_DELAY_IN, START_OF_DATA_IN, + END_OF_DATA_IN, headers_int_counter, put_udp_headers, CUR_MAX, + FRAME_TYPE_IN, DEST_UDP_PORT_IN) +begin + constructNextState <= constructCurrentState; + if( headers_int_counter = cur_max ) then --can be checked everytime - if not in use, counter and cur_max are 0 + case constructCurrentState is + when IDLE => + if( START_OF_DATA_IN = '1' ) then + constructNextState <= DEST_MAC_ADDR; + end if; + when DEST_MAC_ADDR => + constructNextState <= SRC_MAC_ADDR; + when SRC_MAC_ADDR => + constructNextState <= FRAME_TYPE_S; + when FRAME_TYPE_S => + if( FRAME_TYPE_IN = x"0008" ) then + constructNextState <= VERSION; + else -- otherwise transmit data as pure ethernet frame + constructNextState <= SAVE_DATA; + end if; + when VERSION => + constructNextState <= TOS_S; + when TOS_S => + constructNextState <= IP_LENGTH; + when IP_LENGTH => + constructNextState <= IDENT; + when IDENT => + constructNextState <= FLAGS; + when FLAGS => + constructNextState <= TTL_S; + when TTL_S => + constructNextState <= PROTO; + when PROTO => + constructNextState <= HEADER_CS; + when HEADER_CS => + constructNextState <= SRC_IP_ADDR; + when SRC_IP_ADDR => + constructNextState <= DEST_IP_ADDR; + when DEST_IP_ADDR => + if( (put_udp_headers = '1') and (DEST_UDP_PORT_IN /= x"0000") ) then + constructNextState <= SRC_PORT; + else + constructNextState <= SAVE_DATA; + end if; + when SRC_PORT => + constructNextState <= DEST_PORT; + when DEST_PORT => + constructNextState <= UDP_LENGTH; + when UDP_LENGTH => + constructNextState <= UDP_CS; + when UDP_CS => + constructNextState <= SAVE_DATA; + when SAVE_DATA => + if( END_OF_DATA_IN = '1' ) then + constructNextState <= CLEANUP; + end if; + when CLEANUP => + constructNextState <= DELAY; + when DELAY => + if (delay_ctr = FRAME_DELAY_IN) then + constructNextState <= IDLE; + else + constructNextState <= DELAY; + end if; + + when others => + constructNextState <= IDLE; + end case; + end if; +end process constructMachine; + +THE_DELAY_CTR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( (constructCurrentState = IDLE) or (constructCurrentState = CLEANUP) ) then + delay_ctr <= (others => '0'); + elsif( constructCurrentState = DELAY ) then + delay_ctr <= delay_ctr + x"1"; + end if; + + frame_delay_reg <= FRAME_DELAY_IN; + end if; +end process THE_DELAY_CTR_PROC; + +THE_BSM_CONSTR_PROC: process( constructCurrentState ) +begin +--find maximum time in each state & set state bits + case constructCurrentState is + when IDLE => cur_max <= 0; + when DEST_MAC_ADDR => cur_max <= 5; + when SRC_MAC_ADDR => cur_max <= 5; + when FRAME_TYPE_S => cur_max <= 1; + when VERSION => cur_max <= 0; + when TOS_S => cur_max <= 0; + when IP_LENGTH => cur_max <= 1; + when IDENT => cur_max <= 1; + when FLAGS => cur_max <= 1; + when TTL_S => cur_max <= 0; + when PROTO => cur_max <= 0; + when HEADER_CS => cur_max <= 1; + when SRC_IP_ADDR => cur_max <= 3; + when DEST_IP_ADDR => cur_max <= 3; + when SRC_PORT => cur_max <= 1; + when DEST_PORT => cur_max <= 1; + when UDP_LENGTH => cur_max <= 1; + when UDP_CS => cur_max <= 1; + when SAVE_DATA => cur_max <= 0; + when CLEANUP => cur_max <= 0; + when DELAY => cur_max <= 0; + when others => cur_max <= 0; +end case; +end process THE_BSM_CONSTR_PROC; + +THE_HEADERS_INT_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( constructCurrentState = IDLE ) then + headers_int_counter <= 0; + else + if( headers_int_counter = cur_max ) then + headers_int_counter <= 0; + else + headers_int_counter <= headers_int_counter + 1; + end if; + end if; +end if; +end process THE_HEADERS_INT_PROC; + +THE_PUT_UDP_HEADERS_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( FLAGS_OFFSET_IN(12 downto 0) = "0000000000000" ) then + put_udp_headers <= '1'; + else + put_udp_headers <= '0'; + end if; + end if; +end process THE_PUT_UDP_HEADERS_PROC; + +THE_FPF_WREN_PROC : process( constructCurrentState, WR_EN_IN, LINK_OK_IN ) +begin + if ( LINK_OK_IN = '0' ) then + fpf_wr_en <= '0'; + elsif( (constructCurrentState /= IDLE) and (constructCurrentState /= CLEANUP) and (constructCurrentState /= SAVE_DATA) and (constructCurrentState /= DELAY) ) then + fpf_wr_en <= '1'; + elsif( (constructCurrentState = SAVE_DATA) and (WR_EN_IN = '1') ) then + fpf_wr_en <= '1'; + else + fpf_wr_en <= '0'; + end if; +end process THE_FPF_WREN_PROC; + +THE_FPF_DATA_PROC: process( constructCurrentState, DEST_MAC_ADDRESS_IN, SRC_MAC_ADDRESS_IN, FRAME_TYPE_IN, IHL_VERSION_IN, + TOS_IN, ip_size, IDENTIFICATION_IN, FLAGS_OFFSET_IN, TTL_IN, PROTOCOL_IN, + ip_checksum, SRC_IP_ADDRESS_IN, DEST_IP_ADDRESS_IN, + SRC_UDP_PORT_IN, DEST_UDP_PORT_IN, udp_size, udp_checksum, headers_int_counter, DATA_IN ) +begin + case constructCurrentState is + when IDLE => fpf_data <= DEST_MAC_ADDRESS_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when DEST_MAC_ADDR => fpf_data <= DEST_MAC_ADDRESS_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when SRC_MAC_ADDR => fpf_data <= SRC_MAC_ADDRESS_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when FRAME_TYPE_S => fpf_data <= FRAME_TYPE_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when VERSION => fpf_data <= IHL_VERSION_IN; + when TOS_S => fpf_data <= TOS_IN; + when IP_LENGTH => fpf_data <= ip_size(15 - headers_int_counter * 8 downto 8 - headers_int_counter * 8); + when IDENT => fpf_data <= IDENTIFICATION_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when FLAGS => fpf_data <= FLAGS_OFFSET_IN(15 - headers_int_counter * 8 downto 8 - headers_int_counter * 8); + when TTL_S => fpf_data <= TTL_IN; + when PROTO => fpf_data <= PROTOCOL_IN; + when HEADER_CS => fpf_data <= x"ff" - ip_checksum(15 - headers_int_counter * 8 downto 8 - headers_int_counter * 8); + when SRC_IP_ADDR => fpf_data <= SRC_IP_ADDRESS_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when DEST_IP_ADDR => fpf_data <= DEST_IP_ADDRESS_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when SRC_PORT => fpf_data <= SRC_UDP_PORT_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when DEST_PORT => fpf_data <= DEST_UDP_PORT_IN(headers_int_counter * 8 + 7 downto headers_int_counter * 8); + when UDP_LENGTH => fpf_data <= udp_size(15 - headers_int_counter * 8 downto 8 - headers_int_counter * 8); + when UDP_CS => fpf_data <= udp_checksum(15 - headers_int_counter * 8 downto 8 - headers_int_counter * 8); + when SAVE_DATA => fpf_data <= DATA_IN; + when CLEANUP => fpf_data <= x"ab"; + when DELAY => fpf_data <= x"ac"; + when others => fpf_data <= x"00"; + end case; +end process THE_FPF_DATA_PROC; + +THE_SYNC_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + fpf_data_q <= fpf_data; + fpf_wr_en_q <= fpf_wr_en; + fpf_eod_q <= END_OF_DATA_IN; + end if; +end process THE_SYNC_PROC; + +-- count bytes sent +THE_MON_SENT_BYTES_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( LINK_OK_IN = '0' ) then + mon_sent_bytes <= (others => '0'); + elsif( fpf_rd_en = '1' ) then + mon_sent_bytes <= mon_sent_bytes + 1; + else + mon_sent_bytes <= mon_sent_bytes; + end if; + end if; +end process THE_MON_SENT_BYTES_PROC; + +-- count frames sent +THE_MON_SENT_FRAMES_PROC: process( CLK ) +begin + if( rising_edge(CLK) )then + if ( LINK_OK_IN = '0' ) then + mon_sent_frames <= (others => '0'); + elsif( (fpf_wr_en_q = '1') and (fpf_eod_q = '1') ) then -- TO BE TESTED + mon_sent_frames <= mon_sent_frames + 1; + else + mon_sent_frames <= mon_sent_frames; + end if; + end if; +end process THE_MON_SENT_FRAMES_PROC; + +-- Outputs + +FT_TX_DATA_OUT(7 downto 0) <= fpf_data_q; +FT_TX_DATA_OUT(8) <= fpf_eod_q; +FT_TX_WR_OUT <= fpf_wr_en_q; + +READY_OUT <= ready; +HEADERS_READY_OUT <= headers_ready; + +MONITOR_TX_BYTES_OUT <= std_logic_vector(mon_sent_bytes); +MONITOR_TX_FRAMES_OUT <= std_logic_vector(mon_sent_frames); + +end gbe_frame_constr_arch; diff --git a/gbe_trb/base/gbe_frame_receiver.vhd b/gbe_trb/base/gbe_frame_receiver.vhd new file mode 100644 index 0000000..099db77 --- /dev/null +++ b/gbe_trb/base/gbe_frame_receiver.vhd @@ -0,0 +1,717 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + +--******** +-- here all frame checking has to be done, if the frame fits into protocol standards +-- if so FR_FRAME_VALID_OUT is asserted after having received all bytes of a frame +-- otherwise, after receiving all bytes, FR_FRAME_VALID_OUT keeps low and the fifo is cleared +-- also a part of addresses assignment has to be done here + +-- This entity receives an Ethernet frame, disassembles it and checks if the frame has to be processed. +-- In case, decoded information from header is stored in FIFOs and next stage is informed about available +-- data by FR_FRAME_VALID_OUT. + +entity gbe_frame_receiver is +port ( + CLK : in std_logic; -- system clock + RESET : in std_logic; + LINK_OK_IN : in std_logic; + ALLOW_RX_IN : in std_logic; + MY_MAC_IN : in std_logic_vector(47 downto 0); +-- killer ping + MY_TRBNET_ADDRESS_IN : in std_logic_vector(15 downto 0) := (others => '0'); + ISSUE_REBOOT_OUT : out std_logic; +-- input signals from TS_MAC + MAC_RX_EOF_IN : in std_logic; -- End Of Frame + MAC_RX_ER_IN : in std_logic; -- only for statistics + MAC_RXD_IN : in std_logic_vector(7 downto 0); -- RX data + MAC_RX_EN_IN : in std_logic; -- write signal +-- output signal to control logic + FR_Q_OUT : out std_logic_vector(8 downto 0); + FR_RD_EN_IN : in std_logic; + FR_FRAME_VALID_OUT : out std_logic; + FR_GET_FRAME_IN : in std_logic; + FR_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + FR_FRAME_PROTO_OUT : out std_logic_vector(15 downto 0); + FR_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + FR_ALLOWED_TYPES_IN : in std_logic_vector(31 downto 0); + FR_ALLOWED_IP_IN : in std_logic_vector(31 downto 0); + FR_ALLOWED_UDP_IN : in std_logic_vector(31 downto 0); + FR_VLAN_ID_IN : in std_logic_vector(31 downto 0); +-- + FR_SRC_MAC_ADDRESS_OUT : out std_logic_vector(47 downto 0); + FR_DEST_MAC_ADDRESS_OUT : out std_logic_vector(47 downto 0); + FR_SRC_IP_ADDRESS_OUT : out std_logic_vector(31 downto 0); + FR_DEST_IP_ADDRESS_OUT : out std_logic_vector(31 downto 0); + FR_SRC_UDP_PORT_OUT : out std_logic_vector(15 downto 0); + FR_DEST_UDP_PORT_OUT : out std_logic_vector(15 downto 0); +-- + OOB_REGISTER_0_OUT : out std_logic_vector(31 downto 0); + OOB_REGISTER_1_OUT : out std_logic_vector(31 downto 0); + OOB_REGISTER_2_OUT : out std_logic_vector(31 downto 0); + OOB_REGISTER_3_OUT : out std_logic_vector(31 downto 0); +-- + MONITOR_RX_BYTES_OUT : out std_logic_vector(31 downto 0); + MONITOR_RX_FRAMES_OUT : out std_logic_vector(31 downto 0); + MONITOR_DROPPED_OUT : out std_logic_vector(31 downto 0); + DEBUG_OUT : out std_logic_vector(15 downto 0) +); +end gbe_frame_receiver; + +architecture gbe_frame_receiver_arch of gbe_frame_receiver is + +attribute syn_encoding : string; +type filter_states is (IDLE, REMOVE_DEST, REMOVE_SRC, REMOVE_TYPE, SAVE_FRAME, DROP_FRAME, + REMOVE_VID, REMOVE_VTYPE, REMOVE_IP, REMOVE_UDP, DECIDE, CLEANUP); +signal filter_current_state, filter_next_state : filter_states; +attribute syn_encoding of filter_current_state : signal is "onehot"; + +signal fifo_wr_en : std_logic; +signal rx_bytes_ctr : std_logic_vector(15 downto 0); +signal frame_valid_q : std_logic; +signal delayed_frame_valid : std_logic; +signal delayed_frame_valid_q : std_logic; + +signal rec_fifo_empty : std_logic; +signal rec_fifo_full : std_logic; +signal sizes_fifo_full : std_logic; +signal sizes_fifo_empty : std_logic; + +signal remove_ctr : unsigned(7 downto 0); +signal new_frame : std_logic; +signal new_frame_lock : std_logic := '0'; +signal saved_frame_type : std_logic_vector(15 downto 0); +signal saved_vid : std_logic_vector(15 downto 0) := (others => '0'); +signal saved_src_mac : std_logic_vector(47 downto 0); +signal saved_dest_mac : std_logic_vector(47 downto 0); +signal frame_type_valid : std_logic; +signal saved_proto : std_logic_vector(7 downto 0); +signal saved_src_ip : std_logic_vector(31 downto 0); +signal saved_dest_ip : std_logic_vector(31 downto 0); +signal saved_src_udp : std_logic_vector(15 downto 0); +signal saved_dest_udp : std_logic_vector(15 downto 0); + +signal error_frames_ctr : unsigned(15 downto 0); +signal dbg_rec_frames : unsigned(31 downto 0); +signal dbg_drp_frames : unsigned(31 downto 0); +signal mon_rec_bytes : unsigned(31 downto 0); + +signal state : std_logic_vector(3 downto 0); + +signal rx_data : std_logic_vector(8 downto 0); +signal fr_q : std_logic_vector(8 downto 0); + +signal fr_src_ip : std_logic_vector(31 downto 0); +signal fr_dest_ip : std_logic_vector(31 downto 0); +signal fr_dest_udp : std_logic_vector(15 downto 0); +signal fr_src_udp : std_logic_vector(15 downto 0); +signal fr_frame_size : std_logic_vector(15 downto 0); +signal fr_frame_proto : std_logic_vector(15 downto 0); +signal fr_dest_mac : std_logic_vector(47 downto 0); +signal fr_src_mac : std_logic_vector(47 downto 0); +signal fr_ip_proto : std_logic_vector(7 downto 0); + +signal xxx0 : std_logic_vector(7 downto 0); +signal xxx1 : std_logic_vector(7 downto 0); + +signal oob_register_0_int : std_logic_vector(31 downto 0); +signal oob_register_1_int : std_logic_vector(31 downto 0); +signal oob_register_2_int : std_logic_vector(31 downto 0); +signal oob_register_3_int : std_logic_vector(31 downto 0); +signal oob_write : std_logic; + +attribute syn_preserve : boolean; +attribute syn_keep : boolean; +attribute syn_keep of rec_fifo_empty, rec_fifo_full, state, sizes_fifo_empty, sizes_fifo_full : signal is true; +attribute syn_preserve of rec_fifo_empty, rec_fifo_full, state, sizes_fifo_empty, sizes_fifo_full : signal is true; + +begin + +-- new_frame is asserted when first byte of the frame arrives +THE_NEW_FRAME_PROC: process( CLK ) +begin + if( rising_edge(CLK) )then + if ( (LINK_OK_IN = '0') or (MAC_RX_EOF_IN = '1') ) then + new_frame <= '0'; + new_frame_lock <= '0'; + elsif( (new_frame_lock = '0') and (MAC_RX_EN_IN = '1') ) then + new_frame <= '1'; + new_frame_lock <= '1'; + else + new_frame <= '0'; + end if; + end if; +end process THE_NEW_FRAME_PROC; + +THE_FILTER_MACHINE_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + filter_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + filter_current_state <= filter_next_state; + end if; +end process THE_FILTER_MACHINE_PROC; + +THE_FILTER_MACHINE : process( filter_current_state, saved_frame_type, LINK_OK_IN, saved_proto, MY_MAC_IN, + saved_dest_mac, remove_ctr, new_frame, MAC_RX_EOF_IN, frame_type_valid, ALLOW_RX_IN) +begin + case filter_current_state is + + when IDLE => + state <= x"1"; + if( (new_frame = '1') and (ALLOW_RX_IN = '1') and (LINK_OK_IN = '1') ) then + filter_next_state <= REMOVE_DEST; + else + filter_next_state <= IDLE; + end if; + + -- frames arrive without preamble! + when REMOVE_DEST => + state <= x"3"; + if( remove_ctr = x"03" ) then -- counter starts with a delay that's why only 3 + -- destination MAC address filtering here + if( (saved_dest_mac = MY_MAC_IN) or (saved_dest_mac = x"ffffffffffff") ) then -- must accept broadcasts for ARP + filter_next_state <= REMOVE_SRC; + else + filter_next_state <= DECIDE; + end if; + else + filter_next_state <= REMOVE_DEST; + end if; + + when REMOVE_SRC => + state <= x"4"; + if( remove_ctr = x"09" ) then + filter_next_state <= REMOVE_TYPE; + else + filter_next_state <= REMOVE_SRC; + end if; + + when REMOVE_TYPE => + state <= x"5"; + if( remove_ctr = x"0b" ) then + if( saved_frame_type = x"8100" ) then -- VLAN tagged frame + filter_next_state <= REMOVE_VID; + else -- no VLAN tag + if( saved_frame_type = x"0800" ) then -- in case of IP continue removing headers + filter_next_state <= REMOVE_IP; + else + filter_next_state <= DECIDE; + end if; + end if; + else + filter_next_state <= REMOVE_TYPE; + end if; + + when REMOVE_VID => + state <= x"a"; + if( remove_ctr = x"0d" ) then + filter_next_state <= REMOVE_VTYPE; + else + filter_next_state <= REMOVE_VID; + end if; + + when REMOVE_VTYPE => + state <= x"b"; + if( remove_ctr = x"0f" ) then + if( saved_frame_type = x"0800" ) then -- in case of IP continue removing headers + filter_next_state <= REMOVE_IP; + else + filter_next_state <= DECIDE; + end if; + else + filter_next_state <= REMOVE_VTYPE; + end if; + + when REMOVE_IP => + state <= x"c"; + if( remove_ctr = x"11" ) then + if( saved_proto = x"11" ) then -- forced to recognize udp only, TODO check all protocols + filter_next_state <= REMOVE_UDP; + else + filter_next_state <= DECIDE; -- changed from drop + end if; + else + filter_next_state <= REMOVE_IP; + end if; + + when REMOVE_UDP => + state <= x"d"; + if( remove_ctr = x"19" ) then + filter_next_state <= DECIDE; + else + filter_next_state <= REMOVE_UDP; + end if; + + when DECIDE => + state <= x"6"; + if ( frame_type_valid = '1' ) then + filter_next_state <= SAVE_FRAME; + elsif( saved_frame_type = x"0806" ) then + -- ARP? + filter_next_state <= SAVE_FRAME; + else + filter_next_state <= DROP_FRAME; + end if; + + when SAVE_FRAME => + state <= x"7"; + if( MAC_RX_EOF_IN = '1' ) then + filter_next_state <= CLEANUP; + else + filter_next_state <= SAVE_FRAME; + end if; + + when DROP_FRAME => + state <= x"8"; + if( MAC_RX_EOF_IN = '1' ) then + filter_next_state <= CLEANUP; + else + filter_next_state <= DROP_FRAME; + end if; + + when CLEANUP => + state <= x"9"; + filter_next_state <= IDLE; + + when others => null; + + end case; +end process THE_FILTER_MACHINE; + +-- counts the bytes to be removed from the ethernet headers fields +REMOVE_CTR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( (filter_current_state = IDLE) or + ((filter_current_state = REMOVE_VTYPE) and (remove_ctr = x"0f")) or + ((filter_current_state = REMOVE_TYPE) and (remove_ctr = x"0b") and (saved_frame_type /= x"8100")) ) then + remove_ctr <= (others => '1'); + elsif( (MAC_RX_EN_IN = '1') and (filter_current_state /= IDLE) ) then + remove_ctr <= remove_ctr + 1; + end if; + end if; +end process REMOVE_CTR_PROC; + +THE_SAVED_PROTO_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_proto <= (others => '0'); + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"07") ) then + saved_proto <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_PROTO_PROC; + +-- saves the destination mac address of the incoming frame +THE_SAVED_DEST_MAC_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_dest_mac <= (others => '0'); + elsif( (filter_current_state = IDLE) and (MAC_RX_EN_IN = '1') and (new_frame = '0') ) then + saved_dest_mac(7 downto 0) <= MAC_RXD_IN; + elsif( (filter_current_state = IDLE) and (new_frame = '1') and (ALLOW_RX_IN = '1') ) then + saved_dest_mac(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_DEST) and (remove_ctr = x"FF") ) then + saved_dest_mac(23 downto 16) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_DEST) and (remove_ctr = x"00") ) then + saved_dest_mac(31 downto 24) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_DEST) and (remove_ctr = x"01") ) then + saved_dest_mac(39 downto 32) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_DEST) and (remove_ctr = x"02") ) then + saved_dest_mac(47 downto 40) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_DEST_MAC_PROC; + +-- saves the source mac address of the incoming frame +THE_SAVED_SRC_MAC_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_src_mac <= (others => '0'); + elsif( (filter_current_state = REMOVE_DEST) and (remove_ctr = x"03") )then + saved_src_mac(7 downto 0) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_SRC) and (remove_ctr = x"04") ) then + saved_src_mac(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_SRC) and (remove_ctr = x"05") ) then + saved_src_mac(23 downto 16) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_SRC) and (remove_ctr = x"06") ) then + saved_src_mac(31 downto 24) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_SRC) and (remove_ctr = x"07") ) then + saved_src_mac(39 downto 32) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_SRC) and (remove_ctr = x"08") ) then + saved_src_mac(47 downto 40) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_SRC_MAC_PROC; + +-- saves the frame type of the incoming frame for futher check +THE_SAVED_FRAME_TYPE_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_frame_type <= (others => '0'); + elsif( (filter_current_state = REMOVE_SRC) and (remove_ctr = x"09") ) then + saved_frame_type(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_TYPE) and (remove_ctr = x"0a") ) then + saved_frame_type(7 downto 0) <= MAC_RXD_IN; + -- two more cases for VLAN tagged frame + elsif( (filter_current_state = REMOVE_VID) and (remove_ctr = x"0d") ) then + saved_frame_type(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_VTYPE) and (remove_ctr = x"0e") ) then + saved_frame_type(7 downto 0) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_FRAME_TYPE_PROC; + +THE_SAVED_SRC_IP_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_src_ip <= (others => '0'); + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"0a") ) then + saved_src_ip(7 downto 0) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"0b") ) then + saved_src_ip(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"0c") ) then + saved_src_ip(23 downto 16) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"0d") ) then + saved_src_ip(31 downto 24) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_SRC_IP_PROC; + +THE_SAVED_DEST_IP_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_dest_ip <= (others => '0'); + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"0e") ) then + saved_dest_ip(7 downto 0) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"0f") ) then + saved_dest_ip(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"10") ) then + saved_dest_ip(23 downto 16) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_IP) and (remove_ctr = x"11") ) then + saved_dest_ip(31 downto 24) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_DEST_IP_PROC; + +THE_SAVED_SRC_UDP_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_src_udp <= (others => '0'); + elsif( (filter_current_state = REMOVE_UDP) and (remove_ctr = x"12") ) then + saved_src_udp(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_UDP) and (remove_ctr = x"13") ) then + saved_src_udp(7 downto 0) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_SRC_UDP_PROC; + +THE_SAVED_DEST_UDP_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_dest_udp <= (others => '0'); + elsif( (filter_current_state = REMOVE_UDP) and (remove_ctr = x"14") ) then + saved_dest_udp(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_UDP) and (remove_ctr = x"15") ) then + saved_dest_udp(7 downto 0) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_DEST_UDP_PROC; + +-- saves VLAN id when tagged frame spotted +THE_SAVED_VID_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( filter_current_state = CLEANUP ) then + saved_vid <= (others => '0'); + elsif( (filter_current_state = REMOVE_TYPE) and (remove_ctr = x"0b") and (saved_frame_type = x"8100") ) then + saved_vid(15 downto 8) <= MAC_RXD_IN; + elsif( (filter_current_state = REMOVE_VID) and (remove_ctr = x"0c") ) then + saved_vid(7 downto 0) <= MAC_RXD_IN; + end if; + end if; +end process THE_SAVED_VID_PROC; + +THE_TYPE_VALIDATOR: entity gbe_type_validator +port map( + CLK => CLK, + RESET => RESET, + FRAME_TYPE_IN => saved_frame_type, + ALLOWED_TYPES_IN => FR_ALLOWED_TYPES_IN, + SAVED_VLAN_ID_IN => saved_vid, + VLAN_ID_IN => FR_VLAN_ID_IN, + -- IP level + IP_PROTOCOLS_IN => saved_proto, + ALLOWED_IP_PROTOCOLS_IN => FR_ALLOWED_IP_IN, + -- UDP level + UDP_PROTOCOL_IN => saved_dest_udp, + ALLOWED_UDP_PROTOCOLS_IN => FR_ALLOWED_UDP_IN, + -- + VALID_OUT => frame_type_valid +); + +THE_RECEIVE_FIFO: entity fifo_4096x9 +port map( + Data => rx_data, + WrClock => CLK, + RdClock => CLK, + WrEn => fifo_wr_en, + RdEn => FR_RD_EN_IN, + Reset => RESET, + RPReset => RESET, + Q => fr_q, + Empty => rec_fifo_empty, + Full => rec_fifo_full +); + +-- killer ping +THE_KILLER_PING_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( (filter_current_state = SAVE_FRAME) and + (saved_proto = x"01") and + (saved_frame_type = x"0800") and + (rx_bytes_ctr = x"001A") and + (rx_data(7 downto 0) = MY_TRBNET_ADDRESS_IN(7 downto 0)) and + (MAC_RXD_IN = MY_TRBNET_ADDRESS_IN(15 downto 8)) ) then + ISSUE_REBOOT_OUT <= '1'; + else + ISSUE_REBOOT_OUT <= '0'; + end if; + end if; +end process THE_KILLER_PING_PROC; + +THE_SECRET_FRAME_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( (filter_current_state = DECIDE) and + (saved_proto = x"11") and + (saved_frame_type = x"0800") and + (saved_dest_udp = x"d903") and + (saved_src_udp = x"2b67") ) then + oob_write <= '1'; + else + oob_write <= '0'; + end if; + end if; +end process THE_SECRET_FRAME_PROC; + +THE_REGISTERS_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( oob_write = '1' ) then + case saved_src_ip(1 downto 0) is + when b"00" => oob_register_0_int <= saved_dest_ip; + when b"01" => oob_register_1_int <= saved_dest_ip; + when b"10" => oob_register_2_int <= saved_dest_ip; + when others => oob_register_3_int <= saved_dest_ip; + end case; + end if; + end if; +end process THE_REGISTERS_PROC; + +OOB_REGISTER_0_OUT <= oob_register_0_int; +OOB_REGISTER_1_OUT <= oob_register_1_int; +OOB_REGISTER_2_OUT <= oob_register_2_int; +OOB_REGISTER_3_OUT <= oob_register_3_int; + +THE_RX_FIFO_SYNC: process( CLK ) +begin + if rising_edge(CLK) then + + rx_data(8) <= MAC_RX_EOF_IN; + rx_data(7 downto 0) <= MAC_RXD_IN; + + if( MAC_RX_EN_IN = '1' ) then + if ( filter_current_state = SAVE_FRAME ) then + fifo_wr_en <= '1'; +-- elsif( (filter_current_state = REMOVE_VTYPE) and (remove_ctr = x"0f") ) then +-- fifo_wr_en <= '1'; + elsif( (filter_current_state = DECIDE) and (frame_type_valid = '1') ) then + fifo_wr_en <= '1'; + else + fifo_wr_en <= '0'; + end if; + else + fifo_wr_en <= '0'; + end if; + + end if; +end process THE_RX_FIFO_SYNC; + +THE_SIZES_FIFO: entity fifo_512x32 +port map( + Data(15 downto 0) => rx_bytes_ctr, + Data(31 downto 16) => saved_frame_type, + WrClock => CLK, + RdClock => CLK, + WrEn => frame_valid_q, + RdEn => FR_GET_FRAME_IN, + Reset => RESET, + RPReset => RESET, + Q(15 downto 0) => fr_frame_size, + Q(31 downto 16) => fr_frame_proto, + Empty => sizes_fifo_empty, + Full => sizes_fifo_full +); + +THE_MACS_FIFO: entity fifo_512x72 +port map( + Data(47 downto 0) => saved_src_mac, + Data(63 downto 48) => saved_src_udp, + Data(71 downto 64) => (others => '0'), + WrClock => CLK, + RdClock => CLK, + WrEn => frame_valid_q, + RdEn => FR_GET_FRAME_IN, + Reset => RESET, + RPReset => RESET, + Q(47 downto 0) => fr_src_mac, + Q(63 downto 48) => fr_src_udp, + Q(71 downto 64) => xxx0, --open, + Empty => open, + Full => open +); + +THE_MACD_FIFO: entity fifo_512x72 +port map( + Data(47 downto 0) => saved_dest_mac, + Data(63 downto 48) => saved_dest_udp, + Data(71 downto 64) => (others => '0'), + WrClock => CLK, + RdClock => CLK, + WrEn => frame_valid_q, + RdEn => FR_GET_FRAME_IN, + Reset => RESET, + RPReset => RESET, + Q(47 downto 0) => fr_dest_mac, + Q(63 downto 48) => fr_dest_udp, + Q(71 downto 64) => xxx1, --open, + Empty => open, + Full => open +); + +THE_IP_FIFO: entity fifo_512x72 +port map( + Data(31 downto 0) => saved_src_ip, + Data(63 downto 32) => saved_dest_ip, + Data(71 downto 64) => saved_proto, + WrClock => CLK, + RdClock => CLK, + WrEn => frame_valid_q, + RdEn => FR_GET_FRAME_IN, + Reset => RESET, + RPReset => RESET, + Q(31 downto 0) => fr_src_ip, + Q(63 downto 32) => fr_dest_ip, + Q(71 downto 64) => fr_ip_proto, + Empty => open, + Full => open +); + +THE_SYNC_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + FR_SRC_IP_ADDRESS_OUT <= fr_src_ip; + FR_DEST_IP_ADDRESS_OUT <= fr_dest_ip; + FR_IP_PROTOCOL_OUT <= fr_ip_proto; + FR_DEST_UDP_PORT_OUT <= fr_dest_udp; + FR_DEST_MAC_ADDRESS_OUT <= fr_dest_mac; + FR_SRC_MAC_ADDRESS_OUT <= fr_src_mac; + FR_SRC_UDP_PORT_OUT <= fr_src_udp; + FR_FRAME_PROTO_OUT <= fr_frame_proto; + FR_FRAME_SIZE_OUT <= fr_frame_size; + FR_Q_OUT <= fr_q; + -- + delayed_frame_valid <= MAC_RX_EOF_IN; + delayed_frame_valid_q <= delayed_frame_valid; + end if; +end process THE_SYNC_PROC; + +THE_FRAME_VALID_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( (MAC_RX_EOF_IN = '1') and (ALLOW_RX_IN = '1') and (frame_type_valid = '1') ) then + frame_valid_q <= '1'; + else + frame_valid_q <= '0'; + end if; + end if; +end process THE_FRAME_VALID_PROC; + +THE_RX_BYTES_CTR_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + rx_bytes_ctr <= x"0001"; + elsif( rising_edge(CLK) ) then + if( delayed_frame_valid_q = '1' ) then + rx_bytes_ctr <= x"0001"; + elsif( fifo_wr_en = '1' ) then + rx_bytes_ctr <= rx_bytes_ctr + 1; + end if; + end if; +end process THE_RX_BYTES_CTR_PROC; + +THE_ERROR_FRAMES_CTR_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + error_frames_ctr <= (others => '0'); + elsif( rising_edge(CLK) ) then + error_frames_ctr <= error_frames_ctr + 1; + end if; +end process THE_ERROR_FRAMES_CTR_PROC; + +FR_FRAME_VALID_OUT <= frame_valid_q when rising_edge(CLK); + +THE_RECEIVED_FRAMES_CTR: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + dbg_rec_frames <= (others => '0'); + elsif( rising_edge(CLK) ) then + dbg_rec_frames <= dbg_rec_frames + 1; + end if; +end process THE_RECEIVED_FRAMES_CTR; + +THE_DROPPED_FRAMES_CTR: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + dbg_drp_frames <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( (filter_current_state = DECIDE) and (frame_type_valid = '0') ) then + dbg_drp_frames <= dbg_drp_frames + 1; + end if; + end if; +end process THE_DROPPED_FRAMES_CTR; + +MONITOR_DROPPED_OUT <= std_logic_vector(dbg_drp_frames); +MONITOR_RX_FRAMES_OUT <= std_logic_vector(dbg_rec_frames); +MONITOR_RX_BYTES_OUT <= std_logic_vector(mon_rec_bytes); + +THE_MON_REC_BYTES_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + mon_rec_bytes <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( fifo_wr_en = '1' ) then + mon_rec_bytes <= mon_rec_bytes + x"1"; + end if; + end if; +end process; + +end gbe_frame_receiver_arch; diff --git a/gbe_trb/base/gbe_logic_wrapper.vhd b/gbe_trb/base/gbe_logic_wrapper.vhd index d9ef582..b2a5255 100644 --- a/gbe_trb/base/gbe_logic_wrapper.vhd +++ b/gbe_trb/base/gbe_logic_wrapper.vhd @@ -1,14 +1,9 @@ -library IEEE; -use IEEE.std_logic_1164.all; -use IEEE.std_logic_ARITH.all; -use IEEE.std_logic_UNSIGNED.all; +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; library work; -use work.trb_net_std.all; -use work.trb_net_components.all; - ---use work.trb_net_gbe_components.all; -use work.gbe_protocols.all; + use work.gbe_protocols.all; entity gbe_logic_wrapper is generic( @@ -84,7 +79,8 @@ entity gbe_logic_wrapper is ); end entity gbe_logic_wrapper; -architecture RTL of gbe_logic_wrapper is +architecture gbe_logic_wrapper_arch of gbe_logic_wrapper is + signal fr_q : std_logic_vector(8 downto 0); signal fr_rd_en : std_logic; signal fr_frame_valid : std_logic; @@ -160,9 +156,6 @@ architecture RTL of gbe_logic_wrapper is signal dbg_select_gen : std_logic_vector(2 * c_MAX_PROTOCOLS * 32 - 1 downto 0); --- signal global_reset : std_logic; --- signal rst_n : std_logic; --- signal ff : std_logic; signal link_ok : std_logic; signal dhcp_done : std_logic; @@ -184,7 +177,7 @@ begin DHCP_DONE_OUT <= dhcp_done; - MAIN_CONTROL: entity work.trb_net16_gbe_main_control + THE_GBE_MAIN_CONTROL: entity work.gbe_main_control generic map( INCLUDE_SLOWCTRL => INCLUDE_SLOWCTRL, INCLUDE_DHCP => INCLUDE_DHCP, @@ -270,7 +263,7 @@ begin MAKE_RESET_OUT <= make_reset; - TRANSMIT_CONTROLLER: entity trb_net16_gbe_transmit_control2 + THE_TRANSMIT_CONTROL: entity work.gbe_transmit_control port map( CLK => CLK_125_IN, RESET => RESET, --global_reset, @@ -312,7 +305,7 @@ begin MONITOR_TX_PACKETS_OUT => monitor_tx_packets ); - FRAME_CONSTRUCTOR: entity trb_net16_gbe_frame_constr + THE_FRAME_CONSTR: entity work.gbe_frame_constr port map( RESET => RESET, --global_reset, CLK => CLK_125_IN, @@ -349,7 +342,7 @@ begin -- frame_pause <= x"0000" & CFG_THROTTLE_PAUSE_IN; -- TAKE CARE!!! frame_pause <= x"0000" & x"0000"; -- TAKE CARE!!! - RECEIVE_CONTROLLER: entity trb_net16_gbe_receive_control + THE_RECEIVE_CONTROL: entity work.gbe_receive_control port map( CLK => CLK_125_IN, RESET => RESET, --global_reset, @@ -386,7 +379,7 @@ begin DEBUG_OUT => rc_debug ); - FRAME_RECEIVER: entity trb_net16_gbe_frame_receiver + THE_FRAME_RECEIVER: entity work.gbe_frame_receiver port map( CLK => CLK_125_IN, RESET => RESET, --global_reset, @@ -440,4 +433,4 @@ begin MONITOR_GEN_DBG_OUT <= dbg_select_gen; -end architecture RTL; +end architecture gbe_logic_wrapper_arch; diff --git a/gbe_trb/base/gbe_main_control.vhd b/gbe_trb/base/gbe_main_control.vhd new file mode 100644 index 0000000..8166510 --- /dev/null +++ b/gbe_trb/base/gbe_main_control.vhd @@ -0,0 +1,594 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.trb_net_std.all; + use work.gbe_protocols.all; + +entity gbe_main_control is + generic( + INCLUDE_SLOWCTRL : std_logic := '0'; + INCLUDE_DHCP : std_logic := '0'; + INCLUDE_ARP : std_logic := '0'; + INCLUDE_PING : std_logic := '0'; + INCLUDE_FWD : std_logic := '0'; + -- + SLOWCTRL_BUFFER_SIZE : integer range 1 to 4 + ); + port( + CLK : in std_logic; -- system clock + CLK_125 : in std_logic; + RESET : in std_logic; + -- + MC_LINK_OK_OUT : out std_logic; -- remark: set to '1' internally + MC_DHCP_DONE_OUT : out std_logic; -- remark: set if link_current_state = ACTIVE + MY_IP_OUT : out std_logic_vector(31 downto 0); + MC_MY_MAC_IN : in std_logic_vector(47 downto 0); + MY_TRBNET_ADDRESS_IN : in std_logic_vector(15 downto 0); + ISSUE_REBOOT_OUT : out std_logic; + -- signals to/from receive controller + RC_FRAME_WAITING_IN : in std_logic; + RC_LOADING_DONE_OUT : out std_logic; + RC_DATA_IN : in std_logic_vector(8 downto 0); + RC_RD_EN_OUT : out std_logic; + RC_FRAME_SIZE_IN : in std_logic_vector(15 downto 0); + RC_FRAME_PROTO_IN : in std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + -- + RC_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + RC_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + RC_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + RC_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + RC_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + RC_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); + -- signals to/from transmit controller + TC_TRANSMIT_CTRL_OUT : out std_logic; + TC_DATA_OUT : out std_logic_vector(8 downto 0); + TC_RD_EN_IN : in std_logic; + TC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + TC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + TC_DEST_MAC_OUT : out std_logic_vector(47 downto 0); + TC_DEST_IP_OUT : out std_logic_vector(31 downto 0); + TC_DEST_UDP_OUT : out std_logic_vector(15 downto 0); + TC_SRC_MAC_OUT : out std_logic_vector(47 downto 0); + TC_SRC_IP_OUT : out std_logic_vector(31 downto 0); + TC_SRC_UDP_OUT : out std_logic_vector(15 downto 0); + TC_FLAGS_OFFSET_OUT : out std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + TC_IDENT_OUT : out std_logic_vector(15 downto 0); + TC_TRANSMIT_DONE_IN : in std_logic; + -- signals to/from sgmii/gbe pcs_an_complete + PCS_AN_COMPLETE_IN : in std_logic; + MAC_READY_CONF_IN : in std_logic; + -- signals to/from hub + GSC_CLK_IN : in std_logic; + GSC_INIT_DATAREADY_OUT : out std_logic; + GSC_INIT_DATA_OUT : out std_logic_vector(15 downto 0); + GSC_INIT_PACKET_NUM_OUT : out std_logic_vector(2 downto 0); + GSC_INIT_READ_IN : in std_logic; + GSC_REPLY_DATAREADY_IN : in std_logic; + GSC_REPLY_DATA_IN : in std_logic_vector(15 downto 0); + GSC_REPLY_PACKET_NUM_IN : in std_logic_vector(2 downto 0); + GSC_REPLY_READ_OUT : out std_logic; + GSC_BUSY_IN : in std_logic; + CFG_MAX_REPLY_SIZE_IN : in std_logic_vector(31 downto 0); + -- + RESET_TRBNET_IN : in std_logic; + RESET_SCTRL_IN : in std_logic; + MAKE_RESET_OUT : out std_logic; + -- Forwarder + FWD_DST_MAC_IN : in std_logic_vector(47 downto 0); + FWD_DST_IP_IN : in std_logic_vector(31 downto 0); + FWD_DST_UDP_IN : in std_logic_vector(15 downto 0); + FWD_DATA_IN : in std_logic_vector(7 downto 0); + FWD_DATA_VALID_IN : in std_logic; + FWD_SOP_IN : in std_logic; + FWD_EOP_IN : in std_logic; + FWD_READY_OUT : out std_logic; + FWD_FULL_OUT : out std_logic; + -- + MONITOR_SELECT_REC_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_REC_BYTES_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_SENT_BYTES_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_SENT_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_GEN_DBG_OUT : out std_logic_vector(2 * c_MAX_PROTOCOLS * 32 - 1 downto 0); + -- + SCTRL_HIST_OUT : out hist_array; + -- + DEBUG_OUT : out std_logic_vector(63 downto 0) + ); +end gbe_main_control; + +architecture gbe_main_control_arch of gbe_main_control is + + attribute syn_encoding : string; + + type link_states is (INACTIVE, ACTIVE, ENABLE_MAC, TIMEOUT, FINALIZE, WAIT_FOR_BOOT, GET_ADDRESS); + signal link_current_state, link_next_state : link_states; + attribute syn_encoding of link_current_state : signal is "onehot"; + + signal link_ok : std_logic; + signal link_ok_timeout_ctr : unsigned(15 downto 0); + + type flow_states is (IDLE, TRANSMIT_CTRL, WAIT_FOR_FC, CLEANUP); + signal flow_current_state, flow_next_state : flow_states; + attribute syn_encoding of flow_current_state : signal is "onehot"; + + signal state : std_logic_vector(3 downto 0); + signal link_state : std_logic_vector(3 downto 0); + signal redirect_state : std_logic_vector(3 downto 0); + + signal ps_wr_en : std_logic; + signal ps_response_ready : std_logic; + signal ps_busy : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + signal rc_rd_en : std_logic; + signal proto_select : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + signal loaded_bytes_ctr : unsigned(15 downto 0); + + signal dhcp_start : std_logic; + signal dhcp_done : std_logic; + signal wait_ctr : unsigned(31 downto 0); + + signal rc_data_local : std_logic_vector(8 downto 0); + + type redirect_states is (IDLE, CHECK_TYPE, DROP, CHECK_BUSY, LOAD, BUSY, WAIT_ONE, FINISH, CLEANUP); + signal redirect_current_state, redirect_next_state : redirect_states; + attribute syn_encoding of redirect_current_state : signal is "onehot"; + + signal disable_redirect : std_logic; + signal ps_wr_en_q : std_logic; + signal ps_wr_en_qq : std_logic; + + signal tc_data : std_logic_vector(8 downto 0); + + attribute syn_preserve : boolean; + attribute syn_keep : boolean; + attribute syn_keep of link_state, state, redirect_state, dhcp_done : signal is true; + attribute syn_preserve of link_state, state, redirect_state, dhcp_done : signal is true; + + signal mc_busy : std_logic; + signal incl_dhcp : std_logic; + signal flow_state : std_logic_vector(3 downto 0); + signal selector_debug : std_logic_vector(63 downto 0); + +begin + THE_PROTOCOL_SELECTOR: entity work.gbe_protocol_selector + generic map( + INCLUDE_SLOWCTRL => INCLUDE_SLOWCTRL, + INCLUDE_DHCP => INCLUDE_DHCP, + INCLUDE_ARP => INCLUDE_ARP, + INCLUDE_PING => INCLUDE_PING, + INCLUDE_FWD => INCLUDE_FWD, + SLOWCTRL_BUFFER_SIZE => SLOWCTRL_BUFFER_SIZE + ) + port map( + CLK => CLK, + RESET => RESET, + PS_DATA_IN => rc_data_local, + PS_WR_EN_IN => ps_wr_en_qq, + PS_PROTO_SELECT_IN => proto_select, + PS_BUSY_OUT => ps_busy, + PS_FRAME_SIZE_IN => RC_FRAME_SIZE_IN, + PS_RESPONSE_READY_OUT => ps_response_ready, + PS_SRC_MAC_ADDRESS_IN => RC_SRC_MAC_ADDRESS_IN, + PS_DEST_MAC_ADDRESS_IN => RC_DEST_MAC_ADDRESS_IN, + PS_SRC_IP_ADDRESS_IN => RC_SRC_IP_ADDRESS_IN, + PS_DEST_IP_ADDRESS_IN => RC_DEST_IP_ADDRESS_IN, + PS_SRC_UDP_PORT_IN => RC_SRC_UDP_PORT_IN, + PS_DEST_UDP_PORT_IN => RC_DEST_UDP_PORT_IN, + TC_DATA_OUT => tc_data, + TC_RD_EN_IN => TC_RD_EN_IN, + TC_FRAME_SIZE_OUT => TC_FRAME_SIZE_OUT, + TC_FRAME_TYPE_OUT => TC_FRAME_TYPE_OUT, + TC_IP_PROTOCOL_OUT => TC_IP_PROTOCOL_OUT, + TC_IDENT_OUT => TC_IDENT_OUT, + TC_DEST_MAC_OUT => TC_DEST_MAC_OUT, + TC_DEST_IP_OUT => TC_DEST_IP_OUT, + TC_DEST_UDP_OUT => TC_DEST_UDP_OUT, + TC_SRC_MAC_OUT => TC_SRC_MAC_OUT, + TC_SRC_IP_OUT => TC_SRC_IP_OUT, + TC_SRC_UDP_OUT => TC_SRC_UDP_OUT, + MC_BUSY_IN => mc_busy, + MY_MAC_IN => MC_MY_MAC_IN, + MY_IP_OUT => MY_IP_OUT, + DHCP_START_IN => dhcp_start, + DHCP_DONE_OUT => dhcp_done, + GSC_CLK_IN => GSC_CLK_IN, + GSC_INIT_DATAREADY_OUT => GSC_INIT_DATAREADY_OUT, + GSC_INIT_DATA_OUT => GSC_INIT_DATA_OUT, + GSC_INIT_PACKET_NUM_OUT => GSC_INIT_PACKET_NUM_OUT, + GSC_INIT_READ_IN => GSC_INIT_READ_IN, + GSC_REPLY_DATAREADY_IN => GSC_REPLY_DATAREADY_IN, + GSC_REPLY_DATA_IN => GSC_REPLY_DATA_IN, + GSC_REPLY_PACKET_NUM_IN => GSC_REPLY_PACKET_NUM_IN, + GSC_REPLY_READ_OUT => GSC_REPLY_READ_OUT, + GSC_BUSY_IN => GSC_BUSY_IN, + MAKE_RESET_OUT => MAKE_RESET_OUT, + + MY_TRBNET_ADDRESS_IN => MY_TRBNET_ADDRESS_IN, +-- ISSUE_REBOOT_OUT => ISSUE_REBOOT_OUT, + + CFG_MAX_REPLY_SIZE_IN => CFG_MAX_REPLY_SIZE_IN, + + FWD_DST_MAC_IN => FWD_DST_MAC_IN, + FWD_DST_IP_IN => FWD_DST_IP_IN, + FWD_DST_UDP_IN => FWD_DST_UDP_IN, + FWD_DATA_IN => FWD_DATA_IN, + FWD_DATA_VALID_IN => FWD_DATA_VALID_IN, + FWD_SOP_IN => FWD_SOP_IN, + FWD_EOP_IN => FWD_EOP_IN, + FWD_READY_OUT => FWD_READY_OUT, + FWD_FULL_OUT => FWD_FULL_OUT, + + -- input for statistics from outside + MONITOR_SELECT_REC_OUT => MONITOR_SELECT_REC_OUT, + MONITOR_SELECT_REC_BYTES_OUT => MONITOR_SELECT_REC_BYTES_OUT, + MONITOR_SELECT_SENT_BYTES_OUT => MONITOR_SELECT_SENT_BYTES_OUT, + MONITOR_SELECT_SENT_OUT => MONITOR_SELECT_SENT_OUT, + MONITOR_SELECT_GEN_DBG_OUT => MONITOR_SELECT_GEN_DBG_OUT, + SCTRL_HIST_OUT => SCTRL_HIST_OUT, + DEBUG_OUT => selector_debug + ); + + TC_DATA_OUT <= tc_data; + + -- gk 07.11.11 + -- do not select any response constructors when dropping a frame + proto_select <= RC_FRAME_PROTO_IN when disable_redirect = '0' else (others => '0'); + + -- gk 07.11.11 + -- we do not answer at all, unless we are in either ACTIVE or GET_ADDRESS state. + -- in GET_ADDRESS state, we only answer on DHCP frames. + PROC_DISABLE_REDIRECT: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + disable_redirect <= '0'; + elsif( rising_edge(CLK) ) then + if( redirect_current_state = CHECK_TYPE ) then + if ( (link_current_state /= ACTIVE) and (link_current_state /= GET_ADDRESS) ) then + disable_redirect <= '1'; + elsif( (link_current_state = GET_ADDRESS) and (RC_FRAME_PROTO_IN /= "10") ) then -- (UDP, DHCP) + disable_redirect <= '1'; + else + disable_redirect <= '0'; + end if; + end if; + end if; + end process PROC_DISABLE_REDIRECT; + + -- warning + PROC_SYNC: process( CLK ) + begin + if( rising_edge(CLK) ) then + rc_data_local <= RC_DATA_IN; + end if; + end process PROC_SYNC; + + PROC_REDIRECT_FSM: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + redirect_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + redirect_current_state <= redirect_next_state; + end if; + end process PROC_REDIRECT_FSM; + + PROC_REDIRECT_TRANSITIONS: process( redirect_current_state, link_current_state, RC_FRAME_WAITING_IN, + ps_busy, RC_FRAME_PROTO_IN, loaded_bytes_ctr, RC_FRAME_SIZE_IN ) + begin + redirect_state <= x"0"; + + case redirect_current_state is + when IDLE => + redirect_state <= x"1"; + if( RC_FRAME_WAITING_IN = '1' ) then + redirect_next_state <= CHECK_TYPE; + else + redirect_next_state <= IDLE; + end if; + + when CHECK_TYPE => + redirect_state <= x"2"; + if ( link_current_state = ACTIVE ) then + redirect_next_state <= CHECK_BUSY; + elsif( (link_current_state = GET_ADDRESS) and (RC_FRAME_PROTO_IN = "10") ) then + redirect_next_state <= CHECK_BUSY; + else + redirect_next_state <= DROP; + end if; + + when DROP => + redirect_state <= x"3"; + if( loaded_bytes_ctr = unsigned(RC_FRAME_SIZE_IN) - 1 ) then + redirect_next_state <= WAIT_ONE; + else + redirect_next_state <= DROP; + end if; + + when CHECK_BUSY => + redirect_state <= x"4"; + if( or_all(ps_busy and RC_FRAME_PROTO_IN) = '0' ) then + redirect_next_state <= LOAD; + else + redirect_next_state <= BUSY; + end if; + + when LOAD => + redirect_state <= x"5"; + if( loaded_bytes_ctr = unsigned(RC_FRAME_SIZE_IN) - 1 ) then + redirect_next_state <= WAIT_ONE; + else + redirect_next_state <= LOAD; + end if; + + when BUSY => + redirect_state <= x"6"; + if( or_all(ps_busy and RC_FRAME_PROTO_IN) = '0' ) then + redirect_next_state <= LOAD; + else + redirect_next_state <= BUSY; + end if; + + when WAIT_ONE => + redirect_state <= x"7"; + redirect_next_state <= FINISH; + + when FINISH => + redirect_state <= x"8"; + redirect_next_state <= CLEANUP; + + when CLEANUP => + redirect_state <= x"9"; + redirect_next_state <= IDLE; + + when others => redirect_next_state <= IDLE; + + end case; + end process PROC_REDIRECT_TRANSITIONS; + + rc_rd_en <= '1' when redirect_current_state = LOAD or redirect_current_state = DROP else '0'; + RC_RD_EN_OUT <= rc_rd_en; + + PROC_LOADING_DONE: process( CLK ) + begin + if rising_edge(CLK) then + if (RC_DATA_IN(8) = '1' and ps_wr_en_q = '1') then + RC_LOADING_DONE_OUT <= '1'; + else + RC_LOADING_DONE_OUT <= '0'; + end if; + end if; + end process PROC_LOADING_DONE; + + PROC_PS_WR_EN: process( CLK ) + begin + if rising_edge(CLK) then + ps_wr_en <= rc_rd_en; + ps_wr_en_q <= ps_wr_en; + ps_wr_en_qq <= ps_wr_en_q; + end if; + end process PROC_PS_WR_EN; + + PROC_LOADED_BYTES_CTR: process( CLK ) + begin + if rising_edge(CLK) then + if ( redirect_current_state = IDLE) then + loaded_bytes_ctr <= (others => '0'); + elsif( ((redirect_current_state = LOAD) or (redirect_current_state = DROP)) and (rc_rd_en = '1') )then + loaded_bytes_ctr <= loaded_bytes_ctr + x"1"; + end if; + end if; + end process PROC_LOADED_BYTES_CTR; + + --********************* + -- DATA FLOW CONTROL + + PROC_FLOW_FSM: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + flow_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + flow_current_state <= flow_next_state; + end if; + end process PROC_FLOW_FSM; + + PROC_FLOW_TRANSITIONS: process(flow_current_state, TC_TRANSMIT_DONE_IN, ps_response_ready, tc_data) + begin + flow_state <= x"0"; + + case flow_current_state is + when IDLE => + flow_state <= x"1"; + if (ps_response_ready = '1') then + flow_next_state <= TRANSMIT_CTRL; + else + flow_next_state <= IDLE; + end if; + + when TRANSMIT_CTRL => + flow_state <= x"2"; + if (tc_data(8) = '1') then + flow_next_state <= WAIT_FOR_FC; + else + flow_next_state <= TRANSMIT_CTRL; + end if; + + when WAIT_FOR_FC => + flow_state <= x"3"; + if (TC_TRANSMIT_DONE_IN = '1') then + flow_next_state <= CLEANUP; + else + flow_next_state <= WAIT_FOR_FC; + end if; + + when CLEANUP => + flow_state <= x"4"; + flow_next_state <= IDLE; + + when others => flow_next_state <= IDLE; + + end case; + end process PROC_FLOW_TRANSITIONS; + + PROC_BUSY: process( CLK ) + begin + if rising_edge(CLK) then + if (flow_current_state = IDLE and ps_response_ready = '1') then + TC_TRANSMIT_CTRL_OUT <= '1'; + else + TC_TRANSMIT_CTRL_OUT <= '0'; + end if; + + if (flow_current_state = TRANSMIT_CTRL or flow_current_state = WAIT_FOR_FC) then + mc_busy <= '1'; + else + mc_busy <= '0'; + end if; + end if; + end process PROC_BUSY; + + --*********************** + -- LINK STATE CONTROL + + PROC_LINK_FSM: process( RESET, CLK ) + begin + if ( RESET = '1' ) then + link_current_state <= INACTIVE; + elsif( rising_edge(CLK) ) then + link_current_state <= link_next_state; + end if; + end process PROC_LINK_FSM; + + INCL_DHCP_GEN: if (INCLUDE_DHCP = '1') generate + incl_dhcp <= '1'; + end generate INCL_DHCP_GEN; + NOINCL_DHCP_GEN: if (INCLUDE_DHCP = '0') generate + incl_dhcp <= '0'; + end generate NOINCL_DHCP_GEN; + + -- to be reworked. link_ok_timer is not needed anymore! + PROC_LINK_TRANSITIONS: process( link_current_state, dhcp_done, wait_ctr, PCS_AN_COMPLETE_IN, incl_dhcp, MAC_READY_CONF_IN, link_ok_timeout_ctr ) + begin + link_state <= x"0"; + + case link_current_state is + when INACTIVE => + link_state <= x"1"; + if (PCS_AN_COMPLETE_IN = '1') then + link_next_state <= TIMEOUT; + else + link_next_state <= INACTIVE; + end if; + + when TIMEOUT => + link_state <= x"2"; + if (PCS_AN_COMPLETE_IN = '0') then + link_next_state <= INACTIVE; + else + if (link_ok_timeout_ctr = x"ffff") then + link_next_state <= ENABLE_MAC; + else + link_next_state <= TIMEOUT; + end if; + end if; + + when ENABLE_MAC => + link_state <= x"3"; + if (PCS_AN_COMPLETE_IN = '0') then + link_next_state <= INACTIVE; + elsif (MAC_READY_CONF_IN = '1') then + link_next_state <= FINALIZE; + else + link_next_state <= ENABLE_MAC; + end if; + + when FINALIZE => + link_state <= x"4"; + if (PCS_AN_COMPLETE_IN = '0') then + link_next_state <= INACTIVE; + else + link_next_state <= WAIT_FOR_BOOT; + end if; + + when WAIT_FOR_BOOT => + link_state <= x"5"; + if (PCS_AN_COMPLETE_IN = '0') then + link_next_state <= INACTIVE; + else + if (wait_ctr = x"0000_1000") then + if (incl_dhcp = '1') then + link_next_state <= GET_ADDRESS; + else + link_next_state <= ACTIVE; + end if; + else + link_next_state <= WAIT_FOR_BOOT; + end if; + end if; + + when GET_ADDRESS => + link_state <= x"6"; + if (PCS_AN_COMPLETE_IN = '0') then + link_next_state <= INACTIVE; + else + if (dhcp_done = '1') then + link_next_state <= ACTIVE; + else + link_next_state <= GET_ADDRESS; + end if; + end if; + + when ACTIVE => + link_state <= x"7"; + if (PCS_AN_COMPLETE_IN = '0') then + link_next_state <= INACTIVE; + else + link_next_state <= ACTIVE; + end if; + + when others => + link_next_state <= INACTIVE; + + end case; + end process PROC_LINK_TRANSITIONS; + + MC_DHCP_DONE_OUT <= '1' when link_current_state = ACTIVE else '0'; + + PROC_LINK_OK_CTR: process( CLK ) + begin + if( rising_edge(CLK) ) then + if ( link_current_state /= TIMEOUT ) then + link_ok_timeout_ctr <= (others => '0'); + elsif( link_current_state = TIMEOUT ) then + link_ok_timeout_ctr <= link_ok_timeout_ctr + 1; + end if; + + if( link_current_state = GET_ADDRESS ) then + dhcp_start <= '1'; + else + dhcp_start <= '0'; + end if; + end if; + end process PROC_LINK_OK_CTR; + + link_ok <= '1'; -- BUG - what the fuck? + + PROC_WAIT_CTR: process( CLK ) + begin + if( rising_edge(CLK) ) then + if( link_current_state = WAIT_FOR_BOOT ) then + wait_ctr <= wait_ctr + 1; + else + wait_ctr <= (others => '0'); + end if; + end if; + end process PROC_WAIT_CTR; + + MC_LINK_OK_OUT <= link_ok; + + -- END OF LINK STATE CONTROL + --************* + + DEBUG_OUT <= selector_debug; + +end gbe_main_control_arch; diff --git a/gbe_trb/base/gbe_protocol_prioritizer.vhd b/gbe_trb/base/gbe_protocol_prioritizer.vhd new file mode 100644 index 0000000..612d122 --- /dev/null +++ b/gbe_trb/base/gbe_protocol_prioritizer.vhd @@ -0,0 +1,76 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + +--******** +-- maps the frame type and protocol code into internal value which sets the priority + +entity gbe_protocol_prioritizer is +port( + CLK : in std_logic; + RESET : in std_logic; + FRAME_TYPE_IN : in std_logic_vector(15 downto 0); -- recovered frame type + PROTOCOL_CODE_IN : in std_logic_vector(7 downto 0); -- ip protocol + UDP_PROTOCOL_IN : in std_logic_vector(15 downto 0); + CODE_OUT : out std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0) +); +end gbe_protocol_prioritizer; + +architecture gbe_protocol_prioritizer_arch of gbe_protocol_prioritizer is + +begin + +PRIORITIZE: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + CODE_OUT <= (others => '0'); + elsif( rising_edge(CLK) ) then + + CODE_OUT <= (others => '0'); + + --**** HERE ADD YOU PROTOCOL RECOGNITION AT WANTED PRIORITY LEVEL + -- priority level is the bit position in the CODE_OUT vector + -- less significant bit has the higher priority + case FRAME_TYPE_IN is + + -- IPv4 + when x"0800" => + if ( PROTOCOL_CODE_IN = x"11" ) then -- UDP + -- No. 2 = DHCP + if ( UDP_PROTOCOL_IN = x"0044" ) then -- DHCP Client + CODE_OUT(1) <= '1'; + -- No. 4 = SCTRL + elsif( UDP_PROTOCOL_IN = x"6590" ) then -- SCTRL module + CODE_OUT(2) <= '1'; + else + -- branch for pure IPv4 + CODE_OUT <= (others => '0'); + end if; + -- No. 3 = ICMP + elsif( PROTOCOL_CODE_IN = x"01") then -- ICMP + CODE_OUT(4) <= '1'; + else + CODE_OUT <= (others => '0'); + end if; + + -- No. 1 = ARP + when x"0806" => + CODE_OUT(0) <= '1'; + + -- last slot is reserved for Trash + when others => + CODE_OUT <= (others => '0'); + + end case; + + end if; + +end process PRIORITIZE; + +end gbe_protocol_prioritizer_arch; diff --git a/gbe_trb/base/gbe_protocol_selector.vhd b/gbe_trb/base/gbe_protocol_selector.vhd new file mode 100644 index 0000000..7e02fa4 --- /dev/null +++ b/gbe_trb/base/gbe_protocol_selector.vhd @@ -0,0 +1,514 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; +--LIBRARY IEEE; +--USE IEEE.std_logic_1164.ALL; +--USE IEEE.numeric_std.ALL; +--USE IEEE.std_logic_UNSIGNED.ALL; + +library work; + use work.trb_net_std.all; + use work.gbe_protocols.all; + +entity gbe_protocol_selector is + generic( + INCLUDE_SLOWCTRL : std_logic := '0'; + INCLUDE_DHCP : std_logic := '0'; + INCLUDE_ARP : std_logic := '0'; + INCLUDE_PING : std_logic := '0'; + INCLUDE_FWD : std_logic := '0'; + SLOWCTRL_BUFFER_SIZE : integer range 1 to 4 + ); + port( + CLK : in std_logic; -- system clock + RESET : in std_logic; + -- signals to/from main controller + PS_DATA_IN : in std_logic_vector(8 downto 0); + PS_WR_EN_IN : in std_logic; + PS_PROTO_SELECT_IN : in std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + PS_BUSY_OUT : out std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + PS_FRAME_SIZE_IN : in std_logic_vector(15 downto 0); + PS_RESPONSE_READY_OUT : out std_logic; + PS_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + PS_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); + -- signals to/from transmit controller with constructed response + TC_DATA_OUT : out std_logic_vector(8 downto 0); + TC_RD_EN_IN : in std_logic; + TC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + TC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + TC_IDENT_OUT : out std_logic_vector(15 downto 0); + TC_DEST_MAC_OUT : out std_logic_vector(47 downto 0); + TC_DEST_IP_OUT : out std_logic_vector(31 downto 0); + TC_DEST_UDP_OUT : out std_logic_vector(15 downto 0); + TC_SRC_MAC_OUT : out std_logic_vector(47 downto 0); + TC_SRC_IP_OUT : out std_logic_vector(31 downto 0); + TC_SRC_UDP_OUT : out std_logic_vector(15 downto 0); + MC_BUSY_IN : in std_logic; + -- misc signals for response constructors + MY_MAC_IN : in std_logic_vector(47 downto 0); + MY_IP_OUT : out std_logic_vector(31 downto 0); + DHCP_START_IN : in std_logic; + DHCP_DONE_OUT : out std_logic; + GSC_CLK_IN : in std_logic; + GSC_INIT_DATAREADY_OUT : out std_logic; + GSC_INIT_DATA_OUT : out std_logic_vector(15 downto 0); + GSC_INIT_PACKET_NUM_OUT : out std_logic_vector(2 downto 0); + GSC_INIT_READ_IN : in std_logic; + GSC_REPLY_DATAREADY_IN : in std_logic; + GSC_REPLY_DATA_IN : in std_logic_vector(15 downto 0); + GSC_REPLY_PACKET_NUM_IN : in std_logic_vector(2 downto 0); + GSC_REPLY_READ_OUT : out std_logic; + GSC_BUSY_IN : in std_logic; + CFG_MAX_REPLY_SIZE_IN : in std_logic_vector(31 downto 0); -- USED IN SCTRL + MAKE_RESET_OUT : out std_logic; + MY_TRBNET_ADDRESS_IN : in std_logic_vector(15 downto 0); + ISSUE_REBOOT_OUT : out std_logic; + -- Forwarder + FWD_DST_MAC_IN : in std_logic_vector(47 downto 0); + FWD_DST_IP_IN : in std_logic_vector(31 downto 0); + FWD_DST_UDP_IN : in std_logic_vector(15 downto 0); + FWD_DATA_IN : in std_logic_vector(7 downto 0); + FWD_DATA_VALID_IN : in std_logic; + FWD_SOP_IN : in std_logic; + FWD_EOP_IN : in std_logic; + FWD_READY_OUT : out std_logic; + FWD_FULL_OUT : out std_logic; + -- input for statistics from outside + MONITOR_SELECT_REC_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_REC_BYTES_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_SENT_BYTES_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_SENT_OUT : out std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + MONITOR_SELECT_GEN_DBG_OUT : out std_logic_vector(2 * c_MAX_PROTOCOLS * 32 - 1 downto 0); + SCTRL_HIST_OUT : out hist_array; + DEBUG_OUT : out std_logic_vector(63 downto 0) + ); +end gbe_protocol_selector; + +architecture gbe_protocol_selector_arch of gbe_protocol_selector is + + attribute syn_encoding : string; + + signal rd_en : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + signal resp_ready : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + signal tc_wr : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + signal tc_data : std_logic_vector(c_MAX_PROTOCOLS * 9 - 1 downto 0); + signal tc_size : std_logic_vector(c_MAX_PROTOCOLS * 16 - 1 downto 0); + signal tc_type : std_logic_vector(c_MAX_PROTOCOLS * 16 - 1 downto 0); + signal busy : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + signal selected : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + signal tc_mac : std_logic_vector(c_MAX_PROTOCOLS * 48 - 1 downto 0); + signal tc_ip : std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + signal tc_udp : std_logic_vector(c_MAX_PROTOCOLS * 16 - 1 downto 0); + signal tc_src_mac : std_logic_vector(c_MAX_PROTOCOLS * 48 - 1 downto 0); + signal tc_src_ip : std_logic_vector(c_MAX_PROTOCOLS * 32 - 1 downto 0); + signal tc_src_udp : std_logic_vector(c_MAX_PROTOCOLS * 16 - 1 downto 0); + signal tc_ip_proto : std_logic_vector(c_MAX_PROTOCOLS * 8 - 1 downto 0); + + type select_states is (IDLE, LOOP_OVER, SELECT_ONE, PROCESS_REQUEST, CLEANUP); + signal select_current_state, select_next_state : select_states; + attribute syn_encoding of select_current_state : signal is "onehot"; + + signal state : std_logic_vector(3 downto 0); + signal index : integer range 0 to c_MAX_PROTOCOLS - 1; + + signal mult : std_logic; + + signal tc_ident : std_logic_vector(c_MAX_PROTOCOLS * 16 - 1 downto 0); + signal zeros : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + + attribute syn_preserve : boolean; + attribute syn_keep : boolean; + attribute syn_keep of state, mult : signal is true; + attribute syn_preserve of state, mult : signal is true; + + signal my_ip : std_logic_vector(31 downto 0); + signal select_state : std_logic_vector(3 downto 0); + +begin + zeros <= (others => '0'); + MY_IP_OUT <= my_ip; + + ARP_GEN: if( INCLUDE_ARP = '1' ) generate + -- protocol Nr. 1 ARP + THE_ARP: entity work.gbe_response_constructor_ARP + port map( + CLK => CLK, + RESET => RESET, + -- INTERFACE + MY_MAC_IN => MY_MAC_IN, + MY_IP_IN => my_ip, + PS_DATA_IN => PS_DATA_IN, + PS_WR_EN_IN => PS_WR_EN_IN, + PS_ACTIVATE_IN => PS_PROTO_SELECT_IN(0), + PS_RESPONSE_READY_OUT => resp_ready(0), + PS_BUSY_OUT => busy(0), + PS_SELECTED_IN => selected(0), + PS_SRC_MAC_ADDRESS_IN => PS_SRC_MAC_ADDRESS_IN, + PS_DEST_MAC_ADDRESS_IN => PS_DEST_MAC_ADDRESS_IN, + PS_SRC_IP_ADDRESS_IN => PS_SRC_IP_ADDRESS_IN, + PS_DEST_IP_ADDRESS_IN => PS_DEST_IP_ADDRESS_IN, + PS_SRC_UDP_PORT_IN => PS_SRC_UDP_PORT_IN, + PS_DEST_UDP_PORT_IN => PS_DEST_UDP_PORT_IN, + TC_RD_EN_IN => TC_RD_EN_IN, + TC_DATA_OUT => tc_data(1 * 9 - 1 downto 0 * 9), + TC_FRAME_SIZE_OUT => tc_size(1 * 16 - 1 downto 0 * 16), + TC_FRAME_TYPE_OUT => tc_type(1 * 16 - 1 downto 0 * 16), + TC_IP_PROTOCOL_OUT => tc_ip_proto(1 * 8 - 1 downto 0 * 8), + TC_IDENT_OUT => tc_ident(1 * 16 - 1 downto 0 * 16), + TC_DEST_MAC_OUT => tc_mac(1 * 48 - 1 downto 0 * 48), + TC_DEST_IP_OUT => tc_ip(1 * 32 - 1 downto 0 * 32), + TC_DEST_UDP_OUT => tc_udp(1 * 16 - 1 downto 0 * 16), + TC_SRC_MAC_OUT => tc_src_mac(1 * 48 - 1 downto 0 * 48), + TC_SRC_IP_OUT => tc_src_ip(1 * 32 - 1 downto 0 * 32), + TC_SRC_UDP_OUT => tc_src_udp(1 * 16 - 1 downto 0 * 16), + DEBUG_OUT => MONITOR_SELECT_GEN_DBG_OUT(1 * 64 - 1 downto 0 * 64) + -- END OF INTERFACE + ); + end generate ARP_GEN; + + NO_ARP_GEN: if( INCLUDE_ARP = '0' ) generate + resp_ready(0) <= '0'; + busy(0) <= '0'; + end generate NO_ARP_GEN; + + DHCP_GEN: if( INCLUDE_DHCP = '1' ) generate + -- protocol No. 2 DHCP + THE_DHCP: entity work.gbe_response_constructor_DHCP + port map( + CLK => CLK, + RESET => RESET, + -- INTERFACE + MY_MAC_IN => MY_MAC_IN, + MY_IP_IN => my_ip, + PS_DATA_IN => PS_DATA_IN, + PS_WR_EN_IN => PS_WR_EN_IN, + PS_ACTIVATE_IN => PS_PROTO_SELECT_IN(1), + PS_RESPONSE_READY_OUT => resp_ready(1), + PS_BUSY_OUT => busy(1), + PS_SELECTED_IN => selected(1), + PS_SRC_MAC_ADDRESS_IN => PS_SRC_MAC_ADDRESS_IN, + PS_DEST_MAC_ADDRESS_IN => PS_DEST_MAC_ADDRESS_IN, + PS_SRC_IP_ADDRESS_IN => PS_SRC_IP_ADDRESS_IN, + PS_DEST_IP_ADDRESS_IN => PS_DEST_IP_ADDRESS_IN, + PS_SRC_UDP_PORT_IN => PS_SRC_UDP_PORT_IN, + PS_DEST_UDP_PORT_IN => PS_DEST_UDP_PORT_IN, + TC_RD_EN_IN => TC_RD_EN_IN, + TC_DATA_OUT => tc_data(2 * 9 - 1 downto 1 * 9), + TC_FRAME_SIZE_OUT => tc_size(2 * 16 - 1 downto 1 * 16), + TC_FRAME_TYPE_OUT => tc_type(2 * 16 - 1 downto 1 * 16), + TC_IP_PROTOCOL_OUT => tc_ip_proto(2 * 8 - 1 downto 1 * 8), + TC_IDENT_OUT => tc_ident(2 * 16 - 1 downto 1 * 16), + TC_DEST_MAC_OUT => tc_mac(2 * 48 - 1 downto 1 * 48), + TC_DEST_IP_OUT => tc_ip(2 * 32 - 1 downto 1 * 32), + TC_DEST_UDP_OUT => tc_udp(2 * 16 - 1 downto 1 * 16), + TC_SRC_MAC_OUT => tc_src_mac(2 * 48 - 1 downto 1 * 48), + TC_SRC_IP_OUT => tc_src_ip(2 * 32 - 1 downto 1 * 32), + TC_SRC_UDP_OUT => tc_src_udp(2 * 16 - 1 downto 1 * 16), + -- END OF INTERFACE + MY_IP_OUT => my_ip, + DHCP_START_IN => DHCP_START_IN, + DHCP_DONE_OUT => DHCP_DONE_OUT, + DEBUG_OUT => MONITOR_SELECT_GEN_DBG_OUT(2 * 64 - 1 downto 1 * 64) + ); + end generate DHCP_GEN; + + NO_DHCP_GEN: if( INCLUDE_DHCP = '0' ) generate + resp_ready(1) <= '0'; + busy(1) <= '0'; + end generate NO_DHCP_GEN; + + PING_GEN: if( INCLUDE_PING = '1' ) generate + --protocol No. 3 Ping + THE_PING: entity work.gbe_response_constructor_Ping + port map( + CLK => CLK, + RESET => RESET, + ---- INTERFACE + MY_MAC_IN => MY_MAC_IN, + MY_IP_IN => my_ip, + PS_DATA_IN => PS_DATA_IN, + PS_WR_EN_IN => PS_WR_EN_IN, + PS_ACTIVATE_IN => PS_PROTO_SELECT_IN(4), + PS_RESPONSE_READY_OUT => resp_ready(4), + PS_BUSY_OUT => busy(4), + PS_SELECTED_IN => selected(4), + PS_SRC_MAC_ADDRESS_IN => PS_SRC_MAC_ADDRESS_IN, + PS_DEST_MAC_ADDRESS_IN => PS_DEST_MAC_ADDRESS_IN, + PS_SRC_IP_ADDRESS_IN => PS_SRC_IP_ADDRESS_IN, + PS_DEST_IP_ADDRESS_IN => PS_DEST_IP_ADDRESS_IN, + PS_SRC_UDP_PORT_IN => PS_SRC_UDP_PORT_IN, + PS_DEST_UDP_PORT_IN => PS_DEST_UDP_PORT_IN, + TC_RD_EN_IN => TC_RD_EN_IN, + TC_DATA_OUT => tc_data(5 * 9 - 1 downto 4 * 9), + TC_FRAME_SIZE_OUT => tc_size(5 * 16 - 1 downto 4 * 16), + TC_FRAME_TYPE_OUT => tc_type(5 * 16 - 1 downto 4 * 16), + TC_IP_PROTOCOL_OUT => tc_ip_proto(5 * 8 - 1 downto 4 * 8), + TC_IDENT_OUT => tc_ident(5 * 16 - 1 downto 4 * 16), + TC_DEST_MAC_OUT => tc_mac(5 * 48 - 1 downto 4 * 48), + TC_DEST_IP_OUT => tc_ip(5 * 32 - 1 downto 4 * 32), + TC_DEST_UDP_OUT => tc_udp(5 * 16 - 1 downto 4 * 16), + TC_SRC_MAC_OUT => tc_src_mac(5 * 48 - 1 downto 4 * 48), + TC_SRC_IP_OUT => tc_src_ip(5 * 32 - 1 downto 4 * 32), + TC_SRC_UDP_OUT => tc_src_udp(5 * 16 - 1 downto 4 * 16), + DEBUG_OUT => MONITOR_SELECT_GEN_DBG_OUT(5 * 64 - 1 downto 4 * 64) + -- END OF INTERFACE + ); + end generate PING_GEN; + + NO_PING_GEN: if( INCLUDE_PING = '0' ) generate + resp_ready(4) <= '0'; + busy(4) <= '0'; + end generate NO_PING_GEN; + + SCTRL_GEN: if( INCLUDE_SLOWCTRL = '1' ) generate + THE_SCTRL: entity work.gbe_response_constructor_SCTRL + generic map( + SLOWCTRL_BUFFER_SIZE => SLOWCTRL_BUFFER_SIZE + ) + port map( + CLK => CLK, + RESET => RESET, + -- INTERFACE + MY_MAC_IN => MY_MAC_IN, + MY_IP_IN => my_ip, + PS_DATA_IN => PS_DATA_IN, + PS_WR_EN_IN => PS_WR_EN_IN, + PS_ACTIVATE_IN => PS_PROTO_SELECT_IN(2), + PS_RESPONSE_READY_OUT => resp_ready(2), + PS_BUSY_OUT => busy(2), + PS_SELECTED_IN => selected(2), + PS_SRC_MAC_ADDRESS_IN => PS_SRC_MAC_ADDRESS_IN, + PS_DEST_MAC_ADDRESS_IN => PS_DEST_MAC_ADDRESS_IN, + PS_SRC_IP_ADDRESS_IN => PS_SRC_IP_ADDRESS_IN, + PS_DEST_IP_ADDRESS_IN => PS_DEST_IP_ADDRESS_IN, + PS_SRC_UDP_PORT_IN => PS_SRC_UDP_PORT_IN, + PS_DEST_UDP_PORT_IN => PS_DEST_UDP_PORT_IN, + TC_RD_EN_IN => TC_RD_EN_IN, + TC_DATA_OUT => tc_data(3 * 9 - 1 downto 2 * 9), + TC_FRAME_SIZE_OUT => tc_size(3 * 16 - 1 downto 2 * 16), + TC_FRAME_TYPE_OUT => tc_type(3 * 16 - 1 downto 2 * 16), + TC_IP_PROTOCOL_OUT => tc_ip_proto(3 * 8 - 1 downto 2 * 8), + TC_IDENT_OUT => tc_ident(3 * 16 - 1 downto 2 * 16), + TC_DEST_MAC_OUT => tc_mac(3 * 48 - 1 downto 2 * 48), + TC_DEST_IP_OUT => tc_ip(3 * 32 - 1 downto 2 * 32), + TC_DEST_UDP_OUT => tc_udp(3 * 16 - 1 downto 2 * 16), + TC_SRC_MAC_OUT => tc_src_mac(3 * 48 - 1 downto 2 * 48), + TC_SRC_IP_OUT => tc_src_ip(3 * 32 - 1 downto 2 * 32), + TC_SRC_UDP_OUT => tc_src_udp(3 * 16 - 1 downto 2 * 16), + DEBUG_OUT => MONITOR_SELECT_GEN_DBG_OUT(3 * 64 - 1 downto 2 * 64), + -- END OF INTERFACE + GSC_CLK_IN => GSC_CLK_IN, + GSC_INIT_DATAREADY_OUT => GSC_INIT_DATAREADY_OUT, + GSC_INIT_DATA_OUT => GSC_INIT_DATA_OUT, + GSC_INIT_PACKET_NUM_OUT => GSC_INIT_PACKET_NUM_OUT, + GSC_INIT_READ_IN => GSC_INIT_READ_IN, + GSC_REPLY_DATAREADY_IN => GSC_REPLY_DATAREADY_IN, + GSC_REPLY_DATA_IN => GSC_REPLY_DATA_IN, + GSC_REPLY_PACKET_NUM_IN => GSC_REPLY_PACKET_NUM_IN, + GSC_REPLY_READ_OUT => GSC_REPLY_READ_OUT, + GSC_BUSY_IN => GSC_BUSY_IN, + CFG_MAX_REPLY_SIZE_IN => CFG_MAX_REPLY_SIZE_IN, + MAKE_RESET_OUT => MAKE_RESET_OUT, + MONITOR_SELECT_REC_OUT => MONITOR_SELECT_REC_OUT(3 * 32 - 1 downto 2 * 32), + MONITOR_SELECT_REC_BYTES_OUT => MONITOR_SELECT_REC_BYTES_OUT(3 * 32 - 1 downto 2 * 32), + MONITOR_SELECT_SENT_BYTES_OUT => MONITOR_SELECT_SENT_BYTES_OUT(3 * 32 - 1 downto 2 * 32), + MONITOR_SELECT_SENT_OUT => MONITOR_SELECT_SENT_OUT(3 * 32 - 1 downto 2 * 32), + DATA_HIST_OUT => SCTRL_HIST_OUT + ); + end generate SCTRL_GEN; + + NO_SCTRL_GEN: if( INCLUDE_SLOWCTRL = '0' ) generate + resp_ready(2) <= '0'; + busy(2) <= '0'; + MAKE_RESET_OUT <= '0'; + + GSC_INIT_DATAREADY_OUT <= '0'; + GSC_INIT_DATA_OUT <= (others => '0'); + GSC_INIT_PACKET_NUM_OUT <= (others => '0'); + GSC_REPLY_READ_OUT <= '1'; + end generate NO_SCTRL_GEN; + + --------------------------------------------------------------------------------------- + -- once upon a time, this was "READOUT" + resp_ready(3) <= '0'; + busy(3) <= '0'; + --------------------------------------------------------------------------------------- + + FWD_GEN: if( INCLUDE_FWD = '1' ) generate + + THE_FORWARD: entity work.gbe_response_constructor_Forward + port map( + CLK => CLK, + RESET => RESET, + ---- INTERFACE + MY_MAC_IN => MY_MAC_IN, + MY_IP_IN => my_ip, + PS_DATA_IN => PS_DATA_IN, + PS_WR_EN_IN => PS_WR_EN_IN, + PS_ACTIVATE_IN => PS_PROTO_SELECT_IN(5), + PS_RESPONSE_READY_OUT => resp_ready(5), + PS_BUSY_OUT => busy(5), + PS_SELECTED_IN => selected(5), + PS_SRC_MAC_ADDRESS_IN => PS_SRC_MAC_ADDRESS_IN, + PS_DEST_MAC_ADDRESS_IN => PS_DEST_MAC_ADDRESS_IN, + PS_SRC_IP_ADDRESS_IN => PS_SRC_IP_ADDRESS_IN, + PS_DEST_IP_ADDRESS_IN => PS_DEST_IP_ADDRESS_IN, + PS_SRC_UDP_PORT_IN => PS_SRC_UDP_PORT_IN, + PS_DEST_UDP_PORT_IN => PS_DEST_UDP_PORT_IN, + TC_RD_EN_IN => TC_RD_EN_IN, + TC_DATA_OUT => tc_data(6 * 9 - 1 downto 5 * 9), + TC_FRAME_SIZE_OUT => tc_size(6 * 16 - 1 downto 5 * 16), + TC_FRAME_TYPE_OUT => tc_type(6 * 16 - 1 downto 5 * 16), + TC_IP_PROTOCOL_OUT => tc_ip_proto(6 * 8 - 1 downto 5 * 8), + TC_IDENT_OUT => tc_ident(6 * 16 - 1 downto 5 * 16), + TC_DEST_MAC_OUT => tc_mac(6 * 48 - 1 downto 5 * 48), + TC_DEST_IP_OUT => tc_ip(6 * 32 - 1 downto 5 * 32), + TC_DEST_UDP_OUT => tc_udp(6 * 16 - 1 downto 5 * 16), + TC_SRC_MAC_OUT => tc_src_mac(6 * 48 - 1 downto 5 * 48), + TC_SRC_IP_OUT => tc_src_ip(6 * 32 - 1 downto 5 * 32), + TC_SRC_UDP_OUT => tc_src_udp(6 * 16 - 1 downto 5 * 16), + RECEIVED_FRAMES_OUT => open, + SENT_FRAMES_OUT => open, + FWD_DST_MAC_IN => FWD_DST_MAC_IN, + FWD_DST_IP_IN => FWD_DST_IP_IN, + FWD_DST_UDP_IN => FWD_DST_UDP_IN, + FWD_DATA_IN => FWD_DATA_IN, + FWD_DATA_VALID_IN => FWD_DATA_VALID_IN, + FWD_SOP_IN => FWD_SOP_IN, + FWD_EOP_IN => FWD_EOP_IN, + FWD_READY_OUT => FWD_READY_OUT, + FWD_FULL_OUT => FWD_FULL_OUT, + DEBUG_OUT => DEBUG_OUT(31 downto 0) --open + -- END OF INTERFACE + ); + + end generate FWD_GEN; + + DEBUG_OUT(63 downto 32) <= (others => '0'); + + NO_FWD_GEN: if( INCLUDE_FWD = '0' ) generate + resp_ready(5) <= '0'; + busy(5) <= '0'; + DEBUG_OUT(31 downto 0) <= (others => '0'); + end generate NO_FWD_GEN; + + PS_BUSY_OUT <= busy; + + PROC_SELECT_MACHINE: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + select_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + select_current_state <= select_next_state; + end if; + end process PROC_SELECT_MACHINE; + + PROC_SELECT_TRANSITIONS: process(select_current_state, MC_BUSY_IN, resp_ready, index, zeros, busy) + begin + select_state <= x"0"; + + case (select_current_state) is + when IDLE => + select_state <= x"1"; + if (MC_BUSY_IN = '0') then + select_next_state <= LOOP_OVER; + else + select_next_state <= IDLE; + end if; + + when LOOP_OVER => + select_state <= x"2"; + if (resp_ready /= zeros) then + if (resp_ready(index) = '1') then + select_next_state <= SELECT_ONE; + elsif (index = c_MAX_PROTOCOLS) then + select_next_state <= CLEANUP; + else + select_next_state <= LOOP_OVER; + end if; + else + select_next_state <= CLEANUP; + end if; + + when SELECT_ONE => + select_state <= x"3"; + if (MC_BUSY_IN = '1') then + select_next_state <= PROCESS_REQUEST; + else + select_next_state <= SELECT_ONE; + end if; + + when PROCESS_REQUEST => + select_state <= x"4"; + if (busy(index) = '0') then + select_next_state <= CLEANUP; + else + select_next_state <= PROCESS_REQUEST; + end if; + + when CLEANUP => + select_state <= x"5"; + select_next_state <= IDLE; + + when others => select_next_state <= IDLE; + + end case; + end process PROC_SELECT_TRANSITIONS; + + PROC_INDEX: process( CLK ) + begin + if( rising_edge(CLK) ) then + if ( select_current_state = IDLE ) then + index <= 0; + elsif( select_current_state = LOOP_OVER and resp_ready(index) = '0' ) then + index <= index + 1; + end if; + end if; + end process PROC_INDEX; + + PROC_SELECTOR: process( CLK ) + begin + if( rising_edge(CLK) ) then + if( select_current_state = SELECT_ONE or select_current_state = PROCESS_REQUEST ) then + TC_DATA_OUT <= tc_data((index + 1) * 9 - 1 downto index * 9); + TC_FRAME_SIZE_OUT <= tc_size((index + 1) * 16 - 1 downto index * 16); + TC_FRAME_TYPE_OUT <= tc_type((index + 1) * 16 - 1 downto index * 16); + TC_DEST_MAC_OUT <= tc_mac((index + 1) * 48 - 1 downto index * 48); + TC_DEST_IP_OUT <= tc_ip((index + 1) * 32 - 1 downto index * 32); + TC_DEST_UDP_OUT <= tc_udp((index + 1) * 16 - 1 downto index * 16); + TC_SRC_MAC_OUT <= tc_src_mac((index + 1) * 48 - 1 downto index * 48); + TC_SRC_IP_OUT <= tc_src_ip((index + 1) * 32 - 1 downto index * 32); + TC_SRC_UDP_OUT <= tc_src_udp((index + 1) * 16 - 1 downto index * 16); + TC_IP_PROTOCOL_OUT <= tc_ip_proto((index + 1) * 8 - 1 downto index * 8); + TC_IDENT_OUT <= tc_ident((index + 1) * 16 - 1 downto index * 16); + if( select_current_state = SELECT_ONE ) then + PS_RESPONSE_READY_OUT <= '1'; + selected(index) <= '0'; + else + PS_RESPONSE_READY_OUT <= '0'; + selected(index) <= '1'; + end if; + else + TC_DATA_OUT <= (others => '0'); + TC_FRAME_SIZE_OUT <= (others => '0'); + TC_FRAME_TYPE_OUT <= (others => '0'); + TC_DEST_MAC_OUT <= (others => '0'); + TC_DEST_IP_OUT <= (others => '0'); + TC_DEST_UDP_OUT <= (others => '0'); + TC_SRC_MAC_OUT <= (others => '0'); + TC_SRC_IP_OUT <= (others => '0'); + TC_SRC_UDP_OUT <= (others => '0'); + TC_IP_PROTOCOL_OUT <= (others => '0'); + TC_IDENT_OUT <= (others => '0'); + PS_RESPONSE_READY_OUT <= '0'; + selected <= (others => '0'); + end if; + end if; + end process PROC_SELECTOR; + +end gbe_protocol_selector_arch; diff --git a/gbe_trb/base/gbe_receive_control.vhd b/gbe_trb/base/gbe_receive_control.vhd new file mode 100644 index 0000000..4620fbf --- /dev/null +++ b/gbe_trb/base/gbe_receive_control.vhd @@ -0,0 +1,204 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + +entity gbe_receive_control is +port ( + CLK : in std_logic; -- system clock + RESET : in std_logic; +-- signals to/from frame_receiver + RC_DATA_IN : in std_logic_vector(8 downto 0); + FR_RD_EN_OUT : out std_logic; + FR_FRAME_VALID_IN : in std_logic; + FR_GET_FRAME_OUT : out std_logic; + FR_FRAME_SIZE_IN : in std_logic_vector(15 downto 0); + FR_FRAME_PROTO_IN : in std_logic_vector(15 downto 0); + FR_IP_PROTOCOL_IN : in std_logic_vector(7 downto 0); + + FR_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + FR_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + FR_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + FR_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + FR_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + FR_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); + -- signals to/from main controller + RC_RD_EN_IN : in std_logic; + RC_Q_OUT : out std_logic_vector(8 downto 0); + RC_FRAME_WAITING_OUT : out std_logic; + RC_LOADING_DONE_IN : in std_logic; + RC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + RC_FRAME_PROTO_OUT : out std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + RC_SRC_MAC_ADDRESS_OUT : out std_logic_vector(47 downto 0); + RC_DEST_MAC_ADDRESS_OUT : out std_logic_vector(47 downto 0); + RC_SRC_IP_ADDRESS_OUT : out std_logic_vector(31 downto 0); + RC_DEST_IP_ADDRESS_OUT : out std_logic_vector(31 downto 0); + RC_SRC_UDP_PORT_OUT : out std_logic_vector(15 downto 0); + RC_DEST_UDP_PORT_OUT : out std_logic_vector(15 downto 0); + -- statistics + FRAMES_RECEIVED_OUT : out std_logic_vector(31 downto 0); + BYTES_RECEIVED_OUT : out std_logic_vector(31 downto 0); + -- + DEBUG_OUT : out std_logic_vector(63 downto 0) +); +end gbe_receive_control; + +architecture gbe_receive_control_arch of gbe_receive_control is + +attribute syn_encoding : string; + +type load_states is (IDLE, PREPARE, WAIT_ONE, READY); +signal load_current_state, load_next_state : load_states; +attribute syn_encoding of load_current_state : signal is "onehot"; + +signal frames_received_ctr : unsigned(31 downto 0); +signal frames_readout_ctr : unsigned(31 downto 0); +signal bytes_rec_ctr : unsigned(31 downto 0); + +signal state : std_logic_vector(3 downto 0); +signal proto_code : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); +signal reset_prioritizer : std_logic; +signal frame_waiting : std_logic; + +-- debug only +signal saved_proto : std_logic_vector(c_MAX_PROTOCOLS - 1 downto 0); + +begin + +FR_RD_EN_OUT <= RC_RD_EN_IN; +RC_Q_OUT <= RC_DATA_IN; +RC_FRAME_SIZE_OUT <= FR_FRAME_SIZE_IN; +RC_SRC_MAC_ADDRESS_OUT <= FR_SRC_MAC_ADDRESS_IN; +RC_DEST_MAC_ADDRESS_OUT <= FR_DEST_MAC_ADDRESS_IN; +RC_SRC_IP_ADDRESS_OUT <= FR_SRC_IP_ADDRESS_IN; +RC_DEST_IP_ADDRESS_OUT <= FR_DEST_IP_ADDRESS_IN; +RC_SRC_UDP_PORT_OUT <= FR_SRC_UDP_PORT_IN; +RC_DEST_UDP_PORT_OUT <= FR_DEST_UDP_PORT_IN; + +protocol_prioritizer: entity gbe_protocol_prioritizer +port map( + CLK => CLK, + RESET => reset_prioritizer, + -- + FRAME_TYPE_IN => FR_FRAME_PROTO_IN, + PROTOCOL_CODE_IN => FR_IP_PROTOCOL_IN, + UDP_PROTOCOL_IN => FR_DEST_UDP_PORT_IN, + -- + CODE_OUT => proto_code +); + +reset_prioritizer <= '1' when load_current_state = IDLE else '0'; + +RC_FRAME_PROTO_OUT <= proto_code; -- no more ones as the incorrect value, last slot for Trash + +LOAD_MACHINE_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + load_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + load_current_state <= load_next_state; + end if; +end process LOAD_MACHINE_PROC; + +LOAD_MACHINE: process( load_current_state, frames_readout_ctr, frames_received_ctr, RC_LOADING_DONE_IN ) +begin + case load_current_state is + + when IDLE => + state <= x"1"; + if( frames_readout_ctr /= frames_received_ctr ) then -- frame is still waiting in frame_receiver + load_next_state <= PREPARE; + else + load_next_state <= IDLE; + end if; + + when PREPARE => -- prepare frame size + state <= x"2"; + load_next_state <= WAIT_ONE; + + when WAIT_ONE => + load_next_state <= READY; + + when READY => -- wait for reading out the whole frame + state <= x"3"; + if( RC_LOADING_DONE_IN = '1' ) then + load_next_state <= IDLE; + else + load_next_state <= READY; + end if; + + end case; +end process LOAD_MACHINE; + +process( CLK ) +begin + if( rising_edge(CLK) ) then + if( load_current_state = PREPARE ) then + FR_GET_FRAME_OUT <= '1'; + else + FR_GET_FRAME_OUT <= '0'; + end if; + + if( (load_current_state = READY) and (RC_LOADING_DONE_IN = '0') ) then + RC_FRAME_WAITING_OUT <= '1'; + else + RC_FRAME_WAITING_OUT <= '0'; + end if; + end if; +end process; + +FRAMES_REC_CTR_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + frames_received_ctr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( FR_FRAME_VALID_IN = '1' ) then + frames_received_ctr <= frames_received_ctr + 1; + end if; + end if; +end process FRAMES_REC_CTR_PROC; + +FRAMES_READOUT_CTR_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + frames_readout_ctr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( RC_LOADING_DONE_IN = '1' ) then + frames_readout_ctr <= frames_readout_ctr + 1; + end if; + end if; +end process FRAMES_READOUT_CTR_PROC; + +-- debug only +BYTES_REC_CTR_PROC : process( CLK ) +begin + if ( RESET = '1' ) then + bytes_rec_ctr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( FR_FRAME_VALID_IN = '1' ) then + bytes_rec_ctr <= bytes_rec_ctr + unsigned(FR_FRAME_SIZE_IN); + end if; + end if; +end process BYTES_REC_CTR_PROC; + +SAVED_PROTO_PROC : process( CLK ) +begin + if( rising_edge(CLK) ) then + if( load_current_state = READY ) then + if( and_all(proto_code) = '0' ) then + saved_proto <= proto_code; + else + saved_proto <= (others => '0'); + end if; + else + saved_proto <= saved_proto; + end if; + end if; +end process SAVED_PROTO_PROC; + +end gbe_receive_control_arch; diff --git a/gbe_trb/base/gbe_rx_rb.vhd b/gbe_trb/base/gbe_rx_rb.vhd new file mode 100644 index 0000000..b699689 --- /dev/null +++ b/gbe_trb/base/gbe_rx_rb.vhd @@ -0,0 +1,290 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + +entity gbe_rx_rb is + port( + CLK : in std_logic; + RESET : in std_logic; + -- MAC interface (RX) + MAC_RX_DATA_IN : in std_logic_vector(7 downto 0); -- RX data from TSMAC + MAC_RX_WR_IN : in std_logic; -- RX data write from TSMAC + MAC_RX_EOF_IN : in std_logic; -- RX EndOfFrame from TSMAC + MAC_RX_ERROR_IN : in std_logic; -- RX Error from TSMAC + MAC_RX_FIFOFULL_OUT : out std_logic; + -- FIFO interface (TX) + FIFO_FULL_IN : in std_logic; -- TX fifo full, delay read from ring buffer + FIFO_WR_OUT : out std_logic; -- TX fifo write + FIFO_Q_OUT : out std_logic_vector(8 downto 0); -- TX data + FRAME_REQ_IN : in std_logic; -- one pulse starts readout of frame stored in ring buffer + FRAME_ACK_OUT : out std_logic; -- one pulse for "end of frame" + FRAME_AVAIL_OUT : out std_logic; -- number of frames stored in ring buffer + FRAME_START_OUT : out std_logic -- StartOfFrame signal + ); +end entity gbe_rx_rb; + +-- This entity acts as receive buffer for the new GbE media interface. It connects to the MAC RX ports, +-- and is storing incoming Ethernet frames. +-- Broken frames (indicated by MAC_RX_ERROR_IN) are dropped, and in addition, frames which can't be stored +-- completely (due to potential ring buffer overflow) are also dropped. +-- This entity can forward frames on request by doing "DMA": +-- If a frame is requested by FRAME_REQ_IN, the entity decides if a full frame is available (as shown by +-- FRAME_AVAIL_OUT), in case no data is present, a FRAME_ACK_OUT is generated to avoid deadlocks, but +-- no data is transfered. +-- If a frame can be transfered, FRAME_START_OUT is set for one cycle, and data is written out +-- (handshaking with FIFO_FULL_IN) on FIFO_Q_OUT, with data validated by FIFO_WR_OUT. +-- With the EOF signal (FIFO_Q_OUT(8)) set FRAME_ACK_OUT is also set and the transfer ends. + +architecture gbe_rx_rb_arch of gbe_rx_rb is + +-- state machine signals + type state_t is (RX_DENY,RX_READY,RX_FRAME,FRAME_OK,FRAME_BAD,FORWARD,SKIP); + signal STATE, NEXT_STATE : state_t; + +-- Signals + signal rd_ptr : unsigned(11 downto 0); + signal wr_ptr : unsigned(11 downto 0); + signal last_wr_ptr : std_logic_vector(11 downto 0); + signal rb_used_x : unsigned(11 downto 0); + signal rb_full_x : std_logic; + signal rb_empty_x : std_logic; + signal ce_wr_ptr_x : std_logic; + signal ld_wr_ptr_x : std_logic; + signal ce_rd_ptr_x : std_logic; + signal wr_ram_x : std_logic; + signal rd_ram_x : std_logic; + signal ram_q : std_logic_vector(8 downto 0); + signal frame_requested : std_logic; + signal frame_acknowledged : std_logic; + signal fifo_wr_int : std_logic; + signal empty_read_ack : std_logic; + signal normal_read_ack_x : std_logic; + signal sof_int : std_logic; + signal frames_avail : unsigned(7 downto 0); + signal frame_active : std_logic; + signal frame_error : std_logic; + +begin + + -- FrameActive: we must not change to "receive" in the middle of a frame + -- when "buffer full" condition is deasserted. + -- Needs to be extra process, not inside the state machine! + PROC_FRAME_ACTIVE: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + frame_active <= '0'; + elsif( rising_edge(CLK) ) then + if ( (MAC_RX_WR_IN = '1') and (frame_active = '0') ) then + frame_active <= '1'; + elsif( (MAC_RX_EOF_IN = '1') and (frame_active = '1') ) then + frame_active <= '0'; + end if; + end if; + end process PROC_FRAME_ACTIVE; + + -- Read pointer for ring buffer + PROC_RD_PTR: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + rd_ptr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( ce_rd_ptr_x = '1' ) then + rd_ptr <= rd_ptr + 1; + end if; + end if; + end process PROC_RD_PTR; + + -- Write pointer for ring buffer + PROC_WR_PTR: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + wr_ptr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if ( ld_wr_ptr_x = '1' ) then + wr_ptr <= unsigned(last_wr_ptr); + elsif( ce_wr_ptr_x = '1' ) then + wr_ptr <= wr_ptr + 1; + end if; + end if; + end process PROC_WR_PTR; + + -- last write pointer: used to drop a broken frame, in case + PROC_LAST_WR_PTR: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + last_wr_ptr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( (STATE = RX_READY) and (MAC_RX_WR_IN = '1') ) then + last_wr_ptr <= std_logic_vector(wr_ptr); + end if; + end if; + end process PROC_LAST_WR_PTR; + + -- ring buffer fill level + rb_used_x <= wr_ptr - rd_ptr; + + -- ring buffer full + -- TAKE CARE: the last byte of a frame is taken into account + -- by "one less" for the full condition + rb_full_x <= '1' when (rb_used_x(11 downto 1) = b"1111_1111_111") else '0'; + + -- ring buffer empty + rb_empty_x <= '1' when (rb_used_x(11 downto 0) = b"0000_0000_0000") else '0'; + + MAC_RX_FIFOFULL_OUT <= rb_full_x; + + -- DPRAM as ring buffer + THE_DP_RAM: entity work.rb_4k_9 + port map( + WRADDRESS => std_logic_vector(wr_ptr), + RDADDRESS => std_logic_vector(rd_ptr), + DATA(8) => MAC_RX_EOF_IN, + DATA(7 downto 0) => MAC_RX_DATA_IN, + WE => wr_ram_x, + RDCLOCK => CLK, + RDCLOCKEN => '1', + RESET => RESET, + WRCLOCK => CLK, + WRCLOCKEN => '1', + Q => ram_q + ); + + -- write signal + wr_ram_x <= '1' when ((STATE = RX_READY) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) or -- first byte of frame + ((STATE = RX_FRAME) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) -- all other bytes of frame + else '0'; + ce_wr_ptr_x <= '1' when ((STATE = RX_READY) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) or + ((STATE = RX_FRAME) and (MAC_RX_WR_IN = '1') and (rb_full_x = '0')) + else '0'; + + -- FrameError: catches problem with FIFOFULL during a frame write. + PROC_FRAME_ERROR: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + frame_error <= '0'; + elsif( rising_edge(CLK) ) then + if ( (frame_active = '1') and (rb_full_x = '1') and (MAC_RX_WR_IN = '1') ) then + frame_error <= '1'; + elsif( (frame_active = '0') ) then -- could be better! + frame_error <= '0'; + end if; + end if; + end process PROC_FRAME_ERROR; + + -- FrameReq signal, one pulse only + PROC_FRAME_REQ: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + frame_requested <= '0'; + elsif( rising_edge(CLK) ) then + if ( (FRAME_REQ_IN = '1') and (frame_requested = '0') ) then + frame_requested <= '1'; + elsif( ((ram_q(8) = '1') and (frame_requested = '1')) or (empty_read_ack = '1') ) then + frame_requested <= '0'; + end if; + end if; + end process PROC_FRAME_REQ; + + -- NormalReadAck signal: ends a normal data transfer by EOF + normal_read_ack_x <= ram_q(8) and fifo_wr_int; + + -- read signal + rd_ram_x <= '1' when ((frame_requested = '1') and (ram_q(8) = '0') and (FIFO_FULL_IN = '0') and (rb_empty_x = '0')) else '0'; + ce_rd_ptr_x <= '1' when ((frame_requested = '1') and (ram_q(8) = '0') and (FIFO_FULL_IN = '0') and (rb_empty_x = '0')) else '0'; + + empty_read_ack <= FRAME_REQ_IN and rb_empty_x when rising_edge(CLK); + sof_int <= FRAME_REQ_IN and not frame_requested when rising_edge(CLK); + FRAME_START_OUT <= sof_int when rising_edge(CLK); + fifo_wr_int <= rd_ram_x when rising_edge(CLK); + FIFO_WR_OUT <= fifo_wr_int when rising_edge(CLK); + FRAME_ACK_OUT <= normal_read_ack_x or empty_read_ack when rising_edge(CLK); + FIFO_Q_OUT <= ram_q when rising_edge(CLK); + + -- FramesAvailable counter + PROC_FRAMES_AVAIL: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + frames_avail <= (others => '0'); + elsif( rising_edge(CLK) ) then + if ( (STATE = FRAME_OK) and (normal_read_ack_x = '0') ) then + -- one frame written successfully + frames_avail <= frames_avail + 1; + elsif( (STATE /= FRAME_OK) and (normal_read_ack_x = '1') ) then + -- one frame read successfully + frames_avail <= frames_avail - 1; + end if; + end if; + end process PROC_FRAMES_AVAIL; + + FRAME_AVAIL_OUT <= '1' when (frames_avail /= x"00") else '0'; + + ----------------------------------------------------------- + -- statemachine: clocked process + ----------------------------------------------------------- + PROC_FSM: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + STATE <= RX_DENY; + elsif( rising_edge(CLK) ) then + STATE <= NEXT_STATE; + end if; + end process PROC_FSM; + + PROC_STATE_TRANSITIONS: process( STATE, MAC_RX_WR_IN, MAC_RX_EOF_IN, MAC_RX_ERROR_IN, frame_active, rb_full_x ) + begin + ld_wr_ptr_x <= '0'; + + case STATE is + + when RX_DENY => + if( (frame_active = '0') and (rb_full_x = '0') ) then + NEXT_STATE <= RX_READY; + else + NEXT_STATE <= RX_DENY; + end if; + + when RX_READY => + if( MAC_RX_WR_IN = '1' ) then + NEXT_STATE <= RX_FRAME; + else + NEXT_STATE <= RX_READY; + end if; + + when RX_FRAME => + if ( (MAC_RX_EOF_IN = '1') and (MAC_RX_ERROR_IN = '0') and (rb_full_x = '0') ) then + NEXT_STATE <= FRAME_OK; + elsif( (MAC_RX_EOF_IN = '1') and ((MAC_RX_ERROR_IN = '1') or (rb_full_x = '1')) ) then + NEXT_STATE <= FRAME_BAD; + ld_wr_ptr_x <= '1'; + else + NEXT_STATE <= RX_FRAME; + end if; + + when FRAME_OK => + NEXT_STATE <= FORWARD; + + when FORWARD => + if( rb_full_x = '0' ) then + NEXT_STATE <= RX_READY; + else + NEXT_STATE <= RX_DENY; + end if; + + when FRAME_BAD => + NEXT_STATE <= SKIP; + + when SKIP => + if( rb_full_x = '0' ) then + NEXT_STATE <= RX_READY; + else + NEXT_STATE <= RX_DENY; + end if; + + when others => + NEXT_STATE <= RX_DENY; + end case; + end process PROC_STATE_TRANSITIONS; + +end architecture gbe_rx_rb_arch; diff --git a/gbe_trb/base/gbe_sgl_ctrl.vhd b/gbe_trb/base/gbe_sgl_ctrl.vhd new file mode 100644 index 0000000..d9c424b --- /dev/null +++ b/gbe_trb/base/gbe_sgl_ctrl.vhd @@ -0,0 +1,351 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + +entity gbe_sgl_ctrl is + port( + CLK : in std_logic; + RESET : in std_logic; + -- UL port + UL_FIFOFULL_IN : in std_logic := '0'; -- UL TX FIFO is full + UL_FRAME_AVAIL_IN : in std_logic := '0'; -- UL RX has frames available for scattering + UL_FRAME_REQ_OUT : out std_logic; -- UL RX request to send + UL_FRAME_ACK_IN : in std_logic := '0'; -- UL RX sent acknowledge + -- DL ports (includes SCTRL) + DL_FIFOFULL_IN : in std_logic_vector(15 downto 0) := (others => '0'); -- DL TXn FIFO is full + DL_FRAME_AVAIL_IN : in std_logic_vector(15 downto 0) := (others => '0'); -- DL RXn has frames available for scattering + DL_FRAME_REQ_OUT : out std_logic_vector(15 downto 0); -- DL RXn request to send + DL_FRAME_ACK_IN : in std_logic_vector(15 downto 0) := (others => '0'); -- DL RXn sent acknowledge + -- LOCAL port + LOCAL_FIFOFULL_IN : in std_logic := '0'; -- LOCAL TX FIFO is full + LOCAL_FRAME_AVAIL_IN : in std_logic := '0'; -- LOCAL RX has frames available + LOCAL_FRAME_REQ_OUT : out std_logic; -- LOCAL RX request to send + LOCAL_FRAME_ACK_IN : in std_logic := '0'; -- LOCAL RX sent acknowledge + -- + DL_RX_PORT_SEL_OUT : out std_logic_vector(15 downto 0); + DL_RX_PORT_MUX_OUT : out std_logic_vector(3 downto 0); + DL_TX_PORT_SEL_OUT : out std_logic; -- '0' => LOCAL, '1' UL + LOCAL_TX_PORT_SEL_OUT : out std_logic; + UL_TX_PORT_SEL_OUT : out std_logic; + -- + DEBUG : out std_logic_vector(15 downto 0) + ); +end entity gbe_sgl_ctrl; + +architecture gbe_sgl_ctrl_arch of gbe_sgl_ctrl is + +-- Components + +-- state machine signals + type state_t is (IDLE,SC_START,SC_PORT,SC_DELAY,SC_CLEANUP, + GA_START,GA_STORE,GA_PORT,GA_DELAY,GA_CLEANUP, + LC_START,LC_PORT,LC_DELAY,LC_CLEANUP); + signal STATE, NEXT_STATE : state_t; + +-- Signals + signal scatter_fifofull_x : std_logic; + signal gather_fifofull_x : std_logic; + signal local_fifofull_x : std_logic; + signal gather_needed_x : std_logic; + signal store_ports_x : std_logic; + signal stored_ports : std_logic_vector(15 downto 0); + signal all_ports_done_x : std_logic; + signal select_ports : std_logic_vector(15 downto 0); + signal req_ports : std_logic_vector(15 downto 0); + signal next_mux_x : std_logic_vector(3 downto 0); + signal mux_ports : std_logic_vector(3 downto 0); + signal next_port_x : std_logic_vector(15 downto 0); + + signal ul_frame_req_x : std_logic; + signal ul_frame_req : std_logic; + signal local_frame_req_x : std_logic; + signal local_frame_req : std_logic; + + signal dl_tx_port_sel_x : std_logic; + signal local_tx_port_sel_x : std_logic; + signal ul_tx_port_sel_x : std_logic; + + signal bsm : std_logic_vector(3 downto 0); + +begin + + -- Debug signals for hardware + DEBUG(15 downto 4) <= (others => '0'); + DEBUG(3 downto 0) <= bsm; + + -- SCATTER: fifofull is created from DL and LOCAL ports (not SCTRL) + scatter_fifofull_x <= '1' when ((DL_FIFOFULL_IN(15 downto 1) /= b"0000_0000_0000_000") or (LOCAL_FIFOFULL_IN = '1')) + else '0'; + + -- GATHER: fifofull is created from UL and LOCAL + gather_fifofull_x <= '1' when ((UL_FIFOFULL_IN = '1') or (LOCAL_FIFOFULL_IN = '1')) + else '0'; + + -- LOCAL: fifofull is created from UL and DL () + local_fifofull_x <= '1' when ((DL_FIFOFULL_IN(15 downto 1) /= b"0000_0000_0000_000") or (UL_FIFOFULL_IN = '1')) + else '0'; + + -- GATHER: + gather_needed_x <= '1' when (DL_FRAME_AVAIL_IN /= x"0000") + else '0'; + + -- store the src port status + GEN_REGS: for I in 0 to 15 generate + THE_SRC_STORE_PROC: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + stored_ports(I) <= '0'; + elsif( rising_edge(CLK) ) then + if ( store_ports_x = '1' ) then + stored_ports(I) <= DL_FRAME_AVAIL_IN(I); + elsif( DL_FRAME_ACK_IN(I) = '1' ) then + stored_ports(I) <= '0'; + end if; + end if; + end process THE_SRC_STORE_PROC; + end generate; + + all_ports_done_x <= '1' when stored_ports = x"0000" else '0'; + + -- select the port data + THE_SELECT_PORT_PROC: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + select_ports <= (others => '0'); + mux_ports <= (others => '0'); + elsif( rising_edge(CLK) ) then + select_ports <= next_port_x; + mux_ports <= next_mux_x; + end if; + end process THE_SELECT_PORT_PROC; + + DL_RX_PORT_SEL_OUT <= select_ports; + DL_RX_PORT_MUX_OUT <= mux_ports; + + -- port frame request, one clock cycle pulse + req_ports <= not select_ports and next_port_x when rising_edge(CLK); + + DL_FRAME_REQ_OUT <= req_ports; + + -- priority decoced "next port to serve" signals + THE_NEXT_PORT_PROC: process( stored_ports ) + begin + if ( stored_ports(0) = '1' ) then + next_port_x <= x"0001"; + next_mux_x <= x"0"; + elsif( stored_ports(1) = '1' ) then + next_port_x <= x"0002"; + next_mux_x <= x"1"; + elsif( stored_ports(2) = '1' ) then + next_port_x <= x"0004"; + next_mux_x <= x"2"; + elsif( stored_ports(3) = '1' ) then + next_port_x <= x"0008"; + next_mux_x <= x"3"; + elsif( stored_ports(4) = '1' ) then + next_port_x <= x"0010"; + next_mux_x <= x"4"; + elsif( stored_ports(5) = '1' ) then + next_port_x <= x"0020"; + next_mux_x <= x"5"; + elsif( stored_ports(6) = '1' ) then + next_port_x <= x"0040"; + next_mux_x <= x"6"; + elsif( stored_ports(7) = '1' ) then + next_port_x <= x"0080"; + next_mux_x <= x"7"; + elsif( stored_ports(8) = '1' ) then + next_port_x <= x"0100"; + next_mux_x <= x"8"; + elsif( stored_ports(9) = '1' ) then + next_port_x <= x"0200"; + next_mux_x <= x"9"; + elsif( stored_ports(10) = '1' ) then + next_port_x <= x"0400"; + next_mux_x <= x"a"; + elsif( stored_ports(11) = '1' ) then + next_port_x <= x"0800"; + next_mux_x <= x"b"; + elsif( stored_ports(12) = '1' ) then + next_port_x <= x"1000"; + next_mux_x <= x"c"; + elsif( stored_ports(13) = '1' ) then + next_port_x <= x"2000"; + next_mux_x <= x"d"; + elsif( stored_ports(14) = '1' ) then + next_port_x <= x"4000"; + next_mux_x <= x"e"; + elsif( stored_ports(15) = '1' ) then + next_port_x <= x"8000"; + next_mux_x <= x"f"; + else + next_port_x <= x"0000"; + next_mux_x <= x"0"; + end if; + end process THE_NEXT_PORT_PROC; + + ----------------------------------------------------------- + -- Outputs + ----------------------------------------------------------- + UL_FRAME_REQ_OUT <= ul_frame_req; + LOCAL_FRAME_REQ_OUT <= local_frame_req; + DL_TX_PORT_SEL_OUT <= dl_tx_port_sel_x; + LOCAL_TX_PORT_SEL_OUT <= local_tx_port_sel_x; + UL_TX_PORT_SEL_OUT <= ul_tx_port_sel_x; + + ----------------------------------------------------------- + -- statemachine: clocked process + ----------------------------------------------------------- + THE_FSM: process( CLK, RESET ) + begin + if ( RESET = '1' ) then + STATE <= IDLE; + ul_frame_req <= '0'; + local_frame_req <= '0'; + elsif( rising_edge(CLK) ) then + STATE <= NEXT_STATE; + ul_frame_req <= ul_frame_req_x; + local_frame_req <= local_frame_req_x; + end if; + end process THE_FSM; + + ----------------------------------------------------------- + -- + ----------------------------------------------------------- + THE_STATE_TRANSITIONS: process( STATE, UL_FRAME_AVAIL_IN, LOCAL_FRAME_AVAIL_IN, UL_FRAME_ACK_IN, + LOCAL_FRAME_ACK_IN, scatter_fifofull_x, gather_fifofull_x, + local_fifofull_x, all_ports_done_x ) + begin + ul_frame_req_x <= '0'; + local_frame_req_x <= '0'; + store_ports_x <= '0'; + dl_tx_port_sel_x <= '0'; + local_tx_port_sel_x <= '0'; + ul_tx_port_sel_x <= '0'; + + case STATE is + when IDLE => + bsm <= x"0"; + if ( (UL_FRAME_AVAIL_IN = '1') and (scatter_fifofull_x = '0') ) then + NEXT_STATE <= SC_START; + elsif( (gather_needed_x = '1') and (gather_fifofull_x = '0') ) then + NEXT_STATE <= GA_START; + elsif( (LOCAL_FRAME_AVAIL_IN = '1') and (local_fifofull_x = '0') ) then + NEXT_STATE <= LC_START; + else + NEXT_STATE <= IDLE; + end if; + + when SC_START => + bsm <= x"1"; + NEXT_STATE <= SC_PORT; + ul_frame_req_x <= '1'; + dl_tx_port_sel_x <= '1'; + local_tx_port_sel_x <= '1'; + + when SC_PORT => + bsm <= x"2"; + if( UL_FRAME_ACK_IN = '1' ) then + NEXT_STATE <= SC_DELAY; + else + NEXT_STATE <= SC_PORT; + end if; + dl_tx_port_sel_x <= '1'; + local_tx_port_sel_x <= '1'; + + when SC_DELAY => + bsm <= x"3"; + NEXT_STATE <= SC_CLEANUP; + dl_tx_port_sel_x <= '1'; + local_tx_port_sel_x <= '1'; + + when SC_CLEANUP => + bsm <= x"4"; + if ( (gather_needed_x = '1') and (gather_fifofull_x = '0') ) then + NEXT_STATE <= GA_START; + elsif( (LOCAL_FRAME_AVAIL_IN = '1') and (local_fifofull_x = '0') ) then + NEXT_STATE <= LC_START; + elsif( (UL_FRAME_AVAIL_IN = '1') and (scatter_fifofull_x = '0') ) then + NEXT_STATE <= SC_START; + else + NEXT_STATE <= IDLE; + end if; + dl_tx_port_sel_x <= '1'; -- maybe not needed + local_tx_port_sel_x <= '1'; -- maybe not needed + + when GA_START => + bsm <= x"5"; + NEXT_STATE <= GA_STORE; + store_ports_x <= '1'; + ul_tx_port_sel_x <= '1'; + + when GA_STORE => + bsm <= x"6"; + NEXT_STATE <= GA_PORT; + ul_tx_port_sel_x <= '1'; + + when GA_PORT => + bsm <= x"7"; + if( all_ports_done_x = '1' ) then + NEXT_STATE <= GA_DELAY; + else + NEXT_STATE <= GA_PORT; + end if; + ul_tx_port_sel_x <= '1'; + + when GA_DELAY => + bsm <= x"8"; + NEXT_STATE <= GA_CLEANUP; + ul_tx_port_sel_x <= '1'; + + when GA_CLEANUP => + bsm <= x"9"; + if ( (LOCAL_FRAME_AVAIL_IN = '1') and (local_fifofull_x = '0') ) then + NEXT_STATE <= LC_START; + elsif( (UL_FRAME_AVAIL_IN = '1') and (scatter_fifofull_x = '0') ) then + NEXT_STATE <= SC_START; + elsif( (gather_needed_x = '1') and (gather_fifofull_x = '0') ) then + NEXT_STATE <= GA_START; + else + NEXT_STATE <= IDLE; + end if; + ul_tx_port_sel_x <= '1'; -- maybe not needed + + when LC_START => + bsm <= x"a"; + NEXT_STATE <= LC_PORT; + local_frame_req_x <= '1'; + + when LC_PORT => + bsm <= x"b"; + if( LOCAL_FRAME_ACK_IN = '1' ) then + NEXT_STATE <= LC_DELAY; + else + NEXT_STATE <= LC_PORT; + end if; + + when LC_DELAY => + bsm <= x"c"; + NEXT_STATE <= LC_CLEANUP; + + when LC_CLEANUP => + bsm <= x"d"; + if ( (UL_FRAME_AVAIL_IN = '1') and (scatter_fifofull_x = '0') ) then + NEXT_STATE <= SC_START; + elsif( (gather_needed_x = '1') and (gather_fifofull_x = '0') ) then + NEXT_STATE <= GA_START; + elsif( (LOCAL_FRAME_AVAIL_IN = '1') and (local_fifofull_x = '0') ) then + NEXT_STATE <= LC_START; + else + NEXT_STATE <= IDLE; + end if; + + when others => + bsm <= x"f"; + NEXT_STATE <= IDLE; + end case; + end process THE_STATE_TRANSITIONS; + +end architecture gbe_sgl_ctrl_arch; diff --git a/gbe_trb/base/gbe_transmit_control.vhd b/gbe_trb/base/gbe_transmit_control.vhd new file mode 100644 index 0000000..53d1c9a --- /dev/null +++ b/gbe_trb/base/gbe_transmit_control.vhd @@ -0,0 +1,302 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + +entity gbe_transmit_control is +port ( + CLK : in std_logic; + RESET : in std_logic; +-- signal to/from main controller + TC_DATAREADY_IN : in std_logic; + TC_RD_EN_OUT : out std_logic; + TC_DATA_IN : in std_logic_vector(7 downto 0); + TC_FRAME_SIZE_IN : in std_logic_vector(15 downto 0); + TC_FRAME_TYPE_IN : in std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_IN : in std_logic_vector(7 downto 0); + TC_DEST_MAC_IN : in std_logic_vector(47 downto 0); + TC_DEST_IP_IN : in std_logic_vector(31 downto 0); + TC_DEST_UDP_IN : in std_logic_vector(15 downto 0); + TC_SRC_MAC_IN : in std_logic_vector(47 downto 0); + TC_SRC_IP_IN : in std_logic_vector(31 downto 0); + TC_SRC_UDP_IN : in std_logic_vector(15 downto 0); + TC_TRANSMISSION_DONE_OUT : out std_logic; + TC_IDENT_IN : in std_logic_vector(15 downto 0); + TC_MAX_FRAME_IN : in std_logic_vector(15 downto 0); +-- signal to/from frame constructor + FC_DATA_OUT : out std_logic_vector(7 downto 0); + FC_WR_EN_OUT : out std_logic; + FC_READY_IN : in std_logic; + FC_H_READY_IN : in std_logic; + FC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + FC_IP_SIZE_OUT : out std_logic_vector(15 downto 0); + FC_UDP_SIZE_OUT : out std_logic_vector(15 downto 0); + FC_IDENT_OUT : out std_logic_vector(15 downto 0); -- internal packet counter + FC_FLAGS_OFFSET_OUT : out std_logic_vector(15 downto 0); + FC_SOD_OUT : out std_logic; + FC_EOD_OUT : out std_logic; + FC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); +-- + DEST_MAC_ADDRESS_OUT : out std_logic_vector(47 downto 0); + DEST_IP_ADDRESS_OUT : out std_logic_vector(31 downto 0); + DEST_UDP_PORT_OUT : out std_logic_vector(15 downto 0); + SRC_MAC_ADDRESS_OUT : out std_logic_vector(47 downto 0); + SRC_IP_ADDRESS_OUT : out std_logic_vector(31 downto 0); + SRC_UDP_PORT_OUT : out std_logic_vector(15 downto 0); +-- + MONITOR_TX_PACKETS_OUT : out std_logic_vector(31 downto 0); +-- + DEBUG_OUT : out std_logic_vector(63 downto 0) +); +end gbe_transmit_control; + +architecture gbe_transmit_control_arch of gbe_transmit_control is + +attribute syn_encoding : string; + +type transmit_states is (IDLE, PREPARE_HEADERS, WAIT_FOR_H, TRANSMIT, SEND_ONE, SEND_TWO, CLOSE, WAIT_FOR_TRANS, DIVIDE, CLEANUP); +signal transmit_current_state, transmit_next_state : transmit_states; +attribute syn_encoding of transmit_current_state : signal is "onehot"; + +signal tc_rd, tc_rd_q, tc_rd_qq : std_logic; +signal local_end : std_logic_vector(15 downto 0); + +signal actual_frame_bytes, full_packet_size, ip_size, packet_loaded_bytes : std_logic_vector(15 downto 0); +signal go_to_divide, more_fragments : std_logic; +signal first_frame : std_logic; +signal mon_packets_sent_ctr : std_logic_vector(31 downto 0); +signal state : std_logic_vector(3 downto 0); + +begin + +TRANSMIT_MACHINE_PROC : process( CLK, RESET ) +begin + if ( RESET = '1' ) then + transmit_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + transmit_current_state <= transmit_next_state; + end if; +end process TRANSMIT_MACHINE_PROC; + +TRANSMIT_MACHINE : process(transmit_current_state, FC_H_READY_IN, TC_DATAREADY_IN, FC_READY_IN, local_end, TC_MAX_FRAME_IN, actual_frame_bytes, go_to_divide) +begin + state <= x"0"; + case transmit_current_state is + + when IDLE => + state <= x"1"; + if (TC_DATAREADY_IN = '1') then + transmit_next_state <= PREPARE_HEADERS; + else + transmit_next_state <= IDLE; + end if; + + when PREPARE_HEADERS => + state <= x"2"; + transmit_next_state<= WAIT_FOR_H; + + when WAIT_FOR_H => + state <= x"3"; + if (FC_H_READY_IN = '1') then + transmit_next_state <= TRANSMIT; + else + transmit_next_state <= WAIT_FOR_H; + end if; + + when TRANSMIT => + state <= x"4"; + if (local_end = x"0000") then + transmit_next_state <= SEND_ONE; + else + if (actual_frame_bytes = TC_MAX_FRAME_IN - x"1") then + transmit_next_state <= SEND_ONE; + else + transmit_next_state <= TRANSMIT; + end if; + end if; + + when SEND_ONE => + state <= x"5"; + transmit_next_state <= SEND_TWO; + + when SEND_TWO => + state <= x"6"; + transmit_next_state <= CLOSE; + + when CLOSE => + state <= x"7"; + transmit_next_state <= WAIT_FOR_TRANS; + + when WAIT_FOR_TRANS => + state <= x"8"; + if (FC_READY_IN = '1') then + if (go_to_divide = '1') then + transmit_next_state <= DIVIDE; + else + transmit_next_state <= CLEANUP; + end if; + else + transmit_next_state <= WAIT_FOR_TRANS; + end if; + + when DIVIDE => + state <= x"9"; + transmit_next_state <= PREPARE_HEADERS; + + when CLEANUP => + state <= x"a"; + transmit_next_state <= IDLE; + + end case; +end process TRANSMIT_MACHINE; + +tc_rd <= '1' when transmit_current_state = TRANSMIT else '0'; + +TC_RD_EN_OUT <= tc_rd; + +SYNC_PROC : process( CLK ) +begin + if( rising_edge(CLK) ) then + tc_rd_q <= tc_rd; + tc_rd_qq <= tc_rd_q; + FC_WR_EN_OUT <= tc_rd_qq; + end if; +end process SYNC_PROC; + +ACTUAL_FRAME_BYTES_PROC : process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( transmit_current_state = IDLE or transmit_current_state = DIVIDE ) then + actual_frame_bytes <= (others => '0'); + elsif( transmit_current_state = TRANSMIT ) then + actual_frame_bytes <= actual_frame_bytes + x"1"; + end if; + end if; +end process ACTUAL_FRAME_BYTES_PROC; + +GO_TO_DIVIDE_PROC : process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( transmit_current_state = IDLE or transmit_current_state = DIVIDE ) then + go_to_divide <= '0'; + elsif( transmit_current_state = TRANSMIT and actual_frame_bytes = TC_MAX_FRAME_IN - x"1" ) then + go_to_divide <= '1'; + elsif( transmit_current_state = SEND_ONE and full_packet_size = packet_loaded_bytes ) then + go_to_divide <= '0'; + end if; + end if; +end process GO_TO_DIVIDE_PROC; + +LOCAL_END_PROC : process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( transmit_current_state = IDLE and TC_DATAREADY_IN = '1' ) then + local_end <= TC_FRAME_SIZE_IN - x"1"; + full_packet_size <= TC_FRAME_SIZE_IN; + elsif( transmit_current_state = TRANSMIT ) then + local_end <= local_end - x"1"; + full_packet_size <= full_packet_size; + end if; + end if; +end process LOCAL_END_PROC; + +FC_DATA_OUT <= TC_DATA_IN; +FC_SOD_OUT <= '1' when transmit_current_state = WAIT_FOR_H else '0'; +FC_EOD_OUT <= '1' when transmit_current_state = CLOSE else '0'; + +process( CLK ) +begin + if( rising_edge(CLK) ) then + if( transmit_current_state = PREPARE_HEADERS ) then + if( local_end >= TC_MAX_FRAME_IN ) then + ip_size <= TC_MAX_FRAME_IN; + else + ip_size <= local_end + x"1"; + end if; + else + ip_size <= ip_size; + end if; + end if; +end process; +FC_IP_SIZE_OUT <= ip_size; +FC_UDP_SIZE_OUT <= full_packet_size; + +FC_FLAGS_OFFSET_OUT(15 downto 14) <= "00"; +FC_FLAGS_OFFSET_OUT(13) <= more_fragments; + +MORE_FRAGMENTS_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( transmit_current_state = PREPARE_HEADERS ) then + if( local_end >= TC_MAX_FRAME_IN ) then + more_fragments <= '1'; + else + more_fragments <= '0'; + end if; + end if; + end if; +end process MORE_FRAGMENTS_PROC; + +FC_FLAGS_OFFSET_OUT(12 downto 0) <= ('0' & x"000") when first_frame = '1' else (packet_loaded_bytes(15 downto 3) + x"1"); + +PACKET_LOADED_BYTES_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( transmit_current_state = IDLE ) then + packet_loaded_bytes <= x"0000"; + elsif( transmit_current_state = TRANSMIT ) then + packet_loaded_bytes <= packet_loaded_bytes + x"1"; + end if; + end if; +end process PACKET_LOADED_BYTES_PROC; + +FIRST_FRAME_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( transmit_current_state = IDLE ) then + first_frame <= '1'; + elsif( transmit_current_state = DIVIDE ) then + first_frame <= '0'; + end if; + end if; +end process FIRST_FRAME_PROC; + + +TC_TRANSMISSION_DONE_OUT <= '1' when transmit_current_state = CLEANUP else '0'; + +FC_FRAME_TYPE_OUT <= TC_FRAME_TYPE_IN; +FC_IP_PROTOCOL_OUT <= TC_IP_PROTOCOL_IN; +DEST_MAC_ADDRESS_OUT <= TC_DEST_MAC_IN; +DEST_IP_ADDRESS_OUT <= TC_DEST_IP_IN; +DEST_UDP_PORT_OUT <= TC_DEST_UDP_IN; +SRC_MAC_ADDRESS_OUT <= TC_SRC_MAC_IN; +SRC_IP_ADDRESS_OUT <= TC_SRC_IP_IN; +SRC_UDP_PORT_OUT <= TC_SRC_UDP_IN; +FC_IDENT_OUT <= TC_IDENT_IN; + +-- monitoring + +process( CLK, RESET ) +begin + if ( RESET = '1' ) then + mon_packets_sent_ctr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( transmit_current_state = CLEANUP ) then + mon_packets_sent_ctr <= mon_packets_sent_ctr + x"1"; + end if; + end if; +end process; + +MONITOR_TX_PACKETS_OUT <= mon_packets_sent_ctr; + +DEBUG_OUT(3 downto 0) <= state; +DEBUG_OUT(4) <= FC_READY_IN; + +end gbe_transmit_control_arch; + + diff --git a/gbe_trb/base/gbe_type_validator.vhd b/gbe_trb/base/gbe_type_validator.vhd new file mode 100644 index 0000000..4da7ad7 --- /dev/null +++ b/gbe_trb/base/gbe_type_validator.vhd @@ -0,0 +1,130 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + +--******** +-- contains valid frame types codes and performs checking of type and vlan id +-- by default there is place for 32 frame type which is hardcoded value +-- due to allow register which is set by slow control + +entity gbe_type_validator is +port ( + CLK : in std_logic; -- 125MHz clock input + RESET : in std_logic; + -- ethernet level + FRAME_TYPE_IN : in std_logic_vector(15 downto 0); -- recovered frame type + SAVED_VLAN_ID_IN : in std_logic_vector(15 downto 0); -- recovered vlan id + ALLOWED_TYPES_IN : in std_logic_vector(31 downto 0); -- signal from gbe_setup + VLAN_ID_IN : in std_logic_vector(31 downto 0); -- two values from gbe setup + -- IP level + IP_PROTOCOLS_IN : in std_logic_vector(7 downto 0); + ALLOWED_IP_PROTOCOLS_IN : in std_logic_vector(31 downto 0); + -- UDP level + UDP_PROTOCOL_IN : in std_logic_vector(15 downto 0); + ALLOWED_UDP_PROTOCOLS_IN : in std_logic_vector(31 downto 0); + -- result + VALID_OUT : out std_logic +); +end gbe_type_validator; + +architecture gbe_type_validator_arch of gbe_type_validator is + +signal result : std_logic_vector(c_MAX_FRAME_TYPES - 1 downto 0); +signal ip_result : std_logic_vector(c_MAX_IP_PROTOCOLS - 1 downto 0); +signal udp_result : std_logic_vector(c_MAX_UDP_PROTOCOLS - 1 downto 0); +signal partially_valid : std_logic; -- only protocols, vlan to be checked +signal zeros : std_logic_vector(c_MAX_FRAME_TYPES - 1 downto 0); + +begin + + zeros <= (others => '0'); + +-- checks for allowed IP protocols (UDP, ICMP) +IP_RESULTS_GEN: for i in 0 to c_MAX_IP_PROTOCOLS - 1 generate +process( CLK ) +begin + if( rising_edge(CLK) ) then + if( (IP_PROTOCOLS(i) = IP_PROTOCOLS_IN) and (ALLOWED_IP_PROTOCOLS_IN(i) = '1') )then + ip_result(i) <= '1'; + else + ip_result(i) <= '0'; + end if; + end if; +end process; +end generate IP_RESULTS_GEN; + +-- checks for allowed UDP destination ports (DHCP, SCTRL) +UDP_RESULTS_GEN: for i in 0 to c_MAX_UDP_PROTOCOLS - 1 generate +process( CLK ) +begin + if( rising_edge(CLK) ) then + if( (UDP_PROTOCOLS(i) = UDP_PROTOCOL_IN) and (ALLOWED_UDP_PROTOCOLS_IN(i) = '1') ) then + udp_result(i) <= '1'; + else + udp_result(i) <= '0'; + end if; + end if; +end process; +end generate UDP_RESULTS_GEN; + +-- checks for allowed frame type (IPv4, ARP) +FRAME_RESULTS_GEN: for i in 0 to c_MAX_FRAME_TYPES - 1 generate +process( CLK ) +begin + if( rising_edge(CLK) ) then + if( (FRAME_TYPES(i) = FRAME_TYPE_IN) and (ALLOWED_TYPES_IN(i) = '1') ) then + result(i) <= '1'; + else + result(i) <= '0'; + end if; + end if; +end process; +end generate FRAME_RESULTS_GEN; + +PARTIALLY_VALID_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( RESET = '1' ) then + partially_valid <= '0'; + elsif( FRAME_TYPE_IN = x"0800" ) then -- ip frame + if ( IP_PROTOCOLS_IN = x"11" ) then -- in case of udp inside ip + partially_valid <= or_all(udp_result); + elsif( (IP_PROTOCOLS_IN = x"01") or (IP_PROTOCOLS_IN = x"dd") or (IP_PROTOCOLS_IN = x"ee") ) then -- in case of ICMP + partially_valid <= '1'; + else -- do not accept other protocols than udp and icmp inside ip + partially_valid <= '0'; + end if; + elsif( result /= zeros ) then-- other frame + partially_valid <= '1'; + else + partially_valid <= '0'; + end if; + end if; +end process PARTIALLY_VALID_PROC; + +VALID_OUT_PROC: process( CLK ) +begin + if rising_edge(CLK) then + if( partially_valid = '1' ) then + if ( SAVED_VLAN_ID_IN = x"0000" ) then + VALID_OUT <= '1'; + elsif( VLAN_ID_IN = x"0000_0000" ) then + VALID_OUT <= '0'; + elsif( (SAVED_VLAN_ID_IN = VLAN_ID_IN(15 downto 0)) or (SAVED_VLAN_ID_IN = VLAN_ID_IN(31 downto 16)) ) then + VALID_OUT <= '1'; + else + VALID_OUT <= '0'; + end if; + else + VALID_OUT <= '0'; + end if; + end if; +end process VALID_OUT_PROC; + +end gbe_type_validator_arch; diff --git a/gbe_trb/base/gbe_wrapper_fifo.vhd b/gbe_trb/base/gbe_wrapper_fifo.vhd index 067febd..8083748 100644 --- a/gbe_trb/base/gbe_wrapper_fifo.vhd +++ b/gbe_trb/base/gbe_wrapper_fifo.vhd @@ -1,14 +1,9 @@ -library IEEE; -use IEEE.std_logic_1164.all; -use IEEE.std_logic_ARITH.all; -use IEEE.std_logic_UNSIGNED.all; +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; library work; -use work.trb_net_std.all; -use work.trb_net_components.all; - ---use work.trb_net_gbe_components.all; -use work.gbe_protocols.all; + use work.gbe_protocols.all; entity gbe_wrapper_fifo is generic( @@ -76,7 +71,7 @@ entity gbe_wrapper_fifo is ); end entity gbe_wrapper_fifo; -architecture RTL of gbe_wrapper_fifo is +architecture gbe_wrapper_fifo_arch of gbe_wrapper_fifo is signal mac : std_logic_vector(47 downto 0); @@ -125,7 +120,7 @@ begin ------------------------------------------------------------------------------------------------- -- HACK: replace the borken internal FIFO by a ring buffer - THE_FRAME_TX: entity rx_rb + THE_FRAME_TX: entity work.gbe_rx_rb port map( CLK => CLK_125_IN, RESET => RESET, @@ -146,20 +141,19 @@ begin ); ------------------------------------------------------------------------------------------------- - -- debug(127 downto 64) are local - -- debug(63 downto 0) are media interface +-- debug(127 downto 64) are local +-- debug(63 downto 0) are media interface -- DEBUG_OUT <= monitor_gen_dbg(95 downto 64); mac <= MC_UNIQUE_ID_IN(15 downto 8) & MC_UNIQUE_ID_IN(23 downto 16) & MC_UNIQUE_ID_IN(31 downto 24) & x"0" & MC_UNIQUE_ID_IN(35 downto 32) & x"7ada"; - MAKE_RESET_OUT <= '1' when make_reset = '1' else '0'; - - ISSUE_REBOOT_OUT <= '0' when issue_reboot = '0' else '1'; + MAKE_RESET_OUT <= '1' when make_reset = '1' else '0'; + ISSUE_REBOOT_OUT <= '1' when issue_reboot = '1' else '0'; - STATUS_OUT(7 downto 1) <= (others => '0'); - STATUS_OUT(0) <= dhcp_done; -- DHCP has completed - - gbe_inst : entity work.gbe_logic_wrapper + STATUS_OUT(7 downto 1) <= (others => '0'); + STATUS_OUT(0) <= dhcp_done; + + THE_GBE_LOGIC_WRAPPER : entity work.gbe_logic_wrapper generic map( INCLUDE_SLOWCTRL => LINK_HAS_SLOWCTRL, INCLUDE_DHCP => LINK_HAS_DHCP, @@ -231,10 +225,7 @@ begin DEBUG_OUT => DEBUG_OUT --open ); - -- sum_rx_* ??? - -- sum_tx_* ??? - - NOSCTRL_MAP_GEN : if (LINK_HAS_SLOWCTRL = '0') generate + NOSCTRL_MAP_GEN : if( LINK_HAS_SLOWCTRL = '0' ) generate mlt_gsc_clk <= '0'; GSC_INIT_DATAREADY_OUT <= '0'; GSC_INIT_DATA_OUT <= (others => '0'); @@ -247,7 +238,7 @@ begin mlt_gsc_busy <= '0'; end generate NOSCTRL_MAP_GEN; - SCTRL_MAP_GEN : if (LINK_HAS_SLOWCTRL = '1') generate + SCTRL_MAP_GEN : if( LINK_HAS_SLOWCTRL = '1' ) generate mlt_gsc_clk <= GSC_CLK_IN; GSC_INIT_DATAREADY_OUT <= mlt_gsc_init_dataready; GSC_INIT_DATA_OUT <= mlt_gsc_init_data; @@ -260,4 +251,4 @@ begin mlt_gsc_busy <= GSC_BUSY_IN; end generate SCTRL_MAP_GEN; -end architecture RTL; +end architecture gbe_wrapper_fifo_arch; diff --git a/gbe_trb/base/ip_configurator.vhd b/gbe_trb/base/ip_configurator.vhd old mode 100755 new mode 100644 diff --git a/gbe_trb/base/sgl_ctrl.vhd b/gbe_trb/base/sgl_ctrl.vhd index 06ef0af..d9c424b 100644 --- a/gbe_trb/base/sgl_ctrl.vhd +++ b/gbe_trb/base/sgl_ctrl.vhd @@ -1,10 +1,10 @@ library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; library work; -entity sgl_ctrl is +entity gbe_sgl_ctrl is port( CLK : in std_logic; RESET : in std_logic; @@ -32,9 +32,9 @@ entity sgl_ctrl is -- DEBUG : out std_logic_vector(15 downto 0) ); -end entity sgl_ctrl; +end entity gbe_sgl_ctrl; -architecture sgl_ctrl_arch of sgl_ctrl is +architecture gbe_sgl_ctrl_arch of gbe_sgl_ctrl is -- Components @@ -187,6 +187,7 @@ begin end process THE_NEXT_PORT_PROC; ----------------------------------------------------------- + -- Outputs ----------------------------------------------------------- UL_FRAME_REQ_OUT <= ul_frame_req; LOCAL_FRAME_REQ_OUT <= local_frame_req; @@ -347,4 +348,4 @@ begin end case; end process THE_STATE_TRANSITIONS; -end architecture; +end architecture gbe_sgl_ctrl_arch; diff --git a/gbe_trb/base/trb_net16_gbe_frame_constr.vhd b/gbe_trb/base/trb_net16_gbe_frame_constr.vhd old mode 100755 new mode 100644 diff --git a/gbe_trb/base/trb_net16_gbe_frame_trans.vhd b/gbe_trb/base/trb_net16_gbe_frame_trans.vhd old mode 100755 new mode 100644 diff --git a/gbe_trb/protocols/gbe_response_constructor_ARP.vhd b/gbe_trb/protocols/gbe_response_constructor_ARP.vhd new file mode 100644 index 0000000..eec56dc --- /dev/null +++ b/gbe_trb/protocols/gbe_response_constructor_ARP.vhd @@ -0,0 +1,262 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + +entity gbe_response_constructor_ARP is +port ( + CLK : in std_logic; -- system clock + RESET : in std_logic; +-- INTERFACE + MY_MAC_IN : in std_logic_vector(47 downto 0); + MY_IP_IN : in std_logic_vector(31 downto 0); + PS_DATA_IN : in std_logic_vector(8 downto 0); + PS_WR_EN_IN : in std_logic; + PS_ACTIVATE_IN : in std_logic; + PS_RESPONSE_READY_OUT : out std_logic; + PS_BUSY_OUT : out std_logic; + PS_SELECTED_IN : in std_logic; + PS_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + PS_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); +-- + TC_RD_EN_IN : in std_logic; + TC_DATA_OUT : out std_logic_vector(8 downto 0); + TC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + TC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + TC_IDENT_OUT : out std_logic_vector(15 downto 0); + TC_DEST_MAC_OUT : out std_logic_vector(47 downto 0); + TC_DEST_IP_OUT : out std_logic_vector(31 downto 0); + TC_DEST_UDP_OUT : out std_logic_vector(15 downto 0); + TC_SRC_MAC_OUT : out std_logic_vector(47 downto 0); + TC_SRC_IP_OUT : out std_logic_vector(31 downto 0); + TC_SRC_UDP_OUT : out std_logic_vector(15 downto 0); +-- END OF INTERFACE +-- debug + DEBUG_OUT : out std_logic_vector(63 downto 0) +); +end gbe_response_constructor_ARP; + +architecture gbe_response_constructor_ARP_arch of gbe_response_constructor_ARP is + +attribute syn_encoding : string; + +type dissect_states is (IDLE, READ_FRAME, DECIDE, LOAD_FRAME, WAIT_FOR_LOAD, CLEANUP); +signal dissect_current_state, dissect_next_state : dissect_states; +attribute syn_encoding of dissect_current_state: signal is "onehot"; + +type stats_states is (IDLE, LOAD_SENT, LOAD_RECEIVED, CLEANUP); +signal stats_current_state, stats_next_state : stats_states; +attribute syn_encoding of stats_current_state : signal is "onehot"; + +signal saved_opcode : std_logic_vector(15 downto 0); +signal saved_sender_ip : std_logic_vector(31 downto 0); +signal saved_target_ip : std_logic_vector(31 downto 0); +signal data_ctr : integer range 0 to 30; +signal values : std_logic_vector(223 downto 0); +signal tc_data : std_logic_vector(8 downto 0); + +signal state : std_logic_vector(3 downto 0); +signal rec_frames : std_logic_vector(15 downto 0); +signal sent_frames : std_logic_vector(15 downto 0); +signal stat_data_temp : std_logic_vector(31 downto 0); + +signal tc_wr : std_logic; + +attribute syn_preserve : boolean; +attribute syn_keep : boolean; +attribute syn_keep of state : signal is true; +attribute syn_preserve of state : signal is true; + +begin + +values(15 downto 0) <= x"0100"; -- hardware type +values(31 downto 16) <= x"0008"; -- protocol type +values(39 downto 32) <= x"06"; -- hardware size +values(47 downto 40) <= x"04"; -- protocol size +values(63 downto 48) <= x"0200"; --opcode (reply) +values(111 downto 64) <= MY_MAC_IN; -- sender (my) mac +values(143 downto 112) <= MY_IP_IN; +values(191 downto 144) <= PS_SRC_MAC_ADDRESS_IN; -- target mac +values(223 downto 192) <= saved_sender_ip; -- target ip + +DISSECT_MACHINE_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + dissect_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + dissect_current_state <= dissect_next_state; + end if; +end process DISSECT_MACHINE_PROC; + +DISSECT_MACHINE : process(dissect_current_state, MY_IP_IN, PS_WR_EN_IN, PS_ACTIVATE_IN, PS_DATA_IN, data_ctr, PS_SELECTED_IN, saved_target_ip) +begin + case dissect_current_state is + + when IDLE => + state <= x"1"; + if (PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1') then + dissect_next_state <= READ_FRAME; + else + dissect_next_state <= IDLE; + end if; + + when READ_FRAME => + state <= x"2"; + if (PS_DATA_IN(8) = '1') then + dissect_next_state <= DECIDE; + else + dissect_next_state <= READ_FRAME; + end if; + + when DECIDE => + state <= x"3"; + if (saved_target_ip = MY_IP_IN) then + dissect_next_state <= WAIT_FOR_LOAD; + -- in case the request is not for me, drop it + else + dissect_next_state <= IDLE; + end if; + + when WAIT_FOR_LOAD => + state <= x"4"; + if (PS_SELECTED_IN = '1') then + dissect_next_state <= LOAD_FRAME; + else + dissect_next_state <= WAIT_FOR_LOAD; + end if; + + when LOAD_FRAME => + state <= x"5"; + if (data_ctr = 28) then + dissect_next_state <= CLEANUP; + else + dissect_next_state <= LOAD_FRAME; + end if; + + when CLEANUP => + state <= x"e"; + dissect_next_state <= IDLE; + + end case; +end process DISSECT_MACHINE; + +DATA_CTR_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + data_ctr <= 1; + elsif( rising_edge(CLK) ) then + if ( (dissect_current_state = IDLE) and (PS_WR_EN_IN = '0') ) then + data_ctr <= 1; + elsif( dissect_current_state = WAIT_FOR_LOAD ) then + data_ctr <= 1; + elsif( dissect_current_state = IDLE and PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' ) then + data_ctr <= data_ctr + 1; + elsif( dissect_current_state = READ_FRAME and PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' ) then -- in case of saving data from incoming frame + data_ctr <= data_ctr + 1; + elsif( dissect_current_state = LOAD_FRAME and PS_SELECTED_IN = '1' and TC_RD_EN_IN = '1' ) then -- in case of constructing response + data_ctr <= data_ctr + 1; + end if; + end if; +end process DATA_CTR_PROC; + +SAVE_VALUES_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + saved_opcode <= (others => '0'); + saved_sender_ip <= (others => '0'); + saved_target_ip <= (others => '0'); + elsif( rising_edge(CLK) ) then + if (dissect_current_state = READ_FRAME) then + case (data_ctr) is + + when 6 => + saved_opcode(7 downto 0) <= PS_DATA_IN(7 downto 0); + when 7 => + saved_opcode(15 downto 8) <= PS_DATA_IN(7 downto 0); + when 13 => + saved_sender_ip(7 downto 0) <= PS_DATA_IN(7 downto 0); + when 14 => + saved_sender_ip(15 downto 8) <= PS_DATA_IN(7 downto 0); + when 15 => + saved_sender_ip(23 downto 16) <= PS_DATA_IN(7 downto 0); + when 16 => + saved_sender_ip(31 downto 24) <= PS_DATA_IN(7 downto 0); + when 23 => + saved_target_ip(7 downto 0) <= PS_DATA_IN(7 downto 0); + when 24 => + saved_target_ip(15 downto 8) <= PS_DATA_IN(7 downto 0); + when 25 => + saved_target_ip(23 downto 16) <= PS_DATA_IN(7 downto 0); + when 26 => + saved_target_ip(31 downto 24) <= PS_DATA_IN(7 downto 0); + + when others => null; + end case; + end if; + end if; +end process SAVE_VALUES_PROC; + +TC_DATA_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + tc_data(8) <= '0'; + + if (dissect_current_state = LOAD_FRAME) then + for i in 0 to 7 loop + tc_data(i) <= values((data_ctr - 1) * 8 + i); + end loop; + -- mark the last byte + if (data_ctr = 28) then + tc_data(8) <= '1'; + end if; + else + tc_data(7 downto 0) <= (others => '0'); + end if; + + TC_DATA_OUT <= tc_data; + + end if; +end process TC_DATA_PROC; + +PS_RESPONSE_SYNC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( dissect_current_state = WAIT_FOR_LOAD or dissect_current_state = LOAD_FRAME or dissect_current_state = CLEANUP ) then + PS_RESPONSE_READY_OUT <= '1'; + else + PS_RESPONSE_READY_OUT <= '0'; + end if; + + if( dissect_current_state = IDLE ) then + PS_BUSY_OUT <= '0'; + else + PS_BUSY_OUT <= '1'; + end if; + end if; +end process PS_RESPONSE_SYNC; + +TC_FRAME_SIZE_OUT <= x"001c"; -- fixed frame size + +TC_FRAME_TYPE_OUT <= x"0608"; +TC_DEST_MAC_OUT <= PS_SRC_MAC_ADDRESS_IN; +TC_DEST_IP_OUT <= x"00000000"; -- doesnt matter +TC_DEST_UDP_OUT <= x"0000"; -- doesnt matter +TC_SRC_MAC_OUT <= MY_MAC_IN; +TC_SRC_IP_OUT <= x"00000000"; -- doesnt matter +TC_SRC_UDP_OUT <= x"0000"; -- doesnt matter +TC_IP_PROTOCOL_OUT <= x"00"; -- doesnt matter +TC_IDENT_OUT <= (others => '0'); -- doesn't matter + +end gbe_response_constructor_ARP_arch; + + diff --git a/gbe_trb/protocols/gbe_response_constructor_DHCP.vhd b/gbe_trb/protocols/gbe_response_constructor_DHCP.vhd new file mode 100644 index 0000000..52c6df6 --- /dev/null +++ b/gbe_trb/protocols/gbe_response_constructor_DHCP.vhd @@ -0,0 +1,699 @@ +LIBRARY IEEE; + +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.trb_net_gbe_protocols.all; + +entity gbe_response_constructor_DHCP is +port( + CLK : in std_logic; -- system clock + RESET : in std_logic; +-- INTERFACE + MY_MAC_IN : in std_logic_vector(47 downto 0); + MY_IP_IN : in std_logic_vector(31 downto 0); + PS_DATA_IN : in std_logic_vector(8 downto 0); + PS_WR_EN_IN : in std_logic; + PS_ACTIVATE_IN : in std_logic; + PS_RESPONSE_READY_OUT : out std_logic; + PS_BUSY_OUT : out std_logic; + PS_SELECTED_IN : in std_logic; + PS_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + PS_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); +-- + TC_RD_EN_IN : in std_logic; + TC_DATA_OUT : out std_logic_vector(8 downto 0); + TC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + TC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + TC_IDENT_OUT : out std_logic_vector(15 downto 0); + TC_DEST_MAC_OUT : out std_logic_vector(47 downto 0); + TC_DEST_IP_OUT : out std_logic_vector(31 downto 0); + TC_DEST_UDP_OUT : out std_logic_vector(15 downto 0); + TC_SRC_MAC_OUT : out std_logic_vector(47 downto 0); + TC_SRC_IP_OUT : out std_logic_vector(31 downto 0); + TC_SRC_UDP_OUT : out std_logic_vector(15 downto 0); +-- END OF INTERFACE + MY_IP_OUT : out std_logic_vector(31 downto 0); + DHCP_START_IN : in std_logic; + DHCP_DONE_OUT : out std_logic; +-- debug + DEBUG_OUT : out std_logic_vector(63 downto 0) +); +end gbe_response_constructor_DHCP; + + +architecture gbe_response_constructor_DHCP_arch of gbe_response_constructor_DHCP is + +attribute syn_encoding : string; + +type main_states is (BOOTING, DELAY, SENDING_DISCOVER, WAITING_FOR_OFFER, SENDING_REQUEST, WAITING_FOR_ACK, ESTABLISHED); +signal main_current_state, main_next_state : main_states; +attribute syn_encoding of main_current_state: signal is "onehot"; + +type receive_states is (IDLE, DISCARD, CLEANUP, SAVE_VALUES); +signal receive_current_state, receive_next_state : receive_states; +attribute syn_encoding of receive_current_state: signal is "onehot"; + +type discover_states is (IDLE, WAIT_FOR_LOAD, BOOTP_HEADERS, CLIENT_IP, YOUR_IP, ZEROS1, MY_MAC, ZEROS2, VENDOR_VALS, VENDOR_VALS2, TERMINATION, CLEANUP); +signal construct_current_state, construct_next_state : discover_states; +attribute syn_encoding of construct_current_state: signal is "onehot"; + +type stats_states is (IDLE, LOAD_SENT, LOAD_RECEIVED, LOAD_DISCARDED, CLEANUP); +signal stats_current_state, stats_next_state : stats_states; +attribute syn_encoding of stats_current_state : signal is "onehot"; + +signal state : std_logic_vector(3 downto 0); +signal rec_frames : std_logic_vector(15 downto 0); +signal sent_frames : std_logic_vector(15 downto 0); + +signal wait_ctr : std_logic_vector(31 downto 0); -- wait for 5 sec before sending request +signal load_ctr : integer range 0 to 600 := 0; + +signal bootp_hdr : std_logic_vector(95 downto 0); + +signal tc_data : std_logic_vector(8 downto 0); +signal vendor_values : std_logic_vector(175 downto 0); +signal save_ctr : integer range 0 to 600 := 0; +signal saved_transaction_id : std_logic_vector(31 downto 0); +signal saved_proposed_ip : std_logic_vector(31 downto 0); +signal saved_dhcp_type : std_logic_vector(23 downto 0); +signal saved_true_ip : std_logic_vector(31 downto 0); +signal transaction_id : std_logic_vector(31 downto 0); +signal client_ip_reg : std_logic_vector(31 downto 0); +signal your_ip_reg : std_logic_vector(31 downto 0); +signal saved_server_mac : std_logic_vector(47 downto 0); +signal saved_server_ip : std_logic_vector(31 downto 0); +signal state2 : std_logic_vector(3 downto 0); +signal state3 : std_logic_vector(3 downto 0); +signal vendor_values2 : std_logic_vector(47 downto 0); + +signal discarded_ctr : std_logic_vector(15 downto 0); + +signal stat_data_temp : std_logic_vector(31 downto 0); + +attribute syn_preserve : boolean; +attribute syn_keep : boolean; +attribute syn_keep of state, state2 : signal is true; +attribute syn_preserve of state, state2 : signal is true; + +signal wait_value : std_logic_vector(31 downto 0); + +signal my_ip : std_logic_vector(31 downto 0); + +begin + +-- **** +-- fixing the constant values for DHCP request headers +TC_DEST_MAC_OUT <= x"ffffffffffff" when (main_current_state = BOOTING or main_current_state = SENDING_DISCOVER) else saved_server_mac; +TC_DEST_IP_OUT <= x"ffffffff" when (main_current_state = BOOTING or main_current_state = SENDING_DISCOVER) else saved_server_ip; +TC_DEST_UDP_OUT <= x"4300"; +TC_SRC_MAC_OUT <= MY_MAC_IN; +TC_SRC_IP_OUT <= x"00000000" when (main_current_state = BOOTING or main_current_state = SENDING_DISCOVER) else saved_proposed_ip; +TC_SRC_UDP_OUT <= x"4400"; +TC_IP_PROTOCOL_OUT <= x"11"; -- udp +bootp_hdr(7 downto 0) <= x"01"; -- message type(request) +bootp_hdr(15 downto 8) <= x"01"; -- hardware type (eth) +bootp_hdr(23 downto 16) <= x"06"; -- hardware address length +bootp_hdr(31 downto 24) <= x"00"; -- hops +bootp_hdr(63 downto 32) <= transaction_id; -- transaction id; +bootp_hdr(95 downto 64) <= x"0000_0000"; -- seconds elapsed/flags +transaction_id <= x"cefa" & MY_MAC_IN(47 downto 40) & MY_MAC_IN(23 downto 16); +vendor_values(31 downto 0) <= x"63538263"; -- magic cookie (dhcp message) +vendor_values(55 downto 32) <= x"010135" when (main_current_state = BOOTING or main_current_state = SENDING_DISCOVER) else x"030135"; -- dhcp discover, then dhcp request +vendor_values(79 downto 56) <= x"01073d"; -- client identifier +vendor_values(127 downto 80) <= MY_MAC_IN; -- client identifier +vendor_values(143 downto 128) <= x"040c"; -- client name +--vendor_values(175 downto 144) <= x"33425254"; -- client name (TRB3) +vendor_values(175 downto 144) <= x"6f72694b"; -- client name (Kiro) +vendor_values2(15 downto 0) <= x"0436"; -- server identifier +vendor_values2(47 downto 16) <= saved_server_ip; + +--***************** +-- setting of global variable for IP address +my_ip <= saved_true_ip when main_current_state = ESTABLISHED else (others => '0'); +MY_IP_OUT <= my_ip; +-- +--***************** + +SAVE_SERVER_ADDR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( main_current_state = BOOTING ) then + saved_server_mac <= (others => '0'); + saved_server_ip <= (others => '0'); + elsif( (main_current_state = WAITING_FOR_OFFER) and (receive_current_state = SAVE_VALUES and save_ctr = 1) ) then + saved_server_mac <= PS_SRC_MAC_ADDRESS_IN; + saved_server_ip <= PS_SRC_IP_ADDRESS_IN; + end if; + end if; +end process SAVE_SERVER_ADDR_PROC; + + +-- **** MAIN MACHINE PART + +MAIN_MACHINE_PROC: process( CLK, RESET) +begin + if ( RESET = '1' ) then + main_current_state <= BOOTING; + elsif( rising_edge(CLK) ) then + main_current_state <= main_next_state; + end if; +end process MAIN_MACHINE_PROC; + +wait_value <= x"2000_0000"; + +MAIN_MACHINE : process(main_current_state, DHCP_START_IN, construct_current_state, wait_ctr, receive_current_state, PS_DATA_IN, wait_value) +begin + state2 <= x"0"; + + case (main_current_state) is + + when BOOTING => + state2 <= x"1"; + if (DHCP_START_IN = '1') then + main_next_state <= DELAY; + else + main_next_state <= BOOTING; + end if; + + when DELAY => + state2 <= x"2"; + if (wait_ctr = wait_value) then + main_next_state <= SENDING_DISCOVER; + else + main_next_state <= DELAY; + end if; + + when SENDING_DISCOVER => + state2 <= x"3"; + if (construct_current_state = CLEANUP) then + main_next_state <= WAITING_FOR_OFFER; + else + main_next_state <= SENDING_DISCOVER; + end if; + + when WAITING_FOR_OFFER => + state2 <= x"4"; + if (receive_current_state = SAVE_VALUES) and (PS_DATA_IN(8) = '1') then + main_next_state <= SENDING_REQUEST; + elsif (wait_ctr = x"2000_0000") then + main_next_state <= BOOTING; + else + main_next_state <= WAITING_FOR_OFFER; + end if; + + when SENDING_REQUEST => + state2 <= x"5"; + if (construct_current_state = CLEANUP) then + main_next_state <= WAITING_FOR_ACK; + else + main_next_state <= SENDING_REQUEST; + end if; + + when WAITING_FOR_ACK => + state2 <= x"6"; + if (receive_current_state = SAVE_VALUES) and (PS_DATA_IN(8) = '1') then + main_next_state <= ESTABLISHED; + elsif (wait_ctr = x"2000_0000") then + main_next_state <= BOOTING; + else + main_next_state <= WAITING_FOR_ACK; + end if; + + when ESTABLISHED => + state2 <= x"7"; + main_next_state <= ESTABLISHED; + + when others => main_next_state <= BOOTING; + + end case; + +end process MAIN_MACHINE; + +WAIT_CTR_PROC : process(CLK) +begin + if rising_edge(CLK) then + if (main_current_state = SENDING_DISCOVER or main_current_state = SENDING_REQUEST or main_current_state = BOOTING) then + wait_ctr <= (others => '0'); + elsif (main_current_state = WAITING_FOR_ACK and receive_current_state = SAVE_VALUES and PS_DATA_IN(8) = '1') then + wait_ctr <= (others => '0'); + elsif (main_current_state = WAITING_FOR_ACK or main_current_state = WAITING_FOR_OFFER or main_current_state = DELAY or main_current_state = ESTABLISHED) then + wait_ctr <= wait_ctr + x"1"; + else + wait_ctr <= wait_ctr; + end if; + end if; +end process WAIT_CTR_PROC; + +DHCP_DONE_OUT <= '1' when main_current_state = ESTABLISHED else '0'; + + +-- **** MESSAGES RECEIVING PART + +RECEIVE_MACHINE_PROC : process(RESET, CLK) +begin + if RESET = '1' then + receive_current_state <= IDLE; + elsif rising_edge(CLK) then + receive_current_state <= receive_next_state; + end if; +end process RECEIVE_MACHINE_PROC; + +RECEIVE_MACHINE : process(receive_current_state, main_current_state, bootp_hdr, saved_dhcp_type, saved_transaction_id, PS_DATA_IN, PS_DEST_MAC_ADDRESS_IN, MY_MAC_IN, PS_ACTIVATE_IN, PS_WR_EN_IN, save_ctr) +begin + state3 <= x"0"; + + case receive_current_state is + + when IDLE => + state3 <= x"1"; + if (PS_ACTIVATE_IN = '1' and PS_WR_EN_IN = '1') then + if (main_current_state = WAITING_FOR_OFFER or main_current_state = WAITING_FOR_ACK) then -- ready to receive dhcp frame + if (PS_DEST_MAC_ADDRESS_IN = MY_MAC_IN) then -- check if i'm the addressee (discards broadcasts also) + receive_next_state <= SAVE_VALUES; + else + receive_next_state <= DISCARD; -- discard if the frame is not for me + end if; + else + receive_next_state <= DISCARD; -- discard if the frame arrived at wrong time + end if; + else + receive_next_state <= IDLE; + end if; + + when SAVE_VALUES => + state3 <= x"2"; + if (PS_DATA_IN(8) = '1') then + receive_next_state <= CLEANUP; + -- check if the same transaction + elsif (save_ctr = 9) and (saved_transaction_id /= bootp_hdr(63 downto 32)) then + receive_next_state <= DISCARD; + -- if the wrong message at the wrong time + elsif (main_current_state = WAITING_FOR_OFFER) and (save_ctr = 242) and (saved_dhcp_type /= x"020135") then + receive_next_state <= DISCARD; + -- if the wrong message at the wrong time + elsif (main_current_state = WAITING_FOR_ACK) and (save_ctr = 242) and (saved_dhcp_type /= x"050135") then + receive_next_state <= DISCARD; + else + receive_next_state <= SAVE_VALUES; + end if; + + when DISCARD => + state3 <= x"3"; + if (PS_DATA_IN(8) = '1') then + receive_next_state <= CLEANUP; + else + receive_next_state <= DISCARD; + end if; + + when CLEANUP => + state3 <= x"4"; + receive_next_state <= IDLE; + + when others => receive_next_state <= IDLE; + + end case; + +end process RECEIVE_MACHINE; + +SAVE_CTR_PROC : process(CLK) +begin + if rising_edge(CLK) then + if (receive_current_state = IDLE) then + save_ctr <= 0; + elsif (receive_current_state = SAVE_VALUES and PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1') then + save_ctr <= save_ctr + 1; + else + save_ctr <= save_ctr; + end if; + end if; +end process SAVE_CTR_PROC; + +SAVE_VALUES_PROC : process(CLK) +begin + if rising_edge(CLK) then + if (main_current_state = BOOTING) then + saved_transaction_id <= (others => '0'); + saved_proposed_ip <= (others => '0'); + saved_true_ip <= (others => '0'); + saved_dhcp_type <= (others => '0'); + -- dissection of DHCP Offer message + elsif (main_current_state = WAITING_FOR_OFFER and receive_current_state = SAVE_VALUES) then + + saved_true_ip <= saved_true_ip; + + case save_ctr is + + when 3 => + saved_transaction_id(7 downto 0) <= PS_DATA_IN(7 downto 0); + + when 4 => + saved_transaction_id(15 downto 8) <= PS_DATA_IN(7 downto 0); + + when 5 => + saved_transaction_id(23 downto 16) <= PS_DATA_IN(7 downto 0); + + when 6 => + saved_transaction_id(31 downto 24) <= PS_DATA_IN(7 downto 0); + + + when 15 => + saved_proposed_ip(7 downto 0) <= PS_DATA_IN(7 downto 0); + + when 16 => + saved_proposed_ip(15 downto 8) <= PS_DATA_IN(7 downto 0); + + when 17 => + saved_proposed_ip(23 downto 16) <= PS_DATA_IN(7 downto 0); + + when 18 => + saved_proposed_ip(31 downto 24) <= PS_DATA_IN(7 downto 0); + + + when 239 => + saved_dhcp_type(7 downto 0) <= PS_DATA_IN(7 downto 0); + + when 240 => + saved_dhcp_type(15 downto 8) <= PS_DATA_IN(7 downto 0); + + when 241 => + saved_dhcp_type(23 downto 16) <= PS_DATA_IN(7 downto 0); + + when others => null; + + end case; + -- dissection on DHCP Ack message + elsif (main_current_state = WAITING_FOR_ACK and receive_current_state = SAVE_VALUES) then + + saved_proposed_ip <= saved_proposed_ip; + + case save_ctr is + + when 3 => + saved_transaction_id(7 downto 0) <= PS_DATA_IN(7 downto 0); + + when 4 => + saved_transaction_id(15 downto 8) <= PS_DATA_IN(7 downto 0); + + when 5 => + saved_transaction_id(23 downto 16) <= PS_DATA_IN(7 downto 0); + + when 6 => + saved_transaction_id(31 downto 24) <= PS_DATA_IN(7 downto 0); + + + when 15 => + saved_true_ip(7 downto 0) <= PS_DATA_IN(7 downto 0); + + when 16 => + saved_true_ip(15 downto 8) <= PS_DATA_IN(7 downto 0); + + when 17 => + saved_true_ip(23 downto 16) <= PS_DATA_IN(7 downto 0); + + when 18 => + saved_true_ip(31 downto 24) <= PS_DATA_IN(7 downto 0); + + + when 239 => + saved_dhcp_type(7 downto 0) <= PS_DATA_IN(7 downto 0); + + when 240 => + saved_dhcp_type(15 downto 8) <= PS_DATA_IN(7 downto 0); + + when 241 => + saved_dhcp_type(23 downto 16) <= PS_DATA_IN(7 downto 0); + + when others => null; + + end case; + else + saved_transaction_id <= saved_transaction_id; + saved_proposed_ip <= saved_proposed_ip; + saved_true_ip <= saved_true_ip; + saved_dhcp_type <= saved_dhcp_type; + end if; + end if; +end process SAVE_VALUES_PROC; + + +-- **** MESSAGES CONSTRUCTING PART + +CONSTRUCT_MACHINE_PROC : process(RESET, CLK) +begin + if RESET = '1' then + construct_current_state <= IDLE; + elsif rising_edge(CLK) then + if (main_current_state = BOOTING) then + construct_current_state <= IDLE; + else + construct_current_state <= construct_next_state; + end if; + end if; +end process CONSTRUCT_MACHINE_PROC; + +CONSTRUCT_MACHINE : process(construct_current_state, main_current_state, load_ctr, PS_SELECTED_IN) +begin + state <= x"0"; + + case construct_current_state is + + when IDLE => + state <= x"1"; + if (main_current_state = SENDING_DISCOVER) or (main_current_state = SENDING_REQUEST) then + construct_next_state <= WAIT_FOR_LOAD; + else + construct_next_state <= IDLE; + end if; + + when WAIT_FOR_LOAD => + state <= x"2"; + if (PS_SELECTED_IN = '1') then + construct_next_state <= BOOTP_HEADERS; + else + construct_next_state <= WAIT_FOR_LOAD; + end if; + + + when BOOTP_HEADERS => + state <= x"3"; + if (load_ctr = 11) then + construct_next_state <= CLIENT_IP; + else + construct_next_state <= BOOTP_HEADERS; + end if; + + when CLIENT_IP => + state <= x"4"; + if (load_ctr = 15) then + construct_next_state <= YOUR_IP; + else + construct_next_state <= CLIENT_IP; + end if; + + when YOUR_IP => + state <= x"5"; + if (load_ctr = 19) then + construct_next_state <= ZEROS1; + else + construct_next_state <= YOUR_IP; + end if; + + when ZEROS1 => + state <= x"6"; + if (load_ctr = 27) then + construct_next_state <= MY_MAC; + else + construct_next_state <= ZEROS1; + end if; + + when MY_MAC => + state <= x"7"; + if (load_ctr = 33) then + construct_next_state <= ZEROS2; + else + construct_next_state <= MY_MAC; + end if; + + when ZEROS2 => + state <= x"8"; + if (load_ctr = 235) then + construct_next_state <= VENDOR_VALS; + else + construct_next_state <= ZEROS2; + end if; + + when VENDOR_VALS => + state <= x"9"; + if (load_ctr = 257) then + -- for discover it's enough of values + if (main_current_state = SENDING_DISCOVER) then + construct_next_state <= TERMINATION; + -- for request there is some more values needed + else + construct_next_state <= VENDOR_VALS2; + end if; + else + construct_next_state <= VENDOR_VALS; + end if; + + when VENDOR_VALS2 => + state <= x"a"; + if (load_ctr = 263) then + construct_next_state <= TERMINATION; + else + construct_next_state <= VENDOR_VALS2; + end if; + + when TERMINATION => + state <= x"b"; + construct_next_state <= CLEANUP; + + when CLEANUP => + state <= x"c"; + construct_next_state <= IDLE; + + when others => construct_next_state <= IDLE; + + end case; +end process CONSTRUCT_MACHINE; + +LOAD_CTR_PROC : process(CLK) +begin + if rising_edge(CLK) then + if (construct_current_state = IDLE) then + load_ctr <= 0; + elsif (TC_RD_EN_IN = '1') and (PS_SELECTED_IN = '1') then + load_ctr <= load_ctr + 1; + else + load_ctr <= load_ctr; + end if; + end if; +end process LOAD_CTR_PROC; + +TC_DATA_PROC : process(CLK) +begin + if rising_edge(CLK) then + case (construct_current_state) is + + when BOOTP_HEADERS => + for i in 0 to 7 loop + tc_data(i) <= bootp_hdr(load_ctr * 8 + i); + end loop; + tc_data(8) <= '0'; + + when CLIENT_IP => + if (main_current_state = SENDING_DISCOVER) then + tc_data(7 downto 0) <= x"00"; + elsif (main_current_state = SENDING_REQUEST) then + for i in 0 to 7 loop + tc_data(i) <= saved_proposed_ip((load_ctr - 12) * 8 + i); + end loop; + end if; + tc_data(8) <= '0'; + + when YOUR_IP => + tc_data(7 downto 0) <= x"00"; + tc_data(8) <= '0'; + + when ZEROS1 => + tc_data(7 downto 0) <= x"00"; + tc_data(8) <= '0'; + + when MY_MAC => + for i in 0 to 7 loop + tc_data(i) <= MY_MAC_IN((load_ctr - 28) * 8 + i); + end loop; + tc_data(8) <= '0'; + + when ZEROS2 => + tc_data(7 downto 0) <= x"00"; + tc_data(8) <= '0'; + + when VENDOR_VALS => + for i in 0 to 7 loop + tc_data(i) <= vendor_values((load_ctr - 236) * 8 + i); + end loop; + tc_data(8) <= '0'; + + -- needed only for DHCP Request message + when VENDOR_VALS2 => + for i in 0 to 7 loop + tc_data(i) <= vendor_values2((load_ctr - 258) * 8 + i); + end loop; + tc_data(8) <= '0'; + + when TERMINATION => + tc_data(7 downto 0) <= x"ff"; + tc_data(8) <= '1'; + + when others => + tc_data(7 downto 0) <= x"00"; + tc_data(8) <= '0'; + + end case; + + TC_DATA_OUT <= tc_data; + + end if; +end process; + +PS_RESPONSE_SYNC : process( CLK ) +begin + if rising_edge(CLK) then + if (construct_current_state = IDLE or construct_current_state = CLEANUP) then + PS_RESPONSE_READY_OUT <= '0'; + else + PS_RESPONSE_READY_OUT <= '1'; + end if; + + if (construct_current_state = IDLE) then + PS_BUSY_OUT <= '0'; + else + PS_BUSY_OUT <= '1'; + end if; + end if; +end process PS_RESPONSE_SYNC; + +-- fixed sizes for discover and request messages +TC_FRAME_SIZE_OUT <= x"0103" when (main_current_state = SENDING_DISCOVER) else x"0109"; + +TC_FRAME_TYPE_OUT <= x"0008"; -- frame type: ip + +TC_IDENT_OUT <= x"1" & sent_frames(11 downto 0); + +SENT_FRAMES_PROC : process( CLK ) +begin + if rising_edge(CLK) then + if (RESET = '1') then + sent_frames <= (others => '0'); + elsif (construct_current_state = CLEANUP) then + sent_frames <= sent_frames + x"1"; + end if; + end if; +end process SENT_FRAMES_PROC; + +-- **** debug +process( CLK ) +begin + if rising_edge(CLK) then + DEBUG_OUT(3 downto 0) <= state; + DEBUG_OUT(7 downto 4) <= state2; + DEBUG_OUT(11 downto 8) <= state3; + end if; +end process; + +-- **** + +end gbe_response_constructor_DHCP_arch; + + diff --git a/gbe_trb/protocols/gbe_response_constructor_Forward.vhd b/gbe_trb/protocols/gbe_response_constructor_Forward.vhd new file mode 100644 index 0000000..75cf84f --- /dev/null +++ b/gbe_trb/protocols/gbe_response_constructor_Forward.vhd @@ -0,0 +1,254 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; + +-- WARNING: data latency was wrong by one cycle (first byte not sent, last byte duplicated), and +-- size was calculated wrong (one off). Works now FOR ME. To be tested carefully! + +-- BUG: If a frame written triggers FIFOFULL, it must be discarded. Maximum frame payload is 4096bytes. + +entity gbe_response_constructor_Forward is + port ( + CLK : in std_logic; -- system clock + RESET : in std_logic; + -- INTERFACE + MY_MAC_IN : in std_logic_vector(47 downto 0); + MY_IP_IN : in std_logic_vector(31 downto 0); + PS_DATA_IN : in std_logic_vector(8 downto 0); + PS_WR_EN_IN : in std_logic; + PS_ACTIVATE_IN : in std_logic; + PS_RESPONSE_READY_OUT : out std_logic; + PS_BUSY_OUT : out std_logic; + PS_SELECTED_IN : in std_logic; + PS_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + PS_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); + -- + TC_RD_EN_IN : in std_logic; + TC_DATA_OUT : out std_logic_vector(8 downto 0); + TC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + TC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + TC_IDENT_OUT : out std_logic_vector(15 downto 0); + TC_DEST_MAC_OUT : out std_logic_vector(47 downto 0); + TC_DEST_IP_OUT : out std_logic_vector(31 downto 0); + TC_DEST_UDP_OUT : out std_logic_vector(15 downto 0); + TC_SRC_MAC_OUT : out std_logic_vector(47 downto 0); + TC_SRC_IP_OUT : out std_logic_vector(31 downto 0); + TC_SRC_UDP_OUT : out std_logic_vector(15 downto 0); + -- + RECEIVED_FRAMES_OUT : out std_logic_vector(15 downto 0); + SENT_FRAMES_OUT : out std_logic_vector(15 downto 0); + -- END OF INTERFACE + FWD_DST_MAC_IN : in std_logic_vector(47 downto 0); + FWD_DST_IP_IN : in std_logic_vector(31 downto 0); + FWD_DST_UDP_IN : in std_logic_vector(15 downto 0); + FWD_DATA_IN : in std_logic_vector(7 downto 0); + FWD_DATA_VALID_IN : in std_logic; + FWD_SOP_IN : in std_logic; + FWD_EOP_IN : in std_logic; + FWD_READY_OUT : out std_logic; + FWD_FULL_OUT : out std_logic; + -- debug + DEBUG_OUT : out std_logic_vector(31 downto 0) + ); +end gbe_response_constructor_Forward; + +architecture gbe_response_constructor_Forward_arch of gbe_response_constructor_Forward is + +attribute syn_encoding : string; + +type dissect_states is (IDLE, SAVE, WAIT_FOR_LOAD, LOAD, CLEANUP); +signal dissect_current_state, dissect_next_state : dissect_states; +attribute syn_encoding of dissect_current_state: signal is "safe,gray"; + +signal ff_wr_en : std_logic; +signal ff_rd_en : std_logic; +signal resp_bytes_ctr : std_logic_vector(15 downto 0); +signal ff_empty : std_logic; +signal ff_full : std_logic; +signal ff_q : std_logic_vector(8 downto 0); +signal ff_rd_lock : std_logic; + +signal state : std_logic_vector(3 downto 0); +signal rec_frames : std_logic_vector(15 downto 0); +signal sent_frames : std_logic_vector(15 downto 0); + +signal local_eop : std_logic; + +begin + +DISSECT_MACHINE_PROC: process( CLK, RESET ) +begin + if( RESET = '1' ) then + dissect_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + dissect_current_state <= dissect_next_state; + end if; +end process DISSECT_MACHINE_PROC; + +DISSECT_MACHINE: process(dissect_current_state, FWD_SOP_IN, FWD_EOP_IN, ff_q, ff_rd_lock, PS_SELECTED_IN) +begin + case dissect_current_state is + + when IDLE => + state <= x"1"; + if (FWD_SOP_IN = '1') then + dissect_next_state <= SAVE; + else + dissect_next_state <= IDLE; + end if; + + when SAVE => + state <= x"2"; + if (FWD_EOP_IN = '1') then + dissect_next_state <= WAIT_FOR_LOAD; + else + dissect_next_state <= SAVE; + end if; + + when WAIT_FOR_LOAD => + state <= x"3"; + if (PS_SELECTED_IN = '0') then + dissect_next_state <= LOAD; + else + dissect_next_state <= WAIT_FOR_LOAD; + end if; + + when LOAD => + state <= x"4"; + if (ff_q(8) = '1') and (ff_rd_lock = '0') then + dissect_next_state <= CLEANUP; + else + dissect_next_state <= LOAD; + end if; + + when CLEANUP => + state <= x"5"; + dissect_next_state <= IDLE; + + end case; +end process DISSECT_MACHINE; + +PS_BUSY_OUT <= '0' when dissect_current_state = IDLE else '1'; + +ff_wr_en <= '1' when (FWD_DATA_VALID_IN = '1') else '0'; + +local_eop <= '1' when (dissect_current_state = SAVE and FWD_EOP_IN = '1' and FWD_DATA_VALID_IN = '1') else '0'; + +FF_RD_LOCK_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + ff_rd_lock <= '1'; + elsif( rising_edge(CLK) ) then + if( dissect_current_state = LOAD and ff_rd_en = '1' ) then + ff_rd_lock <= '0'; + else + ff_rd_lock <= '1'; + end if; + end if; +end process FF_RD_LOCK_PROC; + +FRAME_FIFO: entity fifo_4096x9 +port map( + Data(7 downto 0) => FWD_DATA_IN, + Data(8) => local_eop, + WrClock => CLK, + RdClock => CLK, + WrEn => ff_wr_en, + RdEn => ff_rd_en, + Reset => RESET, + RPReset => RESET, + Q => ff_q, + Empty => ff_empty, + Full => ff_full +); + +ff_rd_en <= '1' when (TC_RD_EN_IN = '1' and PS_SELECTED_IN = '1') else '0'; + +--TC_DATA_OUT <= ff_q; -- BUG?!? +TC_DATA_OUT <= ff_q when rising_edge(CLK); + +PS_RESPONSE_READY_OUT <= '1' when (dissect_current_state = LOAD) else '0'; + +--TC_FRAME_SIZE_OUT <= resp_bytes_ctr + x"1"; -- BUG?!? +TC_FRAME_SIZE_OUT <= resp_bytes_ctr; + +TC_FRAME_TYPE_OUT <= x"0008"; +TC_DEST_MAC_OUT <= FWD_DST_MAC_IN; +TC_DEST_IP_OUT <= FWD_DST_IP_IN; +TC_DEST_UDP_OUT <= FWD_DST_UDP_IN; +TC_SRC_MAC_OUT <= MY_MAC_IN; +TC_SRC_IP_OUT <= MY_IP_IN; +TC_SRC_UDP_OUT <= FWD_DST_UDP_IN; +TC_IP_PROTOCOL_OUT <= x"11"; +TC_IDENT_OUT <= x"6" & sent_frames(11 downto 0); + +RESP_BYTES_CTR_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + resp_bytes_ctr <= (others => '0'); + elsif( rising_edge(CLK) ) then + if ( dissect_current_state = IDLE ) then + resp_bytes_ctr <= (others => '0'); + elsif( dissect_current_state = SAVE and FWD_DATA_VALID_IN = '1' ) then + resp_bytes_ctr <= resp_bytes_ctr + x"1"; + end if; + + FWD_FULL_OUT <= ff_full; + + if( dissect_current_state = IDLE ) then + FWD_READY_OUT <= '1'; + else + FWD_READY_OUT <= '0'; + end if; + + end if; +end process RESP_BYTES_CTR_PROC; + +REC_FRAMES_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + rec_frames <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( dissect_current_state = IDLE and PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' ) then + rec_frames <= rec_frames + x"1"; + end if; + end if; +end process REC_FRAMES_PROC; + +SENT_FRAMES_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + sent_frames <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( dissect_current_state = WAIT_FOR_LOAD and PS_SELECTED_IN = '0' ) then + sent_frames <= sent_frames + x"1"; + end if; + end if; +end process SENT_FRAMES_PROC; + +RECEIVED_FRAMES_OUT <= rec_frames; +SENT_FRAMES_OUT <= sent_frames; + +-- **** debug +DEBUG_OUT(3 downto 0) <= state; +DEBUG_OUT(4) <= ff_empty; +DEBUG_OUT(5) <= ff_full; +DEBUG_OUT(6) <= ff_wr_en; +DEBUG_OUT(7) <= ff_rd_en; +DEBUG_OUT(15 downto 8) <= ff_q(7 downto 0); +DEBUG_OUT(16) <= ff_q(8); +DEBUG_OUT(17) <= local_eop; +DEBUG_OUT(31 downto 18) <= (others => '0'); +-- **** + +end gbe_response_constructor_Forward_arch; diff --git a/gbe_trb/protocols/gbe_response_constructor_Ping.vhd b/gbe_trb/protocols/gbe_response_constructor_Ping.vhd new file mode 100644 index 0000000..0b79ad6 --- /dev/null +++ b/gbe_trb/protocols/gbe_response_constructor_Ping.vhd @@ -0,0 +1,304 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + +entity gbe_response_constructor_Ping is +port( + CLK : in std_logic; -- system clock + RESET : in std_logic; +-- INTERFACE + MY_MAC_IN : in std_logic_vector(47 downto 0); + MY_IP_IN : in std_logic_vector(31 downto 0); + PS_DATA_IN : in std_logic_vector(8 downto 0); + PS_WR_EN_IN : in std_logic; + PS_ACTIVATE_IN : in std_logic; + PS_RESPONSE_READY_OUT : out std_logic; + PS_BUSY_OUT : out std_logic; + PS_SELECTED_IN : in std_logic; + PS_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + PS_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); +-- + TC_RD_EN_IN : in std_logic; + TC_DATA_OUT : out std_logic_vector(8 downto 0); + TC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + TC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + TC_IDENT_OUT : out std_logic_vector(15 downto 0); + TC_DEST_MAC_OUT : out std_logic_vector(47 downto 0); + TC_DEST_IP_OUT : out std_logic_vector(31 downto 0); + TC_DEST_UDP_OUT : out std_logic_vector(15 downto 0); + TC_SRC_MAC_OUT : out std_logic_vector(47 downto 0); + TC_SRC_IP_OUT : out std_logic_vector(31 downto 0); + TC_SRC_UDP_OUT : out std_logic_vector(15 downto 0); +-- END OF INTERFACE +-- debug + DEBUG_OUT : out std_logic_vector(63 downto 0) +); +end gbe_response_constructor_Ping; + +architecture gbe_response_constructor_Ping_arch of gbe_response_constructor_Ping is + +attribute syn_encoding : string; + +type dissect_states is (IDLE, READ_FRAME, WAIT_FOR_LOAD, LOAD_FRAME, CLEANUP); +signal dissect_current_state, dissect_next_state : dissect_states; +attribute syn_encoding of dissect_current_state: signal is "onehot"; + +type stats_states is (IDLE, LOAD_SENT, LOAD_RECEIVED, CLEANUP); +signal stats_current_state, stats_next_state : stats_states; +attribute syn_encoding of stats_current_state : signal is "onehot"; + +signal sent_frames : std_logic_vector(15 downto 0); + +signal saved_data : std_logic_vector(447 downto 0); +signal saved_headers : std_logic_vector(63 downto 0); + +signal data_ctr : integer range 1 to 1500; +signal data_length : integer range 1 to 1500; +signal tc_data : std_logic_vector(8 downto 0); + +signal checksum : std_logic_vector(15 downto 0); + +signal checksum_l : std_logic_vector(19 downto 0); +signal checksum_r : std_logic_vector(19 downto 0); +signal checksum_ll : std_logic_vector(15 downto 0); +signal checksum_rr : std_logic_vector(15 downto 0); +signal checksum_lll : std_logic_vector(15 downto 0); +signal checksum_rrr : std_logic_vector(15 downto 0); + +begin + +DISSECT_MACHINE_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + dissect_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + dissect_current_state <= dissect_next_state; + end if; +end process DISSECT_MACHINE_PROC; + +DISSECT_MACHINE: process(dissect_current_state, PS_WR_EN_IN, PS_SELECTED_IN, PS_ACTIVATE_IN, PS_DATA_IN, data_ctr, data_length) +begin + case dissect_current_state is + + when IDLE => + if (PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1') then + dissect_next_state <= READ_FRAME; + else + dissect_next_state <= IDLE; + end if; + + when READ_FRAME => + if (PS_DATA_IN(8) = '1') then + dissect_next_state <= WAIT_FOR_LOAD; + else + dissect_next_state <= READ_FRAME; + end if; + + when WAIT_FOR_LOAD => + if (PS_SELECTED_IN = '1') then + dissect_next_state <= LOAD_FRAME; + else + dissect_next_state <= WAIT_FOR_LOAD; + end if; + + when LOAD_FRAME => + if (data_ctr = data_length + 1) then + dissect_next_state <= CLEANUP; + else + dissect_next_state <= LOAD_FRAME; + end if; + + when CLEANUP => + dissect_next_state <= IDLE; + + end case; +end process DISSECT_MACHINE; + +DATA_CTR_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + data_ctr <= 2; + elsif( rising_edge(CLK) ) then + if ( (dissect_current_state = IDLE) or (dissect_current_state = WAIT_FOR_LOAD) ) then + data_ctr <= 2; + elsif( dissect_current_state = READ_FRAME and PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' ) then -- in case of saving data from incoming frame + data_ctr <= data_ctr + 1; + elsif( dissect_current_state = LOAD_FRAME and PS_SELECTED_IN = '1' and TC_RD_EN_IN = '1' ) then -- in case of constructing response + data_ctr <= data_ctr + 1; + end if; + end if; +end process DATA_CTR_PROC; + +DATA_LENGTH_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + data_length <= 1; + elsif( rising_edge(CLK) ) then + if (dissect_current_state = READ_FRAME and PS_DATA_IN(8) = '1') then + data_length <= data_ctr; + end if; + end if; +end process DATA_LENGTH_PROC; + +SAVE_VALUES_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + saved_headers <= (others => '0'); + saved_data <= (others => '0'); + elsif( rising_edge(CLK) ) then + if ( dissect_current_state = IDLE ) then + saved_headers <= (others => '0'); + saved_data <= (others => '0'); + elsif( dissect_current_state = IDLE and PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' ) then + saved_headers(7 downto 0) <= PS_DATA_IN(7 downto 0); + elsif( dissect_current_state = READ_FRAME ) then + if (data_ctr < 9) then -- headers + saved_headers(data_ctr * 8 - 1 downto (data_ctr - 1) * 8) <= PS_DATA_IN(7 downto 0); + elsif (data_ctr > 8) then -- data + saved_data((data_ctr - 8) * 8 - 1 downto (data_ctr - 8 - 1) * 8) <= PS_DATA_IN(7 downto 0); + end if; + elsif( dissect_current_state = LOAD_FRAME ) then + saved_headers(7 downto 0) <= x"00"; + saved_headers(23 downto 16) <= checksum(7 downto 0); + saved_headers(31 downto 24) <= checksum(15 downto 8); + end if; + end if; +end process SAVE_VALUES_PROC; + +CS_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + checksum_l(19 downto 0) <= (others => '0'); + checksum_r(19 downto 0) <= (others => '0'); + checksum_ll(15 downto 0) <= (others => '0'); + checksum_rr(15 downto 0) <= (others => '0'); + checksum_lll(15 downto 0) <= (others => '0'); + checksum_rrr(15 downto 0) <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( dissect_current_state = IDLE ) then + checksum_l(19 downto 0) <= (others => '0'); + checksum_r(19 downto 0) <= (others => '0'); + checksum_ll(15 downto 0) <= (others => '0'); + checksum_rr(15 downto 0) <= (others => '0'); + checksum_lll(15 downto 0) <= (others => '0'); + checksum_rrr(15 downto 0) <= (others => '0'); + elsif( dissect_current_state = READ_FRAME and data_ctr > 4 ) then + if (std_logic_vector(to_unsigned(data_ctr, 1)) = "0") then + checksum_l <= checksum_l + PS_DATA_IN(7 downto 0); + else + checksum_r <= checksum_r + PS_DATA_IN(7 downto 0); + end if; + checksum_ll <= checksum_ll; + checksum_lll <= checksum_lll; + checksum_rr <= checksum_rr; + checksum_rrr <= checksum_rrr; + elsif( dissect_current_state = WAIT_FOR_LOAD ) then + checksum_ll <= x"0000" + checksum_l(7 downto 0) + checksum_r(19 downto 8); + checksum_rr <= x"0000" + checksum_r(7 downto 0) + checksum_l(19 downto 8); + checksum_l <= checksum_l; + checksum_lll <= checksum_lll; + checksum_r <= checksum_r; + checksum_rrr <= checksum_rrr; + elsif( dissect_current_state = LOAD_FRAME and data_ctr = 2 ) then + checksum_lll <= x"0000" + checksum_ll(7 downto 0) + checksum_rr(15 downto 8); + checksum_rrr <= x"0000" + checksum_rr(7 downto 0) + checksum_ll(15 downto 8); + checksum_l <= checksum_l; + checksum_ll <= checksum_ll; + checksum_r <= checksum_r; + checksum_rr <= checksum_rr; + end if; + end if; +end process CS_PROC; +checksum(7 downto 0) <= not (checksum_rrr(7 downto 0) + checksum_lll(15 downto 8)); +checksum(15 downto 8) <= not (checksum_lll(7 downto 0) + checksum_rrr(15 downto 8)); + +TC_DATA_PROC : process( CLK ) +begin + if( rising_edge(CLK) ) then + tc_data(8) <= '0'; + + if( dissect_current_state = LOAD_FRAME ) then + if (data_ctr < 10) then -- headers + for i in 0 to 7 loop + tc_data(i) <= saved_headers((data_ctr - 2) * 8 + i); + end loop; + else -- data + for i in 0 to 7 loop + tc_data(i) <= saved_data((data_ctr - 8 - 2) * 8 + i); + end loop; + + -- mark the last byte + if (data_ctr = data_length + 1) then + tc_data(8) <= '1'; + end if; + end if; + else + tc_data(7 downto 0) <= (others => '0'); + end if; + + TC_DATA_OUT <= tc_data; + + end if; +end process TC_DATA_PROC; + +PS_RESPONSE_SYNC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( dissect_current_state = WAIT_FOR_LOAD or dissect_current_state = LOAD_FRAME or dissect_current_state = CLEANUP ) then + PS_RESPONSE_READY_OUT <= '1'; + else + PS_RESPONSE_READY_OUT <= '0'; + end if; + + if( dissect_current_state = IDLE ) then + PS_BUSY_OUT <= '0'; + else + PS_BUSY_OUT <= '1'; + end if; + end if; +end process PS_RESPONSE_SYNC; + +TC_FRAME_SIZE_OUT <= std_logic_vector(to_unsigned(data_length, 16)); +TC_FRAME_TYPE_OUT <= x"0008"; +TC_DEST_UDP_OUT <= x"0000"; -- not used +TC_SRC_MAC_OUT <= MY_MAC_IN; +TC_SRC_IP_OUT <= MY_IP_IN; +TC_SRC_UDP_OUT <= x"0000"; -- not used +TC_IP_PROTOCOL_OUT <= X"01"; -- ICMP +TC_IDENT_OUT <= x"2" & sent_frames(11 downto 0); + +ADDR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( dissect_current_state = READ_FRAME ) then + TC_DEST_MAC_OUT <= PS_SRC_MAC_ADDRESS_IN; + TC_DEST_IP_OUT <= PS_SRC_IP_ADDRESS_IN; + end if; + end if; +end process ADDR_PROC; + +SENT_FRAMES_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + sent_frames <= (others => '0'); + elsif( rising_edge(CLK) ) then + if( dissect_current_state = CLEANUP ) then + sent_frames <= sent_frames + x"1"; + end if; + end if; +end process SENT_FRAMES_PROC; + +end gbe_response_constructor_Ping_arch; + + diff --git a/gbe_trb/protocols/gbe_response_constructor_SCTRL.vhd b/gbe_trb/protocols/gbe_response_constructor_SCTRL.vhd new file mode 100644 index 0000000..2a47e3f --- /dev/null +++ b/gbe_trb/protocols/gbe_response_constructor_SCTRL.vhd @@ -0,0 +1,635 @@ +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_UNSIGNED.ALL; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.gbe_protocols.all; + + +entity gbe_response_constructor_SCTRL is + generic( + SLOWCTRL_BUFFER_SIZE : integer range 1 to 4 := 1 + ); + port( + CLK : in std_logic; -- system clock + RESET : in std_logic; + -- INTERFACE + MY_MAC_IN : in std_logic_vector(47 downto 0); + MY_IP_IN : in std_logic_vector(31 downto 0); + PS_DATA_IN : in std_logic_vector(8 downto 0); + PS_WR_EN_IN : in std_logic; + PS_ACTIVATE_IN : in std_logic; + PS_RESPONSE_READY_OUT : out std_logic; + PS_BUSY_OUT : out std_logic; + PS_SELECTED_IN : in std_logic; + PS_SRC_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_DEST_MAC_ADDRESS_IN : in std_logic_vector(47 downto 0); + PS_SRC_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_DEST_IP_ADDRESS_IN : in std_logic_vector(31 downto 0); + PS_SRC_UDP_PORT_IN : in std_logic_vector(15 downto 0); + PS_DEST_UDP_PORT_IN : in std_logic_vector(15 downto 0); +-- + TC_RD_EN_IN : in std_logic; + TC_DATA_OUT : out std_logic_vector(8 downto 0); + TC_FRAME_SIZE_OUT : out std_logic_vector(15 downto 0); + TC_FRAME_TYPE_OUT : out std_logic_vector(15 downto 0); + TC_IP_PROTOCOL_OUT : out std_logic_vector(7 downto 0); + TC_IDENT_OUT : out std_logic_vector(15 downto 0); + TC_DEST_MAC_OUT : out std_logic_vector(47 downto 0); + TC_DEST_IP_OUT : out std_logic_vector(31 downto 0); + TC_DEST_UDP_OUT : out std_logic_vector(15 downto 0); + TC_SRC_MAC_OUT : out std_logic_vector(47 downto 0); + TC_SRC_IP_OUT : out std_logic_vector(31 downto 0); + TC_SRC_UDP_OUT : out std_logic_vector(15 downto 0); +-- + DEBUG_OUT : out std_logic_vector(63 downto 0); + -- END OF INTERFACE + -- protocol specific ports + GSC_CLK_IN : in std_logic; + GSC_INIT_DATAREADY_OUT : out std_logic; + GSC_INIT_DATA_OUT : out std_logic_vector(15 downto 0); + GSC_INIT_PACKET_NUM_OUT : out std_logic_vector(2 downto 0); + GSC_INIT_READ_IN : in std_logic; + GSC_REPLY_DATAREADY_IN : in std_logic; + GSC_REPLY_DATA_IN : in std_logic_vector(15 downto 0); + GSC_REPLY_PACKET_NUM_IN : in std_logic_vector(2 downto 0); + GSC_REPLY_READ_OUT : out std_logic; + GSC_BUSY_IN : in std_logic; + MAKE_RESET_OUT : out std_logic; + CFG_MAX_REPLY_SIZE_IN : in std_logic_vector(31 downto 0); + -- end of protocol specific ports + MONITOR_SELECT_REC_OUT : out std_logic_vector(31 downto 0); + MONITOR_SELECT_REC_BYTES_OUT : out std_logic_vector(31 downto 0); + MONITOR_SELECT_SENT_BYTES_OUT : out std_logic_vector(31 downto 0); + MONITOR_SELECT_SENT_OUT : out std_logic_vector(31 downto 0); + DATA_HIST_OUT : out hist_array + ); +end entity gbe_response_constructor_SCTRL; + +architecture gbe_response_constructor_SCTRL_arch of gbe_response_constructor_SCTRL is + +attribute syn_encoding : string; + +type dissect_states is (IDLE, READ_FRAME, WAIT_FOR_HUB, LOAD_TO_HUB, WAIT_FOR_RESPONSE, SAVE_RESPONSE, LOAD_FRAME, WAIT_FOR_LOAD, CLEANUP); +signal dissect_current_state, dissect_next_state : dissect_states; +attribute syn_encoding of dissect_current_state: signal is "onehot"; + +type stats_states is (IDLE, LOAD_RECEIVED, LOAD_REPLY, CLEANUP); +signal stats_current_state, stats_next_state : stats_states; +attribute syn_encoding of stats_current_state : signal is "onehot"; + +signal saved_target_ip : std_logic_vector(31 downto 0); +signal data_ctr : integer range 0 to 30; + +signal rec_frames : std_logic_vector(15 downto 0); + +signal rx_fifo_q : std_logic_vector(17 downto 0); +signal rx_fifo_qq : std_logic_vector(17 downto 0); +signal rx_fifo_wr, rx_fifo_rd : std_logic; +signal tx_eod, rx_eod : std_logic; + +signal tx_fifo_q : std_logic_vector(8 downto 0); +signal tx_fifo_wr, tx_fifo_rd : std_logic; +signal tx_fifo_reset : std_logic; +signal gsc_reply_read : std_logic; +signal gsc_init_dataready : std_logic; +signal gsc_init_dataready_q : std_logic; + +signal tx_data_ctr : std_logic_vector(15 downto 0); +signal tx_loaded_ctr : std_logic_vector(15 downto 0); +signal tx_frame_loaded : std_logic_vector(15 downto 0); + +signal packet_num : std_logic_vector(2 downto 0); + +signal init_ctr, reply_ctr : std_logic_vector(15 downto 0); +signal rx_empty, tx_empty : std_logic; + +signal rx_full, tx_full : std_logic; + +signal size_left : std_logic_vector(15 downto 0); + +signal reset_detected : std_logic := '0'; +signal make_reset : std_logic := '0'; + +signal fifo_rd_q : std_logic; + +signal too_much_data : std_logic; + +signal rx_fifo_data : std_logic_vector(8 downto 0); +signal tx_fifo_data : std_logic_vector(17 downto 0); + +signal tc_wr : std_logic; +signal state : std_logic_vector(3 downto 0); +signal saved_hdr_1 : std_logic_vector(7 downto 0) := x"ab"; +signal saved_hdr_2 : std_logic_vector(7 downto 0) := x"cd"; +signal saved_hdr_ctr : std_logic_vector(3 downto 0); + +signal mon_rec_frames, mon_rec_bytes, mon_sent_frames, mon_sent_bytes : std_logic_vector(31 downto 0); + +attribute syn_preserve : boolean; +attribute syn_keep : boolean; +attribute syn_keep of rx_fifo_wr, rx_fifo_rd, gsc_init_dataready, tx_fifo_wr, tx_fifo_rd, gsc_reply_read, state : signal is true; +attribute syn_preserve of rx_fifo_wr, rx_fifo_rd, gsc_init_dataready, tx_fifo_wr, tx_fifo_rd, gsc_reply_read, state : signal is true; + +signal hist_inst : hist_array; +signal reset_all_hist : std_logic_vector(31 downto 0); + +signal rx_cnt, tx_cnt : std_logic_vector(15 downto 0); + +begin + +MAKE_RESET_OUT <= make_reset; + +receive_fifo: entity work.fifo_2kx9x18_wcnt + PORT map( + Reset => RESET, + RPReset => RESET, + WrClock => CLK, + RdClock => CLK, + Data => rx_fifo_data, + WrEn => rx_fifo_wr, + RdEn => rx_fifo_rd, + Q => rx_fifo_q, + Full => rx_full, + Empty => rx_empty, + WCNT => rx_cnt(11 downto 0) + ); + +--TODO: change to synchronous +rx_fifo_rd <= '1' when (gsc_init_dataready = '1' and dissect_current_state = LOAD_TO_HUB) or + (gsc_init_dataready = '1' and dissect_current_state = WAIT_FOR_HUB and GSC_INIT_READ_IN = '1') or + (dissect_current_state = READ_FRAME and PS_DATA_IN(8) = '1') + else '0'; -- preload first word + +RX_FIFO_WR_SYNC: process( CLK ) +begin + if( rising_edge(CLK) ) then + + if( PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' and (saved_hdr_ctr = "0100" or saved_hdr_ctr = "1000") ) then + rx_fifo_wr <= '1'; + else + rx_fifo_wr <= '0'; + end if; + + rx_fifo_data <= PS_DATA_IN; + end if; +end process RX_FIFO_WR_SYNC; + +SAVED_HDR_CTR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( dissect_current_state = IDLE and PS_WR_EN_IN = '0' and PS_ACTIVATE_IN = '0' ) then + saved_hdr_ctr <= "0001"; + elsif( PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' and saved_hdr_ctr /= "1000" ) then + saved_hdr_ctr(3 downto 0) <= saved_hdr_ctr(2 downto 0) & '0'; + end if; + end if; +end process SAVED_HDR_CTR_PROC; + +SAVED_HDR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' ) then + if( saved_hdr_ctr = "0001" ) then + saved_hdr_1 <= PS_DATA_IN(7 downto 0); + saved_hdr_2 <= saved_hdr_2; + elsif( saved_hdr_ctr = "0010" ) then + saved_hdr_2 <= PS_DATA_IN(7 downto 0); + saved_hdr_1 <= saved_hdr_1; + end if; + end if; + end if; +end process SAVED_HDR_PROC; + +----TODO: add a register +GSC_INIT_DATA_OUT(7 downto 0) <= rx_fifo_q(16 downto 9); +GSC_INIT_DATA_OUT(15 downto 8) <= rx_fifo_q(7 downto 0); + +------ TODO: change it to synchronous +GSC_INIT_PACKET_NUM_OUT <= packet_num; +GSC_INIT_DATAREADY_OUT <= gsc_init_dataready; +gsc_init_dataready <= '1' when (GSC_INIT_READ_IN = '1' and dissect_current_state = LOAD_TO_HUB) or --TODO Ob das so richtig ist, ohne auf fifo_rd zu schauen? + (dissect_current_state = WAIT_FOR_HUB) + else '0'; + +PACKET_NUM_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( dissect_current_state = IDLE ) then + packet_num <= "100"; + elsif( GSC_INIT_READ_IN = '1' and rx_fifo_rd = '1' and packet_num = "100" and dissect_current_state /= READ_FRAME ) then --BUG zählt schon hoch beim fifo_rd weil read schon 1 ist. read geht aber nur auf 1 wenn dataready auf 1 ist + packet_num <= "000"; + elsif( rx_fifo_rd = '1' and packet_num /= "100" ) then + packet_num <= packet_num + "1"; + end if; + end if; +end process PACKET_NUM_PROC; + +tf_4k_gen: if SLOWCTRL_BUFFER_SIZE = 1 generate + transmit_fifo: entity work.fifo_4kx18x9_wcnt + port map( + Reset => tx_fifo_reset, + RPReset => tx_fifo_reset, + WrClock => CLK, + RdClock => CLK, + Data => tx_fifo_data, + WrEn => tx_fifo_wr, + RdEn => tx_fifo_rd, + Q => tx_fifo_q, + Full => tx_full, + Empty => tx_empty, + WCNT => tx_cnt(11 downto 0) + ); +end generate tf_4k_gen; + +tf_65k_gen: if SLOWCTRL_BUFFER_SIZE = 2 generate + transmit_fifo: entity work.fifo_64kx18x9_wcnt + port map( + Reset => tx_fifo_reset, + RPReset => tx_fifo_reset, + WrClock => CLK, + RdClock => CLK, + Data => tx_fifo_data, + WrEn => tx_fifo_wr, + RdEn => tx_fifo_rd, + Q => tx_fifo_q, + Full => tx_full, + Empty => tx_empty, + WCNT => tx_cnt + ); +end generate tf_65k_gen; + +TX_FIFO_WR_SYNC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( GSC_REPLY_DATAREADY_IN = '1' and gsc_reply_read = '1' ) then + tx_fifo_wr <= '1'; + elsif( saved_hdr_ctr = "0010" ) then + tx_fifo_wr <= '1'; + else + tx_fifo_wr <= '0'; + end if; + + if( saved_hdr_ctr = "010" ) then + tx_fifo_data <= '0' & PS_DATA_IN(7 downto 0) & '0' & x"02"; + else + tx_fifo_data(7 downto 0) <= GSC_REPLY_DATA_IN(15 downto 8); + tx_fifo_data(8) <= '0'; + tx_fifo_data(16 downto 9) <= GSC_REPLY_DATA_IN(7 downto 0); + tx_fifo_data(17) <= '0'; + end if; + end if; +end process TX_FIFO_WR_SYNC; + +tx_fifo_rd <= '1' when TC_RD_EN_IN = '1' and PS_SELECTED_IN = '1' else '0'; + +TX_FIFO_SYNC_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + tx_fifo_reset <= '1'; + elsif( rising_edge(CLK) ) then + if( too_much_data = '1' and dissect_current_state = CLEANUP ) then + tx_fifo_reset <= '1'; + else + tx_fifo_reset <= '0'; + end if; + end if; +end process TX_FIFO_SYNC_PROC; + +TC_DATA_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + + TC_DATA_OUT(7 downto 0) <= tx_fifo_q(7 downto 0); + + if( tx_loaded_ctr = tx_data_ctr ) then + TC_DATA_OUT(8) <= '1'; + else + TC_DATA_OUT(8) <= '0'; + end if; + end if; +end process TC_DATA_PROC; + +GSC_REPLY_READ_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( dissect_current_state = WAIT_FOR_RESPONSE or dissect_current_state = SAVE_RESPONSE ) then + gsc_reply_read <= '1'; + else + gsc_reply_read <= '0'; + end if; + end if; +end process GSC_REPLY_READ_PROC; +GSC_REPLY_READ_OUT <= gsc_reply_read; + +-- counter of data received from TRBNet hub +TX_DATA_CTR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if (dissect_current_state = IDLE) then + tx_data_ctr <= (others => '0'); + elsif( tx_fifo_wr = '1' ) then + tx_data_ctr <= tx_data_ctr + x"2"; + end if; + end if; +end process TX_DATA_CTR_PROC; + +TOO_MUCH_DATA_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( dissect_current_state = IDLE ) then + too_much_data <= '0'; + elsif( (dissect_current_state = SAVE_RESPONSE) and (tx_data_ctr = CFG_MAX_REPLY_SIZE_IN(15 downto 0)) ) then + too_much_data <= '1'; + end if; + end if; +end process TOO_MUCH_DATA_PROC; + +-- total counter of data transported to frame constructor +TX_LOADED_CTR_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( dissect_current_state = IDLE ) then + tx_loaded_ctr <= x"0000"; + elsif( dissect_current_state = LOAD_FRAME and PS_SELECTED_IN = '1' and TC_RD_EN_IN = '1' ) then + tx_loaded_ctr <= tx_loaded_ctr + x"1"; + end if; + end if; +end process TX_LOADED_CTR_PROC; + +PS_RESPONSE_SYNC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if( too_much_data = '0' ) then + if( dissect_current_state = WAIT_FOR_LOAD or dissect_current_state = LOAD_FRAME or dissect_current_state = CLEANUP ) then + PS_RESPONSE_READY_OUT <= '1'; + else + PS_RESPONSE_READY_OUT <= '0'; + end if; + end if; + + if( dissect_current_state = IDLE or dissect_current_state = WAIT_FOR_RESPONSE ) then + PS_BUSY_OUT <= '0'; + else + PS_BUSY_OUT <= '1'; + end if; + end if; +end process PS_RESPONSE_SYNC; + +TC_FRAME_TYPE_OUT <= x"0008"; +TC_DEST_MAC_OUT <= PS_SRC_MAC_ADDRESS_IN; +TC_DEST_IP_OUT <= PS_SRC_IP_ADDRESS_IN; +TC_DEST_UDP_OUT(7 downto 0) <= PS_SRC_UDP_PORT_IN(15 downto 8); +TC_DEST_UDP_OUT(15 downto 8) <= PS_SRC_UDP_PORT_IN(7 downto 0); +TC_SRC_MAC_OUT <= MY_MAC_IN; +TC_SRC_IP_OUT <= MY_IP_IN; +TC_SRC_UDP_OUT <= x"9065"; --x"a861"; +TC_IP_PROTOCOL_OUT <= x"11"; +TC_IDENT_OUT <= x"3" & reply_ctr(11 downto 0); + +TC_FRAME_SIZE_OUT <= tx_data_ctr; + +DISSECT_MACHINE_PROC: process( CLK, RESET ) +begin + if ( RESET = '1' ) then + dissect_current_state <= IDLE; + elsif( rising_edge(CLK) ) then + dissect_current_state <= dissect_next_state; + end if; +end process DISSECT_MACHINE_PROC; + +DISSECT_MACHINE: process(dissect_current_state, reset_detected, too_much_data, PS_WR_EN_IN, PS_ACTIVATE_IN, + PS_DATA_IN, PS_SELECTED_IN, GSC_INIT_READ_IN, GSC_REPLY_DATAREADY_IN, tx_loaded_ctr, + tx_data_ctr, rx_fifo_q, GSC_BUSY_IN) +begin + state <= x"0"; + + case dissect_current_state is + + when IDLE => + state <= x"1"; + if (PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1') then + dissect_next_state <= READ_FRAME; + else + dissect_next_state <= IDLE; + end if; + + when READ_FRAME => + state <= x"2"; + if (PS_DATA_IN(8) = '1' and (GSC_INIT_READ_IN = '0')) then + dissect_next_state <= WAIT_FOR_HUB; + elsif (PS_DATA_IN(8) = '1' and (GSC_INIT_READ_IN = '1')) then + dissect_next_state <= LOAD_TO_HUB; + else + dissect_next_state <= READ_FRAME; + end if; + + when WAIT_FOR_HUB => + state <= x"3"; + if (GSC_INIT_READ_IN = '1') then + dissect_next_state <= LOAD_TO_HUB; + else + dissect_next_state <= WAIT_FOR_HUB; + end if; + + when LOAD_TO_HUB => + state <= x"4"; + if ((rx_fifo_q(17) = '1') and (GSC_INIT_READ_IN = '1')) then + if (reset_detected = '1') then + dissect_next_state <= CLEANUP; + else + dissect_next_state <= WAIT_FOR_RESPONSE; + end if; + else + dissect_next_state <= LOAD_TO_HUB; + end if; + + when WAIT_FOR_RESPONSE => + state <= x"5"; + if (GSC_REPLY_DATAREADY_IN = '1') then + dissect_next_state <= SAVE_RESPONSE; + else + dissect_next_state <= WAIT_FOR_RESPONSE; + end if; + + when SAVE_RESPONSE => + state <= x"6"; + if (GSC_REPLY_DATAREADY_IN = '0' and GSC_BUSY_IN = '0') then + if (too_much_data = '0') then + dissect_next_state <= WAIT_FOR_LOAD; + else + dissect_next_state <= CLEANUP; + end if; + else + dissect_next_state <= SAVE_RESPONSE; + end if; + + when WAIT_FOR_LOAD => + state <= x"7"; + if (PS_SELECTED_IN = '1') then + dissect_next_state <= LOAD_FRAME; + else + dissect_next_state <= WAIT_FOR_LOAD; + end if; + + when LOAD_FRAME => + state <= x"8"; + if (tx_loaded_ctr = tx_data_ctr) then + dissect_next_state <= CLEANUP; + else + dissect_next_state <= LOAD_FRAME; + end if; + + when CLEANUP => + state <= x"9"; + dissect_next_state <= IDLE; + + when others => dissect_next_state <= IDLE; + + end case; +end process DISSECT_MACHINE; + +-- reset request packet detection +RESET_DETECTED_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( dissect_current_state = IDLE ) then + reset_detected <= '0'; + elsif( PS_DATA_IN(7 downto 0) = x"80" and PS_WR_EN_IN = '1' and PS_ACTIVATE_IN = '1' and saved_hdr_ctr = "0100" ) then + reset_detected <= '1'; + end if; + end if; +end process RESET_DETECTED_PROC; + +MAKE_RESET_PROC: process( CLK ) +begin + if( rising_edge(CLK) ) then + if ( dissect_current_state = IDLE ) then + make_reset <= '0'; + elsif( dissect_current_state = CLEANUP and reset_detected = '1' ) then + make_reset <= '1'; + end if; + end if; +end process MAKE_RESET_PROC; + + +-- monitoring + +hist_ctrs_gen : for i in 0 to 31 generate + + process( CLK ) + begin + if rising_edge(CLK) then + if (RESET = '1') then + reset_all_hist(i) <= '1'; + elsif (hist_inst(i) = x"ffff_ffff") then + reset_all_hist(i) <= '1'; + else + reset_all_hist(i) <= '0'; + end if; + end if; + end process; + + process(CLK) + begin + if rising_edge(CLK) then + if (reset_all_hist /= x"0000_0000") then + hist_inst(i) <= (others => '0'); + elsif (dissect_current_state = LOAD_FRAME and tx_loaded_ctr = tx_data_ctr and i = to_integer(unsigned(tx_data_ctr(15 downto 11)))) then + hist_inst(i) <= hist_inst(i) + x"1"; + else + hist_inst(i) <= hist_inst(i); + end if; + end if; + end process; + +end generate hist_ctrs_gen; + +DATA_HIST_OUT <= hist_inst; + +process( CLK ) +begin + if rising_edge(CLK) then + DEBUG_OUT(0) <= rx_full; + DEBUG_OUT(1) <= rx_empty; + DEBUG_OUT(2) <= tx_full; + DEBUG_OUT(3) <= tx_empty; + DEBUG_OUT(7 downto 4) <= state; + DEBUG_OUT(23 downto 8) <= rx_cnt; + DEBUG_OUT(39 downto 24) <= tx_cnt; + DEBUG_OUT(63 downto 40) <= (others => '0'); + end if; +end process; + +process( CLK ) +begin + if rising_edge(CLK) then + if (RESET = '1') then + mon_rec_frames <= (others => '0'); + elsif (dissect_current_state = READ_FRAME and PS_DATA_IN(8) = '1') then + mon_rec_frames <= mon_rec_frames + x"1"; + else + mon_rec_frames <= mon_rec_frames; + end if; + end if; +end process; +MONITOR_SELECT_REC_OUT <= mon_rec_frames; + +process( CLK ) +begin + if rising_edge(CLK) then + if (RESET = '1') then + mon_rec_bytes <= (others => '0'); + elsif (rx_fifo_wr = '1') then + mon_rec_bytes <= mon_rec_bytes + x"1"; + else + mon_rec_bytes <= mon_rec_bytes; + end if; + end if; +end process; +MONITOR_SELECT_REC_BYTES_OUT <= mon_rec_bytes; + +process( CLK ) +begin + if rising_edge(CLK) then + if (RESET = '1') then + mon_sent_frames <= (others => '0'); + elsif (dissect_current_state = LOAD_FRAME and tx_loaded_ctr = tx_data_ctr) then + mon_sent_frames <= mon_sent_frames + x"1"; + else + mon_sent_frames <= mon_sent_frames; + end if; + end if; +end process; +MONITOR_SELECT_SENT_OUT <= mon_sent_frames; + +process( CLK ) +begin + if rising_edge(CLK) then + if (RESET = '1') then + mon_sent_bytes <= (others => '0'); + elsif (tx_fifo_rd = '1') then + mon_sent_bytes <= mon_sent_bytes + x"1"; + else + mon_sent_bytes <= mon_sent_bytes; + end if; + end if; +end process; +MONITOR_SELECT_SENT_BYTES_OUT <= mon_sent_bytes; + +-- needed for identification +REPLY_CTR_PROC : process( CLK ) +begin + if rising_edge(CLK) then + if (RESET = '1') then + reply_ctr <= (others => '0'); + elsif (dissect_current_state = LOAD_FRAME and tx_loaded_ctr = tx_data_ctr) then + reply_ctr <= reply_ctr + x"1"; + end if; + end if; +end process REPLY_CTR_PROC; + +end architecture gbe_response_constructor_SCTRL_arch; diff --git a/gbe_trb_ecp3/media/gbe_med_fifo.vhd b/gbe_trb_ecp3/media/gbe_med_fifo.vhd index 07ee55d..4054fb4 100644 --- a/gbe_trb_ecp3/media/gbe_med_fifo.vhd +++ b/gbe_trb_ecp3/media/gbe_med_fifo.vhd @@ -1,13 +1,10 @@ -LIBRARY IEEE; -USE IEEE.std_logic_1164.ALL; -USE IEEE.std_logic_ARITH.ALL; -USE IEEE.std_logic_UNSIGNED.ALL; +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; library work; -use work.trb_net_std.all; -use work.trb_net_components.all; -use work.trb_net_gbe_components.all; -use work.med_sync_define_RS.all; + use work.trb_net_std.all; + use work.med_sync_define_RS.all; -- short documentation: -- LINK_MODE: set to c_IS_SLAVE for uplink port, c_IS_MASTER for downlink port, @@ -807,7 +804,7 @@ begin ); -- RX ringbuffer - THE_FW_RB: entity rx_rb + THE_FW_RB: entity work.gbe_rx_rb port map( CLK => MASTER_CLK_IN, RESET => CLEAR, --RESET, -- CHECKIFWORKS diff --git a/media_interfaces/sync/gbe_tx_reset.vhd b/media_interfaces/sync/gbe_tx_reset.vhd new file mode 100644 index 0000000..2b30c89 --- /dev/null +++ b/media_interfaces/sync/gbe_tx_reset.vhd @@ -0,0 +1,181 @@ +--Media interface TX state machine + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.all; + +entity gbe_tx_reset is + port( + CLEAR : in std_logic; -- async reset, active high, should not be used! + CLK_REF : in std_logic; -- usually local oscillator sourced + TX_PLL_LOL_IN : in std_logic; -- externally or'ed + TX_CLOCK_AVAIL_IN : in std_logic; -- suitable TX clock available + TX_PCS_RST_CH_C_OUT : out std_logic; -- PCS reset + SYNC_TX_QUAD_OUT : out std_logic; -- sync all QUADs to TX bit 0 + LINK_TX_READY_OUT : out std_logic; -- TX lane can use used now + STATE_OUT : out std_logic_vector(3 downto 0) + ); +end entity gbe_tx_reset; + +architecture gbe_tx_reset_arch of gbe_tx_reset is + + constant count_index : integer := 18; -- end of timer + + type statetype is ( IDLE, WAIT_FOR_TIMER, SYNC_ALL, SYNC_DONE, NORMAL ); + + signal CURRENT_STATE : statetype; -- current state of lsm + signal NEXT_STATE : statetype; -- next state of lsm + + signal tx_pcs_rst_ch_c_int : std_logic; + signal sync_tx_quad_int : std_logic; + signal link_tx_ready_int : std_logic; + signal sync_tx_quad_trans : std_logic; + + signal tx_pll_lol_all_q : std_logic; -- synced + signal tx_clock_avail_q : std_logic; -- synced + + signal counter : unsigned(count_index downto 0); + signal timer : std_logic; + signal reset_timer : std_logic; + +begin + +-- This reset handler takes care of enabling all TX SerDes blocks in parallel, +-- independently of RX SerDes blocks. The only difference between master and slave +-- ports is the TX_CLOCK_AVAIL_IN input signal. +-- This will delay the TX SerDes startup until the slave RX port is fully active. + +-- synchronize, just to be on the safe side + SYNC_SFP_SIGS : entity work.signal_sync + generic map( + WIDTH => 2, + DEPTH => 3 + ) + port map( + RESET => '0', + CLK0 => CLK_REF, + CLK1 => CLK_REF, + D_IN(0) => TX_PLL_LOL_IN, + D_IN(1) => TX_CLOCK_AVAIL_IN, + D_OUT(0) => tx_pll_lol_all_q, + D_OUT(1) => tx_clock_avail_q + ); + +-- Timer + THE_TIMER_PROC: process( CLK_REF ) + begin + if( rising_edge(CLK_REF) ) then + if( reset_timer = '1' ) then + counter <= (others => '0'); + else + if( counter(count_index) = '0' ) then + counter <= counter + 1 ; + end if; + end if; + end if; + end process THE_TIMER_PROC; + + timer <= counter(count_index); + +-- State machine clocked process + THE_FSM_PROC: process( CLK_REF, CLEAR ) + begin + if( CLEAR = '1' ) then + CURRENT_STATE <= IDLE; + TX_PCS_RST_CH_C_OUT <= '1'; + LINK_TX_READY_OUT <= '0'; + else + if( rising_edge(CLK_REF) ) then + CURRENT_STATE <= NEXT_STATE; + TX_PCS_RST_CH_C_OUT <= tx_pcs_rst_ch_c_int; + LINK_TX_READY_OUT <= link_tx_ready_int; + end if; + end if; + end process THE_FSM_PROC; + + THE_FSM_DECODE_PROC: process( CURRENT_STATE, timer, tx_pll_lol_all_q, tx_clock_avail_q ) + begin + reset_timer <= '0'; + tx_pcs_rst_ch_c_int <= '0'; + sync_tx_quad_int <= '0'; + link_tx_ready_int <= '0'; + STATE_OUT <= x"F"; + + case CURRENT_STATE is + + when IDLE => + STATE_OUT <= x"1"; + tx_pcs_rst_ch_c_int <= '1'; + reset_timer <= '1'; + if( tx_clock_avail_q = '1' ) then + NEXT_STATE <= WAIT_FOR_TIMER; + else + NEXT_STATE <= IDLE; + end if; + + when WAIT_FOR_TIMER => + STATE_OUT <= x"2"; + tx_pcs_rst_ch_c_int <= '1'; + if( timer = '1' ) then + if( tx_pll_lol_all_q = '0' ) then + NEXT_STATE <= SYNC_ALL; + else + NEXT_STATE <= IDLE; -- restart timer + end if; + else + NEXT_STATE <= WAIT_FOR_TIMER; + end if; + + when SYNC_ALL => + STATE_OUT <= x"3"; + tx_pcs_rst_ch_c_int <= '1'; + reset_timer <= '1'; + sync_tx_quad_int <= '1'; + NEXT_STATE <= SYNC_DONE; + + when SYNC_DONE => + STATE_OUT <= x"4"; + if( timer = '1' ) then + NEXT_STATE <= NORMAL; + else + NEXT_STATE <= SYNC_DONE; + end if; + + when NORMAL => + STATE_OUT <= x"5"; + tx_pcs_rst_ch_c_int <= '0'; + link_tx_ready_int <= '1'; + reset_timer <= '1'; + if( (tx_pll_lol_all_q = '1') or (tx_clock_avail_q = '0') ) then + NEXT_STATE <= IDLE; + else + NEXT_STATE <= NORMAL; + end if; + + when others => + STATE_OUT <= x"f"; + NEXT_STATE <= IDLE; + + end case; + + end process THE_FSM_DECODE_PROC; + + -- TX serializer is operational "at level" of this signal, + -- and gets reset by a transition (according to SerDes Usage Guide). + -- Timer1 is used to delay the TX link ready signal by some cycles. + THE_QUAD_SYNC_PROC: process( CLK_REF, CLEAR ) + begin + if( CLEAR = '1' ) then + sync_tx_quad_trans <= '0'; + else + if( rising_edge(CLK_REF) ) then + if( sync_tx_quad_int = '1' ) then + sync_tx_quad_trans <= not sync_tx_quad_trans; + end if; + end if; + end if; + end process THE_QUAD_SYNC_PROC; + + SYNC_TX_QUAD_OUT <= sync_tx_quad_trans; + +end architecture gbe_tx_reset_arch; diff --git a/special/trb_net_i2cwire.vhd b/special/trb_net_i2cwire.vhd index 4445656..dd863f9 100644 --- a/special/trb_net_i2cwire.vhd +++ b/special/trb_net_i2cwire.vhd @@ -71,36 +71,6 @@ architecture trb_net_i2cwire_arch of trb_net_i2cwire is signal sda_drv : std_logic; signal scl_drv : std_logic; - - -- Components - component i2c_slim is - port( - CLOCK : in std_logic; - RESET : in std_logic; - -- I2C command / setup - I2C_GO_IN : in std_logic; -- startbit to trigger I2C actions - ACTION_IN : in std_logic; -- '0' -> write, '1' -> read - WORD_IN : in std_logic; -- '0' -> byte, '1' -> word - I2C_SPEED_IN : in std_logic_vector(5 downto 0); -- speed adjustment (to be defined) - I2C_ADDR_IN : in std_logic_vector(7 downto 0); -- I2C address byte (R/W bit is ignored) - I2C_CMD_IN : in std_logic_vector(7 downto 0); -- I2C command byte (sent after address byte) - I2C_DW_IN : in std_logic_vector(15 downto 0); -- data word for write command - I2C_DR_OUT : out std_logic_vector(15 downto 0); -- data word from read command - STATUS_OUT : out std_logic_vector(7 downto 0); -- status and error bits - VALID_OUT : out std_logic; - I2C_BUSY_OUT : out std_logic; - I2C_DONE_OUT : out std_logic; - -- I2C connections - SDA_IN : in std_logic; - SDA_OUT : out std_logic; - SCL_IN : in std_logic; - SCL_OUT : out std_logic; - -- Debug - BSM_OUT : out std_logic_vector(4 downto 0) - ); - end component i2c_slim; - - begin @@ -316,7 +286,7 @@ begin end if; end process THE_TIME_COUNTER_PROC; -THE_I2C_SLIM: i2c_slim +THE_I2C_SLIM: entity i2c_slim port map( CLOCK => CLK, RESET => RESET, diff --git a/special/trb_net_i2cwire2.vhd b/special/trb_net_i2cwire2.vhd index b3b2090..b59c2d7 100644 --- a/special/trb_net_i2cwire2.vhd +++ b/special/trb_net_i2cwire2.vhd @@ -72,35 +72,6 @@ architecture trb_net_i2cwire2_arch of trb_net_i2cwire2 is signal sda_drv : std_logic; signal scl_drv : std_logic; - - -- Components - component i2c_slim2 is - port( - CLOCK : in std_logic; - RESET : in std_logic; - -- I2C command / setup - I2C_GO_IN : in std_logic; -- startbit to trigger I2C actions - ACTION_IN : in std_logic; -- '0' -> write, '1' -> read - WORD_IN : in std_logic; -- '0' -> byte, '1' -> word - DIRECT_IN : in std_logic; -- '0' -> normal access, '1' -> direct read - I2C_SPEED_IN : in std_logic_vector(5 downto 0); -- speed adjustment (to be defined) - I2C_ADDR_IN : in std_logic_vector(7 downto 0); -- I2C address byte (R/W bit is ignored) - I2C_CMD_IN : in std_logic_vector(7 downto 0); -- I2C command byte (sent after address byte) - I2C_DW_IN : in std_logic_vector(15 downto 0); -- data word for write command - I2C_DR_OUT : out std_logic_vector(15 downto 0); -- data word from read command - STATUS_OUT : out std_logic_vector(7 downto 0); -- status and error bits - VALID_OUT : out std_logic; - I2C_BUSY_OUT : out std_logic; - I2C_DONE_OUT : out std_logic; - -- I2C connections - SDA_IN : in std_logic; - SDA_OUT : out std_logic; - SCL_IN : in std_logic; - SCL_OUT : out std_logic; - -- Debug - BSM_OUT : out std_logic_vector(3 downto 0) - ); - end component i2c_slim2; begin @@ -331,7 +302,7 @@ begin end if; end process THE_TIME_COUNTER_PROC; -THE_I2C_SLIM: i2c_slim2 +THE_I2C_SLIM: entity i2c_slim2 port map( CLOCK => CLK, RESET => RESET, diff --git a/trb_net16_api_base.vhd b/trb_net16_api_base.vhd index f4565fa..991b11a 100644 --- a/trb_net16_api_base.vhd +++ b/trb_net16_api_base.vhd @@ -225,111 +225,90 @@ begin --------------------------------------- -- a sbuf (to_int direction) --------------------------------------- --- gen_int_sbuf : if SECURE_MODE_TO_INT = 1 generate - SBUF: trb_net16_sbuf - generic map ( - VERSION => SBUF_VERSION) - port map ( - CLK => CLK, - RESET => RESET, - CLK_EN => CLK_EN, - COMB_DATAREADY_IN => next_INT_MASTER_DATAREADY_OUT, - COMB_next_READ_OUT => sbuf_next_READ, - COMB_READ_IN => '1', - COMB_DATA_IN => next_INT_MASTER_DATA_OUT, - COMB_PACKET_NUM_IN => next_INT_MASTER_PACKET_NUM_OUT, - SYN_DATAREADY_OUT => buf_INT_MASTER_DATAREADY_OUT, - SYN_DATA_OUT => INT_MASTER_DATA_OUT, - SYN_PACKET_NUM_OUT => buf_INT_MASTER_PACKET_NUM_OUT, - SYN_READ_IN => INT_MASTER_READ_IN, - STAT_BUFFER => sbuf_status(0) - ); + SBUF: trb_net16_sbuf + generic map ( + VERSION => SBUF_VERSION) + port map ( + CLK => CLK, + RESET => RESET, + CLK_EN => CLK_EN, + COMB_DATAREADY_IN => next_INT_MASTER_DATAREADY_OUT, + COMB_next_READ_OUT => sbuf_next_READ, + COMB_READ_IN => '1', + COMB_DATA_IN => next_INT_MASTER_DATA_OUT, + COMB_PACKET_NUM_IN => next_INT_MASTER_PACKET_NUM_OUT, + SYN_DATAREADY_OUT => buf_INT_MASTER_DATAREADY_OUT, + SYN_DATA_OUT => INT_MASTER_DATA_OUT, + SYN_PACKET_NUM_OUT => buf_INT_MASTER_PACKET_NUM_OUT, + SYN_READ_IN => INT_MASTER_READ_IN, + STAT_BUFFER => sbuf_status(0) + ); - process(CLK) - begin - if rising_edge(CLK) then - if RESET = '1' then - sbuf_free <= '0'; - elsif CLK_EN = '1' then - sbuf_free <= sbuf_next_READ or INT_MASTER_READ_IN; - end if; + process(CLK) + begin + if rising_edge(CLK) then + if RESET = '1' then + sbuf_free <= '0'; + elsif CLK_EN = '1' then + sbuf_free <= sbuf_next_READ or INT_MASTER_READ_IN; end if; - end process; --- end generate; - --- gen_int_nonsbuf : if SECURE_MODE_TO_INT = 0 generate --- buf_INT_MASTER_DATAREADY_OUT <= next_INT_MASTER_DATAREADY_OUT; --- INT_MASTER_DATA_OUT <= next_INT_MASTER_DATA_OUT; --- buf_INT_MASTER_PACKET_NUM_OUT <= next_INT_MASTER_PACKET_NUM_OUT; --- sbuf_free <= INT_MASTER_READ_IN; --- end generate; + end if; + end process; INT_MASTER_PACKET_NUM_OUT <= buf_INT_MASTER_PACKET_NUM_OUT; INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; - --------------------------------------- -- a sbuf (to_apl direction) --------------------------------------- --- gen_apl_sbuf : if SECURE_MODE_TO_APL = 1 generate - SBUF_TO_APL: trb_net16_sbuf - generic map ( - VERSION => SBUF_VERSION) - port map ( - CLK => CLK, - RESET => RESET, - CLK_EN => CLK_EN, - COMB_DATAREADY_IN => next_APL_DATAREADY_OUT, - COMB_next_READ_OUT => sbuf_to_apl_next_READ, - COMB_READ_IN => '1', - COMB_DATA_IN => next_APL_DATA_OUT, - COMB_PACKET_NUM_IN => next_APL_PACKET_NUM_OUT, - SYN_DATAREADY_OUT => reg_APL_DATAREADY_OUT, - SYN_DATA_OUT => reg_APL_DATA_OUT, - SYN_PACKET_NUM_OUT => reg_APL_PACKET_NUM_OUT, - SYN_READ_IN => APL_READ_IN, - STAT_BUFFER => sbuf_status(1) - ); - + SBUF_TO_APL: trb_net16_sbuf + generic map ( + VERSION => SBUF_VERSION) + port map ( + CLK => CLK, + RESET => RESET, + CLK_EN => CLK_EN, + COMB_DATAREADY_IN => next_APL_DATAREADY_OUT, + COMB_next_READ_OUT => sbuf_to_apl_next_READ, + COMB_READ_IN => '1', + COMB_DATA_IN => next_APL_DATA_OUT, + COMB_PACKET_NUM_IN => next_APL_PACKET_NUM_OUT, + SYN_DATAREADY_OUT => reg_APL_DATAREADY_OUT, + SYN_DATA_OUT => reg_APL_DATA_OUT, + SYN_PACKET_NUM_OUT => reg_APL_PACKET_NUM_OUT, + SYN_READ_IN => APL_READ_IN, + STAT_BUFFER => sbuf_status(1) + ); - SBUF_TO_APL2: trb_net_sbuf - generic map ( - VERSION => SBUF_VERSION, - DATA_WIDTH => 3) - port map ( - CLK => CLK, - RESET => RESET, - CLK_EN => CLK_EN, - COMB_DATAREADY_IN => next_APL_DATAREADY_OUT, - COMB_next_READ_OUT => open, - COMB_READ_IN => '1', - COMB_DATA_IN => next_APL_TYP_OUT, - SYN_DATAREADY_OUT => sbuf_apl_type_dataready, - SYN_DATA_OUT => buf_APL_TYP_OUT, - SYN_READ_IN => APL_READ_IN, - STAT_BUFFER => sbuf_status(2) - ); + SBUF_TO_APL2: trb_net_sbuf + generic map ( + VERSION => SBUF_VERSION, + DATA_WIDTH => 3) + port map ( + CLK => CLK, + RESET => RESET, + CLK_EN => CLK_EN, + COMB_DATAREADY_IN => next_APL_DATAREADY_OUT, + COMB_next_READ_OUT => open, + COMB_READ_IN => '1', + COMB_DATA_IN => next_APL_TYP_OUT, + SYN_DATAREADY_OUT => sbuf_apl_type_dataready, + SYN_DATA_OUT => buf_APL_TYP_OUT, + SYN_READ_IN => APL_READ_IN, + STAT_BUFFER => sbuf_status(2) + ); - reg_APL_TYP_OUT <= TYPE_ILLEGAL when reg_APL_DATAREADY_OUT = '0' else buf_APL_TYP_OUT; - process(CLK) - begin - if rising_edge(CLK) then - if RESET = '1' then - sbuf_to_apl_free <= '0'; - elsif CLK_EN = '1' then - sbuf_to_apl_free <= sbuf_to_apl_next_READ; - end if; + reg_APL_TYP_OUT <= TYPE_ILLEGAL when reg_APL_DATAREADY_OUT = '0' else buf_APL_TYP_OUT; + process(CLK) + begin + if rising_edge(CLK) then + if RESET = '1' then + sbuf_to_apl_free <= '0'; + elsif CLK_EN = '1' then + sbuf_to_apl_free <= sbuf_to_apl_next_READ; end if; - end process; --- end generate; - --- gen_apl_nonsbuf : if SECURE_MODE_TO_APL = 0 generate --- reg_APL_DATAREADY_OUT <= next_APL_DATAREADY_OUT; --- reg_APL_DATA_OUT <= next_APL_DATA_OUT; --- reg_APL_PACKET_NUM_OUT <= next_APL_PACKET_NUM_OUT; --- reg_APL_TYP_OUT <= next_APL_TYP_OUT; --- sbuf_to_apl_free <= APL_READ_IN; --- end generate; + end if; + end process; next_APL_DATA_OUT <= fifo_to_apl_data_out; next_APL_PACKET_NUM_OUT <= fifo_to_apl_long_packet_num_out; @@ -344,7 +323,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; -- save packet type --------------------------------------- - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -361,8 +340,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; -- select data for int direction --------------------------------------- - - process(current_combined_header, current_registered_trailer, current_data, out_select) + process( current_combined_header, current_registered_trailer, current_data, out_select ) begin case out_select is when HDR => next_INT_MASTER_DATA_OUT <= current_combined_header; @@ -372,8 +350,6 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end case; end process; - - process(master_counter, fifo_to_int_data_out, registered_trailer_F1, registered_trailer_F2, registered_trailer_F3, registered_trailer_F0, registered_header_F0, registered_header_F1, registered_header_F2, @@ -424,48 +400,29 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; -- fifo to apl --------------------------------------- --- GEN_FIFO_TO_APL: if FIFO_TO_APL_DEPTH >0 generate - FIFO_TO_APL: trb_net16_fifo - generic map ( - DEPTH => FIFO_TO_APL_DEPTH, - USE_VENDOR_CORES => USE_VENDOR_CORES) - port map ( - CLK => CLK, - RESET => RESET, - CLK_EN => CLK_EN, - DATA_IN => fifo_to_apl_data_in, - PACKET_NUM_IN => fifo_to_apl_packet_num_in, - WRITE_ENABLE_IN => fifo_to_apl_write, - DATA_OUT => next_fifo_to_apl_data_out, - PACKET_NUM_OUT => next_fifo_to_apl_packet_num_out, - READ_ENABLE_IN => fifo_to_apl_read, - DATA_COUNT_OUT => fifo_to_apl_data_count, - FULL_OUT => fifo_to_apl_full, - EMPTY_OUT => next_fifo_to_apl_empty - ); --- end generate; - --- GEN_DUMMY_FIFO_TO_APL: if FIFO_TO_APL_DEPTH = 0 generate --- FIFO_TO_APL: trb_net16_dummy_fifo --- port map ( --- CLK => CLK, --- RESET => RESET, --- CLK_EN => CLK_EN, --- DATA_IN => fifo_to_apl_data_in, --- PACKET_NUM_IN => fifo_to_apl_packet_num_in, --- WRITE_ENABLE_IN => fifo_to_apl_write, --- DATA_OUT => next_fifo_to_apl_data_out, --- PACKET_NUM_OUT => next_fifo_to_apl_packet_num_out, --- READ_ENABLE_IN => fifo_to_apl_read, --- FULL_OUT => fifo_to_apl_full, --- EMPTY_OUT => next_fifo_to_apl_empty --- ); --- end generate; + FIFO_TO_APL: trb_net16_fifo + generic map ( + DEPTH => FIFO_TO_APL_DEPTH, + USE_VENDOR_CORES => USE_VENDOR_CORES) + port map ( + CLK => CLK, + RESET => RESET, + CLK_EN => CLK_EN, + DATA_IN => fifo_to_apl_data_in, + PACKET_NUM_IN => fifo_to_apl_packet_num_in, + WRITE_ENABLE_IN => fifo_to_apl_write, + DATA_OUT => next_fifo_to_apl_data_out, + PACKET_NUM_OUT => next_fifo_to_apl_packet_num_out, + READ_ENABLE_IN => fifo_to_apl_read, + DATA_COUNT_OUT => fifo_to_apl_data_count, + FULL_OUT => fifo_to_apl_full, + EMPTY_OUT => next_fifo_to_apl_empty + ); --------------------------------------- -- keep track of fifo to apl read operations --------------------------------------- - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -561,7 +518,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; -- keep track of fifo to int read operations --------------------------------------- - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -578,7 +535,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end if; end process; - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if APL_SEND_IN = '1' then @@ -597,7 +554,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; fifo_to_int_long_packet_num_out(0) <= fifo_to_int_packet_num_out(0); fifo_to_int_long_packet_num_out(1) <= not saved_fifo_to_int_long_packet_num_out(1) when last_fifo_to_int_read = '1' and not saved_fifo_to_int_long_packet_num_out(2) = '1' and saved_fifo_to_int_long_packet_num_out(0) = '1' else saved_fifo_to_int_long_packet_num_out(1); - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -613,7 +570,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; fifo_to_apl_long_packet_num_out(0) <= fifo_to_apl_packet_num_out(0); fifo_to_apl_long_packet_num_out(1) <= not saved_fifo_to_apl_long_packet_num_out(1) when last_fifo_to_apl_read = '1' and not saved_fifo_to_apl_long_packet_num_out(2) = '1' and saved_fifo_to_apl_long_packet_num_out(0) = '1' else saved_fifo_to_apl_long_packet_num_out(1); - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -624,8 +581,6 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end if; end process; - - --------------------------------------- --state machine for direction to APL --------------------------------------- @@ -792,7 +747,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end process; - PROC_FSM_REG : process(CLK) + PROC_FSM_REG: process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -815,7 +770,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end if; end process; - PROC_SEQ_CNT : process(CLK) + PROC_SEQ_CNT: process( CLK ) begin if rising_edge(CLK) then if RESET = '1' or CTRL_SEQNR_RESET = '1' then @@ -826,8 +781,6 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end if; end process; - - PROC_ENDP_REACHED : process(CLK) begin if rising_edge(CLK) then @@ -841,14 +794,10 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end if; end process; - - - --------------------------------------------------------------------- --Connection to FIFOs --------------------------------------------------------------------- - -- connect Transmitter port fifo_to_int_data_in <= APL_DATA_IN; fifo_to_int_packet_num_in <= APL_PACKET_NUM_IN(2) & APL_PACKET_NUM_IN(0); @@ -865,7 +814,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; --Running Signals --------------------------------------------------------------------- - RUN_OUT_gen : process(CLK) + RUN_OUT_gen: process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -889,7 +838,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end process; APL_RUN_OUT <= buf_APL_RUN_OUT; - RUNNING_gen : process(CLK) + RUNNING_gen: process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -914,7 +863,6 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; --Header & Trailer Words --------------------------------------------------------------------- - --get target address from active APL gentarget1: if API_TYPE = 1 generate combined_header_F1 <= APL_TARGET_ADDRESS_IN; @@ -922,7 +870,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; --save target address for passive api gentarget0: if API_TYPE = 0 generate - reg_hdr_f1: process(CLK) + reg_hdr_f1: process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -950,7 +898,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; combined_trailer_F3(11 downto 4) <= sequence_counter; -- SEQNR combined_trailer_F3(3 downto 0) <= APL_DTYPE_IN; - PROC_REG3 : process(CLK) + PROC_REG3: process( CLK ) begin if rising_edge(CLK) then if update_registered_trailer = '1' then @@ -967,7 +915,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end if; end process; - PROC_REG_HDR : process(CLK) + PROC_REG_HDR: process( CLK ) begin if rising_edge(CLK) then if update_registered_header = '1' then @@ -983,7 +931,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; --Decode FSM states --------------------------------------------------------------------- - process(state_to_apl) + process( state_to_apl ) begin case state_to_apl is when sa_IDLE => state_bits_to_apl <= "000"; @@ -994,7 +942,7 @@ INT_MASTER_DATAREADY_OUT <= buf_INT_MASTER_DATAREADY_OUT; end case; end process; - process(state_to_int) + process( state_to_int ) begin case state_to_int is when IDLE => state_bits_to_int <= "000"; diff --git a/trb_net16_endpoint_standalone_sctrl.vhd b/trb_net16_endpoint_standalone_sctrl.vhd index 39404ca..e186f7c 100644 --- a/trb_net16_endpoint_standalone_sctrl.vhd +++ b/trb_net16_endpoint_standalone_sctrl.vhd @@ -9,7 +9,6 @@ use work.trb_net_std.all; use work.trb_net_components.all; use work.config.all; - entity trb_net16_endpoint_standalone_sctrl is generic ( FIFO_TO_INT_DEPTH : integer := 6; diff --git a/trb_net16_regIO.vhd b/trb_net16_regIO.vhd index 23e3d6e..27d1870 100644 --- a/trb_net16_regIO.vhd +++ b/trb_net16_regIO.vhd @@ -8,9 +8,6 @@ use work.trb_net_components.all; use work.version.all; use work.config.all; - - - entity trb_net16_regIO is generic ( NUM_STAT_REGS : integer range 0 to 6 := 3; --log2 of number of status registers @@ -197,7 +194,7 @@ begin --------------------------------------------------------------------- --5bit address decoder for registers --------------------------------------------------------------------- - pattern_gen_inst : trb_net_pattern_gen + pattern_gen_inst: trb_net_pattern_gen generic map( WIDTH => 5 ) @@ -211,7 +208,7 @@ begin -- trbnet addresses --------------------------------------------------------------------- - the_addresses : trb_net16_addresses + the_addresses: trb_net16_addresses generic map( INIT_ADDRESS => INIT_ADDRESS, INIT_UNIQUE_ID => INIT_UNIQUE_ID, @@ -241,12 +238,11 @@ begin STAT_DEBUG => buf_STAT_ADDR_DEBUG ); - --------------------------------------------------------------------- -- Main State Machine --------------------------------------------------------------------- - fsm : process(API_DATA_IN, API_PACKET_NUM_IN, API_TYP_IN, API_DATAREADY_IN, API_READ_IN, + fsm: process(API_DATA_IN, API_PACKET_NUM_IN, API_TYP_IN, API_DATAREADY_IN, API_READ_IN, address, saved_Reg_high, saved_Reg_low, saved_operation, current_state, buf_API_SEND_OUT, next_packet_counter, buf_API_DATA_OUT, buf_API_SHORT_TRANSFER_OUT, REGISTERS_IN, buf_REGISTERS_OUT, reg_enable_pattern, DAT_NO_MORE_DATA_IN, @@ -664,7 +660,7 @@ begin end process; - reg_fsm : process(CLK) + reg_fsm: process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -716,7 +712,7 @@ begin --------------------------------------------------------------------- -- Packet Numbers --------------------------------------------------------------------- - reg_packet_counter : process(CLK) + reg_packet_counter: process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -727,7 +723,7 @@ begin end if; end process; - next_packet_counter_proc : process(API_READ_IN, buf_API_DATAREADY_OUT, packet_counter) + next_packet_counter_proc: process( API_READ_IN, buf_API_DATAREADY_OUT, packet_counter ) begin if buf_API_DATAREADY_OUT = '1' and API_READ_IN = '1' then if packet_counter = "011" then @@ -743,7 +739,7 @@ begin --------------------------------------------------------------------- -- Generate output to API --------------------------------------------------------------------- - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if RESET = '1' then @@ -792,7 +788,7 @@ begin -- Read from DAT port --------------------------------------------------------------------- --save Dataready_in in case API can not read immediately - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if RESET = '1' or current_state = IDLE then @@ -805,7 +801,7 @@ begin end if; end process; - process(CLK) + process( CLK ) begin if rising_edge(CLK) then if DAT_DATAREADY_IN = '1' then @@ -974,7 +970,7 @@ begin COMMON_CTRL_REG_OUT <= buf_COMMON_CTRL_REG_OUT; - PROC_STROBES : process(CLK) + PROC_STROBES: process( CLK ) begin if rising_edge(CLK) then COMMON_STAT_REG_STROBE <= next_COMMON_STAT_REG_STROBE; @@ -1009,7 +1005,7 @@ begin STAT(30) <= API_READ_IN; STAT(31) <= '0'; - process(current_state) + process( current_state ) begin case current_state is when IDLE => state_bits <= "0000"; @@ -1031,7 +1027,6 @@ begin end case; end process; - STAT_ADDR_DEBUG(2 downto 0) <= state_bits(2 downto 0); STAT_ADDR_DEBUG(3) <= ADR_DONT_UNDERSTAND; STAT_ADDR_DEBUG(4) <= API_DATAREADY_IN; @@ -1043,7 +1038,4 @@ begin STAT_ADDR_DEBUG(14) <= ADR_SEND_OUT; STAT_ADDR_DEBUG(15) <= ADR_DATAREADY_OUT; - - end architecture; -