Skip to content
Snippets Groups Projects
Commit 2afadcae authored by Pieter Donker's avatar Pieter Donker
Browse files

changed eth1g_master, now with state machine.

parent 2eb0eb6e
No related branches found
No related tags found
2 merge requests!28Master,!13Resolve STAT-266
......@@ -48,7 +48,7 @@ ENTITY unb2b_arp_ping IS
g_stamp_date : NATURAL := 0; -- Date (YYYYMMDD) -- set by QSF
g_stamp_time : NATURAL := 0; -- Time (HHMMSS) -- set by QSF
g_revision_id : STRING := ""; -- revision id -- set by QSF
g_factory_image : BOOLEAN := TRUE;
g_factory_image : BOOLEAN := FALSE; --TRUE;
g_protect_addr_range: BOOLEAN := FALSE
);
PORT (
......@@ -138,7 +138,6 @@ ARCHITECTURE str OF unb2b_arp_ping IS
SIGNAL eth1g_reg_interrupt : STD_LOGIC; -- Interrupt
SIGNAL eth1g_ram_mosi : t_mem_mosi := c_mem_mosi_rst; -- ETH rx frame and tx frame memory
SIGNAL eth1g_ram_miso : t_mem_miso;
SIGNAL eth1g_init_done : STD_LOGIC; -- Init done from eth1g_setup
-- EPCS read
SIGNAL reg_dpmm_data_mosi : t_mem_mosi := c_mem_mosi_rst;
......@@ -203,7 +202,7 @@ BEGIN
g_aux => c_unb2b_board_aux,
g_factory_image => g_factory_image,
g_udp_offload => g_sim, -- use g_udp_offload to enable ETH instance in simulation
g_udp_offload_nof_streams => 0, -- use g_udp_offload, but no UDP offload streams
g_udp_offload_nof_streams => 3, -- use g_udp_offload, but no UDP offload streams
g_protect_addr_range => g_protect_addr_range
)
PORT MAP (
......@@ -309,20 +308,24 @@ BEGIN
);
-- normaly done by unb_os
p_wdi : PROCESS(st_clk)
p_wdi : PROCESS(mm_clk)
BEGIN
IF wdi_cnt = 1000 THEN
IF rising_edge(mm_clk) THEN
IF wdi_cnt = 5000 THEN
pout_wdi <= NOT pout_wdi;
wdi_cnt <= 0;
ELSE
wdi_cnt <= wdi_cnt + 1;
END IF;
END IF;
END PROCESS;
eth1g_mm_rst <= mm_rst;
u_eth1g_master : ENTITY eth1g_lib.eth1g_master
--u_eth1g_master : ENTITY eth1g_lib.eth1g_master(beh)
u_eth1g_master : ENTITY eth1g_lib.eth1g_master(rtl)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
......@@ -339,6 +342,7 @@ BEGIN
src_ip => src_ip
);
u_front_led : ENTITY unb2b_board_lib.unb2b_board_qsfp_leds
GENERIC MAP (
g_sim => g_sim,
......
hdl_lib_name = eth1g
hdl_library_clause_name = eth1g_lib
hdl_lib_uses_synth = dp common eth
hdl_lib_uses_synth = dp common eth tech_tse
hdl_lib_uses_sim =
hdl_lib_technology =
synth_files =
src/vhdl/eth1g.vhd
src/vhdl/eth1g_mem_pkg.vhd
src/vhdl/eth1g_master.vhd
test_bench_files =
......
This diff is collapsed.
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
-- Author: -
-- Purpose:
-- 1) Initial setup eth1g via the MM tse and MM reg port
-- 2) Loop control eth1g via MM reg port and reg_interrupt to receive and
-- transmit packets via the MM ram port.
-- Description:
--
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, tech_tse_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE common_lib.common_network_total_header_pkg.ALL;
USE tech_tse_lib.tech_tse_pkg.ALL;
PACKAGE eth1g_mem_pkg IS
------------------------------------------------------------------------------
-- MM bus access functions
------------------------------------------------------------------------------
-- The mm_miso input needs to be declared as signal, because otherwise the
-- procedure does not notice a change (also not when the mm_clk is declared
-- as signal).
-- Write data to the MM bus
PROCEDURE proc_mem_mm_bus_wr(CONSTANT wr_addr : IN NATURAL; -- [31:0]
CONSTANT wr_data : IN INTEGER; -- [31:0]
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso; -- used for waitrequest
SIGNAL mm_mosi : OUT t_mem_mosi);
PROCEDURE proc_mem_mm_bus_wr(CONSTANT wr_addr : IN INTEGER; -- [31:0]
SIGNAL wr_data : IN STD_LOGIC_VECTOR; -- [31:0]
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso; -- used for waitrequest
SIGNAL mm_mosi : OUT t_mem_mosi);
-- Read data request to the MM bus
PROCEDURE proc_mem_mm_bus_rd(CONSTANT rd_addr : IN NATURAL; -- [31:0]
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso; -- used for waitrequest
SIGNAL mm_mosi : OUT t_mem_mosi);
-- Wait for read data valid after read latency mm_clk cycles
PROCEDURE proc_mem_mm_bus_rd_latency(CONSTANT c_rd_latency : IN NATURAL;
SIGNAL mm_clk : IN STD_LOGIC);
-- supported packet data types
CONSTANT c_tech_tse_data_type_symbols : NATURAL := 0;
CONSTANT c_tech_tse_data_type_counter : NATURAL := 1;
CONSTANT c_tech_tse_data_type_arp : NATURAL := 2;
CONSTANT c_tech_tse_data_type_ping : NATURAL := 3; -- over IP/ICMP
CONSTANT c_tech_tse_data_type_udp : NATURAL := 4; -- over IP
FUNCTION func_tech_tse_header_size(data_type : NATURAL) RETURN NATURAL; -- raw ethernet: 4 header words, protocol ethernet: 11 header words
-- Configure the TSE MAC
PROCEDURE proc_tech_tse_setup(CONSTANT c_promis_en : IN BOOLEAN;
CONSTANT c_tse_tx_fifo_depth : IN NATURAL;
CONSTANT c_tse_rx_fifo_depth : IN NATURAL;
CONSTANT c_tx_ready_latency : IN NATURAL;
CONSTANT src_mac : IN STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE);
SIGNAL psc_access : OUT STD_LOGIC;
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso;
SIGNAL mm_mosi : OUT t_mem_mosi);
END eth1g_mem_pkg;
PACKAGE BODY eth1g_mem_pkg IS
------------------------------------------------------------------------------
-- Private functions
------------------------------------------------------------------------------
-- Issues a rd or a wr MM access
PROCEDURE proc_mm_access(SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_access : OUT STD_LOGIC) IS
BEGIN
mm_access <= '1';
IF rising_edge(mm_clk) THEN
mm_access <= '0';
END IF;
END proc_mm_access;
-- Issues a rd or a wr MM access and wait for it to have finished
PROCEDURE proc_mm_access(SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_waitreq : IN STD_LOGIC;
SIGNAL mm_access : OUT STD_LOGIC) IS
BEGIN
mm_access <= '1';
WAIT UNTIL rising_edge(mm_clk);
WHILE mm_waitreq='1' LOOP
WAIT UNTIL rising_edge(mm_clk);
END LOOP;
mm_access <= '0';
END proc_mm_access;
FUNCTION func_map_pcs_addr(pcs_addr : NATURAL) RETURN NATURAL IS
BEGIN
RETURN pcs_addr * 2 + c_tech_tse_byte_addr_pcs_offset;
END func_map_pcs_addr;
------------------------------------------------------------------------------
-- Public functions
------------------------------------------------------------------------------
-- Write data to the MM bus
PROCEDURE proc_mem_mm_bus_wr(CONSTANT wr_addr : IN NATURAL;
CONSTANT wr_data : IN INTEGER;
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso;
SIGNAL mm_mosi : OUT t_mem_mosi) IS
BEGIN
mm_mosi.address <= TO_MEM_ADDRESS(wr_addr);
mm_mosi.wrdata <= TO_MEM_DATA(wr_data);
proc_mm_access(mm_clk, mm_miso.waitrequest, mm_mosi.wr);
END proc_mem_mm_bus_wr;
PROCEDURE proc_mem_mm_bus_wr(CONSTANT wr_addr : IN INTEGER;
SIGNAL wr_data : IN STD_LOGIC_VECTOR;
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso;
SIGNAL mm_mosi : OUT t_mem_mosi) IS
BEGIN
mm_mosi.address <= TO_MEM_ADDRESS(wr_addr);
mm_mosi.wrdata <= RESIZE_MEM_DATA(wr_data);
proc_mm_access(mm_clk, mm_miso.waitrequest, mm_mosi.wr);
END proc_mem_mm_bus_wr;
-- Read data request to the MM bus
-- Use proc_mem_mm_bus_rd_latency() to wait for the MM MISO rd_data signal
-- to show the data after some read latency
PROCEDURE proc_mem_mm_bus_rd(CONSTANT rd_addr : IN NATURAL;
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso;
SIGNAL mm_mosi : OUT t_mem_mosi) IS
BEGIN
mm_mosi.address <= TO_MEM_ADDRESS(rd_addr);
mm_mosi.rd <= '1';
proc_mm_access(mm_clk, mm_miso.waitrequest, mm_mosi.rd);
mm_mosi.rd <= '0';
END proc_mem_mm_bus_rd;
-- Wait for read data valid after read latency mm_clk cycles
-- Directly assign mm_miso.rddata to capture the read data
PROCEDURE proc_mem_mm_bus_rd_latency(CONSTANT c_rd_latency : IN NATURAL;
SIGNAL mm_clk : IN STD_LOGIC) IS
BEGIN
FOR I IN 0 TO c_rd_latency-1 LOOP WAIT UNTIL rising_edge(mm_clk); END LOOP;
END proc_mem_mm_bus_rd_latency;
FUNCTION func_tech_tse_header_size(data_type : NATURAL) RETURN NATURAL IS
BEGIN
CASE data_type IS
WHEN c_tech_tse_data_type_symbols => RETURN c_network_total_header_32b_eth_nof_words;
WHEN c_tech_tse_data_type_counter => RETURN c_network_total_header_32b_eth_nof_words;
WHEN OTHERS => NULL;
END CASE;
RETURN c_network_total_header_32b_nof_words;
END func_tech_tse_header_size;
-- . The src_mac[47:0] = 0x123456789ABC for MAC address 12-34-56-78-9A-BC
PROCEDURE proc_tech_tse_setup(CONSTANT c_promis_en : IN BOOLEAN;
CONSTANT c_tse_tx_fifo_depth : IN NATURAL;
CONSTANT c_tse_rx_fifo_depth : IN NATURAL;
CONSTANT c_tx_ready_latency : IN NATURAL;
CONSTANT src_mac : IN STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE);
SIGNAL psc_access : OUT STD_LOGIC;
SIGNAL mm_clk : IN STD_LOGIC;
SIGNAL mm_miso : IN t_mem_miso;
SIGNAL mm_mosi : OUT t_mem_mosi) IS
CONSTANT c_mac0 : INTEGER := TO_SINT(hton(src_mac(47 DOWNTO 16), 4));
CONSTANT c_mac1 : INTEGER := TO_SINT(hton(src_mac(15 DOWNTO 0), 2));
BEGIN
-- PSC control
psc_access <= '1';
proc_mem_mm_bus_rd(func_map_pcs_addr(16#22#), mm_clk, mm_miso, mm_mosi); -- REV --> 0x0901
proc_mem_mm_bus_wr(func_map_pcs_addr(16#28#), 16#0008#, mm_clk, mm_miso, mm_mosi); -- IF_MODE <-- Force 1GbE, no autonegatiation
proc_mem_mm_bus_rd(func_map_pcs_addr(16#00#), mm_clk, mm_miso, mm_mosi); -- CONTROL --> 0x1140
proc_mem_mm_bus_rd(func_map_pcs_addr(16#02#), mm_clk, mm_miso, mm_mosi); -- STATUS --> 0x000D
proc_mem_mm_bus_wr(func_map_pcs_addr(16#00#), 16#0140#, mm_clk, mm_miso, mm_mosi); -- CONTROL <-- Auto negotiate disable
--proc_mem_mm_bus_wr(func_map_pcs_addr(16#00#), 16#1140#, mm_clk, mm_miso, mm_mosi); -- CONTROL <-- Auto negotiate enable
psc_access <= '0';
-- MAC control
proc_mem_mm_bus_rd(16#000#, mm_clk, mm_miso, mm_mosi); -- REV --> CUST_VERSION & 0x0901
IF c_promis_en=FALSE THEN
proc_mem_mm_bus_wr(16#008#, 16#0100004B#, mm_clk, mm_miso, mm_mosi);
ELSE
proc_mem_mm_bus_wr(16#008#, 16#0100005B#, mm_clk, mm_miso, mm_mosi);
END IF;
-- COMMAND_CONFIG <--
-- Only the bits relevant to UniBoard are explained here, others are 0
-- [ 0] = TX_ENA = 1, enable tx datapath
-- [ 1] = RX_ENA = 1, enable rx datapath
-- [ 2] = XON_GEN = 0
-- [ 3] = ETH_SPEED = 1, enable 1GbE operation
-- [ 4] = PROMIS_EN = 0, when 1 then receive all frames
-- [ 5] = PAD_EN = 0, when 1 enable receive padding removal (requires ethertype=payload length)
-- [ 6] = CRC_FWD = 1, enable receive CRC forward
-- [ 7] = PAUSE_FWD = 0
-- [ 8] = PAUSE_IGNORE = 0
-- [ 9] = TX_ADDR_INS = 0, when 1 then MAX overwrites tx SRC MAC with mac_0,1 or one of the supplemental mac
-- [ 10] = HD_ENA = 0
-- [ 11] = EXCESS_COL = 0
-- [ 12] = LATE_COL = 0
-- [ 13] = SW_RESET = 0, when 1 MAC disables tx and rx, clear statistics and flushes receive FIFO
-- [ 14] = MHAS_SEL = 0, select multicast address resolutions hash-code mode
-- [ 15] = LOOP_ENA = 0
-- [18-16] = TX_ADDR_SEL[2:0] = 000, TX_ADDR_INS insert mac_0,1 or one of the supplemental mac
-- [ 19] = MAGIC_EN = 0
-- [ 20] = SLEEP = 0
-- [ 21] = WAKEUP = 0
-- [ 22] = XOFF_GEN = 0
-- [ 23] = CNT_FRM_ENA = 0
-- [ 24] = NO_LGTH_CHECK = 1, when 0 then check payload length of received frames (requires ethertype=payload length)
-- [ 25] = ENA_10 = 0
-- [ 26] = RX_ERR_DISC = 0, when 1 then discard erroneous frames (requires store and forward mode, so rx_section_full=0)
-- when 0 then pass on with rx_err[0]=1
-- [ 27] = DISABLE_RD_TIMEOUT = 0
-- [30-28] = RSVD = 000
-- [ 31] = CNT_RESET = 0, when 1 clear statistics
proc_mem_mm_bus_wr(16#00C#, c_mac0, mm_clk, mm_miso, mm_mosi); -- MAC_0
proc_mem_mm_bus_wr(16#010#, c_mac1, mm_clk, mm_miso, mm_mosi); -- MAC_1 <-- SRC_MAC = 12-34-56-78-9A-BC
proc_mem_mm_bus_wr(16#05C#, 16#0000000C#, mm_clk, mm_miso, mm_mosi); -- TX_IPG_LENGTH <-- interpacket gap = 12
--proc_mem_mm_bus_wr(16#014#, 16#000005EE#, mm_clk, mm_miso, mm_mosi); -- FRM_LENGTH <-- receive max frame length = 1518
proc_mem_mm_bus_wr(16#014#, 16#0000233A#, mm_clk, mm_miso, mm_mosi); -- FRM_LENGTH <-- receive max frame length = 9018
-- FIFO legenda:
-- . Tx section full = There is enough data in the FIFO to start reading it, when 0 then store and forward.
-- . Rx section full = There is enough data in the FIFO to start reading it, when 0 then store and forward.
-- . Tx section empty = There is not much empty space anymore in the FIFO, warn user via ff_tx_septy
-- . Rx section empty = There is not much empty space anymore in the FIFO, inform remote device via XOFF flow control
-- . Tx almost full = Assert ff_tx_a_full and deassert ff_tx_rdy. Furthermore TX_ALMOST_FULL = c_tx_ready_latency+3,
-- so choose 3 for zero tx ready latency
-- . Rx almost full = Assert ff_rx_a_full and if the user is not ready ff_rx_rdy then:
-- --> break off the reception with an error to avoid FIFO overflow
-- . Tx almost empty = Assert ff_tx_a_empty and if the FIFO does not contain a eop yet then:
-- --> break off the transmission with an error to avoid FIFO underflow
-- . Rx almost empty = Assert ff_rx_a_empty
-- Typical FIFO values:
-- . TX_SECTION_FULL = 16 > 8 = TX_ALMOST_EMPTY
-- . RX_SECTION_FULL = 16 > 8 = RX_ALMOST_EMPTY
-- . TX_SECTION_EMPTY = D-16 < D-3 = Tx FIFO depth - TX_ALMOST_FULL
-- . RX_SECTION_EMPTY = D-16 < D-8 = Rx FIFO depth - RX_ALMOST_FULL
-- . c_tse_tx_fifo_depth = 1 M9K = 256*32b = 1k * 8b is sufficient when the Tx user respects ff_tx_rdy, to store a complete
-- ETH packet would require 1518 byte, so 2 M9K = 2k * 8b
-- . c_tse_rx_fifo_depth = 1 M9K = 256*32b = 1k * 8b is sufficient when the Rx user ff_rx_rdy is sufficiently active
proc_mem_mm_bus_wr(16#01C#, c_tse_rx_fifo_depth-16, mm_clk, mm_miso, mm_mosi); -- RX_SECTION_EMPTY <-- default FIFO depth - 16, >3
proc_mem_mm_bus_wr(16#020#, 16, mm_clk, mm_miso, mm_mosi); -- RX_SECTION_FULL <-- default 16
proc_mem_mm_bus_wr(16#024#, c_tse_tx_fifo_depth-16, mm_clk, mm_miso, mm_mosi); -- TX_SECTION_EMPTY <-- default FIFO depth - 16, >3
proc_mem_mm_bus_wr(16#028#, 16, mm_clk, mm_miso, mm_mosi); -- TX_SECTION_FULL <-- default 16, >~ 8 otherwise no tx
proc_mem_mm_bus_wr(16#02C#, 8, mm_clk, mm_miso, mm_mosi); -- RX_ALMOST_EMPTY <-- default 8
proc_mem_mm_bus_wr(16#030#, 8, mm_clk, mm_miso, mm_mosi); -- RX_ALMOST_FULL <-- default 8
proc_mem_mm_bus_wr(16#034#, 8, mm_clk, mm_miso, mm_mosi); -- TX_ALMOST_EMPTY <-- default 8
proc_mem_mm_bus_wr(16#038#, c_tx_ready_latency+3, mm_clk, mm_miso, mm_mosi); -- TX_ALMOST_FULL <-- default 3
proc_mem_mm_bus_rd(16#0E8#, mm_clk, mm_miso, mm_mosi); -- TX_CMD_STAT --> 0x00040000 : [18]=1 TX_SHIFT16, [17]=0 OMIT_CRC
proc_mem_mm_bus_rd(16#0EC#, mm_clk, mm_miso, mm_mosi); -- RX_CMD_STAT --> 0x02000000 : [25]=1 RX_SHIFT16
WAIT UNTIL rising_edge(mm_clk);
END proc_tech_tse_setup;
END eth1g_mem_pkg;
\ No newline at end of file
......@@ -82,8 +82,16 @@ PACKAGE tech_tse_pkg IS
col : STD_LOGIC;
END RECORD;
FUNCTION func_tech_tse_map_pcs_addr(pcs_addr : NATURAL) RETURN NATURAL;
END tech_tse_pkg;
PACKAGE BODY tech_tse_pkg IS
FUNCTION func_tech_tse_map_pcs_addr(pcs_addr : NATURAL) RETURN NATURAL IS
BEGIN
RETURN pcs_addr * 2 + c_tech_tse_byte_addr_pcs_offset;
END func_tech_tse_map_pcs_addr;
END tech_tse_pkg;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment