top.v 是整个网络综合实验工程的顶层模块,如图1所示。在这个模块里例化了PLL时钟模块IP核,和网络综合实验的核心模块ETH_CORE.v。

图1 top.v模块
代码如下:
`timescale 1ns / 1ps
module top #
(
parameter MAC_TX_CRC_EN = 1, // 0: MAC DON'T CALC CRC; 1: MAC CALC CRC
parameter [47:0] TX_MAC_SRC = 48'h46_72_61_73_65_72,
parameter [47:0] TX_MAC_DES = 48'hff_ff_ff_ff_ff_ff,
parameter [31:0] TX_IP_SRC = 32'hc0a8003d,
parameter [31:0] TX_IP_DES = 32'hc0a800a8,
parameter [15:0] UDP_TX_SRC_PORT = 10000,
parameter [15:0] UDP_TX_DES_PORT = 10000,
parameter UDP_TX_CHECKSUM_EN = 1, // 0: UDP checksum = 16'h0000; 1: calc checksum
parameter [31:0] RX_IP_SRC = 32'hc0a800a8,
parameter RX_IP_SRC_EN = 1, // 0: don't check src ip address; 1: check src ip address
parameter [31:0] RX_IP_DES = 32'hc0a8003d,
parameter RX_IP_DES_EN = 1, // 0: don't check des ip address; 1: check des ip address
parameter [15:0] UDP_RX_SRC_PORT = 10000,
parameter UDP_RX_SRC_PORT_EN = 1, // 0: don't check udp src port; 1: check udp src port
parameter [15:0] UDP_RX_DES_PORT = 10000,
parameter UDP_RX_DES_PORT_EN = 1, // 0: don't check udp des port; 1: check udp des port
parameter MAIN_CLK = 125,
parameter PHY_SPEED = "AUTO" // "AUTO", "1G", "100M", "10M"
)
(
input OSC_CLK,
output E_MDC,
inout E_MDIO,
input E_RXC,
input E_RXDV,
input [3:0] E_RXD,
output E_TXC, //以太网发送时钟
output E_TXEN, //发送使能
output [3:0] E_TXD, //发送数据
output ETH_RSTN,
input ETH_IRQ,
// input [7:0] SW,
output [7:0] LED //发送指示灯
);
//=========================================================================
//时钟模块
wire locked;
wire clk_200m;
wire clk_125m;
wire clk_125m_90;
MMCM SYS_DCM_inst
(
// Clock in ports
.clk_in1 (OSC_CLK),
// Clock out ports
.clk_out1 (clk_200m), // 200M
.clk_out2 (clk_125m), // 125M
.clk_out3 (clk_125m_90), // 125M
// Status and control signals
.reset (1'b0), // input reset
.locked (locked) // output locked
);
wire sys_clk = clk_125m;
wire ref_clk = clk_200m;
reg locked_r = 0;
always @ (posedge sys_clk)
locked_r <= locked;
reg [7:0] lock_cnt = 0;
reg reset = 1;
always @ (posedge sys_clk)
if(!locked_r)
begin
lock_cnt <= 0;
reset <= 1;
end
else
begin
if(&lock_cnt) reset <= 0;
else lock_cnt <= lock_cnt + 1;
end
wire sys_rst_n = ~reset;
//=========================================================================
wire e_mdio_i;
wire e_mdio_o;
wire e_mdio_t;
IOBUF #(
.SLEW("SLOW") // Specify the output slew rate
) mdio_inst (
.O (e_mdio_i), // Buffer output
.IO (E_MDIO), // Buffer inout port (connect directly to top-level port)
.I (e_mdio_o), // Buffer input
.T (e_mdio_t) // 3-state enable input, high=input, low=output
);
wire [7:0] udp_dout;
wire udp_dout_en;
wire [7:0] udp_din = udp_dout;
wire udp_din_vld = udp_dout_en;
wire [2:0] eth_speed;
ETH_CORE #
(
// TX
.MAC_TX_CRC_EN (MAC_TX_CRC_EN),
.TX_MAC_SRC (TX_MAC_SRC),
.TX_MAC_DES (TX_MAC_DES),
.TX_IP_SRC (TX_IP_SRC),
.TX_IP_DES (TX_IP_DES),
.UDP_TX_SRC_PORT (UDP_TX_SRC_PORT),
.UDP_TX_DES_PORT (UDP_TX_DES_PORT),
.UDP_TX_CHECKSUM_EN (UDP_TX_CHECKSUM_EN),
// RX
.RX_IP_SRC (RX_IP_SRC),
.RX_IP_SRC_EN (RX_IP_SRC_EN),
.RX_IP_DES (RX_IP_DES),
.RX_IP_DES_EN (RX_IP_DES_EN),
.UDP_RX_SRC_PORT (UDP_RX_SRC_PORT),
.UDP_RX_SRC_PORT_EN (UDP_RX_SRC_PORT_EN),
.UDP_RX_DES_PORT (UDP_RX_DES_PORT),
.UDP_RX_DES_PORT_EN (UDP_RX_DES_PORT_EN),
.MAIN_CLK (MAIN_CLK), // 125m sys_clk
.PHY_SPEED (PHY_SPEED) // "AUTO", "1G", "100M", "10M"
)
ETH_CORE_inst
(
.ref_clk (ref_clk),
.E_RXC (E_RXC),
.E_RXDV (E_RXDV),
.E_RXD (E_RXD),
.E_TXC (E_TXC), //以太网发送时钟
.E_TXEN (E_TXEN), //发送使能
.E_TXD (E_TXD), //发送数据
// sys clk
.sys_clk (sys_clk),
.e_mdc (E_MDC),
.e_mdio_i (e_mdio_i),
.e_mdio_o (e_mdio_o),
.e_mdio_t (e_mdio_t),
.eth_speed (eth_speed),
.udp_din (udp_din),
.udp_din_vld(udp_din_vld),
.udp_din_rdy(udp_din_rdy),
.udp_dout (udp_dout),
.udp_dout_en(udp_dout_en),
.reset (reset)
);
reg [31:0] led_cnt;
always @ (posedge sys_clk or posedge reset)
if(reset) led_cnt <= 0;
else led_cnt <= led_cnt + 1;
reg [2:0] eth_speed_r = 0;
always @ (posedge sys_clk or posedge reset)
if(reset) eth_speed_r <= 0;
else eth_speed_r <= ~eth_speed;
assign LED[0] = 1;
assign LED[1] = led_cnt[25];
assign LED[4:2] = 3'b111;
assign LED[7:5] = eth_speed_r;
assign ETH_RSTN = 1'b1;
//=========================================================================
endmodule
注意从top.v传递了很多参数到下层模块:
parameter MAC_TX_CRC_EN = 1, // 0: MAC DON’T CALC CRC; 1: MAC CALC CRC
parameter [47:0] TX_MAC_SRC = 48’h46_72_61_73_65_73, //源MAC地址
parameter [47:0] TX_MAC_DES = 48’hff_ff_ff_ff_ff_ff, //目的MAC地址
//发送相关参数
parameter [31:0] TX_IP_SRC = 32’hc0a8003e, //源IP地址(这里指FPGA)
parameter [31:0] TX_IP_DES = 32’hc0a8002e, //目的IP地址(这里指主机)
parameter [15:0] UDP_TX_SRC_PORT = 10000, //源端口(这里指FPGA)
parameter [15:0] UDP_TX_DES_PORT = 10000, //目的端口(这里指主机)
parameter UDP_TX_CHECKSUM_EN = 1, // 0: UDP checksum = 16’h0000; 1: calc checksum
//接收相关参数
parameter [31:0] RX_IP_SRC = 32’hc0a8002e, //源IP地址(这里指主机)
parameter RX_IP_SRC_EN = 1, // 0: don’t check src ip address; 1: check src ip address
parameter [31:0] RX_IP_DES = 32’hc0a8003e, //目的IP地址(这里指FPGA)
parameter RX_IP_DES_EN = 1, // 0: don’t check des ip address; 1: check des ip address
parameter [15:0] UDP_RX_SRC_PORT = 10000, //源端口(这里指主机)
parameter UDP_RX_SRC_PORT_EN = 1, // 0: don’t check udp src port; 1: check udp src port
parameter [15:0] UDP_RX_DES_PORT = 10000, //目的端口(这里指FPGA)
parameter UDP_RX_DES_PORT_EN = 1, // 0: don’t check udp des port; 1: check udp des port
parameter MAIN_CLK = 125, //时钟主频,单位是MHz
parameter PHY_SPEED = “AUTO” // “AUTO”, “1G”, “100M”, “10M”
ETH_CORE.v是网络综合实验的核心模块,如图2所示。例化了ETH_UDP.v,ETH_IP.v,ETH_MAC.v 和eth_phy_core.v四个模块。其代码如下:

图2 ETH_CORE.v模块
`timescale 1ns / 1ps
module ETH_CORE #
(
// TX
parameter MAC_TX_CRC_EN = 1,
parameter [47:0] TX_MAC_SRC = 48'h66_72_61_73_65_72,
parameter [47:0] TX_MAC_DES = 48'hff_ff_ff_ff_ff_ff,
parameter [31:0] TX_IP_SRC = 32'hc0a8003d,
parameter [31:0] TX_IP_DES = 32'hc0a800ff,
parameter [15:0] UDP_TX_SRC_PORT = 16'hffff,
parameter [15:0] UDP_TX_DES_PORT = 16'hffff,
parameter UDP_TX_CHECKSUM_EN = 0,
// RX
parameter [31:0] RX_IP_SRC = 32'hc0a8003d,
parameter RX_IP_SRC_EN = 0,
parameter [31:0] RX_IP_DES = 32'hc0a800ff,
parameter RX_IP_DES_EN = 0,
parameter [15:0] UDP_RX_SRC_PORT = 16'hffff,
parameter UDP_RX_SRC_PORT_EN = 0,
parameter [15:0] UDP_RX_DES_PORT = 16'hffff,
parameter UDP_RX_DES_PORT_EN = 0,
parameter MAIN_CLK = 125,
parameter PHY_SPEED = "AUTO" // "AUTO", "1G", "100M", "10M"
)
(
input ref_clk,
input E_RXC,
input E_RXDV,
input [3:0] E_RXD,
output E_TXC, //以太网发送时钟
output E_TXEN, //发送使能
output [3:0] E_TXD, //发送数据
input sys_clk,
output e_mdc,
input e_mdio_i,
output e_mdio_o,
output e_mdio_t,
output [2:0] eth_speed,
input [7:0] udp_din,
input udp_din_vld,
output udp_din_rdy,
(* mark_debug = "true" *) output [7:0] udp_dout,
(* mark_debug = "true" *) output udp_dout_en,
input reset
);
//=========================================================================
localparam IP_BUF_SIZE = 10;
localparam IP_IDX_BIT = 1;
//=========================================================================
wire udp_tx_wea;
wire [IP_BUF_SIZE + IP_IDX_BIT - 1:0] udp_tx_addra;
wire [15:0] udp_tx_dina;
wire [15:0] udp_tx_douta;
wire udp_rx_web;
wire [IP_BUF_SIZE + IP_IDX_BIT - 1:0] udp_rx_addrb;
wire [15:0] udp_rx_doutb;
(* mark_debug = "true" *)wire [4:0] udp_error;
ETH_UDP #
(
.TX_IP_SRC (TX_IP_SRC),
.TX_IP_DES (TX_IP_DES),
.UDP_TX_SRC_PORT (UDP_TX_SRC_PORT),
.UDP_TX_DES_PORT (UDP_TX_DES_PORT),
.UDP_TX_CHECKSUM_EN (UDP_TX_CHECKSUM_EN),
.UDP_RX_SRC_PORT (UDP_RX_SRC_PORT),
.UDP_RX_SRC_PORT_EN (UDP_RX_SRC_PORT_EN),
.UDP_RX_DES_PORT (UDP_RX_DES_PORT),
.UDP_RX_DES_PORT_EN (UDP_RX_DES_PORT_EN),
.IP_BUF_SIZE (IP_BUF_SIZE),
.IP_IDX_BIT (IP_IDX_BIT)
)
ETH_UDP_inst
(
.sys_clk (sys_clk),
// tx
.udp_din (udp_din),
.udp_din_vld (udp_din_vld),
.udp_din_rdy (udp_din_rdy),
.udp_tx_wea (udp_tx_wea),
.udp_tx_addra (udp_tx_addra),
.udp_tx_dina (udp_tx_dina),
.udp_tx_douta (udp_tx_douta),
// rx
.udp_rx_web (udp_rx_web),
.udp_rx_addrb (udp_rx_addrb),
.udp_rx_doutb (udp_rx_doutb),
.udp_dout (udp_dout),
.udp_dout_en (udp_dout_en),
.udp_error (udp_error),
.reset (reset)
);
//=========================================================================
localparam MAC_TXBUF_SIZE = IP_BUF_SIZE + 1;
localparam MAC_TXIDX_BIT = IP_IDX_BIT;
//=========================================================================
wire [17:0] ip_fifo_din;
wire ip_fifo_we;
wire [15:0] ip_fifo_cnt;
wire ip_rx_web;
wire [IP_BUF_SIZE + IP_IDX_BIT - 1:0] ip_rx_addrb;
wire [15:0] ip_rx_doutb;
(* mark_debug = "true" *)wire [7:0] rx_ip_err;
ETH_IP #
(
.TX_MAC_SRC (TX_MAC_SRC),
.TX_MAC_DES (TX_MAC_DES),
.TX_IP_SRC (TX_IP_SRC),
.TX_IP_DES (TX_IP_DES),
.RX_IP_SRC (RX_IP_SRC),
.RX_IP_SRC_EN (RX_IP_SRC_EN),
.RX_IP_DES (RX_IP_DES),
.RX_IP_DES_EN (RX_IP_DES_EN),
.IP_BUF_SIZE (IP_BUF_SIZE),
.IP_IDX_BIT (IP_IDX_BIT)
)
ETH_IP_inst
(
.sys_clk (sys_clk),
.udp_tx_wea (udp_tx_wea),
.udp_tx_addra (udp_tx_addra),
.udp_tx_dina (udp_tx_dina),
.udp_tx_douta (udp_tx_douta),
.ip_fifo_din (ip_fifo_din),
.ip_fifo_we (ip_fifo_we),
.ip_fifo_cnt (ip_fifo_cnt),
// =================================
.udp_rx_web (udp_rx_web),
.udp_rx_addrb (udp_rx_addrb),
.udp_rx_doutb (udp_rx_doutb),
.ip_rx_web (ip_rx_web),
.ip_rx_addrb (ip_rx_addrb),
.ip_rx_doutb (ip_rx_doutb),
.rx_ip_err (rx_ip_err),
// =================================
.reset (reset)
);
//=========================================================================
wire phy_rx_clk;
(* mark_debug = "true" *)wire [7:0] phy_rx_data;
(* mark_debug = "true" *)wire phy_rx_toggle;
(* mark_debug = "true" *)wire phy_rx_dv;
wire phy_tx_clk = phy_rx_clk;
(* mark_debug = "true" *)wire [7:0] phy_tx_data;
(* mark_debug = "true" *)wire [1:0] phy_tx_en;
(* mark_debug = "true" *)wire [7:0] mac_error;
wire smi_done;
ETH_MAC #
(
.MAC_TX_CRC_EN (MAC_TX_CRC_EN),
.IP_BUF_SIZE (IP_BUF_SIZE),
.IP_IDX_BIT (IP_IDX_BIT),
.MAC_TXBUF_SIZE (MAC_TXBUF_SIZE),
.MAC_TXIDX_BIT (MAC_TXIDX_BIT)
)
ETH_MAC_inst
(
.sys_clk (sys_clk),
// tx
.ip_fifo_din (ip_fifo_din),
.ip_fifo_we (ip_fifo_we),
.ip_fifo_cnt (ip_fifo_cnt),
// rx
.ip_rx_web (ip_rx_web),
.ip_rx_addrb (ip_rx_addrb),
.ip_rx_doutb (ip_rx_doutb),
.mac_error (mac_error),
// =================================
.phy_rx_clk (phy_rx_clk),
.phy_rx_data (phy_rx_data),
.phy_rx_toggle (phy_rx_toggle),
.phy_rx_dv (phy_rx_dv),
.phy_tx_clk (phy_tx_clk),
.phy_tx_data (phy_tx_data),
.phy_tx_en (phy_tx_en),
.smi_done (smi_done),
.eth_speed (eth_speed),
// =================================
.reset (reset)
);
//=========================================================================
eth_phy_core #
(
.MAIN_CLK (MAIN_CLK),
.PHY_SPEED (PHY_SPEED)
)
eth_phy_core_inst
(
.ref_clk (ref_clk),
.E_RXC (E_RXC),
.E_RXDV (E_RXDV),
.E_RXD (E_RXD),
.E_TXC (E_TXC), //以太网发送时钟
.E_TXEN (E_TXEN), //发送使能
.E_TXD (E_TXD), //发送数据
.sys_clk (sys_clk),
.smi_done (smi_done),
.e_mdc (e_mdc),
.e_mdio_i (e_mdio_i),
.e_mdio_o (e_mdio_o),
.e_mdio_t (e_mdio_t),
.eth_speed (eth_speed),
.phy_rx_clk (phy_rx_clk),
.phy_rx_dv (phy_rx_dv),
.phy_rx_data (phy_rx_data),
.phy_rx_toggle (phy_rx_toggle),
.phy_tx_clk (phy_tx_clk),
.phy_tx_data (phy_tx_data),
.phy_tx_en (phy_tx_en),
.reset (reset)
);
//=========================================================================
endmodule
在ETH_CORE.v模块中也有一些参数传递给下层的子模块,如下所示:
localparam IP_BUF_SIZE = 10;
localparam IP_IDX_BIT = 1;
localparam MAC_TXBUF_SIZE = IP_BUF_SIZE + 1;
localparam MAC_TXIDX_BIT = IP_IDX_BIT;
这些参数主要用来参数化IP和MAC层使用的A/B Buffer和FIFO,提高模块的通用性。
这些代码如何获取到呢