From c29b039c66106e17e1f20f27f70df990b9c43a60 Mon Sep 17 00:00:00 2001 From: Erik Kooistra <kooistra@astron.nl> Date: Thu, 20 Nov 2014 14:25:41 +0000 Subject: [PATCH] Added tb_tech_eth_10g.vhd. --- .../technology/eth_10g/tb_tech_eth_10g.vhd | 329 ++++++++++++++++++ libraries/technology/eth_10g/tech_eth_10g.vhd | 36 +- 2 files changed, 341 insertions(+), 24 deletions(-) create mode 100644 libraries/technology/eth_10g/tb_tech_eth_10g.vhd diff --git a/libraries/technology/eth_10g/tb_tech_eth_10g.vhd b/libraries/technology/eth_10g/tb_tech_eth_10g.vhd new file mode 100644 index 0000000000..00080460fe --- /dev/null +++ b/libraries/technology/eth_10g/tb_tech_eth_10g.vhd @@ -0,0 +1,329 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>. +-- +------------------------------------------------------------------------------- + +-- Purpose: Testbench for tech_eth_10g the 10G Ethernet IP technology wrapper. +-- Description: +-- The tb is self checking based on: +-- . proc_tech_mac_10g_rx_packet() for expected header and data type +-- . tx_pkt_cnt=rx_pkt_cnt > 0 must be true at the tb_end. +-- Usage: +-- > as 10 +-- > run -all + +LIBRARY IEEE, technology_lib, tech_mac_10g_lib, common_lib, dp_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.common_interface_layers_pkg.ALL; +USE common_lib.common_network_layers_pkg.ALL; +USE common_lib.common_network_total_header_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE technology_lib.technology_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; +USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL; +USE tech_mac_10g_lib.tb_tech_mac_10g_pkg.ALL; + + +ENTITY tb_tech_eth_10g IS + -- Test bench control parameters + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + -- g_data_type = c_tb_tech_mac_10g_data_type_symbols = 0 + -- g_data_type = c_tb_tech_mac_10g_data_type_counter = 1 + g_data_type : NATURAL := c_tb_tech_mac_10g_data_type_symbols + ); +END tb_tech_eth_10g; + + +ARCHITECTURE tb OF tb_tech_eth_10g IS + + CONSTANT mm_clk_period : TIME := 20 ns; -- 50 MHz + CONSTANT tx_ref_clk_156_period : TIME := 6.4 ns; -- 156.25 MHz + CONSTANT phy_delay : TIME := 0 ns; + + CONSTANT c_st_loopback : BOOLEAN := FALSE; -- default FALSE to verify the DUT, else use TRUE to verify the tb itself without the DUT + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_nof_tx_not_valid : NATURAL := 0; -- when > 0 then pull tx valid low for c_nof_tx_not_valid beats during tx + --CONSTANT c_pkt_length_arr : t_nat_natural_arr := (0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1472, 1473, 9000); + CONSTANT c_pkt_length_arr : t_nat_natural_arr := array_init(0, 50, 1) & (1472, 1473) & 9000; -- frame longer than 1518-46 = 1472 is received with rx_sosi.err = 8 + -- jumbo frame is 9018-46 = 8972 + CONSTANT c_nof_pkt : NATURAL := c_pkt_length_arr'LENGTH; + + CONSTANT c_dst_mac : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"10FA01020300"; + CONSTANT c_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"123456789ABC"; -- = 12-34-56-78-9A-BC + CONSTANT c_src_mac_tx : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := c_src_mac; + --CONSTANT c_src_mac_tx : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"100056789ABC"; -- = 10-00-56-78-9A-BC + CONSTANT c_ethertype : STD_LOGIC_VECTOR(c_network_eth_type_slv'RANGE) := X"10FA"; + CONSTANT c_etherlen : STD_LOGIC_VECTOR(c_network_eth_type_slv'RANGE) := "0000000000010000"; + + -- Packet headers + CONSTANT c_eth_header_ethertype : t_network_eth_header := (c_dst_mac, c_src_mac_tx, c_ethertype); + CONSTANT c_eth_header_etherlen : t_network_eth_header := (c_dst_mac, c_src_mac_tx, c_etherlen); + + SIGNAL total_header : t_network_total_header := c_network_total_header_ones; -- default fill all fields with value 1 + + -- Clocks and reset + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL mm_clk : STD_LOGIC := '0'; -- memory-mapped bus clock + SIGNAL mm_rst : STD_LOGIC; -- reset synchronous with mm_clk + SIGNAL tx_ref_clk_312 : STD_LOGIC := '1'; -- mac_10g + SIGNAL tx_ref_clk_156 : STD_LOGIC := '0'; -- mac_10g reference clock + SIGNAL tx_rst : STD_LOGIC; -- reset synchronous with tx_ref_clk_156 + SIGNAL rx_phy_clk_312 : STD_LOGIC := '1'; -- mac_10g + SIGNAL rx_phy_clk_156 : STD_LOGIC := '0'; -- mac_10g rx clock from phy = tx_ref_clk_156 in this tb + SIGNAL rx_rst : STD_LOGIC; -- reset synchronous with rx_phy_clk_156 = tx_ref_clk_156 in this tb + + -- 10G MAC control interface + SIGNAL mm_init : STD_LOGIC := '1'; + SIGNAL mm_mosi_wrdata : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- 32 bit; + SIGNAL mm_mosi : t_mem_mosi; + SIGNAL mm_miso : t_mem_miso; + SIGNAL mm_miso_rdval : STD_LOGIC; + SIGNAL mm_miso_rddata : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- 32 bit; + + -- 10G MAC transmit interface + -- . The tb is the ST source + SIGNAL tx_en : STD_LOGIC := '1'; + SIGNAL tx_siso : t_dp_siso; + SIGNAL tx_siso_arr : t_dp_siso_arr(0 DOWNTO 0); + SIGNAL tx_sosi : t_dp_sosi; + SIGNAL tx_sosi_data : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0); -- 64 bit + SIGNAL tx_sosi_arr : t_dp_sosi_arr(0 DOWNTO 0); + + -- 10G MAC receive interface + -- . The tb is the ST sink + SIGNAL rx_siso : t_dp_siso; + SIGNAL rx_sosi : t_dp_sosi; + SIGNAL rx_sosi_data : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0); -- 64 bit + + -- 10G PHY serial interface + SIGNAL tx_serial_arr : OUT STD_LOGIC_VECTOR(0 DOWNTO 0); + SIGNAL rx_serial_arr : IN STD_LOGIC_VECTOR(0 DOWNTO 0); + + -- Verification + SIGNAL expected_sosi_arr : t_dp_sosi_arr(0 TO c_nof_pkt-1); + + SIGNAL tx_pkt_cnt : NATURAL := 0; + SIGNAL rx_pkt_cnt : NATURAL := 0; + +BEGIN + + -- run 50 us + mm_clk <= NOT mm_clk AFTER mm_clk_period/2; -- MM clock + tx_ref_clk_156 <= NOT tx_ref_clk_156 AFTER tx_ref_clk_156_period/2; -- mac_10g tx reference clock + tx_ref_clk_312 <= NOT tx_ref_clk_312 AFTER tx_ref_clk_156_period/4; + rx_phy_clk_156 <= tx_ref_clk_156; -- use tx_ref_clk_156 to model PHY + rx_phy_clk_312 <= tx_ref_clk_312; + + mm_rst <= '1', '0' AFTER mm_clk_period*10; + tx_rst <= '1', '0' AFTER tx_ref_clk_156_period*10; + rx_rst <= '1', '0' AFTER tx_ref_clk_156_period*10; + + -- debug signals to ease monitoring in wave window + tx_sosi_data <= tx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0); + rx_sosi_data <= rx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0); + + mm_mosi_wrdata <= mm_mosi.wrdata(c_word_w-1 DOWNTO 0); + mm_miso_rddata <= mm_miso.rddata(c_word_w-1 DOWNTO 0); + mm_miso_rdval <= '1' WHEN mm_mosi.rd='1' AND mm_miso.waitrequest='0' ELSE '0'; -- c_rd_latency = 1 + + -- Use signal to leave unused fields 'X' + total_header.eth <= c_eth_header_ethertype; + + p_mm_setup : PROCESS + BEGIN + mm_init <= '1'; + mm_mosi.wr <= '0'; + mm_mosi.rd <= '0'; + + -- wait until after reset release + proc_common_wait_until_low(mm_clk, mm_rst); + proc_common_wait_some_cycles(mm_clk, 10); + + proc_tech_mac_10g_setup(g_technology, + c_src_mac, + mm_clk, mm_miso, mm_mosi); + mm_init <= '0'; + WAIT; + END PROCESS; + + + p_ff_transmitter : PROCESS + BEGIN + -- . Avalon ST + tx_sosi <= c_dp_sosi_rst; + + WHILE mm_init/='0' LOOP + WAIT UNTIL rising_edge(tx_ref_clk_156); + END LOOP; + proc_common_wait_some_cycles(tx_ref_clk_156, 10); + + -- Loopback txp->rxp so use promiscuous mode or use DST_MAC = c_src_mac to send to itself + + -- TX frame: + -- . I=0 is empty payload, so only 4 words of the ETH header with 46 padding zeros, so empty = 2 + -- . For I=1 to 46 the payload length remains 46 with padding zeros, so empty = 2 + -- . For I>46 the payload length is I and empty = 4 - (I mod 4) + + FOR I IN 0 TO c_nof_pkt-1 LOOP + proc_tech_mac_10g_tx_packet(total_header, c_pkt_length_arr(I), g_data_type, c_rl, c_nof_tx_not_valid, tx_ref_clk_156, tx_en, tx_siso, tx_sosi); + proc_common_wait_some_cycles(tx_ref_clk_156, 0); + END LOOP; + + proc_common_wait_some_cycles(tx_ref_clk_156, c_pkt_length_arr(c_nof_pkt-1)/c_tech_mac_10g_symbols_per_beat); + proc_common_wait_some_cycles(tx_ref_clk_156, 100); + tb_end <= '1'; + WAIT; + END PROCESS; + + + p_ff_receiver : PROCESS + BEGIN + -- . Avalon ST + rx_siso <= c_dp_siso_hold; + + WHILE mm_init/='0' LOOP + WAIT UNTIL rising_edge(rx_phy_clk_156); + END LOOP; + + -- Receive forever + WHILE TRUE LOOP + proc_tech_mac_10g_rx_packet(total_header, g_data_type, rx_phy_clk_156, rx_sosi, rx_siso); + END LOOP; + + WAIT; + END PROCESS; + + + p_ff_store_tx_sosi_at_eop : PROCESS(tx_ref_clk_156) + VARIABLE vI : NATURAL := 0; + BEGIN + IF rising_edge(tx_ref_clk_156) THEN + IF tx_sosi.eop='1' THEN + expected_sosi_arr(vI) <= tx_sosi; + vI := vI +1; + END IF; + END IF; + END PROCESS; + + p_ff_verify_rx_sosi_at_eop : PROCESS(rx_phy_clk_156) + VARIABLE vI : NATURAL := 0; + VARIABLE vLow : NATURAL := 0; + BEGIN + IF rising_edge(rx_phy_clk_156) THEN + IF rx_sosi.eop='1' THEN + -- frame shorter than 64 get padded so em + IF c_pkt_length_arr(vI) < 64 - 14 - 20 - 8 - 4 THEN -- = minimum frame 64 - ETH 14 - IP 20 - UDP 8 - CRC 4 + -- frame shorter than 64 get padded so empty after stripping the Rx CRC is fixed 4, which becomes 6 due to pre header padding for UDP word align + IF TO_UINT(rx_sosi.empty) /= 6 THEN + REPORT "RX: Wrong padded empty" SEVERITY ERROR; + END IF; + ELSE + IF rx_sosi.empty /= expected_sosi_arr(vI).empty THEN + REPORT "RX: Wrong empty" SEVERITY ERROR; + ELSE + vLow := TO_UINT(rx_sosi.empty)*8; + ASSERT rx_sosi.data(63 DOWNTO vLow) = expected_sosi_arr(vI).data(63 DOWNTO vLow) REPORT "RX: Wrong data at eop" SEVERITY ERROR; + END IF; + END IF; + vI := vI +1; + END IF; + END IF; + END PROCESS; + + -- Rewire DP to DP array type. + tx_sosi_arr(0) <= tx_sosi; + tx_siso <= tx_siso_arr(0); + + rx_siso_arr(0) <= rx_siso; + rx_sosi <= rx_sosi_arr(0); + + gen_dut : IF c_st_loopback=FALSE GENERATE + dut : ENTITY work.tech_eth_10g + GENERIC MAP ( + g_technology => g_technology, + g_sim => FALSE, + g_nof_channels => 1, + --g_pre_header_padding => FALSE + g_pre_header_padding => TRUE + ) + PORT MAP ( + -- Transceiver PLL reference clock + tr_ref_clk_644 : IN STD_LOGIC := '0'; -- 644.531250 MHz for 10GBASE-R + + -- MM + mm_clk => mm_clk, + mm_rst => mm_rst, + + mac_mosi => mm_mosi, -- CSR = control status register + mac_miso => mm_miso, + + -- Clocks + clk_312 => tx_ref_clk_312, + clk_156 => tx_ref_clk_156, -- 156.25 MHz local reference + rst_156 => tx_rst, + + -- ST + tx_snk_in_arr => tx_sosi_arr, -- 64 bit data @ clk_156 + tx_snk_out_arr => tx_siso_arr, + + rx_src_out_arr => rx_sosi_arr, -- 64 bit data @ clk_156 + rx_src_in_arr => rx_siso_arr, + + -- Serial + tx_serial_arr => tx_serial_arr, + rx_serial_arr => rx_serial_arr + ); + END GENERATE; + + no_dut : IF c_st_loopback=TRUE GENERATE + rx_sosi <= tx_sosi; + tx_siso <= rx_siso; + END GENERATE; + + -- Loopback serial + rx_serial_arr <= TRANSPORT tx_serial_arr AFTER phy_delay; + + -- Verification + tx_pkt_cnt <= tx_pkt_cnt + 1 WHEN tx_sosi.sop='1' AND rising_edge(tx_ref_clk_156); + rx_pkt_cnt <= rx_pkt_cnt + 1 WHEN rx_sosi.eop='1' AND rising_edge(rx_phy_clk_156); + + p_tb_end : PROCESS + BEGIN + WAIT UNTIL tb_end='1'; + + -- Verify that all transmitted packets have been received + IF tx_pkt_cnt=0 THEN + REPORT "No packets were transmitted." SEVERITY ERROR; + ELSIF rx_pkt_cnt=0 THEN + REPORT "No packets were received." SEVERITY ERROR; + ELSIF tx_pkt_cnt/=rx_pkt_cnt THEN + REPORT "Not all transmitted packets were received." SEVERITY ERROR; + END IF; + + -- Stop the simulation + ASSERT FALSE REPORT "Simulation finished." SEVERITY FAILURE; + WAIT; + END PROCESS; + +END tb; diff --git a/libraries/technology/eth_10g/tech_eth_10g.vhd b/libraries/technology/eth_10g/tech_eth_10g.vhd index 42ff9117be..99a07a5c5e 100644 --- a/libraries/technology/eth_10g/tech_eth_10g.vhd +++ b/libraries/technology/eth_10g/tech_eth_10g.vhd @@ -23,6 +23,8 @@ -- Purpose: Combine mac_10g and 10gbase_r -- Description: +-- . For c_tech_stratixiv: not available (yet) +-- -- . For c_tech_arria10: -- __________________ -- | | @@ -53,42 +55,28 @@ ENTITY tech_eth_10g IS ); PORT ( -- Transceiver PLL reference clock - tr_ref_clk_156 : IN STD_LOGIC := '0'; -- 156.26 MHz for XAUI tr_ref_clk_644 : IN STD_LOGIC := '0'; -- 644.531250 MHz for 10GBASE-R -- MM mm_clk : IN STD_LOGIC; mm_rst : IN STD_LOGIC; - mac_mosi : IN t_mem_mosi; -- MAG_10G (CSR) - mac_miso : OUT t_mem_miso; + mac_mosi : IN t_mem_mosi; -- MAG_10G (CSR), aggregated for all g_nof_channels + mac_miso : OUT t_mem_miso; + + -- Clocks + clk_312 : IN STD_LOGIC := '0'; + clk_156 : IN STD_LOGIC := '0'; + rst_156 : IN STD_LOGIC := '0'; - xaui_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- XAUI - xaui_miso : OUT t_mem_miso; - -- ST - tx_snk_in_arr : IN t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0); -- 64 bit data + tx_snk_in_arr : IN t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0); -- 64 bit data @ clk_156 tx_snk_out_arr : OUT t_dp_siso_arr(g_nof_channels-1 DOWNTO 0); - rx_src_out_arr : OUT t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0); -- 64 bit data + rx_src_out_arr : OUT t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0); -- 64 bit data @ clk_156 rx_src_in_arr : IN t_dp_siso_arr(g_nof_channels-1 DOWNTO 0); - -- XAUI - cal_rec_clk : IN STD_LOGIC := '0'; - - crc_rx_ready_arr : OUT STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0); -- crc = synchronous to Cal_Rec_Clk - crc_tx_ready_arr : OUT STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0); - - a_rx_channelaligned_arr : OUT STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0); - - xaui_rx_arr : IN t_xaui_arr(g_nof_channels-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0')); - xaui_tx_arr : OUT t_xaui_arr(g_nof_channels-1 DOWNTO 0); - - -- 10GBASE-R - clk_312 : IN STD_LOGiC := '0'; - clk_156 : IN STD_LOGiC := '0'; - rst_156 : IN STD_LOGiC := '0'; - + -- Serial tx_serial_arr : OUT STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0); rx_serial_arr : IN STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0) := (OTHERS=>'0') ); -- GitLab