Commit 408c7ef8 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

Added simulation models

parent 89ba64fb
`define ADDR_MDIO_MCR 7'h0
`define MDIO_MCR_RESV_OFFSET 0
`define MDIO_MCR_RESV 32'h0000001f
`define MDIO_MCR_UNI_EN_OFFSET 5
`define MDIO_MCR_UNI_EN 32'h00000020
`define MDIO_MCR_SPEED1000_OFFSET 6
`define MDIO_MCR_SPEED1000 32'h00000040
`define MDIO_MCR_CTST_OFFSET 7
`define MDIO_MCR_CTST 32'h00000080
`define MDIO_MCR_FULLDPLX_OFFSET 8
`define MDIO_MCR_FULLDPLX 32'h00000100
`define MDIO_MCR_ANRESTART_OFFSET 9
`define MDIO_MCR_ANRESTART 32'h00000200
`define MDIO_MCR_ISOLATE_OFFSET 10
`define MDIO_MCR_ISOLATE 32'h00000400
`define MDIO_MCR_PDOWN_OFFSET 11
`define MDIO_MCR_PDOWN 32'h00000800
`define MDIO_MCR_ANENABLE_OFFSET 12
`define MDIO_MCR_ANENABLE 32'h00001000
`define MDIO_MCR_SPEED100_OFFSET 13
`define MDIO_MCR_SPEED100 32'h00002000
`define MDIO_MCR_LOOPBACK_OFFSET 14
`define MDIO_MCR_LOOPBACK 32'h00004000
`define MDIO_MCR_RESET_OFFSET 15
`define MDIO_MCR_RESET 32'h00008000
`define ADDR_MDIO_MSR 7'h4
`define MDIO_MSR_ERCAP_OFFSET 0
`define MDIO_MSR_ERCAP 32'h00000001
`define MDIO_MSR_JCD_OFFSET 1
`define MDIO_MSR_JCD 32'h00000002
`define MDIO_MSR_LSTATUS_OFFSET 2
`define MDIO_MSR_LSTATUS 32'h00000004
`define MDIO_MSR_ANEGCAPABLE_OFFSET 3
`define MDIO_MSR_ANEGCAPABLE 32'h00000008
`define MDIO_MSR_RFAULT_OFFSET 4
`define MDIO_MSR_RFAULT 32'h00000010
`define MDIO_MSR_ANEGCOMPLETE_OFFSET 5
`define MDIO_MSR_ANEGCOMPLETE 32'h00000020
`define MDIO_MSR_MFSUPPRESS_OFFSET 6
`define MDIO_MSR_MFSUPPRESS 32'h00000040
`define MDIO_MSR_UNIDIRABLE_OFFSET 7
`define MDIO_MSR_UNIDIRABLE 32'h00000080
`define MDIO_MSR_ESTATEN_OFFSET 8
`define MDIO_MSR_ESTATEN 32'h00000100
`define MDIO_MSR_100HALF2_OFFSET 9
`define MDIO_MSR_100HALF2 32'h00000200
`define MDIO_MSR_100FULL2_OFFSET 10
`define MDIO_MSR_100FULL2 32'h00000400
`define MDIO_MSR_10HALF_OFFSET 11
`define MDIO_MSR_10HALF 32'h00000800
`define MDIO_MSR_10FULL_OFFSET 12
`define MDIO_MSR_10FULL 32'h00001000
`define MDIO_MSR_100HALF_OFFSET 13
`define MDIO_MSR_100HALF 32'h00002000
`define MDIO_MSR_100FULL_OFFSET 14
`define MDIO_MSR_100FULL 32'h00004000
`define MDIO_MSR_100BASE4_OFFSET 15
`define MDIO_MSR_100BASE4 32'h00008000
`define ADDR_MDIO_PHYSID1 7'h8
`define MDIO_PHYSID1_OUI_OFFSET 0
`define MDIO_PHYSID1_OUI 32'h0000ffff
`define ADDR_MDIO_PHYSID2 7'hc
`define MDIO_PHYSID2_REV_NUM_OFFSET 0
`define MDIO_PHYSID2_REV_NUM 32'h0000000f
`define MDIO_PHYSID2_MMNUM_OFFSET 4
`define MDIO_PHYSID2_MMNUM 32'h000003f0
`define MDIO_PHYSID2_OUI_OFFSET 10
`define MDIO_PHYSID2_OUI 32'h0000fc00
`define ADDR_MDIO_ADVERTISE 7'h10
`define MDIO_ADVERTISE_RSVD3_OFFSET 0
`define MDIO_ADVERTISE_RSVD3 32'h0000001f
`define MDIO_ADVERTISE_FULL_OFFSET 5
`define MDIO_ADVERTISE_FULL 32'h00000020
`define MDIO_ADVERTISE_HALF_OFFSET 6
`define MDIO_ADVERTISE_HALF 32'h00000040
`define MDIO_ADVERTISE_PAUSE_OFFSET 7
`define MDIO_ADVERTISE_PAUSE 32'h00000180
`define MDIO_ADVERTISE_RSVD2_OFFSET 9
`define MDIO_ADVERTISE_RSVD2 32'h00000e00
`define MDIO_ADVERTISE_RFAULT_OFFSET 12
`define MDIO_ADVERTISE_RFAULT 32'h00003000
`define MDIO_ADVERTISE_RSVD1_OFFSET 14
`define MDIO_ADVERTISE_RSVD1 32'h00004000
`define MDIO_ADVERTISE_NPAGE_OFFSET 15
`define MDIO_ADVERTISE_NPAGE 32'h00008000
`define ADDR_MDIO_LPA 7'h14
`define MDIO_LPA_RSVD3_OFFSET 0
`define MDIO_LPA_RSVD3 32'h0000001f
`define MDIO_LPA_FULL_OFFSET 5
`define MDIO_LPA_FULL 32'h00000020
`define MDIO_LPA_HALF_OFFSET 6
`define MDIO_LPA_HALF 32'h00000040
`define MDIO_LPA_PAUSE_OFFSET 7
`define MDIO_LPA_PAUSE 32'h00000180
`define MDIO_LPA_RSVD2_OFFSET 9
`define MDIO_LPA_RSVD2 32'h00000e00
`define MDIO_LPA_RFAULT_OFFSET 12
`define MDIO_LPA_RFAULT 32'h00003000
`define MDIO_LPA_LPACK_OFFSET 14
`define MDIO_LPA_LPACK 32'h00004000
`define MDIO_LPA_NPAGE_OFFSET 15
`define MDIO_LPA_NPAGE 32'h00008000
`define ADDR_MDIO_EXPANSION 7'h18
`define MDIO_EXPANSION_RSVD1_OFFSET 0
`define MDIO_EXPANSION_RSVD1 32'h00000001
`define MDIO_EXPANSION_LWCP_OFFSET 1
`define MDIO_EXPANSION_LWCP 32'h00000002
`define MDIO_EXPANSION_ENABLENPAGE_OFFSET 2
`define MDIO_EXPANSION_ENABLENPAGE 32'h00000004
`define MDIO_EXPANSION_RSVD2_OFFSET 3
`define MDIO_EXPANSION_RSVD2 32'h0000fff8
`define ADDR_MDIO_ESTATUS 7'h3c
`define MDIO_ESTATUS_RSVD1_OFFSET 0
`define MDIO_ESTATUS_RSVD1 32'h00000fff
`define MDIO_ESTATUS_1000_THALF_OFFSET 12
`define MDIO_ESTATUS_1000_THALF 32'h00001000
`define MDIO_ESTATUS_1000_TFULL_OFFSET 13
`define MDIO_ESTATUS_1000_TFULL 32'h00002000
`define MDIO_ESTATUS_1000_XHALF_OFFSET 14
`define MDIO_ESTATUS_1000_XHALF 32'h00004000
`define MDIO_ESTATUS_1000_XFULL_OFFSET 15
`define MDIO_ESTATUS_1000_XFULL 32'h00008000
`define ADDR_MDIO_WR_SPEC 7'h40
`define MDIO_WR_SPEC_TX_CAL_OFFSET 0
`define MDIO_WR_SPEC_TX_CAL 32'h00000001
`define MDIO_WR_SPEC_RX_CAL_STAT_OFFSET 1
`define MDIO_WR_SPEC_RX_CAL_STAT 32'h00000002
`define MDIO_WR_SPEC_CAL_CRST_OFFSET 2
`define MDIO_WR_SPEC_CAL_CRST 32'h00000004
`define MDIO_WR_SPEC_BSLIDE_OFFSET 4
`define MDIO_WR_SPEC_BSLIDE 32'h000000f0
`define ADDR_EP_ECR 8'h0
`define EP_ECR_PORTID_OFFSET 0
`define EP_ECR_PORTID 32'h0000001f
`define EP_ECR_RST_CNT_OFFSET 5
`define EP_ECR_RST_CNT 32'h00000020
`define EP_ECR_TX_EN_FRA_OFFSET 6
`define EP_ECR_TX_EN_FRA 32'h00000040
`define EP_ECR_RX_EN_FRA_OFFSET 7
`define EP_ECR_RX_EN_FRA 32'h00000080
`define ADDR_EP_TSCR 8'h4
`define EP_TSCR_EN_TXTS_OFFSET 0
`define EP_TSCR_EN_TXTS 32'h00000001
`define EP_TSCR_EN_RXTS_OFFSET 1
`define EP_TSCR_EN_RXTS 32'h00000002
`define EP_TSCR_CS_START_OFFSET 2
`define EP_TSCR_CS_START 32'h00000004
`define EP_TSCR_CS_DONE_OFFSET 3
`define EP_TSCR_CS_DONE 32'h00000008
`define ADDR_EP_RFCR 8'h8
`define EP_RFCR_A_RUNT_OFFSET 0
`define EP_RFCR_A_RUNT 32'h00000001
`define EP_RFCR_A_GIANT_OFFSET 1
`define EP_RFCR_A_GIANT 32'h00000002
`define EP_RFCR_A_HP_OFFSET 2
`define EP_RFCR_A_HP 32'h00000004
`define EP_RFCR_A_FRAG_OFFSET 3
`define EP_RFCR_A_FRAG 32'h00000008
`define EP_RFCR_QMODE_OFFSET 4
`define EP_RFCR_QMODE 32'h00000030
`define EP_RFCR_FIX_PRIO_OFFSET 6
`define EP_RFCR_FIX_PRIO 32'h00000040
`define EP_RFCR_PRIO_VAL_OFFSET 8
`define EP_RFCR_PRIO_VAL 32'h00000700
`define EP_RFCR_VID_VAL_OFFSET 16
`define EP_RFCR_VID_VAL 32'h0fff0000
`define ADDR_EP_FCR 8'hc
`define EP_FCR_RXPAUSE_OFFSET 0
`define EP_FCR_RXPAUSE 32'h00000001
`define EP_FCR_TXPAUSE_OFFSET 1
`define EP_FCR_TXPAUSE 32'h00000002
`define EP_FCR_TX_THR_OFFSET 8
`define EP_FCR_TX_THR 32'h0000ff00
`define EP_FCR_TX_QUANTA_OFFSET 16
`define EP_FCR_TX_QUANTA 32'hffff0000
`define ADDR_EP_MACH 8'h10
`define ADDR_EP_MACL 8'h14
`define ADDR_EP_DMCR 8'h18
`define EP_DMCR_EN_OFFSET 0
`define EP_DMCR_EN 32'h00000001
`define EP_DMCR_N_AVG_OFFSET 16
`define EP_DMCR_N_AVG 32'h0fff0000
`define ADDR_EP_DMSR 8'h1c
`define EP_DMSR_PS_VAL_OFFSET 0
`define EP_DMSR_PS_VAL 32'h00ffffff
`define EP_DMSR_PS_RDY_OFFSET 24
`define EP_DMSR_PS_RDY 32'h01000000
`define ADDR_EP_MDIO_CR 8'h20
`define EP_MDIO_CR_DATA_OFFSET 0
`define EP_MDIO_CR_DATA 32'h0000ffff
`define EP_MDIO_CR_ADDR_OFFSET 16
`define EP_MDIO_CR_ADDR 32'h00ff0000
`define EP_MDIO_CR_RW_OFFSET 31
`define EP_MDIO_CR_RW 32'h80000000
`define ADDR_EP_MDIO_SR 8'h24
`define EP_MDIO_SR_RDATA_OFFSET 0
`define EP_MDIO_SR_RDATA 32'h0000ffff
`define EP_MDIO_SR_READY_OFFSET 31
`define EP_MDIO_SR_READY 32'h80000000
`define ADDR_EP_IDCODE 8'h28
`define ADDR_EP_DSR 8'h2c
`define EP_DSR_LSTATUS_OFFSET 0
`define EP_DSR_LSTATUS 32'h00000001
`define EP_DSR_LACT_OFFSET 1
`define EP_DSR_LACT 32'h00000002
`define ADDR_EP_AFCR 8'h30
`define EP_AFCR_ENABLE_OFFSET 0
`define EP_AFCR_ENABLE 32'h00000001
`define EP_AFCR_RULE_SEL_OFFSET 1
`define EP_AFCR_RULE_SEL 32'h0000000e
`define EP_AFCR_MATRIX_ADDR_OFFSET 4
`define EP_AFCR_MATRIX_ADDR 32'h00000ff0
`define EP_AFCR_MATRIX_DATA_OFFSET 12
`define EP_AFCR_MATRIX_DATA 32'h000ff000
`define EP_AFCR_MATRIX_WRITE_P_OFFSET 20
`define EP_AFCR_MATRIX_WRITE_P 32'h00100000
`define ADDR_EP_AFR0 8'h34
`define EP_AFR0_DMAC_EN_OFFSET 0
`define EP_AFR0_DMAC_EN 32'h00000001
`define EP_AFR0_VID_EN_OFFSET 1
`define EP_AFR0_VID_EN 32'h00000002
`define EP_AFR0_ETYPE_EN_OFFSET 2
`define EP_AFR0_ETYPE_EN 32'h00000004
`define EP_AFR0_VID_OFFSET 3
`define EP_AFR0_VID 32'h00007ff8
`define ADDR_EP_AFR1 8'h38
`define EP_AFR1_DMAC_LO_OFFSET 0
`define EP_AFR1_DMAC_LO 32'hffffffff
`define ADDR_EP_AFR2 8'h3c
`define EP_AFR2_DMAC_HI_OFFSET 0
`define EP_AFR2_DMAC_HI 32'h0000ffff
`define EP_AFR2_ETYPE_OFFSET 16
`define EP_AFR2_ETYPE 32'hffff0000
`define BASE_EP_RMON_RAM 8'h80
`define SIZE_EP_RMON_RAM 32'h20
// Fabric TAP emulator example.
// usage: (as root)
// tunctl -t tap0
// ifconfig tap0 192.168.100.100
// arping -I tap0 192.168.100.101
// you should see some ARP requests coming
`timescale 1ns / 1ps
`include "fabric_emu.sv"
`include "fabric_emu_tap.sv"
module main;
const int c_clock_period = 8;
reg clk = 0;
reg rst_n = 0;
`WRF_WIRES(from_tap); // Data coming from tap0 interface
`WRF_WIRES(to_tap); // Data going to tap0 interface
// generate clock and reset signals
always #(c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
// Two fabric emulators talking to each other
fabric_emu_tap U_tap
(
.clk_sys_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, from_tap), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, to_tap)
);
fabric_emu U_emu
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, to_tap),
`WRF_CONNECT_SINK(tx, from_tap)
);
// Check if there's anything received by the TAP emulator
always @(posedge clk) if (U_emu.poll())
begin
ether_frame_t frame;
$display("TAP Emulator received a frame!");
U_emu.receive(frame);
dump_frame_header("EmuB RX: ", frame);
frame.hdr.src = 'h010203040506; // modify the MAC address and send the frame back to tap interface
U_emu.send(frame.hdr, frame.payload, frame.size);
end
endmodule // main
This diff is collapsed.
`ifndef __FABRIC_EMU_DEFS_SV
`define __FABRIC_EMU_DEFS_SV
/* Ethernet frame header extended with WR-compliant OOB signalling */
typedef struct {
bit no_mac; // when 1, there's no valid source MAC present in the frame header and the SRC MAC field must be filled by the endpoint
bit [47:0] dst; // DST MAC
bit [47:0] src; // SRC MAC
bit [15:0] ethertype;
bit is_802_1q; // when 1, the frame has 802.1q header
bit [11:0] vid; // VLAN ID
bit [2:0] prio; // PCP priority tag
int oob_type; // OOB TYPE: OOB_TYPE_TXTS = TX frame ID (for TX timestamping), OOB_TYPE_RXTS = RX timestamp
bit[15:0] oob_fid; //
bit [27:0] timestamp_r;
bit [3:0] timestamp_f;
bit [4:0] port_id;
bit has_timestamp; // when 1, the TX/RX timestamp is valid
} ether_header_t;
/* Full ethernet frame */
typedef struct {
ether_header_t hdr;
int size;
bit[7:0] payload[$];
bit[31:0] fcs;
bit error;
bit has_payload;
} ether_frame_t;
/* WR-compliant TX frame timestamp */
typedef struct {
bit[15:0] fid;
bit [4:0] pid;
bit [27:0] timestamp_r;
bit [3:0] timestamp_f;
} tx_timestamp_t;
`timescale 1ns/1ps
/* Bus widths definition, taken from global_defs.vhd */
`define c_wrsw_ctrl_size 4
`define c_wrsw_oob_frame_id_size 16
`define c_wrsw_timestamp_size_r 28
`define c_wrsw_timestamp_size_f 4
`define c_wrsw_mac_addr_width 48
`define c_wrsw_vid_width 12
`define c_wrsw_prio_width 3
/* ctrl bus codes */
`define c_wrsw_ctrl_none 4'h0
`define c_wrsw_ctrl_dst_mac 4'h1
`define c_wrsw_ctrl_src_mac 4'h2
`define c_wrsw_ctrl_ethertype 4'h3
`define c_wrsw_ctrl_vid_prio 4'h4
`define c_wrsw_ctrl_tx_oob 4'h5
`define c_wrsw_ctrl_rx_oob 4'h6
`define c_wrsw_ctrl_payload 4'h7
/* OOB types */
`define OOB_TYPE_TXTS 1
`define OOB_TYPE_RXTS 2
`define QUEUE_MAX_FRAMES 128
//
// WhiteRabbit Fabric Interface (WRF) Macros
//
// declares basic fabric interface (only the mandatory singals)
// sink port list in a verilog/SV module, prefixed with "prefix":
// for example `WRF_PORTS_SINK(test) will generate the following signals
// test_sof_p1_i, test_eof_p1_i, test_data_i, etc....
`define WRF_PORTS_SINK(prefix) \
input [15:0] prefix``_data_i,\
input [3:0] prefix``_ctrl_i,\
input prefix``_bytesel_i,\
input prefix``_sof_p1_i,\
input prefix``_eof_p1_i,\
output prefix``_dreq_o,\
input prefix``_valid_i,\
input prefix``_rerror_p1_i
// same as above but with all WRF signals
`define WRF_FULL_PORTS_SINK(prefix) \
`WRF_PORTS_SINK(prefix),\
output prefix``_terror_p1_o,\
input prefix``_idle_i,\
input prefix``_tabort_p1_i,\
output prefix``_rabort_p1_o
// like the macro above, but for fabric source, mandatory signals only
`define WRF_PORTS_SOURCE(prefix) \
output [15:0] prefix``_data_o,\
output [3:0] prefix``_ctrl_o,\
output prefix``_bytesel_o,\
output prefix``_sof_p1_o,\
output prefix``_eof_p1_o,\
input prefix``_dreq_i,\
output prefix``_valid_o,\
output prefix``_rerror_p1_o
// same as above, but for full WRF
`define WRF_FULL_PORTS_SOURCE(prefix) \
`WRF_PORTS_SOURCE(prefix), \
input prefix``_terror_p1_i,\
output prefix``_idle_o,\
output prefix``_tabort_p1_o,\
input prefix``_rabort_p1_i
// declares a list of verilog/SV wires for a given fabric name
`define WRF_WIRES(prefix) \
wire [15:0] prefix``_data;\
wire [3 :0] prefix``_ctrl;\
wire prefix``_bytesel;\
wire prefix``_dreq;\
wire prefix``_valid;\
wire prefix``_sof_p1;\
wire prefix``_eof_p1;\
wire prefix``_rerror_p1;
// same as above, but for full WRF
`define WRF_FULL_WIRES(prefix) \
`WRF_WIRES(prefix)\
wire prefix``_terror_p1;\
wire prefix``_idle;\
wire prefix``_tabort_p1;\
wire prefix``_rabort_p1;
// Connects fabric sink ports prefixed with port_pfx to fabric wires prefixed with fab_pfx
`define _WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx) \
.port_pfx``_data_i(fab_pfx``_data),\
.port_pfx``_ctrl_i(fab_pfx``_ctrl),\
.port_pfx``_bytesel_i(fab_pfx``_bytesel),\
.port_pfx``_dreq_o(fab_pfx``_dreq),\
.port_pfx``_valid_i(fab_pfx``_valid),\
.port_pfx``_sof_p1_i(fab_pfx``_sof_p1),\
.port_pfx``_eof_p1_i(fab_pfx``_eof_p1),\
.port_pfx``_rerror_p1_i(fab_pfx``_rerror_p1)
// full fabric I/F version
`define WRF_FULL_CONNECT_SINK(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx), \
.port_pfx``_terror_p1_o(fab_pfx``_terror_p1),\
.port_pfx``_tabort_p1_i(fab_pfx``_tabort_p1),\
.port_pfx``_rabort_p1_o(fab_pfx``_rabort_p1),\
.port_pfx``_idle_i(fab_pfx``_idle)
// Connects fabric sink ports prefixed with port_pfx to fabric wires prefixed with fab_pfx
`define WRF_CONNECT_SINK(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx), \
.port_pfx``_terror_p1_o(),\
.port_pfx``_tabort_p1_i(1'b0),\
.port_pfx``_rabort_p1_o(),\
.port_pfx``_idle_i(1'b0)
`define _WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx) \
.port_pfx``_data_o(fab_pfx``_data),\
.port_pfx``_ctrl_o(fab_pfx``_ctrl),\
.port_pfx``_bytesel_o(fab_pfx``_bytesel),\
.port_pfx``_dreq_i(fab_pfx``_dreq),\
.port_pfx``_valid_o(fab_pfx``_valid),\
.port_pfx``_sof_p1_o(fab_pfx``_sof_p1),\
.port_pfx``_eof_p1_o(fab_pfx``_eof_p1),\
.port_pfx``_rerror_p1_o(fab_pfx``_rerror_p1)
// same as above, but for source ports, full WRF version
`define WRF_FULL_CONNECT_SOURCE(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx),\
.port_pfx``_terror_p1_i(fab_pfx``_terror_p1),\
.port_pfx``_tabort_p1_o(fab_pfx``_tabort_p1),\
.port_pfx``_rabort_p1_i(fab_pfx``_rabort_p1),\
.port_pfx``_idle_o(fab_pfx``_idle)
// same as above, but for source ports, basic WRF version
`define WRF_CONNECT_SOURCE(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx),\
.port_pfx``_terror_p1_i(1'b0),\
.port_pfx``_tabort_p1_o(),\
.port_pfx``_rabort_p1_i(1'b0),\
.port_pfx``_idle_o()
`endif
\ No newline at end of file
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`timescale 1ns / 1ps
`include "fabric_emu.sv"
module main;
const int c_clock_period = 8;
reg clk = 0;
reg rst_n = 0;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
// generate clock and reset signals
always #(c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
// Two fabric emulators talking to each other
fabric_emu U_emuA
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ba), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, ab)
);
fabric_emu U_emuB
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ab),
`WRF_CONNECT_SINK(tx, ba)
);
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(U_emuA.ready); // wait until both emulators are initialized
wait(U_emuB.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<100;i++)
buffer[i] = i;
// simulate some flow throttling
U_emuA.simulate_rx_throttling(1, 50);
U_emuA.send(hdr, buffer, 100);
hdr.src = 'h0f0e0a0b0d00;
U_emuB.send(hdr, buffer, 50);
end
// Check if there's anything received by EMU B
always @(posedge clk) if (U_emuB.poll())
begin
ether_frame_t frame;
$display("Emulator B received a frame!");
U_emuB.receive(frame);
dump_frame_header("EmuB RX: ", frame);
end
// Check if there's anything received by EMU A
always @(posedge clk) if (U_emuA.poll())
begin
ether_frame_t frame;
$display("Emulator A received a frame!");
U_emuA.receive(frame);
dump_frame_header("EmuA RX: ", frame);
end
endmodule // main
`timescale 1ns/1ps
/* Ethernet FCS calculator class */
class CCRC32;
protected bit [31:0] crc;
protected bit [31:0] crc_tab[256];
function new();
reg [31:0] c, poly;
int i, j;
poly = 32'hEDB88320;
for (i = 0; i < 256; i++) begin
c = i;
for (j = 8; j > 0; j--) begin
if (c & 1)
c = (c >> 1) ^ poly;
else
c >>= 1;
end
crc_tab[i] = c;
end
crc = 32'hffffffff;
endfunction // new
function bit[31:0] bitrev(bit[31:0] x, int n);
reg [31:0] y= 0;
int i;
for(i=0;i<n;i++) if(x & (1<<i)) y|= 1<< (n-1-i);
bitrev=y;
endfunction
task update_int(bit[7:0] x);
crc = ((crc >> 8) & 32'h00FFFFFF) ^ crc_tab[(crc ^ bitrev(x,8)) & 32'hFF];
endtask
task update(input [15:0] x, int bytesel);
update_int(x[15:8]);
if(!bytesel)
update_int(x[7:0]);
endtask // update
function bit[31:0] get();
get = bitrev(crc ^ 32'hffffffff, 32);
endfunction // get
endclass
/* Simple packet queue */
class CPacketQueue;
protected int head, tail, count;
protected int size;
protected ether_frame_t d[];
function new (int _size);
size = _size;
head = 0;
tail = 0;
count = 0;
d = new [_size];
endfunction // new
task push(input ether_frame_t frame);
if(count == size) begin
$display("CPacketQueue::push(): queue overflow");
$stop();
end
d[head] = frame;
head++; if(head == size) head = 0;
count++;
endtask // push
task pop (output ether_frame_t frame);
if(count <= 0) begin
$display("CPacketQueue::pop(): queue empty");
$stop();
end
frame = d[tail];
tail++; if(tail == size) tail = 0;
count--;
endtask // pop
function int get_count();
return count;
endfunction // get_count
/* Looks for a packet with matching OOB frame identifier and updates it with the new timestamp value */
function int update_tx_timestamp(input [15:0] oob_fid,
input [4:0] port_id,
input [31:0] ts_value);
int i;
i = tail;
while(i != head)
begin
if(d[i].hdr.oob_type == `OOB_TYPE_TXTS && d[i].hdr.oob_fid == oob_fid) begin