-
Eric Kooistra authored
- Use common_network_layers_pkg from common (was eth_layers in $UNB) - Use tech_tse_pkg and tb_tech_tse_pkg from tech_tse_lib (was work=tse_lib in $UNB)
Eric Kooistra authored- Use common_network_layers_pkg from common (was eth_layers in $UNB) - Use tech_tse_pkg and tb_tech_tse_pkg from tech_tse_lib (was work=tse_lib in $UNB)
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tb_eth.vhd 28.25 KiB
-------------------------------------------------------------------------------
--
-- 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;