【【通信协议ARP的verilog实现】】
eth_arp_test.v
c
module eth_arp_test(
input sys_clk , //系统时钟
input sys_rst_n , //系统复位信号,低电平有效
input touch_key , //触摸按键,用于触发开发板发出ARP请求
//PL以太网RGMII接口
input eth_rxc , //RGMII接收数据时钟
input eth_rx_ctl , //RGMII输入数据有效信号
input [3:0] eth_rxd , //RGMII输入数据
output eth_txc , //RGMII发送数据时钟
output eth_tx_ctl , //RGMII输出数据有效信号
output [3:0] eth_txd , //RGMII输出数据
output eth_rst_n //以太网芯片复位信号,低电平有效
);
//parameter define
//开发板MAC地址 00-11-22-33-44-55
parameter BOARD_MAC = 48'h00_11_22_33_44_55;
//开发板IP地址 192.168.1.10
parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd10};
//目的MAC地址 ff_ff_ff_ff_ff_ff
parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
//目的IP地址 192.168.1.102
parameter DES_IP = {8'd192,8'd168,8'd1,8'd102};
//输入数据IO延时(如果为n,表示延时n*78ps)
parameter IDELAY_VALUE = 0;
//wire define
wire clk_200m ; //用于IO延时的时钟
wire gmii_rx_clk; //GMII接收时钟
wire gmii_rx_dv ; //GMII接收数据有效信号
wire [7:0] gmii_rxd ; //GMII接收数据
wire gmii_tx_clk; //GMII发送时钟
wire gmii_tx_en ; //GMII发送数据使能信号
wire [7:0] gmii_txd ; //GMII发送数据
wire arp_rx_done; //ARP接收完成信号
wire arp_rx_type; //ARP接收类型 0:请求 1:应答
wire [47:0] src_mac ; //接收到目的MAC地址
wire [31:0] src_ip ; //接收到目的IP地址
wire arp_tx_en ; //ARP发送使能信号
wire arp_tx_type; //ARP发送类型 0:请求 1:应答
wire tx_done ; //发送的目标MAC地址
wire [47:0] des_mac ; //发送的目标IP地址
wire [31:0] des_ip ; //以太网发送完成信号
//*****************************************************
//** main code
//*****************************************************
assign des_mac = src_mac;
assign des_ip = src_ip;
assign eth_rst_n = sys_rst_n;
//PLL
clk_wiz_0 clk_wiz_0_inst
(
// Clock out ports
.clk_out1(clk_200m), // output clk_out1
// Status and control signals
.reset(~sys_rst_n), // input reset
.locked(locked), // output locked
// Clock in ports
.clk_in1(sys_clk)); // input clk_in1
//GMII接口转RGMII接口
gmii_to_rgmii u_gmii_to_rgmii(
.idelay_clk (clk_200m ),
.gmii_rx_clk (gmii_rx_clk ),
.gmii_rx_dv (gmii_rx_dv ),
.gmii_rxd (gmii_rxd ),
.gmii_tx_clk (gmii_tx_clk ),
.gmii_tx_en (gmii_tx_en ),
.gmii_txd (gmii_txd ),
.rgmii_rxc (eth_rxc ),
.rgmii_rx_ctl (eth_rx_ctl ),
.rgmii_rxd (eth_rxd ),
.rgmii_txc (eth_txc ),
.rgmii_tx_ctl (eth_tx_ctl ),
.rgmii_txd (eth_txd )
);
//ARP通信
arp u_arp(
.rst_n (sys_rst_n ),
.gmii_rx_clk (gmii_rx_clk),
.gmii_rx_dv (gmii_rx_dv ),
.gmii_rxd (gmii_rxd ),
.gmii_tx_clk (gmii_tx_clk),
.gmii_tx_en (gmii_tx_en ),
.gmii_txd (gmii_txd ),
.arp_rx_done (arp_rx_done),
.arp_rx_type (arp_rx_type),
.src_mac (src_mac ),
.src_ip (src_ip ),
.arp_tx_en (arp_tx_en ),
.arp_tx_type (arp_tx_type),
.des_mac (des_mac ),
.des_ip (des_ip ),
.tx_done (tx_done )
);
//ARP控制
arp_ctrl u_arp_ctrl(
.clk (gmii_rx_clk),
.rst_n (sys_rst_n),
.touch_key (touch_key),
.arp_rx_done (arp_rx_done),
.arp_rx_type (arp_rx_type),
.arp_tx_en (arp_tx_en),
.arp_tx_type (arp_tx_type)
);
endmodule
arp_ctrl.v
c
module arp_ctrl(
input clk ,
input rst_n ,
input touch_key ,
input arp_rx_done ,
input arp_rx_type ,
output reg arp_tx_en ,
output reg arp_tx_type
);
// reg define
reg touch_key_d0 ;
reg touch_key_d1 ;
reg touch_key_d2 ;
wire pos_touch_key ;
//--------------------------------------------//
//-----------------main code ----------------//
//--------------------------------------------//
assign pos_touch_key = ~touch_key_d2 & touch_key_d1 ;
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
begin
touch_key_d0 <= 0 ;
touch_key_d1 <= 0 ;
touch_key_d2 <= 0 ;
end
else
begin
touch_key_d0 <= touch_key ;
touch_key_d1 <= touch_key_d0 ;
touch_key_d2 <= touch_key_d1 ;
end
end
always@(posedge clk or negedge rst_n )
begin
if(rst_n == 0)
begin
arp_tx_en <= 0 ;
arp_tx_type <= 0 ;
end
else
begin
if(pos_touch_key == 1)
begin // 发送请求
arp_tx_en <= 1 ;
arp_tx_type <= 0 ;
end
else if((arp_rx_done ==1) & (arp_rx_type == 0))
begin
arp_tx_en <= 1 ;
arp_tx_type <= 1 ;
end
else
arp_tx_en <= 0 ;
end
end
endmodule
arp_rx.v
c
module arp_rx #(
parameter BOARD_MAC = 48'h00_11_22_33_44_55, //开发板mac地址
parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd10}
)(
input clk , // 时钟信号
input rst_n , //
input gmii_rx_dv , //
input [7 : 0] gmii_rxd ,
output reg arp_rx_done ,
output reg arp_rx_type ,
output reg [47 : 0] src_mac ,
output reg [31 : 0] src_ip
);
//---------------------------------------------------//
// parameter and define //
//---------------------------------------------------//
localparam st_idle = 5'b0_0001 ; //初始状态,等待接收前导码
localparam st_preamble = 5'b0_0010 ; //接收前导码状态
localparam st_eth_head = 5'b0_0100 ; //接收以太网帧头
localparam st_arp_data = 5'b0_1000 ; //接收ARP数据
localparam st_rx_end = 5'b1_0000 ; //接收结束
localparam ETH_TPYE = 16'h0806 ; // 以太网帧类型ARP
//---------------------------------------------------------
reg [4 : 0] cur_state ;
reg [4 : 0] next_state ;
reg skip_en ;
reg error_en ;
reg [4 : 0] cnt ;
reg [47 : 0] des_mac_t ;
reg [31 : 0] des_ip_t ; //接收到的目的IP地址
reg [47 : 0] src_mac_t ; //接收到的源MAC地址
reg [31 : 0] src_ip_t ; //接收到的源IP地址
reg [15 : 0] eth_type ; //以太网类型
reg [15 : 0] op_data ; //操作码
// ---------------------------------------------- //
// -------next is main code --------------------- //
// ---------------------------------------------- //
always@(posedge clk or negedge rst_n )
begin
if(rst_n == 0)
begin
cur_state <= st_idle ;
end
else
begin
cur_state <= next_state ;
end
end
always@(posedge clk or negedge rst_n )
begin
if(rst_n == 0 )
begin
next_state <= st_idle ;
end
else
begin
case(cur_state)
st_idle :
begin
if(skip_en == 1)
begin
next_state <= st_preamble ;
end
else
begin
next_state <= st_idle ;
end
end
st_preamble :
begin
if(skip_en == 1)
begin
next_state <= st_eth_head ;
end
else
begin
if(error_en == 1)
begin
next_state <= st_rx_end ;
end
else
begin
next_state <= st_preamble ;
end
end
end
st_eth_head :
begin
if(skip_en == 1)
begin
next_state <= st_arp_data ;
end
else
begin
if(error_en == 1)
begin
next_state <= st_rx_end ;
end
else
begin
next_state <= st_eth_head ;
end
end
end
st_arp_data :
begin
if(skip_en == 1)
begin
next_state <= st_rx_end ;
end
else if(error_en == 1)
begin
next_state <= st_rx_end ;
end
else
begin
next_state <= st_arp_data ;
end
end
st_rx_end :
begin
if(skip_en == 1)
begin
next_state <= st_idle ;
end
else
begin
next_state <= st_rx_end ;
end
end
default :
begin
next_state <= st_idle ;
end
endcase
end
end
// 三段状态机的第三段
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
begin
skip_en <= 0 ;
error_en <= 0 ;
cnt <= 0 ;
arp_rx_done <= 0 ;
des_mac_t <= 0 ;
des_ip_t <= 0 ;
src_mac_t <= 0 ;
src_ip_t <= 0 ;
eth_type <= 0 ;
op_data <= 0 ;
arp_rx_type <= 0 ;
src_mac <= 0 ;
src_ip <= 0 ;
end
else
begin
skip_en <= 0 ;
error_en <= 0 ;
arp_rx_done <= 0 ;
case(next_state)
st_idle :
begin
if((gmii_rx_dv == 1)&&(gmii_rxd ==8'h55 ) ==1 )
skip_en <= 1 ;
else
;
end
st_preamble :
begin
if(gmii_rx_dv == 1)
begin
// 再计数-6次判断是否满足条件
cnt <= cnt + 1 ;
if((cnt < 6)&&(gmii_rxd != 8'h55) ==1)
begin
error_en <= 1 ;
end
else
begin
if(cnt == 6)
begin
cnt <= 0 ;
if(gmii_rxd == 8'hd5)
begin
skip_en <= 1 ;
end
else
begin
error_en <= 1 ;
end
end
else
;
end
end
else
;
end
// 因为是接收状态所以只需要判断目的是否满足条件就好
st_eth_head :
begin
if(gmii_rx_dv == 1)
begin
cnt <= cnt + 1 ;
if(cnt < 6)
begin
des_mac_t <= {des_mac_t[39 : 0],gmii_rxd} ;
end
else if(cnt == 6)
begin
// 其实去判断一下自己接收的地址是否是正确的即可
if((des_mac_t != BOARD_MAC) &&(des_mac_t != 48'hff_ff_ff_ff_ff_ff))
error_en <= 1 ;
end
else if(cnt == 12)
begin
eth_type[15 : 8] <= gmii_rxd ;
end
else if(cnt == 13)
begin
eth_type[7 : 0] <= gmii_rxd ;
cnt <= 0 ;
if(eth_type[15:8] == ETH_TPYE[15:8] //判断是否为ARP协议
&& gmii_rxd == ETH_TPYE[7:0])
skip_en <= 1'b1;
else
error_en <= 1'b1;
end
else
;
end
else
;
end
st_arp_data :
begin
if(gmii_rx_dv == 1 )
begin
cnt <= cnt + 1 ;
if(cnt == 6)
begin
op_data[15 : 8] <= gmii_rxd ;
end
else if( cnt == 7)
begin
op_data[7 : 0] <= gmii_rxd ;
end
else if(cnt>=8 && cnt < 14)
begin
src_mac_t <= {src_mac_t[39: 0],gmii_rxd} ;
end
else if(cnt>=14 && cnt <18 )
begin
src_ip_t <= {src_ip_t[23:0],gmii_rxd} ;
end
else if(cnt >=24 && cnt <28)
begin
des_ip_t <= {des_ip_t[23 : 0],gmii_rxd} ;
end
else if(cnt == 28)
begin
cnt <= 0 ;
if(des_ip_t == BOARD_IP)
begin
if((op_data ==1 )|| (op_data ==2) )
begin
skip_en <= 1 ;
arp_rx_done <= 1 ;
src_mac <= src_mac_t ;
src_ip <= src_ip_t;
src_mac_t <= 48'd0;
src_ip_t <= 32'd0;
des_mac_t <= 48'd0;
des_ip_t <= 32'd0;
if(op_data == 16'd1)
arp_rx_type <= 1'b0; //ARP请求
else
arp_rx_type <= 1'b1; //ARP应答
end
else
error_en <= 1'b1;
end
else
error_en <= 1'b1;
end
else
;
end
else
;
end
st_rx_end :
begin
cnt <= 5'd0;
//单包数据接收完成
if(gmii_rx_dv == 1'b0 && skip_en == 1'b0)
skip_en <= 1'b1;
else
;
end
default :
;
endcase
end
end
endmodule
arp_tx.v
c
module arp_tx(
input clk ,
input rst_n ,
input arp_tx_en ,
input arp_tx_type ,
input [31 : 0] des_ip ,
input [47 : 0] des_mac ,
input [31 : 0] crc_data ,
input [7 : 0] crc_next ,
output reg [7 : 0] gmii_txd ,
output reg crc_clr ,
output reg crc_en ,
output reg gmii_tx_en ,
output reg tx_done
);
//parameter define
//开发板MAC地址 00-11-22-33-44-55
parameter BOARD_MAC = 48'h00_11_22_33_44_55;
//开发板IP地址 192.168.1.10
parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd10};
//目的MAC地址 ff_ff_ff_ff_ff_ff
parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
//目的IP地址 192.168.1.102
parameter DES_IP = {8'd192,8'd168,8'd1,8'd102};
//localparam define
localparam st_idle = 5'b0_0001; //初始状态,等待开始发送信号
localparam st_preamble = 5'b0_0010; //发送前导码+帧起始界定符
localparam st_eth_head = 5'b0_0100; //发送以太网帧头
localparam st_arp_data = 5'b0_1000; //
localparam st_crc = 5'b1_0000; //发送CRC校验值
localparam ETH_TYPE = 16'h0806 ; //以太网帧类型 ARP协议
localparam HD_TYPE = 16'h0001 ; //硬件类型 以太网
localparam PROTOCOL_TYPE= 16'h0800 ; //上层协议为IP协议
//以太网数据最小为46个字节,不足部分填充数据
localparam MIN_DATA_NUM = 16'd46 ;
//reg define
reg [4:0] cur_state ;
reg [4:0] next_state ;
reg [7:0] preamble[7:0] ; //前导码+SFD
reg [7:0] eth_head[13:0]; //以太网首部
reg [7:0] arp_data[27:0]; //ARP数据
reg tx_en_d0 ; //arp_tx_en信号延时
reg tx_en_d1 ;
reg tx_en_d2 ;
reg skip_en ; //控制状态跳转使能信号
reg [5:0] cnt ;
reg [4:0] data_cnt ; //发送数据个数计数器
reg tx_done_t ;
//wire define
wire pos_tx_en ; //arp_tx_en信号上升沿
//*****************************************************
//** main code
//*****************************************************
assign pos_tx_en = (~tx_en_d2) & tx_en_d1;
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
begin
tx_en_d0 <= 1'b0 ;
tx_en_d1 <= 1'b0 ;
tx_en_d2 <= 1'b0 ;
end
else
begin
tx_en_d0 <= arp_tx_en ;
tx_en_d1 <= tx_en_d0 ;
tx_en_d2 <= tx_en_d1 ;
end
end
//(三段式状态机)同步时序描述状态转移
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cur_state <= st_idle;
else
cur_state <= next_state;
end
//组合逻辑判断状态转移条件
always @(*)
begin
next_state = st_idle;
case(cur_state)
st_idle :
begin //空闲状态
if(skip_en)
next_state = st_preamble;
else
next_state = st_idle;
end
st_preamble :
begin //发送前导码+帧起始界定符
if(skip_en)
next_state = st_eth_head;
else
next_state = st_preamble;
end
st_eth_head :
begin //发送以太网首部
if(skip_en)
next_state = st_arp_data;
else
next_state = st_eth_head;
end
st_arp_data :
begin //发送ARP数据
if(skip_en)
next_state = st_crc;
else
next_state = st_arp_data;
end
st_crc:
begin //发送CRC校验值
if(skip_en)
next_state = st_idle;
else
next_state = st_crc;
end
default :
next_state = st_idle;
endcase
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0 )
begin
skip_en <= 0 ;
cnt <= 6'd0 ;
data_cnt <= 5'd0 ;
crc_en <= 1'b0 ;
gmii_tx_en <= 1'b0 ;
gmii_txd <= 8'd0 ;
tx_done_t <= 1'b0 ;
//初始化数组
//前导码 7个8'h55 + 1个8'hd5
preamble[0] <= 8'h55;
preamble[1] <= 8'h55;
preamble[2] <= 8'h55;
preamble[3] <= 8'h55;
preamble[4] <= 8'h55;
preamble[5] <= 8'h55;
preamble[6] <= 8'h55;
preamble[7] <= 8'hd5;
//以太网帧头
eth_head[0] <= DES_MAC[47:40]; //目的MAC地址
eth_head[1] <= DES_MAC[39:32];
eth_head[2] <= DES_MAC[31:24];
eth_head[3] <= DES_MAC[23:16];
eth_head[4] <= DES_MAC[15:8];
eth_head[5] <= DES_MAC[7:0];
eth_head[6] <= BOARD_MAC[47:40]; //源MAC地址
eth_head[7] <= BOARD_MAC[39:32];
eth_head[8] <= BOARD_MAC[31:24];
eth_head[9] <= BOARD_MAC[23:16];
eth_head[10] <= BOARD_MAC[15:8];
eth_head[11] <= BOARD_MAC[7:0];
eth_head[12] <= ETH_TYPE[15:8]; //以太网帧类型
eth_head[13] <= ETH_TYPE[7:0];
//ARP数据
arp_data[0] <= HD_TYPE[15:8]; //硬件类型
arp_data[1] <= HD_TYPE[7:0];
arp_data[2] <= PROTOCOL_TYPE[15:8]; //上层协议类型
arp_data[3] <= PROTOCOL_TYPE[7:0];
arp_data[4] <= 8'h06; //硬件地址长度,6
arp_data[5] <= 8'h04; //协议地址长度,4
arp_data[6] <= 8'h00; //OP,操作码 8'h01:ARP请求 8'h02:ARP应答
arp_data[7] <= 8'h01;
arp_data[8] <= BOARD_MAC[47:40]; //发送端(源)MAC地址
arp_data[9] <= BOARD_MAC[39:32];
arp_data[10] <= BOARD_MAC[31:24];
arp_data[11] <= BOARD_MAC[23:16];
arp_data[12] <= BOARD_MAC[15:8];
arp_data[13] <= BOARD_MAC[7:0];
arp_data[14] <= BOARD_IP[31:24]; //发送端(源)IP地址
arp_data[15] <= BOARD_IP[23:16];
arp_data[16] <= BOARD_IP[15:8];
arp_data[17] <= BOARD_IP[7:0];
arp_data[18] <= DES_MAC[47:40]; //接收端(目的)MAC地址
arp_data[19] <= DES_MAC[39:32];
arp_data[20] <= DES_MAC[31:24];
arp_data[21] <= DES_MAC[23:16];
arp_data[22] <= DES_MAC[15:8];
arp_data[23] <= DES_MAC[7:0];
arp_data[24] <= DES_IP[31:24]; //接收端(目的)IP地址
arp_data[25] <= DES_IP[23:16];
arp_data[26] <= DES_IP[15:8];
arp_data[27] <= DES_IP[7:0];
end
else
begin
skip_en <= 1'b0;
crc_en <= 1'b0;
gmii_tx_en <= 1'b0;
tx_done_t <= 1'b0;
case(next_state)
st_idle :
begin
if(pos_tx_en)
begin
skip_en <= 1'b1;
//如果目标MAC地址和IP地址已经更新,则发送正确的地址
if((des_mac != 48'b0) || (des_ip != 32'd0))
begin
eth_head[0] <= des_mac[47:40];
eth_head[1] <= des_mac[39:32];
eth_head[2] <= des_mac[31:24];
eth_head[3] <= des_mac[23:16];
eth_head[4] <= des_mac[15:8];
eth_head[5] <= des_mac[7:0];
arp_data[18] <= des_mac[47:40];
arp_data[19] <= des_mac[39:32];
arp_data[20] <= des_mac[31:24];
arp_data[21] <= des_mac[23:16];
arp_data[22] <= des_mac[15:8];
arp_data[23] <= des_mac[7:0];
arp_data[24] <= des_ip[31:24];
arp_data[25] <= des_ip[23:16];
arp_data[26] <= des_ip[15:8];
arp_data[27] <= des_ip[7:0];
end
else
;
if(arp_tx_type == 1'b0)
arp_data[7] <= 8'h01; //ARP请求
else
arp_data[7] <= 8'h02; //ARP应答
end
else
;
end
st_preamble :
begin //发送前导码+帧起始界定符
gmii_tx_en <= 1'b1;
gmii_txd <= preamble[cnt];
if(cnt == 6'd7)
begin
skip_en <= 1'b1;
cnt <= 1'b0;
end
else
cnt <= cnt + 1'b1;
end
st_eth_head :
begin //发送以太网首部
gmii_tx_en <= 1'b1;
crc_en <= 1'b1;
gmii_txd <= eth_head[cnt];
if (cnt == 6'd13)
begin
skip_en <= 1'b1;
cnt <= 1'b0;
end
else
cnt <= cnt + 1'b1;
end
st_arp_data :
begin //发送ARP数据
crc_en <= 1'b1;
gmii_tx_en <= 1'b1;
//至少发送46个字节
if (cnt == MIN_DATA_NUM - 1'b1)
begin
skip_en <= 1'b1;
cnt <= 1'b0;
data_cnt <= 1'b0;
end
else
cnt <= cnt + 1'b1;
if(data_cnt <= 6'd27)
begin
data_cnt <= data_cnt + 1'b1;
gmii_txd <= arp_data[data_cnt];
end
else
gmii_txd <= 8'd0; //Padding,填充0
end
st_crc :
begin //发送CRC校验值
gmii_tx_en <= 1'b1;
cnt <= cnt + 1'b1;
if(cnt == 6'd0)
gmii_txd <= {~crc_next[0], ~crc_next[1], ~crc_next[2],~crc_next[3],
~crc_next[4], ~crc_next[5], ~crc_next[6],~crc_next[7]};
else if(cnt == 6'd1)
gmii_txd <= {~crc_data[16], ~crc_data[17], ~crc_data[18],
~crc_data[19], ~crc_data[20], ~crc_data[21],
~crc_data[22],~crc_data[23]};
else if(cnt == 6'd2)
begin
gmii_txd <= {~crc_data[8], ~crc_data[9], ~crc_data[10],
~crc_data[11],~crc_data[12], ~crc_data[13],
~crc_data[14],~crc_data[15]};
end
else if(cnt == 6'd3)
begin
gmii_txd <= {~crc_data[0], ~crc_data[1], ~crc_data[2],~crc_data[3],
~crc_data[4], ~crc_data[5], ~crc_data[6],~crc_data[7]};
tx_done_t <= 1'b1;
skip_en <= 1'b1;
cnt <= 1'b0;
end
else
;
end
default :
;
endcase
end
end
//发送完成信号及crc值复位信号
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
tx_done <= 1'b0;
crc_clr <= 1'b0;
end
else
begin
tx_done <= tx_done_t;
crc_clr <= tx_done_t;
end
end
endmodule
arp.v
c
module arp(
input rst_n ,
// GMII
input gmii_rx_clk ,
input gmii_rx_dv ,
input [7 : 0] gmii_rxd ,
input gmii_tx_clk ,
output gmii_tx_en ,
output [7 : 0] gmii_txd ,
//用户接口
input arp_tx_en ,
input arp_tx_type ,
input [31 : 0] des_ip ,
input [47 : 0] des_mac ,
output arp_rx_done ,
output arp_rx_type ,
output [31 : 0] src_ip ,
output [47 : 0] src_mac ,
output tx_done
);
//parameter define
//开发板MAC地址 00-11-22-33-44-55
parameter BOARD_MAC = 48'h00_11_22_33_44_55;
//开发板IP地址 192.168.1.10
parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd10};
//目的MAC地址 ff_ff_ff_ff_ff_ff
parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
//目的IP地址 192.168.1.102
parameter DES_IP = {8'd192,8'd168,8'd1,8'd102};
//wire define
wire crc_en ; //CRC开始校验使能
wire crc_clr ; //CRC数据复位信号
wire [7:0] crc_d8 ; //输入待校验8位数据
wire [31:0] crc_data; //CRC校验数据
wire [31:0] crc_next; //CRC下次校验完成数据
//*****************************************************
//** main code
//*****************************************************
assign crc_d8 = gmii_txd;
//ARP接收模块
arp_rx
#(
.BOARD_MAC (BOARD_MAC), //参数例化
.BOARD_IP (BOARD_IP )
)
u_arp_rx(
.clk (gmii_rx_clk),
.rst_n (rst_n),
.gmii_rx_dv (gmii_rx_dv),
.gmii_rxd (gmii_rxd ),
.arp_rx_done (arp_rx_done),
.arp_rx_type (arp_rx_type),
.src_mac (src_mac ),
.src_ip (src_ip )
);
//ARP发送模块
arp_tx
#(
.BOARD_MAC (BOARD_MAC), //参数例化
.BOARD_IP (BOARD_IP ),
.DES_MAC (DES_MAC ),
.DES_IP (DES_IP )
)
u_arp_tx(
.clk (gmii_tx_clk),
.rst_n (rst_n),
.arp_tx_en (arp_tx_en ),
.arp_tx_type (arp_tx_type),
.des_mac (des_mac ),
.des_ip (des_ip ),
.crc_data (crc_data ),
.crc_next (crc_next[31:24]),
.tx_done (tx_done ),
.gmii_tx_en (gmii_tx_en),
.gmii_txd (gmii_txd ),
.crc_en (crc_en ),
.crc_clr (crc_clr )
);
//以太网发送CRC校验模块
crc32_d8 u_crc32_d8(
.clk (gmii_tx_clk),
.rst_n (rst_n ),
.data (crc_d8 ),
.crc_en (crc_en ),
.crc_clr (crc_clr ),
.crc_data (crc_data ),
.crc_next (crc_next )
);
endmodule
crc_32_d8.v
c
module crc32_d8(
input clk , //时钟信号
input rst_n , //复位信号,低电平有效
input [7:0] data , //输入待校验8位数据
input crc_en , //crc使能,开始校验标志
input crc_clr , //crc数据复位信号
output reg [31:0] crc_data, //CRC校验数据
output [31:0] crc_next //CRC下次校验完成数据
);
//*****************************************************
//** main code
//*****************************************************
//输入待校验8位数据,需要先将高低位互换
wire [7:0] data_t;
assign data_t = {data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]};
//CRC32的生成多项式为:G(x)= x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11
//+ x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
assign crc_next[0] = crc_data[24] ^ crc_data[30] ^ data_t[0] ^ data_t[6];
assign crc_next[1] = crc_data[24] ^ crc_data[25] ^ crc_data[30] ^ crc_data[31]
^ data_t[0] ^ data_t[1] ^ data_t[6] ^ data_t[7];
assign crc_next[2] = crc_data[24] ^ crc_data[25] ^ crc_data[26] ^ crc_data[30]
^ crc_data[31] ^ data_t[0] ^ data_t[1] ^ data_t[2] ^ data_t[6]
^ data_t[7];
assign crc_next[3] = crc_data[25] ^ crc_data[26] ^ crc_data[27] ^ crc_data[31]
^ data_t[1] ^ data_t[2] ^ data_t[3] ^ data_t[7];
assign crc_next[4] = crc_data[24] ^ crc_data[26] ^ crc_data[27] ^ crc_data[28]
^ crc_data[30] ^ data_t[0] ^ data_t[2] ^ data_t[3] ^ data_t[4]
^ data_t[6];
assign crc_next[5] = crc_data[24] ^ crc_data[25] ^ crc_data[27] ^ crc_data[28]
^ crc_data[29] ^ crc_data[30] ^ crc_data[31] ^ data_t[0]
^ data_t[1] ^ data_t[3] ^ data_t[4] ^ data_t[5] ^ data_t[6]
^ data_t[7];
assign crc_next[6] = crc_data[25] ^ crc_data[26] ^ crc_data[28] ^ crc_data[29]
^ crc_data[30] ^ crc_data[31] ^ data_t[1] ^ data_t[2] ^ data_t[4]
^ data_t[5] ^ data_t[6] ^ data_t[7];
assign crc_next[7] = crc_data[24] ^ crc_data[26] ^ crc_data[27] ^ crc_data[29]
^ crc_data[31] ^ data_t[0] ^ data_t[2] ^ data_t[3] ^ data_t[5]
^ data_t[7];
assign crc_next[8] = crc_data[0] ^ crc_data[24] ^ crc_data[25] ^ crc_data[27]
^ crc_data[28] ^ data_t[0] ^ data_t[1] ^ data_t[3] ^ data_t[4];
assign crc_next[9] = crc_data[1] ^ crc_data[25] ^ crc_data[26] ^ crc_data[28]
^ crc_data[29] ^ data_t[1] ^ data_t[2] ^ data_t[4] ^ data_t[5];
assign crc_next[10] = crc_data[2] ^ crc_data[24] ^ crc_data[26] ^ crc_data[27]
^ crc_data[29] ^ data_t[0] ^ data_t[2] ^ data_t[3] ^ data_t[5];
assign crc_next[11] = crc_data[3] ^ crc_data[24] ^ crc_data[25] ^ crc_data[27]
^ crc_data[28] ^ data_t[0] ^ data_t[1] ^ data_t[3] ^ data_t[4];
assign crc_next[12] = crc_data[4] ^ crc_data[24] ^ crc_data[25] ^ crc_data[26]
^ crc_data[28] ^ crc_data[29] ^ crc_data[30] ^ data_t[0]
^ data_t[1] ^ data_t[2] ^ data_t[4] ^ data_t[5] ^ data_t[6];
assign crc_next[13] = crc_data[5] ^ crc_data[25] ^ crc_data[26] ^ crc_data[27]
^ crc_data[29] ^ crc_data[30] ^ crc_data[31] ^ data_t[1]
^ data_t[2] ^ data_t[3] ^ data_t[5] ^ data_t[6] ^ data_t[7];
assign crc_next[14] = crc_data[6] ^ crc_data[26] ^ crc_data[27] ^ crc_data[28]
^ crc_data[30] ^ crc_data[31] ^ data_t[2] ^ data_t[3] ^ data_t[4]
^ data_t[6] ^ data_t[7];
assign crc_next[15] = crc_data[7] ^ crc_data[27] ^ crc_data[28] ^ crc_data[29]
^ crc_data[31] ^ data_t[3] ^ data_t[4] ^ data_t[5] ^ data_t[7];
assign crc_next[16] = crc_data[8] ^ crc_data[24] ^ crc_data[28] ^ crc_data[29]
^ data_t[0] ^ data_t[4] ^ data_t[5];
assign crc_next[17] = crc_data[9] ^ crc_data[25] ^ crc_data[29] ^ crc_data[30]
^ data_t[1] ^ data_t[5] ^ data_t[6];
assign crc_next[18] = crc_data[10] ^ crc_data[26] ^ crc_data[30] ^ crc_data[31]
^ data_t[2] ^ data_t[6] ^ data_t[7];
assign crc_next[19] = crc_data[11] ^ crc_data[27] ^ crc_data[31] ^ data_t[3] ^ data_t[7];
assign crc_next[20] = crc_data[12] ^ crc_data[28] ^ data_t[4];
assign crc_next[21] = crc_data[13] ^ crc_data[29] ^ data_t[5];
assign crc_next[22] = crc_data[14] ^ crc_data[24] ^ data_t[0];
assign crc_next[23] = crc_data[15] ^ crc_data[24] ^ crc_data[25] ^ crc_data[30]
^ data_t[0] ^ data_t[1] ^ data_t[6];
assign crc_next[24] = crc_data[16] ^ crc_data[25] ^ crc_data[26] ^ crc_data[31]
^ data_t[1] ^ data_t[2] ^ data_t[7];
assign crc_next[25] = crc_data[17] ^ crc_data[26] ^ crc_data[27] ^ data_t[2] ^ data_t[3];
assign crc_next[26] = crc_data[18] ^ crc_data[24] ^ crc_data[27] ^ crc_data[28]
^ crc_data[30] ^ data_t[0] ^ data_t[3] ^ data_t[4] ^ data_t[6];
assign crc_next[27] = crc_data[19] ^ crc_data[25] ^ crc_data[28] ^ crc_data[29]
^ crc_data[31] ^ data_t[1] ^ data_t[4] ^ data_t[5] ^ data_t[7];
assign crc_next[28] = crc_data[20] ^ crc_data[26] ^ crc_data[29] ^ crc_data[30]
^ data_t[2] ^ data_t[5] ^ data_t[6];
assign crc_next[29] = crc_data[21] ^ crc_data[27] ^ crc_data[30] ^ crc_data[31]
^ data_t[3] ^ data_t[6] ^ data_t[7];
assign crc_next[30] = crc_data[22] ^ crc_data[28] ^ crc_data[31] ^ data_t[4] ^ data_t[7];
assign crc_next[31] = crc_data[23] ^ crc_data[29] ^ data_t[5];
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
crc_data <= 32'hff_ff_ff_ff;
else if(crc_clr) //CRC校验值复位
crc_data <= 32'hff_ff_ff_ff;
else if(crc_en)
crc_data <= crc_next;
end
endmodule
gmii_to_rgmii.v
c
module gmii_to_rgmii(
input idelay_clk , //IDELAY时钟
//以太网GMII接口
output gmii_rx_clk , //GMII接收时钟
output gmii_rx_dv , //GMII接收数据有效信号
output [7:0] gmii_rxd , //GMII接收数据
output gmii_tx_clk , //GMII发送时钟
input gmii_tx_en , //GMII发送数据使能信号
input [7:0] gmii_txd , //GMII发送数据
//以太网RGMII接口
input rgmii_rxc , //RGMII接收时钟
input rgmii_rx_ctl, //RGMII接收数据控制信号
input [3:0] rgmii_rxd , //RGMII接收数据
output rgmii_txc , //RGMII发送时钟
output rgmii_tx_ctl, //RGMII发送数据控制信号
output [3:0] rgmii_txd //RGMII发送数据
);
parameter IDEAY_VALUE = 0 ;
// ------------------------------------ //
// -------------main code ------------ //
// ------------------------------------ //
assign gmii_tx_clk = gmii_rx_clk ;
// rgmii
rgmii_rx u_rgmii_rx(
.idelay_clk ( idelay_clk ),
.rgmii_rxc ( rgmii_rxc ),
.rgmii_rx_ctl ( rgmii_rx_ctl ),
.rgmii_rxd ( rgmii_rxd ),
.gmii_rx_clk ( gmii_rx_clk ),
.gmii_rx_dv ( gmii_rx_dv ),
.gmii_rxd ( gmii_rxd )
);
// gmii
rgmii_tx u_rgmii_tx(
.gmii_tx_clk ( gmii_tx_clk ),
.gmii_tx_en ( gmii_tx_en ),
.gmii_txd ( gmii_txd ),
.rgmii_txc ( rgmii_txc ),
.rgmii_tx_ctl ( rgmii_tx_ctl ),
.rgmii_txd ( rgmii_txd )
);
endmodule
rgmii_rx.v
c
module rgmii_rx(
input idelay_clk , // 200Mhz时钟,IDELAY时钟
// 这一段是以太网RGNII接口
input rgmii_rxc , // RGMII接收时钟
input rgmii_rx_ctl , // RGMII接收时钟控制信号
input [3 : 0] rgmii_rxd , // RGMII接收数据
// 以太�? GMII接口
output gmii_rx_clk ,
output gmii_rx_dv ,
output [7 : 0] gmii_rxd
);
// -------------------------------------------//
// ------parameter and define--------------- //
// -------------------------------------------//
parameter IDELAY_VALUE = 0 ;
wire rgmii_rxc_bufg ; //全局时钟缓冲
wire rgmii_rxc_bufio ; //全局时钟IO缓存 -- 接在了BUFIO后面�?
wire rgmii_rx_ctl_delay ;
wire [3 : 0] rgmii_rxd_delay ;
wire [1 : 0] gmii_rxdv_t ; // 两位GMII接收信号
// ---------------------------------------------//
// ------------ main code ---------------------//
//----------------------------------------------//
assign gmii_rx_clk = rgmii_rxc_bufg ;
assign gmii_rx_dv = gmii_rxdv_t[0] & gmii_rxdv_t[1] ;
// 全局时钟缓存
BUFG BUFG_inst(
.I (rgmii_rxc) ,
.O (rgmii_rxc_bufg)
);
// 全局时钟缓存
BUFIO BUFIO_inst (
.I (rgmii_rxc),
.O (rgmii_rxc_bufio)
);
//������ʱ����
// Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
(* IODELAY_GROUP = "rgmii_rx_delay" *)
IDELAYCTRL IDELAYCTRL_inst (
.RDY(), // 1-bit output: Ready output
.REFCLK(idelay_clk), // 1-bit input: Reference clock input
.RST(1'b0) // 1-bit input: Active high reset input
);
//rgmii_rx_ctl������ʱ��˫�ز���
(* IODELAY_GROUP = "rgmii_rx_delay" *)
IDELAYE2 #(
.IDELAY_TYPE ("FIXED"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
.IDELAY_VALUE (IDELAY_VALUE), // Input delay tap setting (0-31)
.REFCLK_FREQUENCY(200.0) // IDELAYCTRL clock input frequency in MHz
)
u_delay_rx_ctrl (
.CNTVALUEOUT (), // 5-bit output: Counter value output
.DATAOUT (rgmii_rx_ctl_delay),// 1-bit output: Delayed data output
.C (1'b0), // 1-bit input: Clock input
.CE (1'b0), // 1-bit input: enable increment/decrement
.CINVCTRL (1'b0), // 1-bit input: Dynamic clock inversion input
.CNTVALUEIN (5'b0), // 5-bit input: Counter value input
.DATAIN (1'b0), // 1-bit input: Internal delay data input
.IDATAIN (rgmii_rx_ctl), // 1-bit input: Data input from the I/O
.INC (1'b0), // 1-bit input: Increment / Decrement tap delay
.LD (1'b0), // 1-bit input: Load IDELAY_VALUE input
.LDPIPEEN (1'b0), // 1-bit input: Enable PIPELINE register
.REGRST (1'b0) // 1-bit input: Active-high reset tap-delay input
);
//����˫�ز����Ĵ���
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"),// "OPPOSITE_EDGE", "SAME_EDGE"
// or "SAME_EDGE_PIPELINED"
.INIT_Q1 (1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2 (1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE ("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
) u_iddr_rx_ctl (
.Q1 (gmii_rxdv_t[0]), // 1-bit output for positive edge of clock
.Q2 (gmii_rxdv_t[1]), // 1-bit output for negative edge of clock
.C (rgmii_rxc_bufio), // 1-bit clock input
.CE (1'b1), // 1-bit clock enable input
.D (rgmii_rx_ctl_delay), // 1-bit DDR data input
.R (1'b0), // 1-bit reset
.S (1'b0) // 1-bit set
);
//rgmii_rxd������ʱ��˫�ز���
genvar i;
generate for (i=0; i<4; i=i+1)
(* IODELAY_GROUP = "rgmii_rx_delay" *)
begin : rxdata_bus
//������ʱ
(* IODELAY_GROUP = "rgmii_rx_delay" *)
IDELAYE2 #(
.IDELAY_TYPE ("FIXED"), // FIXED,VARIABLE,VAR_LOAD,VAR_LOAD_PIPE
.IDELAY_VALUE (IDELAY_VALUE), // Input delay tap setting (0-31)
.REFCLK_FREQUENCY(200.0) // IDELAYCTRL clock input frequency in MHz
)
u_delay_rxd (
.CNTVALUEOUT (), // 5-bit output: Counter value output
.DATAOUT (rgmii_rxd_delay[i]),// 1-bit output: Delayed data output
.C (1'b0), // 1-bit input: Clock input
.CE (1'b0), // 1-bit input: enable increment/decrement
.CINVCTRL (1'b0), // 1-bit input: Dynamic clock inversion
.CNTVALUEIN (5'b0), // 5-bit input: Counter value input
.DATAIN (1'b0), // 1-bit input: Internal delay data input
.IDATAIN (rgmii_rxd[i]), // 1-bit input: Data input from the I/O
.INC (1'b0), // 1-bit input: Inc/Decrement tap delay
.LD (1'b0), // 1-bit input: Load IDELAY_VALUE input
.LDPIPEEN (1'b0), // 1-bit input: Enable PIPELINE register
.REGRST (1'b0) // 1-bit input: Active-high reset tap-delay
);
//����˫�ز����Ĵ���
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"),// "OPPOSITE_EDGE", "SAME_EDGE"
// or "SAME_EDGE_PIPELINED"
.INIT_Q1 (1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2 (1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE ("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
) u_iddr_rxd (
.Q1 (gmii_rxd[i]), // 1-bit output for positive edge of clock
.Q2 (gmii_rxd[4+i]), // 1-bit output for negative edge of clock
.C (rgmii_rxc_bufio), // 1-bit clock input rgmii_rxc_bufio
.CE (1'b1), // 1-bit clock enable input
.D (rgmii_rxd_delay[i]), // 1-bit DDR data input
.R (1'b0), // 1-bit reset
.S (1'b0) // 1-bit set
);
end
endgenerate
endmodule
rgmii_tx.v
c
module rgmii_tx(
// GMII 发送端口
input gmii_tx_clk , // GMII 发送信号
input gmii_tx_en , // GMII 输出数据有效信号
input [7 : 0] gmii_txd ,
//RGMII 发送端口
output rgmii_txc ,
output rgmii_tx_ctl ,
output [3 : 0] rgmii_txd
);
// --------------------------------------------- //
// -------------- main code -------------------- //
// --------------------------------------------- //
assign rgmii_txc = gmii_tx_clk ; // 输出时钟
// 输出双沿采样
ODDR #(
.DDR_CLK_EDGE ("SAME_EDGE") ,
.INIT (1'b0) ,
.SRTYPE ("SYNC")
) ODDR_inst (
.Q (rgmii_tx_ctl) ,
.C (gmii_tx_clk) ,
.CE (1'b1) ,
.D1 (gmii_tx_en) , // positive egde
.D2 (gmii_tx_en) , // negative edge
.R (1'b0) ,
.S (1'b0)
);
genvar i;
generate for (i=0; i<4; i=i+1)
begin : txdata_bus
ODDR #(
.DDR_CLK_EDGE ("SAME_EDGE") ,
.INIT (1'b0),
.SRTYPE ("SYNC")
) ODDR_inst (
.Q (rgmii_txd[i]) ,
.C (gmii_tx_clk) ,
.CE (1'b1) ,
.D1 (gmii_txd[i]) ,
.D2 (gmii_txd[4+i]) ,
.R (1'b0) ,
.S (1'b0)
);
end
endgenerate
endmodule
tb_arp.v
c
此模块用于arp的仿真 包括arp.v arp_tx.v arp_rx.v
`timescale 1ns/1ns //定义仿真时间单位1ns和仿真时间精度为1ns
module tb_arp;
//parameter define
parameter T = 8; //时钟周期为8ns
parameter OP_CYCLE = 100; //操作周期
//开发板MAC地址 00-11-22-33-44-55
parameter BOARD_MAC = 48'h00_11_22_33_44_55;
//实际开发板IP地址 192.168.1.10
//为了返回应答,仿真代码将开发板地址设置与目的IP地址相同
parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd102};
//目的MAC地址 ff_ff_ff_ff_ff_ff
parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
//目的IP地址 192.168.1.102
parameter DES_IP = {8'd192,8'd168,8'd1,8'd102};
//reg define
reg gmii_clk; //时钟信号
reg sys_rst_n; //复位信号
reg arp_tx_en ; //ARP发送使能信号
reg arp_tx_type; //ARP发送类型 0:请求 1:应答
reg [3:0] flow_cnt ;
reg [13:0] delay_cnt ;
//wire define
wire gmii_rx_clk; //GMII接收时钟
wire gmii_rx_dv ; //GMII接收数据有效信号
wire [7:0] gmii_rxd ; //GMII接收数据
wire gmii_tx_clk; //GMII发送时钟
wire gmii_tx_en ; //GMII发送数据使能信号
wire [7:0] gmii_txd ; //GMII发送数据
wire arp_rx_done; //ARP接收完成信号
wire arp_rx_type; //ARP接收类型 0:请求 1:应答
wire [47:0] src_mac ; //接收到目的MAC地址
wire [31:0] src_ip ; //接收到目的IP地址
wire [47:0] des_mac ; //发送的目标MAC地址
wire [31:0] des_ip ; //发送的目标IP地址
wire tx_done ; //以太网发送完成信号
//*****************************************************
//** main code
//*****************************************************
assign gmii_rx_clk = gmii_clk ;
assign gmii_tx_clk = gmii_clk ;
assign gmii_rx_dv = gmii_tx_en ;
assign gmii_rxd = gmii_txd ;
assign des_mac = src_mac;
assign des_ip = src_ip;
//给输入信号初始值
initial begin
gmii_clk = 1'b0;
sys_rst_n = 1'b0; //复位
#(T+1) sys_rst_n = 1'b1; //在第(T+1)ns的时候复位信号信号拉高
end
//125Mhz的时钟,周期则为1/125Mhz=8ns,所以每4ns,电平取反一次
always #(T/2) gmii_clk = ~gmii_clk;
always @(posedge gmii_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
arp_tx_en <= 1'b0;
arp_tx_type <= 1'b0;
delay_cnt <= 1'b0;
flow_cnt <= 1'b0;
end
else begin
case(flow_cnt)
'd0 : flow_cnt <= flow_cnt + 1'b1;
'd1 : begin
arp_tx_en <= 1'b1;
arp_tx_type <= 1'b0; //发送ARP请求
flow_cnt <= flow_cnt + 1'b1;
end
'd2 : begin
arp_tx_en <= 1'b0;
flow_cnt <= flow_cnt + 1'b1;
end
'd3 : begin
if(tx_done)
flow_cnt <= flow_cnt + 1'b1;
end
'd4 : begin
delay_cnt <= delay_cnt + 1'b1;
if(delay_cnt == OP_CYCLE - 1'b1)
flow_cnt <= flow_cnt + 1'b1;
end
'd5 : begin
arp_tx_en <= 1'b1;
arp_tx_type <= 1'b1; //发送ARP应答
flow_cnt <= flow_cnt + 1'b1;
end
'd6 : begin
arp_tx_en <= 1'b0;
flow_cnt <= flow_cnt + 1'b1;
end
'd7 : begin
if(tx_done)
flow_cnt <= flow_cnt + 1'b1;
end
default:;
endcase
end
end
//ARP通信
arp
#(
.BOARD_MAC (BOARD_MAC), //参数例化
.BOARD_IP (BOARD_IP ),
.DES_MAC (DES_MAC ),
.DES_IP (DES_IP )
)
u_arp(
.rst_n (sys_rst_n ),
.gmii_rx_clk (gmii_rx_clk),
.gmii_rx_dv (gmii_rx_dv ),
.gmii_rxd (gmii_rxd ),
.gmii_tx_clk (gmii_tx_clk),
.gmii_tx_en (gmii_tx_en ),
.gmii_txd (gmii_txd ),
.arp_rx_done (arp_rx_done),
.arp_rx_type (arp_rx_type),
.src_mac (src_mac ),
.src_ip (src_ip ),
.arp_tx_en (arp_tx_en ),
.arp_tx_type (arp_tx_type),
.des_mac (des_mac ),
.des_ip (des_ip ),
.tx_done (tx_done )
);
endmodule
注意点
本实验使用了Xillix的原语 在rgmii_rx.v模块中使用了 BUFG BUFIO IDELAYCTRL IDELAYE2 这几个原语
并且PLL 设置的clocking wizard 为输入50MHz 输出200MHz
基于ZYNQ 7020的xdc如下
c
create_clock -period 20.000 -name sys_clk [get_ports sys_clk]
create_clock -period 8.000 -name eth_rxc [get_ports eth_rxc]
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports touch_key]
set_property -dict {PACKAGE_PIN K17 IOSTANDARD LVCMOS33} [get_ports eth_rxc]
set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS33} [get_ports eth_rx_ctl]
set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[0]}]
set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[1]}]
set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[2]}]
set_property -dict {PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[3]}]
set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports eth_txc]
set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS33} [get_ports eth_tx_ctl]
set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports {eth_txd[0]}]
set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {eth_txd[1]}]
set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports {eth_txd[2]}]
set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports {eth_txd[3]}]
set_property -dict {PACKAGE_PIN G15 IOSTANDARD LVCMOS33} [get_ports eth_rst_n]