------------------------------------------------------------------------------- -- -- Copyright (C) 2010 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, dp_lib, tech_tse_lib; USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.tb_common_mem_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; USE common_lib.eth_layers_pkg.ALL; USE WORK.eth_pkg.ALL; USE tech_tse_lib.tech_tse_pkg.ALL; USE tech_tse_lib.tb_tech_tse_pkg.ALL; ENTITY tb_eth IS -- Test bench control parameters GENERIC ( -- g_data_type = c_tb_tse_data_type_symbols = 0 -- g_data_type = c_tb_tse_data_type_counter = 1 -- g_data_type = c_tb_tse_data_type_arp = 2 -- g_data_type = c_tb_tse_data_type_ping = 3 -- g_data_type = c_tb_tse_data_type_udp = 4 g_data_type : NATURAL := c_tb_tse_data_type_udp ); END tb_eth; ARCHITECTURE tb OF tb_eth IS -- as 10 -- run 100 us CONSTANT sys_clk_period : TIME := 10 ns; -- 100 MHz CONSTANT eth_clk_period : TIME := 8 ns; -- 125 MHz CONSTANT cable_delay : TIME := 12 ns; CONSTANT c_cross_clock_domain : BOOLEAN := TRUE; -- use FALSE when mm_clk and st_clk are the same, else use TRUE to cross the clock domain -- TSE constants CONSTANT c_promis_en : BOOLEAN := FALSE; CONSTANT c_tx_ready_latency : NATURAL := c_tse_tx_ready_latency; -- 0, 1 are supported, must match TSE MAC c_tse_tx_ready_latency CONSTANT c_nof_tx_not_valid : NATURAL := 0; -- when > 0 then pull tx valid low for c_nof_tx_not_valid beats during tx -- Payload user data CONSTANT c_tb_nof_data : NATURAL := 0; -- nof UDP user data, nof ping padding data CONSTANT c_tb_ip_nof_data : NATURAL := c_udp_header_len + c_tb_nof_data; -- nof IP data, -- also suits ICMP, because c_icmp_header_len = c_udp_header_len CONSTANT c_tb_reply_payload : BOOLEAN := TRUE; -- TRUE copy rx payload into response payload, else header only (e.g. for ARP) -- Packet headers -- . Ethernet header CONSTANT c_word_align : STD_LOGIC_VECTOR(c_eth_word_align_w-1 DOWNTO 0) := TO_UVEC(c_eth_word_align, c_eth_word_align_w); CONSTANT c_lcu_src_mac : STD_LOGIC_VECTOR(c_eth_mac_slv'RANGE) := X"10FA01020300"; CONSTANT c_dut_src_mac : STD_LOGIC_VECTOR(c_eth_mac_slv'RANGE) := X"123456789ABC"; -- = 12-34-56-78-9A-BC CONSTANT c_dut_src_mac_hi : NATURAL := TO_UINT(c_dut_src_mac(c_eth_mac_addr_w-1 DOWNTO c_word_w)); CONSTANT c_dut_src_mac_lo : NATURAL := TO_UINT(c_dut_src_mac( c_word_w-1 DOWNTO 0)); -- support only ARP and IPv4 over ETH CONSTANT c_dut_ethertype : NATURAL := sel_a_b(g_data_type-c_tb_tse_data_type_arp, c_eth_type_ip, c_eth_type_arp); CONSTANT c_tx_eth_header : t_eth_header := (word_align => c_word_align, dst_mac => c_dut_src_mac, src_mac => c_lcu_src_mac, eth_type => TO_UVEC(c_dut_ethertype, c_eth_type_w)); CONSTANT c_exp_eth_header : t_eth_header := (word_align => c_tx_eth_header.word_align, -- = dst_mac => c_tx_eth_header.src_mac, -- \/ src_mac => c_tx_eth_header.dst_mac, -- /\ eth_type => c_tx_eth_header.eth_type); -- = -- . IP header CONSTANT c_lcu_ip_addr : NATURAL := 16#05060708#; -- = 05:06:07:08 CONSTANT c_dut_ip_addr : NATURAL := 16#01020304#; CONSTANT c_tb_ip_total_length : NATURAL := c_ip_total_length + c_tb_ip_nof_data; -- support only ping protocol or UDP protocol over IP CONSTANT c_tb_ip_protocol : NATURAL := sel_a_b(g_data_type-c_tb_tse_data_type_ping, c_ip_protocol_udp, c_ip_protocol_icmp); CONSTANT c_tx_ip_header : t_ip_header := (version => TO_UVEC(c_ip_version, c_ip_version_w), header_length => TO_UVEC(c_ip_header_length, c_ip_header_length_w), services => TO_UVEC(c_ip_services, c_ip_services_w), total_length => TO_UVEC(c_tb_ip_total_length, c_ip_total_length_w), identification => TO_UVEC(c_ip_identification, c_ip_identification_w), flags => TO_UVEC(c_ip_flags, c_ip_flags_w), fragment_offset => TO_UVEC(c_ip_fragment_offset, c_ip_fragment_offset_w), time_to_live => TO_UVEC(c_ip_time_to_live, c_ip_time_to_live_w), protocol => TO_UVEC(c_tb_ip_protocol, c_ip_protocol_w), header_checksum => TO_UVEC(c_ip_header_checksum, c_ip_header_checksum_w), -- init value (or try 0xEBBD = 60349) src_ip_addr => TO_UVEC(c_lcu_ip_addr, c_ip_addr_w), dst_ip_addr => TO_UVEC(c_dut_ip_addr, c_ip_addr_w)); CONSTANT c_exp_ip_header : t_ip_header := (version => c_tx_ip_header.version, -- = header_length => c_tx_ip_header.header_length, -- = services => c_tx_ip_header.services, -- = total_length => c_tx_ip_header.total_length, -- = identification => c_tx_ip_header.identification, -- = flags => c_tx_ip_header.flags, -- = fragment_offset => c_tx_ip_header.fragment_offset, -- = time_to_live => c_tx_ip_header.time_to_live, -- = protocol => c_tx_ip_header.protocol, -- = header_checksum => c_tx_ip_header.header_checksum, -- init value src_ip_addr => c_tx_ip_header.dst_ip_addr, -- \/ dst_ip_addr => c_tx_ip_header.src_ip_addr); -- /\ -- . ARP packet CONSTANT c_tx_arp_packet : t_arp_packet := (htype => TO_UVEC(c_arp_htype, c_arp_htype_w), ptype => TO_UVEC(c_arp_ptype, c_arp_ptype_w), hlen => TO_UVEC(c_arp_hlen, c_arp_hlen_w), plen => TO_UVEC(c_arp_plen, c_arp_plen_w), oper => TO_UVEC(c_arp_oper_request, c_arp_oper_w), sha => c_lcu_src_mac, spa => TO_UVEC(c_lcu_ip_addr, c_ip_addr_w), tha => c_dut_src_mac, tpa => TO_UVEC(c_dut_ip_addr, c_ip_addr_w)); CONSTANT c_exp_arp_packet : t_arp_packet := (htype => c_tx_arp_packet.htype, ptype => c_tx_arp_packet.ptype, hlen => c_tx_arp_packet.hlen, plen => c_tx_arp_packet.plen, oper => TO_UVEC(c_arp_oper_reply, c_arp_oper_w), -- reply sha => c_tx_arp_packet.tha, -- \/ spa => c_tx_arp_packet.tpa, -- /\ \/ tha => c_tx_arp_packet.sha, -- / \ /\ tpa => c_tx_arp_packet.spa); -- / \ CONSTANT c_arp_htype : NATURAL := 1; -- Hardware type, 1=ethernet CONSTANT c_arp_ptype : NATURAL := c_eth_type_ip; -- Protocol type, do ARP for IPv4 CONSTANT c_arp_hlen : NATURAL := c_eth_mac_addr_len; -- Hardware length = 6 CONSTANT c_arp_plen : NATURAL := c_ip_addr_len; -- Protocol length = 4 CONSTANT c_arp_oper : NATURAL := 1; -- Operator, 1=request, (2=reply) -- . ICMP header CONSTANT c_tx_icmp_header : t_icmp_header := (msg_type => TO_UVEC(c_icmp_msg_type_request, c_icmp_msg_type_w), -- ping request code => TO_UVEC(c_icmp_code, c_icmp_code_w), checksum => TO_UVEC(c_icmp_checksum, c_icmp_checksum_w), -- init value id => TO_UVEC(c_icmp_id, c_icmp_id_w), sequence => TO_UVEC(c_icmp_sequence, c_icmp_sequence_w)); CONSTANT c_exp_icmp_header : t_icmp_header := (msg_type => TO_UVEC(c_icmp_msg_type_reply, c_icmp_msg_type_w), -- ping reply code => c_tx_icmp_header.code, checksum => c_tx_icmp_header.checksum, -- init value id => c_tx_icmp_header.id, sequence => c_tx_icmp_header.sequence); -- . UDP header CONSTANT c_dut_udp_port_ctrl : NATURAL := 11; -- ETH demux UDP for control CONSTANT c_dut_udp_port_st0 : NATURAL := 57; -- ETH demux UDP port 0 CONSTANT c_dut_udp_port_st1 : NATURAL := 58; -- ETH demux UDP port 1 CONSTANT c_dut_udp_port_st2 : NATURAL := 59; -- ETH demux UDP port 2 CONSTANT c_dut_udp_port_en : NATURAL := 16#10000#; -- ETH demux UDP port enable bit 16 CONSTANT c_lcu_udp_port : NATURAL := 10; -- UDP port used for src_port CONSTANT c_dut_udp_port_st : NATURAL := c_dut_udp_port_st0; -- UDP port used for dst_port CONSTANT c_tb_udp_total_length : NATURAL := c_udp_total_length + c_tb_nof_data; CONSTANT c_tx_udp_header : t_udp_header := (src_port => TO_UVEC(c_lcu_udp_port, c_udp_port_w), dst_port => TO_UVEC(c_dut_udp_port_ctrl, c_udp_port_w), -- or use c_dut_udp_port_st# total_length => TO_UVEC(c_tb_udp_total_length, c_udp_total_length_w), checksum => TO_UVEC(c_udp_checksum, c_udp_checksum_w)); -- init value CONSTANT c_exp_udp_header : t_udp_header := (src_port => c_tx_udp_header.dst_port, -- \/ dst_port => c_tx_udp_header.src_port, -- /\ total_length => c_tx_udp_header.total_length, -- = checksum => c_tx_udp_header.checksum); -- init value SIGNAL tx_total_header : t_eth_total_header; -- transmitted packet header SIGNAL exp_total_header : t_eth_total_header; -- expected received packet header -- ETH control CONSTANT c_dut_control_rx_en : NATURAL := 2**c_eth_mm_reg_control_bi.rx_en; CONSTANT c_dut_control_tx_en : NATURAL := 2**c_eth_mm_reg_control_bi.tx_en; -- Clocks and reset SIGNAL eth_clk : STD_LOGIC := '0'; -- tse reference clock SIGNAL sys_clk : STD_LOGIC := '0'; -- system clock SIGNAL st_clk : STD_LOGIC; -- stream clock SIGNAL st_rst : STD_LOGIC := '1'; -- reset synchronous with st_clk SIGNAL mm_clk : STD_LOGIC; -- memory-mapped bus clock SIGNAL mm_rst : STD_LOGIC := '1'; -- reset synchronous with mm_clk -- ETH TSE interface SIGNAL dut_tse_init : STD_LOGIC := '1'; SIGNAL dut_eth_init : STD_LOGIC := '1'; SIGNAL eth_tse_miso : t_mem_miso; SIGNAL eth_tse_mosi : t_mem_mosi; SIGNAL eth_psc_access : STD_LOGIC; SIGNAL eth_txp : STD_LOGIC; SIGNAL eth_rxp : STD_LOGIC; SIGNAL eth_led : t_tse_led; -- ETH MM registers interface SIGNAL eth_reg_miso : t_mem_miso; SIGNAL eth_reg_mosi : t_mem_mosi; SIGNAL eth_reg_interrupt : STD_LOGIC; SIGNAL eth_mm_reg_control : t_eth_mm_reg_control; SIGNAL eth_mm_reg_status : t_eth_mm_reg_status; SIGNAL eth_ram_miso : t_mem_miso; SIGNAL eth_ram_mosi : t_mem_mosi; -- ETH UDP data path interface SIGNAL udp_tx_sosi_arr : t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0); SIGNAL udp_tx_siso_arr : t_dp_siso_arr(c_eth_nof_udp_ports-1 DOWNTO 0); SIGNAL udp_rx_siso_arr : t_dp_siso_arr(c_eth_nof_udp_ports-1 DOWNTO 0); SIGNAL udp_rx_sosi_arr : t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0); -- LCU TSE interface SIGNAL lcu_init : STD_LOGIC := '1'; SIGNAL lcu_tse_miso : t_mem_miso; SIGNAL lcu_tse_mosi : t_mem_mosi; SIGNAL lcu_psc_access : STD_LOGIC; SIGNAL lcu_tx_en : STD_LOGIC := '1'; SIGNAL lcu_tx_siso : t_dp_siso; SIGNAL lcu_tx_sosi : t_dp_sosi; SIGNAL lcu_tx_mac_in : t_tse_tx_mac; SIGNAL lcu_tx_mac_out : t_tse_tx_mac; SIGNAL lcu_rx_sosi : t_dp_sosi; SIGNAL lcu_rx_siso : t_dp_siso; SIGNAL lcu_rx_mac_out : t_tse_rx_mac; SIGNAL lcu_txp : STD_LOGIC; SIGNAL lcu_rxp : STD_LOGIC; SIGNAL lcu_led : t_tse_led; BEGIN -- run 50 us eth_clk <= NOT eth_clk AFTER eth_clk_period/2; -- TSE reference clock sys_clk <= NOT sys_clk AFTER sys_clk_period/2; -- System clock mm_clk <= sys_clk; st_clk <= sys_clk; p_reset : PROCESS BEGIN -- reset release st_rst <= '1'; mm_rst <= '1'; FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; mm_rst <= '0'; WAIT UNTIL rising_edge(st_clk); st_rst <= '0'; FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; WAIT; END PROCESS; -- Use signal to leave unused fields 'X' tx_total_header.eth <= c_tx_eth_header; tx_total_header.arp <= c_tx_arp_packet; tx_total_header.ip <= c_tx_ip_header; tx_total_header.icmp <= c_tx_icmp_header; tx_total_header.udp <= c_tx_udp_header; exp_total_header.eth <= c_exp_eth_header; exp_total_header.arp <= c_exp_arp_packet; exp_total_header.ip <= c_exp_ip_header; exp_total_header.icmp <= c_exp_icmp_header; exp_total_header.udp <= c_exp_udp_header; ------------------------------------------------------------------------------ -- DUT ------------------------------------------------------------------------------ p_tse_setup : PROCESS BEGIN dut_tse_init <= '1'; eth_tse_mosi.wr <= '0'; eth_tse_mosi.rd <= '0'; -- Wait for ETH init WHILE dut_eth_init='1' LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; -- Setup the TSE MAC proc_tse_setup(c_promis_en, c_tse_tx_fifo_depth, c_tse_rx_fifo_depth, c_tx_ready_latency, c_dut_src_mac, eth_psc_access, mm_clk, eth_tse_miso, eth_tse_mosi); dut_tse_init <= '0'; WAIT; END PROCESS; p_eth_control : PROCESS VARIABLE v_eth_control_word : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); BEGIN -- ETH setup dut_eth_init <= '1'; eth_reg_mosi.wr <= '0'; eth_reg_mosi.rd <= '0'; eth_ram_mosi.address <= (OTHERS=>'0'); eth_ram_mosi.wr <= '0'; eth_ram_mosi.rd <= '0'; -- Wait for reset release WHILE mm_rst='1' LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; -- Setup the DEMUX UDP proc_mem_mm_bus_wr(c_eth_reg_demux_wi+0, c_dut_udp_port_en+c_dut_udp_port_st0, mm_clk, eth_reg_miso, eth_reg_mosi); -- UDP port stream 0 proc_mem_mm_bus_wr(c_eth_reg_demux_wi+1, c_dut_udp_port_en+c_dut_udp_port_st1, mm_clk, eth_reg_miso, eth_reg_mosi); -- UDP port stream 1 proc_mem_mm_bus_wr(c_eth_reg_demux_wi+2, c_dut_udp_port_en+c_dut_udp_port_st2, mm_clk, eth_reg_miso, eth_reg_mosi); -- UDP port stream 2 proc_mem_mm_bus_rd(c_eth_reg_demux_wi+0, mm_clk, eth_reg_miso, eth_reg_mosi); proc_mem_mm_bus_rd(c_eth_reg_demux_wi+1, mm_clk, eth_reg_miso, eth_reg_mosi); proc_mem_mm_bus_rd(c_eth_reg_demux_wi+2, mm_clk, eth_reg_miso, eth_reg_mosi); -- Setup the RX config proc_mem_mm_bus_wr(c_eth_reg_config_wi+0, c_dut_src_mac_lo, mm_clk, eth_reg_miso, eth_reg_mosi); -- control MAC address lo word proc_mem_mm_bus_wr(c_eth_reg_config_wi+1, c_dut_src_mac_hi, mm_clk, eth_reg_miso, eth_reg_mosi); -- control MAC address hi halfword proc_mem_mm_bus_wr(c_eth_reg_config_wi+2, c_dut_ip_addr, mm_clk, eth_reg_miso, eth_reg_mosi); -- control IP address proc_mem_mm_bus_wr(c_eth_reg_config_wi+3, c_dut_udp_port_ctrl, mm_clk, eth_reg_miso, eth_reg_mosi); -- control UDP port -- Enable RX proc_mem_mm_bus_wr(c_eth_reg_control_wi+0, c_dut_control_rx_en, mm_clk, eth_reg_miso, eth_reg_mosi); -- control rx en dut_eth_init <= '0'; -- Wait for TSE init WHILE dut_tse_init='1' LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; -- Response control WHILE TRUE LOOP eth_mm_reg_status <= c_eth_mm_reg_status_rst; eth_mm_reg_control <= c_eth_mm_reg_control_rst; -- wait for rx_avail interrupt IF eth_reg_interrupt='1' THEN -- read status register to read the status proc_mem_mm_bus_rd(c_eth_reg_status_wi+0, mm_clk, eth_reg_miso, eth_reg_mosi); -- read result available in eth_mm_reg_status proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); eth_mm_reg_status <= func_eth_mm_reg_status(eth_reg_miso.rddata); WAIT UNTIL rising_edge(mm_clk); -- write status register to acknowledge the interrupt proc_mem_mm_bus_wr(c_eth_reg_status_wi+0, 0, mm_clk, eth_reg_miso, eth_reg_mosi); -- void value -- prepare control register for response IF c_tb_reply_payload=TRUE THEN eth_mm_reg_control.tx_nof_words <= INCR_UVEC(eth_mm_reg_status.rx_nof_words, -1); -- -1 to skip the CRC word for the response eth_mm_reg_control.tx_empty <= eth_mm_reg_status.rx_empty; ELSE eth_mm_reg_control.tx_nof_words <= TO_UVEC(c_eth_total_header_nof_words, c_eth_max_frame_nof_words_w); eth_mm_reg_control.tx_empty <= TO_UVEC(0, c_eth_empty_w); END IF; eth_mm_reg_control.tx_en <= '1'; eth_mm_reg_control.rx_en <= '1'; WAIT UNTIL rising_edge(mm_clk); -- wait for interrupt removal due to status register read access WHILE eth_reg_interrupt='1' LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; -- write control register to enable tx IF c_tb_reply_payload=TRUE THEN -- . copy the received payload to the response payload (overwrite part of the default response header in case of raw ETH) FOR I IN func_tb_tse_header_size(g_data_type) TO TO_UINT(eth_mm_reg_control.tx_nof_words)-1 LOOP proc_mem_mm_bus_rd(c_eth_ram_rx_offset+I, mm_clk, eth_ram_miso, eth_ram_mosi); proc_mem_mm_bus_rd_latency(c_mem_ram_rd_latency, mm_clk); proc_mem_mm_bus_wr(c_eth_ram_tx_offset+I, TO_SINT(eth_ram_miso.rddata(c_word_w-1 DOWNTO 0)), mm_clk, eth_ram_miso, eth_ram_mosi); END LOOP; --ELSE -- . only reply header END IF; v_eth_control_word := func_eth_mm_reg_control(eth_mm_reg_control); proc_mem_mm_bus_wr(c_eth_reg_control_wi+0, TO_UINT(v_eth_control_word), mm_clk, eth_reg_miso, eth_reg_mosi); -- write continue register to make the ETH module continue proc_mem_mm_bus_wr(c_eth_reg_continue_wi, 0, mm_clk, eth_reg_miso, eth_reg_mosi); -- void value END IF; WAIT UNTIL rising_edge(mm_clk); END LOOP; WAIT; END PROCESS; ------------------------------------------------------------------------------ -- LCU ------------------------------------------------------------------------------ p_lcu_setup : PROCESS BEGIN lcu_init <= '1'; lcu_tse_mosi.wr <= '0'; lcu_tse_mosi.rd <= '0'; -- Wait for reset release WHILE mm_rst='1' LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; -- Setup the LCU TSE MAC proc_tse_setup(c_promis_en, c_tse_tx_fifo_depth, c_tse_rx_fifo_depth, c_tx_ready_latency, c_lcu_src_mac, lcu_psc_access, mm_clk, lcu_tse_miso, lcu_tse_mosi); -- Wait for DUT init done WHILE dut_tse_init/='0' LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP; lcu_init <= '0'; WAIT; END PROCESS; p_lcu_transmitter : PROCESS BEGIN -- . Avalon ST lcu_tx_sosi.data <= (OTHERS=>'0'); lcu_tx_sosi.valid <= '0'; lcu_tx_sosi.sop <= '0'; lcu_tx_sosi.eop <= '0'; lcu_tx_sosi.empty <= (OTHERS=>'0'); lcu_tx_sosi.err <= (OTHERS=>'0'); -- . MAC specific lcu_tx_mac_in.crc_fwd <= '0'; -- when '0' then TSE MAC generates the TX CRC field WHILE lcu_init/='0' LOOP WAIT UNTIL rising_edge(st_clk); END LOOP; FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(st_clk); END LOOP; -- proc_tse_tx_packet(tx_total_header, 100, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); FOR I IN 0 TO 40 LOOP proc_tse_tx_packet(tx_total_header, I, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); --FOR J IN 0 TO 9 LOOP WAIT UNTIL rising_edge(st_clk); END LOOP; END LOOP; -- proc_tse_tx_packet(tx_total_header, 104, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 105, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 1472, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 1500, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 101, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 1000, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 102, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 1000, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 103, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 104, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); -- proc_tse_tx_packet(tx_total_header, 105, g_data_type, c_tx_ready_latency, c_nof_tx_not_valid, st_clk, lcu_tx_en, lcu_tx_siso, lcu_tx_sosi); WAIT; END PROCESS; p_lcu_receiver : PROCESS BEGIN -- . Avalon ST lcu_rx_siso <= c_dp_siso_hold; WHILE lcu_init/='0' LOOP WAIT UNTIL rising_edge(st_clk); END LOOP; -- Verification of multiple rx packets is only supported when all packets -- are of the same g_data_type, because the rx process can only support -- one expected result. The proc_tse_rx_packet does not (yet) interpret the -- actually received packet, it relies on the preset expected total_header. -- Receive forever WHILE TRUE LOOP proc_tse_rx_packet(exp_total_header, g_data_type, st_clk, lcu_rx_sosi, lcu_rx_siso); END LOOP; WAIT; END PROCESS; -- Wire ethernet cable between lcu and dut eth_rxp <= TRANSPORT lcu_txp AFTER cable_delay; lcu_rxp <= TRANSPORT eth_txp AFTER cable_delay; gen_udp_rx_siso_rdy: FOR i IN 0 TO c_eth_nof_udp_ports-1 GENERATE udp_rx_siso_arr(i).ready <= '1'; END GENERATE; dut : ENTITY work.eth GENERIC MAP ( g_cross_clock_domain => c_cross_clock_domain ) PORT MAP ( -- Clocks and reset mm_rst => mm_rst, mm_clk => mm_clk, eth_clk => eth_clk, st_rst => st_rst, st_clk => st_clk, -- UDP transmit interface -- . ST sink udp_tx_snk_in_arr => udp_tx_sosi_arr, udp_tx_snk_out_arr => udp_tx_siso_arr, -- UDP receive interface -- . ST source udp_rx_src_in_arr => udp_rx_siso_arr, udp_rx_src_out_arr => udp_rx_sosi_arr, -- Control Memory Mapped Slaves tse_sla_in => eth_tse_mosi, tse_sla_out => eth_tse_miso, reg_sla_in => eth_reg_mosi, reg_sla_out => eth_reg_miso, reg_sla_interrupt => eth_reg_interrupt, ram_sla_in => eth_ram_mosi, ram_sla_out => eth_ram_miso, -- PHY interface eth_txp => eth_txp, eth_rxp => eth_rxp, -- LED interface tse_led => eth_led ); lcu : ENTITY work.tse PORT MAP ( -- Clocks and reset mm_rst => mm_rst, mm_clk => mm_clk, eth_clk => eth_clk, tx_snk_clk => st_clk, rx_src_clk => st_clk, -- Memory Mapped Slave mm_sla_in => lcu_tse_mosi, mm_sla_out => lcu_tse_miso, -- MAC transmit interface -- . ST sink tx_snk_in => lcu_tx_sosi, tx_snk_out => lcu_tx_siso, -- . MAC specific tx_mac_in => lcu_tx_mac_in, tx_mac_out => lcu_tx_mac_out, -- MAC receive interface -- . ST Source rx_src_in => lcu_rx_siso, rx_src_out => lcu_rx_sosi, -- . MAC specific rx_mac_out => lcu_rx_mac_out, -- PHY interface eth_txp => lcu_txp, eth_rxp => lcu_rxp, tse_led => lcu_led ); END tb;