Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
H
HDL
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
RTSD
HDL
Commits
7ce22b6d
Commit
7ce22b6d
authored
Oct 29, 2014
by
Eric Kooistra
Browse files
Options
Downloads
Patches
Plain Diff
SVN copy-renamed tb_ip_stratixiv_tse_sgmii_lvds.vhd to ip_arria10. No functional changes yet.
parent
55c051be
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
libraries/technology/ip_arria10/tse_sgmii_lvds/tb_ip_arria10_tse_sgmii_lvds.vhd
+723
-0
723 additions, 0 deletions
...p_arria10/tse_sgmii_lvds/tb_ip_arria10_tse_sgmii_lvds.vhd
with
723 additions
and
0 deletions
libraries/technology/ip_arria10/tse_sgmii_lvds/tb_ip_arria10_tse_sgmii_lvds.vhd
0 → 100644
+
723
−
0
View file @
7ce22b6d
-------------------------------------------------------------------------------
--
-- 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 ip_arria10_tse_sgmii_lvds.
-- Description:
-- The testbench in /testbench/tse_sgmii_lvds/tse_sgmii_lvds_tb.vhd that is
-- generated by the MegaWizard provides an elaborate testbench. For
-- Uniboard purposes in tb/ a minimal testbench tb_tse_sgmii_lvds.vhd was
-- derived manually from the generated testbench. This tb_tse_sgmii_lvds
-- is more easy to use.
-- The tb is self checking based on that tx_pkt_cnt=rx_pkt_cnt must be true
-- at the tb_end.
-- Usage:
-- > as 10
-- > run -all
LIBRARY
IEEE
,
common_lib
;
USE
IEEE
.
std_logic_1164
.
ALL
;
USE
IEEE
.
numeric_std
.
ALL
;
USE
common_lib
.
common_pkg
.
ALL
;
ENTITY
tb_ip_arria10_tse_sgmii_lvds
IS
END
tb_ip_arria10_tse_sgmii_lvds
;
ARCHITECTURE
tb
OF
tb_ip_arria10_tse_sgmii_lvds
IS
CONSTANT
sys_clk_period
:
TIME
:
=
10
ns
;
-- 100 MHz
CONSTANT
eth_clk_period
:
TIME
:
=
8
ns
;
-- 125 MHz
CONSTANT
c_tse_reg_addr_w
:
NATURAL
:
=
8
;
-- = max 256 MAC registers
CONSTANT
c_tse_byte_addr_w
:
NATURAL
:
=
c_tse_reg_addr_w
+
2
;
CONSTANT
c_tse_byte_addr_pcs_offset
:
NATURAL
:
=
16
#
200
#
;
-- table 4.8, 4.9 in ug_ethernet.pdf
CONSTANT
c_tse_data_w
:
NATURAL
:
=
c_word_w
;
-- = 32
CONSTANT
c_tse_symbol_w
:
NATURAL
:
=
c_byte_w
;
-- = 8
CONSTANT
c_tse_symbol_max
:
NATURAL
:
=
2
**
c_tse_symbol_w
-1
;
-- = 255
CONSTANT
c_tse_symbols_per_beat
:
NATURAL
:
=
c_tse_data_w
/
c_tse_symbol_w
;
-- = 4
CONSTANT
c_tse_pcs_reg_addr_w
:
NATURAL
:
=
5
;
-- = max 32 PCS registers
CONSTANT
c_tse_pcs_halfword_addr_w
:
NATURAL
:
=
c_tse_pcs_reg_addr_w
+
1
;
-- table 4.17 in ug_ethernet.pdf
CONSTANT
c_tse_pcs_byte_addr_w
:
NATURAL
:
=
c_tse_pcs_reg_addr_w
+
2
;
CONSTANT
c_tse_pcs_data_w
:
NATURAL
:
=
c_halfword_w
;
-- = 16;
CONSTANT
c_tse_empty_w
:
NATURAL
:
=
2
;
CONSTANT
c_tse_tx_error_w
:
NATURAL
:
=
1
;
CONSTANT
c_tse_rx_error_w
:
NATURAL
:
=
6
;
CONSTANT
c_tse_error_w
:
NATURAL
:
=
largest
(
c_tse_tx_error_w
,
c_tse_rx_error_w
);
CONSTANT
c_tse_err_stat_w
:
NATURAL
:
=
18
;
CONSTANT
c_tse_frm_type_w
:
NATURAL
:
=
4
;
CONSTANT
c_tse_tx_fifo_depth
:
NATURAL
:
=
256
;
-- nof words for Tx FIFO
CONSTANT
c_tse_rx_fifo_depth
:
NATURAL
:
=
256
;
-- nof words for Rx FIFO
CONSTANT
c_tse_promis_en
:
BOOLEAN
:
=
FALSE
;
--CONSTANT c_tse_promis_en : BOOLEAN := TRUE;
CONSTANT
c_tx_data_type
:
NATURAL
:
=
1
;
-- 0 = symbols, 1 = counter
CONSTANT
c_tx_ready_latency
:
NATURAL
:
=
0
;
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_eth_dst_mac
:
STD_LOGIC_VECTOR
(
47
DOWNTO
0
)
:
=
X"10FA01020300"
;
CONSTANT
c_eth_src_mac
:
STD_LOGIC_VECTOR
(
47
DOWNTO
0
)
:
=
X"123456789ABC"
;
-- = 12-34-56-78-9A-BC
CONSTANT
c_eth_ethertype
:
STD_LOGIC_VECTOR
(
15
DOWNTO
0
)
:
=
X"10FA"
;
TYPE
t_mm_bus
IS
RECORD
-- Master In Slave Out
waitreq
:
STD_LOGIC
;
rddata
:
STD_LOGIC_VECTOR
(
c_tse_data_w
-1
DOWNTO
0
);
-- Master Out Slave In
address
:
STD_LOGIC_VECTOR
(
c_tse_byte_addr_w
-1
DOWNTO
0
);
wrdata
:
STD_LOGIC_VECTOR
(
c_tse_data_w
-1
DOWNTO
0
);
wr
:
STD_LOGIC
;
rd
:
STD_LOGIC
;
END
RECORD
;
PROCEDURE
proc_dbg_mm_bus
(
SIGNAL
mm_miso
:
IN
t_mm_bus
;
SIGNAL
mm_mosi
:
IN
t_mm_bus
;
SIGNAL
dbg_mm
:
OUT
t_mm_bus
)
IS
BEGIN
dbg_mm
.
waitreq
<=
mm_miso
.
waitreq
;
dbg_mm
.
rddata
<=
mm_miso
.
rddata
;
dbg_mm
.
address
<=
mm_mosi
.
address
;
dbg_mm
.
wrdata
<=
mm_mosi
.
wrdata
;
dbg_mm
.
wr
<=
mm_mosi
.
wr
;
dbg_mm
.
rd
<=
mm_mosi
.
rd
;
END
proc_dbg_mm_bus
;
-- Wait for MM access (either read or write) 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
;
-- Use word addressing for MAC registers according to table 4.8, 4.9
PROCEDURE
proc_wr_mac
(
CONSTANT
mac_addr
:
IN
NATURAL
;
CONSTANT
mac_data
:
IN
NATURAL
;
SIGNAL
mm_clk
:
IN
STD_LOGIC
;
SIGNAL
mm_miso
:
IN
t_mm_bus
;
SIGNAL
mm_mosi
:
OUT
t_mm_bus
)
IS
BEGIN
mm_mosi
.
address
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
mac_addr
,
c_tse_byte_addr_w
));
mm_mosi
.
wrdata
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
mac_data
,
c_tse_data_w
));
proc_mm_access
(
mm_clk
,
mm_miso
.
waitreq
,
mm_mosi
.
wr
);
END
proc_wr_mac
;
PROCEDURE
proc_rd_mac
(
CONSTANT
mac_addr
:
IN
NATURAL
;
SIGNAL
mac_data
:
OUT
NATURAL
;
SIGNAL
mm_clk
:
IN
STD_LOGIC
;
SIGNAL
mm_miso
:
IN
t_mm_bus
;
SIGNAL
mm_mosi
:
OUT
t_mm_bus
)
IS
BEGIN
mm_mosi
.
address
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
mac_addr
,
c_tse_byte_addr_w
));
proc_mm_access
(
mm_clk
,
mm_miso
.
waitreq
,
mm_mosi
.
rd
);
MAC_data
<=
TO_INTEGER
(
UNSIGNED
(
mm_miso
.
rddata
));
END
proc_rd_mac
;
-- Use halfword addressing for PCS register to match table 4.17
PROCEDURE
proc_wr_pcs
(
CONSTANT
pcs_addr
:
IN
NATURAL
;
CONSTANT
pcs_data
:
IN
NATURAL
;
SIGNAL
mm_clk
:
IN
STD_LOGIC
;
SIGNAL
mm_miso
:
IN
t_mm_bus
;
SIGNAL
mm_mosi
:
OUT
t_mm_bus
)
IS
BEGIN
mm_mosi
.
address
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
pcs_addr
*
2
+
c_tse_byte_addr_pcs_offset
,
c_tse_byte_addr_w
));
mm_mosi
.
wrdata
<=
(
OTHERS
=>
'0'
);
mm_mosi
.
wrdata
(
c_tse_pcs_data_w
-1
DOWNTO
0
)
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
pcs_data
,
c_tse_pcs_data_w
));
proc_mm_access
(
mm_clk
,
mm_miso
.
waitreq
,
mm_mosi
.
wr
);
END
proc_wr_pcs
;
PROCEDURE
proc_rd_pcs
(
CONSTANT
pcs_addr
:
IN
NATURAL
;
SIGNAL
pcs_data
:
OUT
NATURAL
;
SIGNAL
mm_clk
:
IN
STD_LOGIC
;
SIGNAL
mm_miso
:
IN
t_mm_bus
;
SIGNAL
mm_mosi
:
OUT
t_mm_bus
)
IS
BEGIN
mm_mosi
.
address
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
pcs_addr
*
2
+
c_tse_byte_addr_pcs_offset
,
c_tse_byte_addr_w
));
proc_mm_access
(
mm_clk
,
mm_miso
.
waitreq
,
mm_mosi
.
rd
);
pcs_data
<=
TO_INTEGER
(
UNSIGNED
(
mm_miso
.
rddata
(
c_tse_pcs_data_w
-1
DOWNTO
0
)));
END
proc_rd_pcs
;
TYPE
t_tse_stream
IS
RECORD
-- Source In or Sink Out
ready
:
STD_LOGIC
;
-- Source Out or Sink In
data
:
STD_LOGIC_VECTOR
(
c_tse_data_w
-1
DOWNTO
0
);
valid
:
STD_LOGIC
;
sop
:
STD_LOGIC
;
eop
:
STD_LOGIC
;
empty
:
STD_LOGIC_VECTOR
(
c_tse_empty_w
-1
DOWNTO
0
);
err
:
STD_LOGIC_VECTOR
(
c_tse_error_w
-1
DOWNTO
0
);
END
RECORD
;
PROCEDURE
proc_dbg_tse_stream_src
(
SIGNAL
src_in
:
IN
t_tse_stream
;
SIGNAL
src_out
:
IN
t_tse_stream
;
SIGNAL
dbg_src
:
OUT
t_tse_stream
)
IS
BEGIN
dbg_src
.
ready
<=
src_in
.
ready
;
dbg_src
.
data
<=
src_out
.
data
;
dbg_src
.
valid
<=
src_out
.
valid
;
dbg_src
.
sop
<=
src_out
.
sop
;
dbg_src
.
eop
<=
src_out
.
eop
;
dbg_src
.
empty
<=
src_out
.
empty
;
dbg_src
.
err
<=
src_out
.
err
;
END
proc_dbg_tse_stream_src
;
PROCEDURE
proc_dbg_tse_stream_snk
(
SIGNAL
snk_in
:
IN
t_tse_stream
;
SIGNAL
snk_out
:
IN
t_tse_stream
;
SIGNAL
dbg_snk
:
OUT
t_tse_stream
)
IS
BEGIN
dbg_snk
.
ready
<=
snk_out
.
ready
;
dbg_snk
.
data
<=
snk_in
.
data
;
dbg_snk
.
valid
<=
snk_in
.
valid
;
dbg_snk
.
sop
<=
snk_in
.
sop
;
dbg_snk
.
eop
<=
snk_in
.
eop
;
dbg_snk
.
empty
<=
snk_in
.
empty
;
dbg_snk
.
err
<=
snk_in
.
err
;
END
proc_dbg_tse_stream_snk
;
-- Handle TX ready
-- Only support tx_ready_latency=0 or 1, corresponding to TX_ALMOST_FULL=3 or 4
-- Support for tx_ready_latency>1 requires keeping previous ready information
-- in a STD_LOGIC_VECTOR(tx_ready_latency-1 DOWNTO 0).
PROCEDURE
proc_ready_latency
(
CONSTANT
c_latency
:
IN
NATURAL
;
SIGNAL
clk
:
IN
STD_LOGIC
;
SIGNAL
ready
:
IN
STD_LOGIC
;
CONSTANT
c_valid
:
IN
STD_LOGIC
;
CONSTANT
c_sop
:
IN
STD_LOGIC
;
CONSTANT
c_eop
:
IN
STD_LOGIC
;
SIGNAL
out_valid
:
OUT
STD_LOGIC
;
SIGNAL
out_sop
:
OUT
STD_LOGIC
;
SIGNAL
out_eop
:
OUT
STD_LOGIC
)
IS
BEGIN
IF
c_latency
=
0
THEN
out_valid
<=
c_valid
;
out_sop
<=
c_sop
;
out_eop
<=
c_eop
;
WAIT
UNTIL
rising_edge
(
clk
);
WHILE
ready
/=
'1'
LOOP
WAIT
UNTIL
rising_edge
(
clk
);
END
LOOP
;
END
IF
;
IF
c_latency
=
1
THEN
WHILE
ready
/=
'1'
LOOP
out_valid
<=
'0'
;
out_sop
<=
'0'
;
out_eop
<=
'0'
;
WAIT
UNTIL
rising_edge
(
clk
);
END
LOOP
;
out_valid
<=
c_valid
;
out_sop
<=
c_sop
;
out_eop
<=
c_eop
;
WAIT
UNTIL
rising_edge
(
clk
);
END
IF
;
END
proc_ready_latency
;
-- Transmit user packet
-- . Use word aligned payload data, so with half word inserted before the 14 byte header
-- . Packets can be send immediately after eachother so new sop directly after last eop
-- . The word rate is controlled by respecting ready from the MAC
PROCEDURE
proc_tx_packet
(
CONSTANT
dst_mac_addr
:
IN
STD_LOGIC_VECTOR
(
c_eth_dst_mac
'RANGE
);
CONSTANT
src_mac_addr
:
IN
STD_LOGIC_VECTOR
(
c_eth_src_mac
'RANGE
);
CONSTANT
ethertype
:
IN
STD_LOGIC_VECTOR
(
c_eth_ethertype
'RANGE
);
CONSTANT
data_len
:
IN
NATURAL
;
-- in symbols = octets = bytes
SIGNAL
dp_clk
:
IN
STD_LOGIC
;
SIGNAL
dp_src_in
:
IN
t_tse_stream
;
SIGNAL
dp_src_out
:
OUT
t_tse_stream
)
IS
CONSTANT
c_mod
:
NATURAL
:
=
data_len
MOD
c_tse_symbols_per_beat
;
CONSTANT
c_nof_data_beats
:
NATURAL
:
=
data_len
/
c_tse_symbols_per_beat
+
sel_a_b
(
c_mod
,
1
,
0
);
CONSTANT
c_empty
:
NATURAL
:
=
sel_a_b
(
c_mod
,
c_tse_symbols_per_beat
-
c_mod
,
0
);
VARIABLE
v_sym
:
UNSIGNED
(
c_tse_symbol_w
-1
DOWNTO
0
)
:
=
(
OTHERS
=>
'0'
);
VARIABLE
v_num
:
UNSIGNED
(
c_tse_data_w
-1
DOWNTO
0
)
:
=
(
OTHERS
=>
'0'
);
BEGIN
-- DST MAC
dp_src_out
.
empty
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
0
,
c_tse_empty_w
));
dp_src_out
.
data
<=
(
OTHERS
=>
'0'
);
dp_src_out
.
data
(
15
DOWNTO
0
)
<=
hton
(
dst_mac_addr
(
15
DOWNTO
0
));
-- send to itself
proc_ready_latency
(
c_tx_ready_latency
,
dp_clk
,
dp_src_in
.
ready
,
'1'
,
'1'
,
'0'
,
dp_src_out
.
valid
,
dp_src_out
.
sop
,
dp_src_out
.
eop
);
dp_src_out
.
data
<=
hton
(
dst_mac_addr
(
47
DOWNTO
16
));
proc_ready_latency
(
c_tx_ready_latency
,
dp_clk
,
dp_src_in
.
ready
,
'1'
,
'0'
,
'0'
,
dp_src_out
.
valid
,
dp_src_out
.
sop
,
dp_src_out
.
eop
);
-- SRC MAC
dp_src_out
.
data
<=
hton
(
src_mac_addr
(
31
DOWNTO
0
));
proc_ready_latency
(
c_tx_ready_latency
,
dp_clk
,
dp_src_in
.
ready
,
'1'
,
'0'
,
'0'
,
dp_src_out
.
valid
,
dp_src_out
.
sop
,
dp_src_out
.
eop
);
-- SRC MAC & ETHERTYPE
dp_src_out
.
data
<=
hton
(
src_mac_addr
(
47
DOWNTO
32
))
&
hton
(
c_eth_ethertype
);
-- DATA
FOR
I
IN
0
TO
c_nof_data_beats
-1
LOOP
proc_ready_latency
(
c_tx_ready_latency
,
dp_clk
,
dp_src_in
.
ready
,
'1'
,
'0'
,
'0'
,
dp_src_out
.
valid
,
dp_src_out
.
sop
,
dp_src_out
.
eop
);
IF
c_tx_data_type
=
0
THEN
-- data : X"01020304", X"05060708", X"090A0B0C", etc
FOR
J
IN
c_tse_symbols_per_beat
-1
DOWNTO
0
LOOP
v_sym
:
=
v_sym
+
1
;
dp_src_out
.
data
((
J
+
1
)
*
c_tse_symbol_w
-1
DOWNTO
J
*
c_tse_symbol_w
)
<=
STD_LOGIC_VECTOR
(
v_sym
);
END
LOOP
;
ELSE
-- data : X"00000001", X"00000002", X"00000003", etc
v_num
:
=
v_num
+
1
;
dp_src_out
.
data
<=
STD_LOGIC_VECTOR
(
v_num
);
END
IF
;
-- tb : pull valid low for some time during the middle of the payload
IF
c_nof_tx_not_valid
>
0
AND
I
=
c_nof_data_beats
/
2
THEN
dp_src_out
.
valid
<=
'0'
;
FOR
I
IN
0
TO
c_nof_tx_not_valid
LOOP
WAIT
UNTIL
rising_edge
(
dp_clk
);
END
LOOP
;
dp_src_out
.
valid
<=
'1'
;
END
IF
;
END
LOOP
;
IF
c_empty
>
0
THEN
dp_src_out
.
empty
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
c_empty
,
c_tse_empty_w
));
FOR
J
IN
c_empty
-1
DOWNTO
0
LOOP
dp_src_out
.
data
((
J
+
1
)
*
c_tse_symbol_w
-1
DOWNTO
J
*
c_tse_symbol_w
)
<=
(
OTHERS
=>
'0'
);
END
LOOP
;
END
IF
;
proc_ready_latency
(
c_tx_ready_latency
,
dp_clk
,
dp_src_in
.
ready
,
'1'
,
'0'
,
'1'
,
dp_src_out
.
valid
,
dp_src_out
.
sop
,
dp_src_out
.
eop
);
dp_src_out
.
data
<=
(
OTHERS
=>
'0'
);
dp_src_out
.
valid
<=
'0'
;
dp_src_out
.
eop
<=
'0'
;
dp_src_out
.
empty
<=
STD_LOGIC_VECTOR
(
TO_UNSIGNED
(
0
,
c_tse_empty_w
));
END
proc_tx_packet
;
PROCEDURE
proc_valid_sop
(
SIGNAL
clk
:
IN
STD_LOGIC
;
SIGNAL
in_valid
:
IN
STD_LOGIC
;
SIGNAL
in_sop
:
IN
STD_LOGIC
)
IS
BEGIN
WAIT
UNTIL
rising_edge
(
clk
);
WHILE
in_valid
/=
'1'
AND
in_sop
/=
'1'
LOOP
WAIT
UNTIL
rising_edge
(
clk
);
END
LOOP
;
END
proc_valid_sop
;
PROCEDURE
proc_valid
(
SIGNAL
clk
:
IN
STD_LOGIC
;
SIGNAL
in_valid
:
IN
STD_LOGIC
)
IS
BEGIN
WAIT
UNTIL
rising_edge
(
clk
);
WHILE
in_valid
/=
'1'
LOOP
WAIT
UNTIL
rising_edge
(
clk
);
END
LOOP
;
END
proc_valid
;
-- Receive packet
-- . Use word aligned payload data, so with half word inserted before the 14 byte header
-- . Packets can be always be received, assume the user application is always ready
-- . The CRC32 is also passed on to the user at eop.
-- . Note that when empty/=0 then the CRC32 is not word aligned, so therefore use prev_data to be able
-- to handle part of last data word in case empty/=0 at eop
PROCEDURE
proc_rx_packet
(
CONSTANT
dst_mac_addr
:
IN
STD_LOGIC_VECTOR
(
c_eth_dst_mac
'RANGE
);
CONSTANT
src_mac_addr
:
IN
STD_LOGIC_VECTOR
(
c_eth_src_mac
'RANGE
);
CONSTANT
ethertype
:
IN
STD_LOGIC_VECTOR
(
c_eth_ethertype
'RANGE
);
SIGNAL
dp_clk
:
IN
STD_LOGIC
;
SIGNAL
dp_snk_in
:
IN
t_tse_stream
;
SIGNAL
dp_snk_out
:
OUT
t_tse_stream
)
IS
VARIABLE
v_sym
:
UNSIGNED
(
c_tse_symbol_w
-1
DOWNTO
0
)
:
=
(
OTHERS
=>
'0'
);
VARIABLE
v_num
:
UNSIGNED
(
c_tse_data_w
-1
DOWNTO
0
)
:
=
(
OTHERS
=>
'0'
);
VARIABLE
v_empty
:
NATURAL
;
VARIABLE
v_first
:
BOOLEAN
:
=
TRUE
;
VARIABLE
v_data
:
STD_LOGIC_VECTOR
(
c_tse_data_w
-1
DOWNTO
0
);
VARIABLE
v_prev_data
:
STD_LOGIC_VECTOR
(
c_tse_data_w
-1
DOWNTO
0
);
BEGIN
-- Keep ff_rx_snk_out.ready='1' all the time
dp_snk_out
.
ready
<=
'1'
;
-- Verify DST MAC
proc_valid_sop
(
dp_clk
,
dp_snk_in
.
valid
,
dp_snk_in
.
sop
);
ASSERT
dp_snk_in
.
data
(
31
DOWNTO
16
)
=
X"0000"
REPORT
"RX: Alignment half word not zero"
SEVERITY
ERROR
;
ASSERT
dp_snk_in
.
data
(
15
DOWNTO
0
)
=
hton
(
dst_mac_addr
(
15
DOWNTO
0
))
REPORT
"RX: Wrong dst_mac_addr(15 DOWNTO 0)"
SEVERITY
ERROR
;
proc_valid
(
dp_clk
,
dp_snk_in
.
valid
);
ASSERT
dp_snk_in
.
data
(
31
DOWNTO
0
)
=
hton
(
dst_mac_addr
(
47
DOWNTO
16
))
REPORT
"RX: Wrong dst_mac_addr(47 DOWNTO 16)"
SEVERITY
ERROR
;
-- Verify SRC MAC
proc_valid
(
dp_clk
,
dp_snk_in
.
valid
);
ASSERT
dp_snk_in
.
data
(
31
DOWNTO
0
)
=
hton
(
src_mac_addr
(
31
DOWNTO
0
))
REPORT
"RX: Wrong src_mac_addr(31 DOWNTO 0)"
SEVERITY
ERROR
;
-- Verify SRC MAC & ETHERTYPE
proc_valid
(
dp_clk
,
dp_snk_in
.
valid
);
ASSERT
dp_snk_in
.
data
(
31
DOWNTO
16
)
=
hton
(
src_mac_addr
(
47
DOWNTO
32
))
REPORT
"RX: Wrong src_mac_addr(47 DOWNTO 32)"
SEVERITY
ERROR
;
ASSERT
dp_snk_in
.
data
(
15
DOWNTO
0
)
=
hton
(
c_eth_ethertype
)
REPORT
"RX: Wrong ethertype"
SEVERITY
ERROR
;
-- Verify DATA
v_first
:
=
TRUE
;
proc_valid
(
dp_clk
,
dp_snk_in
.
valid
);
WHILE
dp_snk_in
.
eop
/=
'1'
LOOP
v_prev_data
:
=
v_data
;
v_data
:
=
dp_snk_in
.
data
;
IF
v_first
=
FALSE
THEN
IF
c_tx_data_type
=
0
THEN
-- data : X"01020304", X"05060708", X"090A0B0C", etc
FOR
J
IN
c_tse_symbols_per_beat
-1
DOWNTO
0
LOOP
v_sym
:
=
v_sym
+
1
;
ASSERT
UNSIGNED
(
v_prev_data
((
J
+
1
)
*
c_tse_symbol_w
-1
DOWNTO
J
*
c_tse_symbol_w
))
=
v_sym
REPORT
"RX: Wrong data symbol"
SEVERITY
ERROR
;
END
LOOP
;
ELSE
-- data : X"00000001", X"00000002", X"00000003", etc
v_num
:
=
v_num
+
1
;
ASSERT
UNSIGNED
(
v_prev_data
)
=
v_num
REPORT
"RX: Wrong data word"
SEVERITY
ERROR
;
END
IF
;
END
IF
;
v_first
:
=
FALSE
;
proc_valid
(
dp_clk
,
dp_snk_in
.
valid
);
END
LOOP
;
-- Verify last DATA and CRC32 if empty /=0 else the last word is only the CRC32
v_prev_data
:
=
v_data
;
v_data
:
=
dp_snk_in
.
data
;
v_empty
:
=
TO_INTEGER
(
UNSIGNED
(
dp_snk_in
.
empty
));
IF
v_empty
>
0
THEN
FOR
J
IN
v_empty
-1
DOWNTO
0
LOOP
v_prev_data
((
J
+
1
)
*
c_tse_symbol_w
-1
DOWNTO
J
*
c_tse_symbol_w
)
:
=
(
OTHERS
=>
'0'
);
END
LOOP
;
IF
c_tx_data_type
=
0
THEN
-- data : X"01020304", X"05060708", X"090A0B0C", etc
FOR
J
IN
c_tse_symbols_per_beat
-1
DOWNTO
v_empty
LOOP
-- ignore CRC32 symbols in last data word
v_sym
:
=
v_sym
+
1
;
ASSERT
UNSIGNED
(
v_prev_data
((
J
+
1
)
*
c_tse_symbol_w
-1
DOWNTO
J
*
c_tse_symbol_w
))
=
v_sym
REPORT
"RX: Wrong empty data symbol"
SEVERITY
ERROR
;
END
LOOP
;
ELSE
-- data : X"00000001", X"00000002", X"00000003", etc
v_num
:
=
v_num
+
1
;
FOR
J
IN
v_empty
-1
DOWNTO
0
LOOP
v_num
((
J
+
1
)
*
c_tse_symbol_w
-1
DOWNTO
J
*
c_tse_symbol_w
)
:
=
(
OTHERS
=>
'0'
);
-- force CRC32 symbols in last data word to 0
END
LOOP
;
ASSERT
UNSIGNED
(
v_prev_data
)
=
v_num
REPORT
"RX: Wrong empty data word"
SEVERITY
ERROR
;
END
IF
;
ELSE
-- No verify on CRC32 word
END
IF
;
END
proc_rx_packet
;
-- Clocks and reset
SIGNAL
tb_end
:
STD_LOGIC
:
=
'0'
;
SIGNAL
eth_clk
:
STD_LOGIC
:
=
'0'
;
SIGNAL
sys_clk
:
STD_LOGIC
:
=
'0'
;
SIGNAL
dp_clk
:
STD_LOGIC
;
SIGNAL
mm_clk
:
STD_LOGIC
;
SIGNAL
mm_rst
:
STD_LOGIC
;
-- TSE MAC control interface
SIGNAL
mm_init
:
STD_LOGIC
:
=
'1'
;
SIGNAL
mm_miso
:
t_mm_bus
;
-- master in slave out
SIGNAL
mm_mosi
:
t_mm_bus
;
-- master out slave in
SIGNAL
pcs_rddata
:
NATURAL
;
-- [c_tse_pcs_data_w-1:0]
SIGNAL
tse_led_an
:
STD_LOGIC
;
SIGNAL
tse_led_link
:
STD_LOGIC
;
-- TSE MAC transmit interface
-- . Avalon ST source
SIGNAL
ff_tx_src_in
:
t_tse_stream
;
SIGNAL
ff_tx_src_out
:
t_tse_stream
;
-- . MAC specific
SIGNAL
ff_tx_crc_fwd
:
STD_LOGIC
;
SIGNAL
ff_tx_septy
:
STD_LOGIC
;
SIGNAL
ff_tx_a_full
:
STD_LOGIC
;
SIGNAL
ff_tx_a_empty
:
STD_LOGIC
;
SIGNAL
ff_tx_uflow
:
STD_LOGIC
;
-- TSE MAC receive interface
-- . Avalon ST sink
SIGNAL
ff_rx_snk_in
:
t_tse_stream
;
SIGNAL
ff_rx_snk_out
:
t_tse_stream
;
-- . MAC specific
SIGNAL
ff_rx_ethertype
:
STD_LOGIC_VECTOR
(
c_tse_err_stat_w
-1
DOWNTO
0
);
SIGNAL
ff_rx_frm_type
:
STD_LOGIC_VECTOR
(
c_tse_frm_type_w
-1
DOWNTO
0
);
SIGNAL
ff_rx_dsav
:
STD_LOGIC
;
SIGNAL
ff_rx_a_full
:
STD_LOGIC
;
SIGNAL
ff_rx_a_empty
:
STD_LOGIC
;
-- TSE PHY interface
SIGNAL
eth_txp
:
STD_LOGIC
;
SIGNAL
eth_rxp
:
STD_LOGIC
;
-- Verification
SIGNAL
tx_pkt_cnt
:
NATURAL
:
=
0
;
SIGNAL
rx_pkt_cnt
:
NATURAL
:
=
0
;
-- Debug signals to combine valid in and out of records
SIGNAL
dbg_mm
:
t_mm_bus
;
SIGNAL
dbg_ff_tx
:
t_tse_stream
;
SIGNAL
dbg_ff_rx
:
t_tse_stream
;
BEGIN
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
;
dp_clk
<=
sys_clk
;
-- Debug signals to combine valid in and out of records
proc_dbg_mm_bus
(
mm_miso
,
mm_mosi
,
dbg_mm
);
proc_dbg_tse_stream_src
(
ff_tx_src_in
,
ff_tx_src_out
,
dbg_ff_tx
);
proc_dbg_tse_stream_snk
(
ff_rx_snk_in
,
ff_rx_snk_out
,
dbg_ff_rx
);
-- run 1 us
p_mm_stimuli
:
PROCESS
BEGIN
mm_init
<=
'1'
;
mm_mosi
.
wr
<=
'0'
;
mm_mosi
.
rd
<=
'0'
;
-- reset release
mm_rst
<=
'1'
;
FOR
I
IN
0
TO
9
LOOP
WAIT
UNTIL
rising_edge
(
mm_clk
);
END
LOOP
;
mm_rst
<=
'0'
;
FOR
I
IN
0
TO
9
LOOP
WAIT
UNTIL
rising_edge
(
mm_clk
);
END
LOOP
;
-- PSC control
proc_rd_pcs
(
16
#
22
#
,
pcs_rddata
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- REV --> 0x0901
proc_wr_pcs
(
16
#
28
#
,
16
#
0008
#
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- IF_MODE <-- Force 1GbE, no autonegatiation
proc_rd_pcs
(
16
#
00
#
,
pcs_rddata
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- CONTROL --> 0x1140
proc_rd_pcs
(
16
#
02
#
,
pcs_rddata
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- STATUS --> 0x000D
proc_wr_pcs
(
16
#
00
#
,
16
#
0140
#
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- CONTROL <-- Auto negotiate disable
-- MAC control
proc_rd_mac
(
16
#
000
#
,
pcs_rddata
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- REV --> CUST_VERSION & 0x0901
IF
c_tse_promis_en
=
FALSE
THEN
proc_wr_mac
(
16
#
008
#
,
16
#
0100004
B
#
,
mm_clk
,
mm_miso
,
mm_mosi
);
ELSE
proc_wr_mac
(
16
#
008
#
,
16
#
0100005
B
#
,
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_wr_mac
(
16
#
00
C
#
,
16
#
56789
ABC
#
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- MAC_0
proc_wr_mac
(
16
#
010
#
,
16
#
00001234
#
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- MAC_1 <-- SRC_MAC = 12-34-56-78-9A-BC
proc_wr_mac
(
16
#
05
C
#
,
16
#
0000000
C
#
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- TX_IPG_LENGTH <-- interpacket gap = 12
proc_wr_mac
(
16
#
014
#
,
16
#
000005
EE
#
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- FRM_LENGTH <-- receive max frame length = 1518
-- 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_wr_mac
(
16
#
01
C
#
,
c_tse_rx_fifo_depth
-16
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- RX_SECTION_EMPTY <-- default FIFO depth - 16, >3
proc_wr_mac
(
16
#
020
#
,
16
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- RX_SECTION_FULL <-- default 16
proc_wr_mac
(
16
#
024
#
,
c_tse_tx_fifo_depth
-16
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- TX_SECTION_EMPTY <-- default FIFO depth - 16, >3
proc_wr_mac
(
16
#
028
#
,
16
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- TX_SECTION_FULL <-- default 16, >~ 8 otherwise no tx
proc_wr_mac
(
16
#
02
C
#
,
8
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- RX_ALMOST_EMPTY <-- default 8
proc_wr_mac
(
16
#
030
#
,
8
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- RX_ALMOST_FULL <-- default 8
proc_wr_mac
(
16
#
034
#
,
8
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- TX_ALMOST_EMPTY <-- default 8
proc_wr_mac
(
16
#
038
#
,
c_tx_ready_latency
+
3
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- TX_ALMOST_FULL <-- default 3
proc_rd_mac
(
16
#
0
E8
#
,
pcs_rddata
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- TX_CMD_STAT --> 0x00040000 : [18]=1 TX_SHIFT16, [17]=0 OMIT_CRC
proc_rd_mac
(
16
#
0
EC
#
,
pcs_rddata
,
mm_clk
,
mm_miso
,
mm_mosi
);
-- RX_CMD_STAT --> 0x02000000 : [25]=1 RX_SHIFT16
WAIT
UNTIL
rising_edge
(
mm_clk
);
mm_init
<=
'0'
;
WAIT
;
END
PROCESS
;
p_tx_frame
:
PROCESS
BEGIN
-- . Avalon ST
ff_tx_src_out
.
data
<=
(
OTHERS
=>
'0'
);
ff_tx_src_out
.
valid
<=
'0'
;
ff_tx_src_out
.
sop
<=
'0'
;
ff_tx_src_out
.
eop
<=
'0'
;
ff_tx_src_out
.
empty
<=
(
OTHERS
=>
'0'
);
ff_tx_src_out
.
err
<=
(
OTHERS
=>
'0'
);
-- . MAC specific
ff_tx_crc_fwd
<=
'0'
;
WHILE
mm_init
/=
'0'
LOOP
WAIT
UNTIL
rising_edge
(
dp_clk
);
END
LOOP
;
FOR
I
IN
0
TO
9
LOOP
WAIT
UNTIL
rising_edge
(
dp_clk
);
END
LOOP
;
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, "0000000000010000", 16, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 16, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 16, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
proc_tx_packet
(
c_eth_src_mac
,
c_eth_src_mac
,
c_eth_ethertype
,
1499
,
dp_clk
,
ff_tx_src_in
,
ff_tx_src_out
);
-- verify st empty
proc_tx_packet
(
c_eth_src_mac
,
c_eth_src_mac
,
c_eth_ethertype
,
1500
,
dp_clk
,
ff_tx_src_in
,
ff_tx_src_out
);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
-- proc_tx_packet(c_eth_src_mac, c_eth_src_mac, c_eth_ethertype, 1500, dp_clk, ff_tx_src_in, ff_tx_src_out);
FOR
I
IN
0
TO
1500
*
2
LOOP
WAIT
UNTIL
rising_edge
(
dp_clk
);
END
LOOP
;
tb_end
<=
'1'
;
WAIT
;
END
PROCESS
;
p_rx_frame
:
PROCESS
BEGIN
-- . Avalon ST
ff_rx_snk_out
.
ready
<=
'0'
;
WHILE
mm_init
/=
'0'
LOOP
WAIT
UNTIL
rising_edge
(
dp_clk
);
END
LOOP
;
-- Receive forever
WHILE
TRUE
LOOP
proc_rx_packet
(
c_eth_src_mac
,
c_eth_src_mac
,
c_eth_ethertype
,
dp_clk
,
ff_rx_snk_in
,
ff_rx_snk_out
);
END
LOOP
;
WAIT
;
END
PROCESS
;
dut
:
ENTITY
work
.
ip_arria10_tse_sgmii_lvds
-- The ip_arria10_tse_sgmii_lvds needs to be regenerated if its parameters are changed.
-- . ENABLE_SHIFT16 = 1 : Align packet headers to 32 bit, useful for Nios data handling
-- . ENABLE_SUP_ADDR = 0 : An extra MAC addresses can e.g. be used as service MAC for tests
-- . ENA_HASH = 0 : A multi cast hash table can be used to address all nodes at once
-- . STAT_CNT_ENA = 0 : PHY statistics counts are useful for monitoring, but not realy needed
-- . EG_FIFO = 256 : Tx FIFO depth in nof 32 bit words (256 --> 1 M9K)
-- . ING_FIFO = 256 : Rx FIFO depth in nof 32 bit words (256 --> 1 M9K)
PORT
MAP
(
-- MAC transmit interface
-- . Avalon ST
ff_tx_clk
=>
dp_clk
,
ff_tx_rdy
=>
ff_tx_src_in
.
ready
,
ff_tx_data
=>
ff_tx_src_out
.
data
,
ff_tx_wren
=>
ff_tx_src_out
.
valid
,
ff_tx_sop
=>
ff_tx_src_out
.
sop
,
ff_tx_eop
=>
ff_tx_src_out
.
eop
,
ff_tx_mod
=>
ff_tx_src_out
.
empty
,
ff_tx_err
=>
ff_tx_src_out
.
err
(
0
),
-- . MAC specific
ff_tx_crc_fwd
=>
ff_tx_crc_fwd
,
-- when '0' MAC inserts CRC32 after eop
ff_tx_septy
=>
ff_tx_septy
,
-- when '0' then tx FIFO goes above section-empty threshold
ff_tx_a_full
=>
ff_tx_a_full
,
-- when '1' then tx FIFO goes above almost-full threshold
ff_tx_a_empty
=>
ff_tx_a_empty
,
-- when '1' then tx FIFO goes below almost-empty threshold
tx_ff_uflow
=>
ff_tx_uflow
,
-- when '1' then tx FIFO underflow
-- MAC receive interface
-- . Avalon STs
ff_rx_clk
=>
dp_clk
,
ff_rx_rdy
=>
ff_rx_snk_out
.
ready
,
ff_rx_data
=>
ff_rx_snk_in
.
data
,
ff_rx_dval
=>
ff_rx_snk_in
.
valid
,
ff_rx_sop
=>
ff_rx_snk_in
.
sop
,
ff_rx_eop
=>
ff_rx_snk_in
.
eop
,
ff_rx_mod
=>
ff_rx_snk_in
.
empty
,
rx_err
=>
ff_rx_snk_in
.
err
,
-- [5] collision error (can only occur in half duplex mode)
-- [4] PHY error on GMII
-- [3] receive frame truncated due to FIFO overflow
-- [2] CRC-32 error
-- [1] invalid length
-- [0] = OR of [1:5]
-- . MAC specific
rx_err_stat
=>
ff_rx_ethertype
,
-- [17,16] VLAN info, [15:0] Ethernet lentgh/type field
rx_frm_type
=>
ff_rx_frm_type
,
-- [3]=VLAN, [2]=Broadcast, [1]=Multicast, [0]=Unicast
ff_rx_dsav
=>
ff_rx_dsav
,
-- rx frame available, but not necessarily a complete frame
ff_rx_a_full
=>
ff_rx_a_full
,
-- when '1' then rx FIFO goes above almost-full threshold
ff_rx_a_empty
=>
ff_rx_a_empty
,
-- when '1' sthen rx FIFO goes below almost-empty threshold
-- Reset
reset
=>
mm_rst
,
-- asynchronous reset (choose synchronous to mm_clk)
-- MM control interface
clk
=>
mm_clk
,
address
=>
mm_mosi
.
address
(
c_tse_byte_addr_w
-1
DOWNTO
2
),
readdata
=>
mm_miso
.
rddata
,
read
=>
mm_mosi
.
rd
,
writedata
=>
mm_mosi
.
wrdata
,
write
=>
mm_mosi
.
wr
,
waitrequest
=>
mm_miso
.
waitreq
,
-- Status LEDs
led_an
=>
tse_led_an
,
-- '1' = autonegation completed
led_link
=>
tse_led_link
,
-- '1' = successful link synchronisation
led_disp_err
=>
OPEN
,
-- TBI character error
led_char_err
=>
OPEN
,
-- TBI disparity errorreceived
-- Serial 1.25 Gbps
ref_clk
=>
eth_clk
,
txp
=>
eth_txp
,
rxp
=>
eth_rxp
);
-- Loopback
eth_rxp
<=
eth_txp
;
-- Verification
tx_pkt_cnt
<=
tx_pkt_cnt
+
1
WHEN
ff_tx_src_out
.
sop
=
'1'
AND
rising_edge
(
dp_clk
);
rx_pkt_cnt
<=
rx_pkt_cnt
+
1
WHEN
ff_rx_snk_in
.
eop
=
'1'
AND
rising_edge
(
dp_clk
);
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
;
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment