您的位置:首页 > 教育 > 培训 > 定制网站建设程序流程_网页打不开怎么解决手机_网站广告投放价格表_seo排名优化哪家好

定制网站建设程序流程_网页打不开怎么解决手机_网站广告投放价格表_seo排名优化哪家好

2025/1/10 15:51:37 来源:https://blog.csdn.net/m0_69082048/article/details/144932519  浏览:    关键词:定制网站建设程序流程_网页打不开怎么解决手机_网站广告投放价格表_seo排名优化哪家好
定制网站建设程序流程_网页打不开怎么解决手机_网站广告投放价格表_seo排名优化哪家好

纯verilog实现,仅使用锁相环IP、FIFO IP,方便跨平台移植。支持ping指令。

以太网系列文章:

以太网ICMP协议(ping指令)——FPGA学习笔记25-CSDN博客

以太网ARP协议——FPGA学习笔记23-CSDN博客 

以太网PHY_MDIO通信(基于RTL8211)--FPGA学习笔记22_mdio前导码-CSDN博客

FPGA千兆网口数据传输MDIO接口——FPGA学习笔记3_yt8531sh原理图-CSDN博客 

 

一、UDP简介

        UDP(User Datagram Protocol),即用户数据报协议, 是一种面向无连接的传输层协议。无连接是指在传输数据时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。由于使用 UDP 协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输(如视频会议等)都会采用 UDP 协议进行传输,这种情况即使偶尔丢失一两个数据包,也不会对接收结果
产生太大影响。

 

二、UDP协议

UDP 首部共 8 个字节,同 IP 首部一样,也是一行以 32 位(4 个字节)为单位。
源端口号: 16 位发送端端口号,用于区分不同服务的端口,端口号的范围从 0 到 65535。
目的端口号: 16 位接收端端口号。
UDP 长度: 16 位 UDP 长度,包含 UDP 首部长度+数据长度,单位是字节(byte)。
UDP 校验和: 16 位 UDP 校验和。 UDP 计算校验和的方法和计算 IP 数据报首部校验和的方法相似,但不同的是 IP 数据报的校验和只检验 IP 数据报的首部,而 UDP 校验和包含三个部分: UDP 伪首部, UDP 首部和 UDP 的数据部分伪首部的数据是从 IP 数据报头和 UDP 数据报头获取的,包括源 IP 地址,目的 IP地址,协议类型和 UDP 长度,其目的是让 UDP 两次检查数据是否已经正确到达目的地,只是单纯为了做校验用的。在大多数使用场景中接收端并不检测 UDP 校验和,因此这里不做过多介绍。

用户数据打包在 UDP 协议中, UDP 协议又是基于 IP 协议之上的, IP 协议又是走 MAC 层发送的,即从包含关系来说: MAC 帧中的数据段为 IP 数据报, IP 报文中的数据段为 UDP 报文, UDP 报文中的数据段为用户希望传输的数据内容。


三、目标实现UDP协议(含ICMP协议)

四、代码编写

1、UDP框图

(1)udp_rx

 

module udp_rx(input                clk         ,    //时钟信号input                rst_n       ,    //复位信号,低电平有效input                gmii_rx_dv  ,    //GMII输入数据有效信号input        [7:0]   gmii_rxd    ,    //GMII输入数据output  reg          rec_pkt_done,    //以太网单包数据接收完成信号output  reg          rec_en      ,    //以太网接收的数据使能信号output  reg  [7 :0]  rec_data    ,output  reg  [15:0]  rec_byte_num     //以太网接收的有效字数 单位:byte     
);//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};localparam  st_idle     = 7'b000_0001; //初始状态,等待接收前导码
localparam  st_preamble = 7'b000_0010; //接收前导码状态 
localparam  st_eth_head = 7'b000_0100; //接收以太网帧头
localparam  st_ip_head  = 7'b000_1000; //接收IP首部
localparam  st_udp_head = 7'b001_0000; //接收UDP首部
localparam  st_rx_data  = 7'b010_0000; //接收有效数据
localparam  st_rx_end   = 7'b100_0000; //接收结束localparam  ETH_TYPE    = 16'h0800   ; //以太网协议类型 IP协议
localparam  UDP_TYPE    = 8'd17      ; //UDP协议类型reg  [6:0]   cur_state       ;
reg  [6:0]   next_state      ;reg          skip_en         ; //控制状态跳转使能信号
reg          error_en        ; //解析错误使能信号
reg  [4:0]   cnt             ; //解析数据计数器
reg  [47:0]  des_mac         ; //目的MAC地址
reg  [15:0]  eth_type        ; //以太网类型
reg  [31:0]  des_ip          ; //目的IP地址
reg  [5:0]   ip_head_byte_num; //IP首部长度
reg  [15:0]  udp_byte_num    ; //UDP长度
reg  [15:0]  data_byte_num   ; //数据长度
reg  [15:0]  data_cnt        ; //有效数据计数    //*****************************************************
//**                    main code
//*****************************************************//(三段式状态机)同步时序描述状态转移
always @(posedge clk or negedge rst_n) beginif(!rst_n)cur_state <= st_idle;  elsecur_state <= next_state;
end//组合逻辑判断状态转移条件
always @(*) beginnext_state = st_idle;case(cur_state)st_idle : begin                                     //等待接收前导码if(skip_en) next_state = st_preamble;elsenext_state = st_idle;    endst_preamble : begin                                 //接收前导码if(skip_en) next_state = st_eth_head;else if(error_en) next_state = st_rx_end;    elsenext_state = st_preamble;    endst_eth_head : begin                                 //接收以太网帧头if(skip_en) next_state = st_ip_head;else if(error_en) next_state = st_rx_end;elsenext_state = st_eth_head;           end  st_ip_head : begin                                  //接收IP首部if(skip_en)next_state = st_udp_head;else if(error_en)next_state = st_rx_end;elsenext_state = st_ip_head;       end st_udp_head : begin                                 //接收UDP首部if(skip_en)next_state = st_rx_data;elsenext_state = st_udp_head;    end                st_rx_data : begin                                  //接收有效数据if(skip_en)next_state = st_rx_end;elsenext_state = st_rx_data;    end                           st_rx_end : begin                                   //接收结束if(skip_en)next_state = st_idle;elsenext_state = st_rx_end;          enddefault : next_state = st_idle;endcase                                          
end    //时序电路描述状态输出,解析以太网数据
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginend else beginskip_en         <=  1'b0;error_en        <=  1'b0;rec_pkt_done    <=  1'b0;case (next_state)st_idle    :beginif ((gmii_rx_dv == 1'b1)&&(gmii_rxd == 8'h55)) beginskip_en     <=  1'b1;end endst_preamble:beginif (gmii_rx_dv) begincnt <= cnt + 1'b1;if((cnt < 5'd6) && (gmii_rxd != 8'h55))  //7个8'h55  error_en <= 1'b1;else if(cnt==5'd6) begincnt <= 5'd0;if(gmii_rxd==8'hd5)                  //1个8'hd5skip_en <= 1'b1;elseerror_en <= 1'b1;    endend endst_eth_head:beginif(gmii_rx_dv) begincnt <= cnt + 1'b1;if(cnt < 5'd6) des_mac <= {des_mac[39:0],gmii_rxd}; //目的MAC地址else if(cnt == 5'd12) eth_type[15:8] <= gmii_rxd;          //以太网协议类型else if(cnt == 5'd13) begineth_type[7:0] <= gmii_rxd;cnt <= 5'd0;//判断MAC地址是否为开发板MAC地址或者公共地址if(((des_mac == BOARD_MAC) ||(des_mac == 48'hff_ff_ff_ff_ff_ff))&& eth_type[15:8] == ETH_TYPE[15:8] && gmii_rxd == ETH_TYPE[7:0])            skip_en <= 1'b1;elseerror_en <= 1'b1;end        end  endst_ip_head :beginif (gmii_rx_dv) begincnt <= cnt + 1'b1;if (cnt == 5'd0) beginip_head_byte_num <= {gmii_rxd[3:0],2'd0};endelse if (cnt == 5'd9) beginif (gmii_rxd != UDP_TYPE) beginerror_en    <= 1'b1;cnt         <= 5'd0;endend else if ((cnt >= 5'd16)&&(cnt <= 5'd18))begin       //目的IP地址des_ip  <=  {des_ip[23:0],gmii_rxd};endelse if (cnt == 5'd19) begindes_ip  <=  {des_ip[23:0],gmii_rxd};        if ({des_ip[23:0],gmii_rxd} == BOARD_IP) begin  //判断目的IP是否为开发板skip_en     <= 1'b1;cnt         <= 5'd0;endelse begin                                      //IP错误error_en    <=  1'b0;cnt         <=  5'd0;end end end endst_udp_head:beginif (gmii_rx_dv) begincnt <= cnt + 1'b1;if ((cnt >= 5'd4)&&(cnt <= 5'd5)) begin             //解析UDP字节长度udp_byte_num    <=  {udp_byte_num[7:0],gmii_rxd};end else if(cnt == 5'd7) begin                          //有效长度=字节长度-首部长度data_byte_num   <=  udp_byte_num - 16'd8;skip_en         <=  1'b1;cnt             <=  5'd0;endend endst_rx_data :beginif (gmii_rx_dv) begindata_cnt    <=  data_cnt + 1'b1 ;                   //接收数据计数器rec_data    <=  gmii_rxd        ;                   //以太网接收数据rec_en      <=  1'b1            ;                   //接收数据使能信号if (data_cnt == data_byte_num - 1'b1) beginskip_en         <=  1'b1;data_cnt        <=  16'd0;rec_pkt_done    <=  1'b1;rec_byte_num    <=  data_byte_num;              //以太网接收数据有效数量end end endst_rx_end  :beginrec_en  <=  1'b0;                                       //单包数据传输完成if ((gmii_rx_dv == 1'b0) && (skip_en == 1'b0 ) ) beginskip_en <=  1'b1;endend default: ;endcaseend
end
endmodule

仿真结果: 

 

(2)udp_tx

 

module udp_tx(    input                clk        , //时钟信号input                rst_n      , //复位信号,低电平有效input                tx_start_en, //以太网开始发送信号input        [ 7:0]  tx_data    , //以太网待发送数据 input        [15:0]  tx_byte_num, //以太网发送的有效字节数input        [47:0]  des_mac    , //发送的目标MAC地址input        [31:0]  des_ip     , //发送的目标IP地址    input        [31:0]  crc_data   , //CRC校验数据input        [ 7:0]  crc_next   , //CRC下次校验完成数据output  reg          tx_done    , //以太网发送完成信号output  reg          tx_req     , //读数据请求信号output  reg          gmii_tx_en , //GMII输出数据有效信号output  reg  [7:0]   gmii_txd   , //GMII输出数据output  reg          crc_en     , //CRC开始校验使能output  reg          crc_clr      //CRC数据复位信号 
);//parameter define
//开发板MAC地址 00-11-22-33-44-55
parameter BOARD_MAC = 48'h00_11_22_33_44_55;
//开发板IP地址 192.168.1.123     
parameter BOARD_IP  = {8'd192,8'd168,8'd1,8'd123}; 
//目的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  st_idle      = 7'b000_0001; //初始状态,等待开始发送信号
localparam  st_check_sum = 7'b000_0010; //IP首部校验和
localparam  st_preamble  = 7'b000_0100; //发送前导码+帧起始界定符
localparam  st_eth_head  = 7'b000_1000; //发送以太网帧头
localparam  st_ip_head   = 7'b001_0000; //发送IP首部+UDP首部
localparam  st_tx_data   = 7'b010_0000; //发送数据
localparam  st_crc       = 7'b100_0000; //发送CRC校验值localparam  ETH_TYPE     = 16'h0800  ;  //以太网协议类型 IP协议
//以太网数据最小46个字节,IP首部20个字节+UDP首部8个字节
//所以数据至少46-20-8=18个字节
localparam  MIN_DATA_NUM = 16'd18    ;  //reg define
reg  [6:0]   cur_state          ;
reg  [6:0]   next_state         ;        
reg  [7:0]   preamble   [7:0]   ; //前导码
reg  [7:0]   eth_head   [13:0]  ; //以太网首部
reg  [31:0]  ip_head    [6:0]   ; //IP首部 + UDP首部                      
reg          start_en_d0        ;
reg          start_en_d1        ;
reg          start_en_d2        ;
reg  [15:0]  tx_data_num        ; //发送的有效数据字节个数
reg  [15:0]  total_num          ; //总字节数
reg          trig_tx_en         ;
reg  [15:0]  udp_num            ; //UDP字节数
reg          skip_en            ; //控制状态跳转使能信号
reg  [4:0]   cnt                ;
reg  [31:0]  check_buffer       ; //首部校验和
reg  [1:0]   tx_bit_sel         ;
reg  [15:0]  data_cnt           ; //发送数据个数计数器
reg          tx_done_t          ;
reg  [4:0]   real_add_cnt       ; //以太网数据实际多发的字节数//wire define                       
wire         pos_start_en       ;//开始发送数据上升沿
wire [15:0]  real_tx_data_num   ;//实际发送的字节数(以太网最少字节要求)//采tx_start_en上升沿
assign  pos_start_en        = (!start_en_d2) & start_en_d1 ;
//判断实际发送数据
assign  real_tx_data_num    = (tx_data_num >= MIN_DATA_NUM) ? tx_data_num : MIN_DATA_NUM ;//采tx_start_en上升沿
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginstart_en_d0 <=  1'd0;start_en_d1 <=  1'd0;start_en_d2 <=  1'd0;end else beginstart_en_d0 <=  tx_start_en;start_en_d1 <=  start_en_d0;start_en_d2 <=  start_en_d1;end
end//寄存数据有效长度
always @(posedge clk or negedge rst_n) beginif (!rst_n) begintx_data_num <=  16'd0;      //发送的有效数据字节个数total_num   <=  16'd0;      //总字节数udp_num     <=  16'd0;      //UDP字节数end else beginif (pos_start_en && cur_state == st_idle) begin//有效数据长度tx_data_num     <=  tx_byte_num ;//IP长度:有效数据长度 + IP首部长度total_num       <=  tx_data_num + 16'd28;//UDP长度:有效数据 + UDP首部长度udp_num         <=  tx_byte_num + 16'd8;end end
end//寄存触发发送信号
always @(posedge clk or negedge rst_n) beginif(!rst_n) trig_tx_en <= 1'b0;elsetrig_tx_en <= pos_start_en;end//(三段式状态机)同步时序描述状态转移
always @(posedge clk or negedge rst_n) beginif(!rst_n)cur_state <= st_idle;  elsecur_state <= next_state;
end//组合逻辑判断状态转移条件
always @(*) beginnext_state = st_idle;case(cur_state)st_idle     : begin                               //等待发送数据if(skip_en)                next_state = st_check_sum;elsenext_state = st_idle;end  st_check_sum: begin                               //IP首部校验if(skip_en)next_state = st_preamble;elsenext_state = st_check_sum;    end                             st_preamble : begin                               //发送前导码+帧起始界定符if(skip_en)next_state = st_eth_head;elsenext_state = st_preamble;      endst_eth_head : begin                               //发送以太网首部if(skip_en)next_state = st_ip_head;elsenext_state = st_eth_head;      end              st_ip_head : begin                                //发送IP首部+UDP首部               if(skip_en)next_state = st_tx_data;elsenext_state = st_ip_head;      endst_tx_data : begin                                //发送数据                  if(skip_en)next_state = st_crc;elsenext_state = st_tx_data;      endst_crc: begin                                     //发送CRC校验值if(skip_en)next_state = st_idle;elsenext_state = st_crc;      enddefault : next_state = st_idle;   endcase
end                      //时序电路描述状态输出,解析以太网数据
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginskip_en             <= 1'b0 ; cnt                 <= 5'd0 ;check_buffer        <= 32'd0;ip_head[1][31:16]   <= 16'd0;       //IP首部表示tx_bit_sel          <= 2'b0 ;crc_en              <= 1'b0 ;gmii_tx_en          <= 1'b0 ;gmii_txd            <= 8'd0 ;tx_req              <= 1'b0 ;tx_done_t           <= 1'b0 ; data_cnt            <= 16'd0;real_add_cnt        <= 5'd0 ;//初始化数组    //前导码 7个8'h55 + 1个8'hd5preamble[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   ;//目的MAC地址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]    ;//源MAC地址eth_head[6]     <=  BOARD_MAC[47:40];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]   ;  end else beginskip_en     <= 1'b0;crc_en      <= 1'b0;gmii_tx_en  <= 1'b0;tx_done_t   <= 1'b0;case (next_state)st_idle      :begin                                         //等待发送数据if(trig_tx_en) beginskip_en     <= 1'b1; //版本号:4 首部长度:5(单位:32bit,20byte/4=5)ip_head[0]  <= {8'h45,8'h00,total_num};   //16位标识,每次发送累加1      ip_head[1][31:16]   <= ip_head[1][31:16] + 1'b1; //bit[15:13]: 010表示不分片ip_head[1][15:0]    <= 16'h4000;    //协议:17(udp)                  ip_head[2]  <= {8'h40,8'd17,16'h0};   //源IP地址               ip_head[3]  <= BOARD_IP;//目的IP地址    if(des_ip != 32'd0)ip_head[4]  <= des_ip;elseip_head[4]  <= DES_IP;       //16位源端口号:1234  16位目的端口号:1234                      ip_head[5]  <= {16'd1234,16'd1234};  //16位udp长度,16位udp校验和              ip_head[6]  <= {udp_num,16'h0000};  //更新MAC地址if(des_mac != 48'b0) begin//目的MAC地址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];endend   endst_check_sum :begin                                         //IP首部校验和cnt <= cnt + 1'b1;if (cnt == 5'd0) begin                                             check_buffer <=   ip_head[0][31:16] + ip_head[0][15:0]+ ip_head[1][31:16] + ip_head[1][15:0]+ ip_head[2][31:16] + ip_head[2][15:0]+ ip_head[3][31:16] + ip_head[3][15:0]+ ip_head[4][31:16] + ip_head[4][15:0];endelse if(cnt == 5'd1)                      //可能出现进位,累加一次check_buffer <= check_buffer[31:16] + check_buffer[15:0];else if(cnt == 5'd2) begin                //可能再次出现进位,累加一次check_buffer <= check_buffer[31:16] + check_buffer[15:0];end                             else if(cnt == 5'd3) begin                //按位取反 skip_en <= 1'b1;cnt     <= 5'd0;            ip_head[2][15:0] <= ~check_buffer[15:0];end endst_preamble  :begin                                         //发送前导码+帧起始界定符gmii_tx_en  <=  1'b1;gmii_txd    <=  preamble[cnt];if (cnt == 5'd7) beginskip_en <=  1'b1;cnt     <=  5'd0;endelse begincnt <= cnt + 1'b1;endendst_eth_head  :begin                                         //发送以太网首部gmii_tx_en  <=  1'b1;crc_en      <=  1'b1;gmii_txd    <=  eth_head[cnt];if (cnt == 5'd13) beginskip_en <=  1'b1;cnt     <=  5'd0;endelse begincnt <= cnt + 1'b1;endendst_ip_head   :begin                                         //发送IP首部 + UDP首部gmii_tx_en  <=  1'b1;crc_en      <=  1'b1;tx_bit_sel  <=  tx_bit_sel + 1'b1;if (tx_bit_sel == 2'd0) begingmii_txd    <=  ip_head[cnt][31:24];endelse if (tx_bit_sel == 2'd1) begingmii_txd    <=  ip_head[cnt][23:16];end else if (tx_bit_sel == 2'd2) begingmii_txd    <=  ip_head[cnt][15:8];if (cnt == 5'd6) begin//提前读请求数据,等待数据有效时发送tx_req <= 1'b1;     end else begintx_req <= 1'b0;   endendelse if (tx_bit_sel == 2'd3) begin      //tx_bit_sel自动溢出gmii_txd    <=  ip_head[cnt][7:0];if (cnt == 5'd6) beginskip_en <=  1'b1;cnt     <=  5'd0;end else begincnt     <=  cnt + 1'b1;    end    end endst_tx_data   :begin                                         //发送数据gmii_tx_en  <=  1'b1;crc_en      <=  1'b1;gmii_txd    <=  tx_data;tx_bit_sel  <=  tx_bit_sel + 1'b1;if (data_cnt < tx_data_num - 16'd1) begindata_cnt <= data_cnt + 1'b1;endelse if (data_cnt == tx_data_num - 16'd1) begin//如果发送的有效数据少于18个字节,在后面填补充位//补充的值为最后一次发送的有效数据if (data_cnt + real_add_cnt < real_tx_data_num - 16'd1) beginreal_add_cnt <= real_add_cnt + 1'b1;end else beginskip_en         <=  1'b1;data_cnt        <=  16'd0;real_add_cnt    <=  5'd0;tx_bit_sel      <=  3'd0;    endend if (data_cnt == tx_byte_num - 16'd2) begintx_req <= 1'b0;endendst_crc      : begin                                         //发送CRC校验值gmii_tx_en <= 1'b1;tx_bit_sel <= tx_bit_sel + 3'd1;tx_req <= 1'b0;  if(tx_bit_sel == 3'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(tx_bit_sel == 3'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(tx_bit_sel == 3'd2) begingmii_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]};                              endelse if(tx_bit_sel == 3'd3) begingmii_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;end else ;end  default: ;endcaseend
end//发送完成信号及crc值复位信号
always @(posedge clk or negedge rst_n) beginif(!rst_n) begintx_done <= 1'b0;crc_clr <= 1'b0;endelse begintx_done <= tx_done_t;crc_clr <= tx_done_t;end
endendmodule

仿真结果:

2、协议栈顶层

(1)框图及顶层

module eth_udp_loop(input                   sys_rst_n           ,   //系统复位信号,低电平有效 //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输出数据          
);//parameter define
parameter  BOARD_MAC = 48'h00_11_22_33_44_55;       //开发板MAC地址 00-11-22-33-44-55
parameter  BOARD_IP  = {8'd192,8'd168,8'd1,8'd10};  //开发板IP地址 192.168.1.10
parameter  DES_MAC   = 48'hff_ff_ff_ff_ff_ff;       //目的MAC地址 ff_ff_ff_ff_ff_ff
parameter  DES_IP    = {8'd192,8'd168,8'd1,8'd102}; //目的IP地址 192.168.1.102     
parameter  IDELAY_VALUE = 15;                       //输入数据IO延时,此处为0,即不延时(如果为n,表示延时n*78ps) //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_gmii_tx_en	        ;   //ARP GMII输出数据有效信号 
wire          [7:0]     arp_gmii_txd  	        ;   //ARP 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          [47:0]    des_mac       	        ;   //发送的目标MAC地址
wire          [31:0]    des_ip        	        ;   //发送的目标IP地址   
wire                    arp_tx_done   	        ;   //ARP发送完成信号wire                    icmp_gmii_tx_en	        ;   //ICMP GMII输出数据有效信号 
wire          [7:0]     icmp_gmii_txd  	        ;   //ICMP GMII输出数据
wire                    icmp_rec_pkt_done       ;   //ICMP单包数据接收完成信号
wire                    icmp_rec_en             ;   //ICMP接收的数据使能信号
wire          [ 7:0]    icmp_rec_data           ;   //ICMP接收的数据
wire          [15:0]    icmp_rec_byte_num       ;   //ICMP接收的有效字节数 单位:byte 
wire          [15:0]    icmp_tx_byte_num        ;   //ICMP发送的有效字节数 单位:byte 
wire                    icmp_tx_done   	        ;   //ICMP发送完成信号
wire                    icmp_tx_req             ;   //ICMP读数据请求信号
wire          [ 7:0]    icmp_tx_data            ;   //ICMP待发送数据
wire                    icmp_tx_start_en        ;   //ICMP发送开始使能信号wire                    udp_gmii_tx_en	        ;   //UDP GMII输出数据有效信号 
wire          [7:0]     udp_gmii_txd  	        ;   //UDP GMII输出数据
wire                    rec_pkt_done  	        ;   //UDP单包数据接收完成信号
wire                    udp_rec_en    	        ;   //UDP接收的数据使能信号
wire          [ 7:0]    udp_rec_data  	        ;   //UDP接收的数据
wire          [15:0]    rec_byte_num  	        ;   //UDP接收的有效字节数 单位:byte 
wire          [15:0]    tx_byte_num   	        ;   //UDP发送的有效字节数 单位:byte 
wire                    udp_tx_done   	        ;   //UDP发送完成信号
wire                    udp_tx_req    	        ;   //UDP读数据请求信号
wire          [ 7:0]    udp_tx_data   	        ;   //UDP待发送数据
wire                    tx_start_en   	        ;   //UDP发送开始使能信号wire          [7:0]	    rec_data			    ;   //FIFO写入数据
wire        		    rec_en			        ;   //FIFO写使能
wire        		    tx_req			        ;   //FIFO读使能
wire          [7:0]	    tx_data	    	        ;   //FIFO读出数据assign icmp_tx_start_en =   icmp_rec_pkt_done   ;   //ICMP 接收端结束标志,作为 ICMP发送端开始标志
assign icmp_tx_byte_num =   icmp_rec_byte_num   ;   //ICMP 接收端数据个数,作为 ICMP发送端发送数据 assign tx_start_en      =   rec_pkt_done        ;   //UDP 接收端结束标志,作为 UDP发送开始使能信号
assign tx_byte_num      =   rec_byte_num        ;   //UDP 接收端数据个数,作为 UDP发送端发送数据个数assign des_mac          =   src_mac             ;   //ARP 接收到的 源MAC,作为 ICMP\UDP 目的MAC,实际为电脑端MAC
assign des_ip           =   src_ip              ;   //ARP 接收到的 源IP ,作为 ICMP\UDP 目的IP ,实际为电脑端IP//数据位于异步FIFO之中,如需单独使用一侧功能,可以修改FIFO数据//需要注意写入有效数据数量要与此处相同,一定要注意 数据个数与FIFO读出数据对齐!!!!!!! //MMCM/PLL 产生200Mhz时钟--> gmii2rgmii
clk_wiz_0 u_clk_wiz_0
(.clk_out1           (clk_200m           ),      // output clk_out1.reset              (~sys_rst_n         ),      // input reset.locked             (locked             ),      // output locked.clk_in1            (eth_rxc            )       // PHY侧提供eth_rxc时钟125Mhz
);  //GMII接口转RGMII接口
gmii_to_rgmii 
#(.IDELAY_VALUE       (IDELAY_VALUE       )
)      
u_gmii_to_rgmii(        .idelay_clk         (clk_200m           ),      //IDELAY时钟//以太网GMII接口    .gmii_rx_clk        (gmii_rx_clk        ),      //GMII接收时钟.gmii_rx_dv         (gmii_rx_dv         ),      //GMII接收数据有效信号.gmii_rxd           (gmii_rxd           ),      //GMII接收数据.gmii_tx_clk        (gmii_tx_clk        ),      //GMII发送时钟.gmii_tx_en         (gmii_tx_en         ),      //GMII发送数据使能信号.gmii_txd           (gmii_txd           ),      //GMII发送数据   //以太网RGMII接口   .rgmii_rxc          (eth_rxc            ),      //RGMII接收时钟.rgmii_rx_ctl       (eth_rx_ctl         ),      //RGMII接收数据控制信号.rgmii_rxd          (eth_rxd            ),      //RGMII接收数据.rgmii_txc          (eth_txc            ),      //RGMII发送时钟    .rgmii_tx_ctl       (eth_tx_ctl         ),      //RGMII发送数据控制信号.rgmii_txd          (eth_txd            )       //RGMII发送数据   
);//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接口  //input.gmii_rx_clk        (gmii_rx_clk	    ),      //GMII接收数据时钟.gmii_rx_dv         (gmii_rx_dv 	    ),      //GMII输入数据有效信号.gmii_rxd           (gmii_rxd   	    ),      //GMII输入数据.gmii_tx_clk        (gmii_tx_clk	    ),      //GMII发送数据时钟//output.gmii_tx_en         (arp_gmii_tx_en     ),      //GMII输出数据有效信号.gmii_txd           (arp_gmii_txd       ),      //GMII输出数据         //用户接口                           //output.arp_rx_done        (arp_rx_done	    ),      //ARP接收完成信号.arp_rx_type        (arp_rx_type	    ),      //ARP接收类型 0:请求  1:应答.src_mac            (src_mac    	    ),      //接收到目的MAC地址.src_ip             (src_ip     	    ),      //接收到目的IP地址 //input   .arp_tx_en          (arp_tx_en  	    ),      //ARP发送使能信号.arp_tx_type        (arp_tx_type	    ),      //ARP发送类型 0:请求  1:应答.des_mac            (des_mac    	    ),      //发送的目标MAC地址.des_ip             (des_ip     	    ),      //发送的目标IP地址//output.tx_done            (arp_tx_done	    )       //以太网发送完成信号    
);  //ICMP通信  
icmp                                             
#(.BOARD_MAC          (BOARD_MAC          ),      //参数例化.BOARD_IP           (BOARD_IP           ),.DES_MAC            (DES_MAC            ),.DES_IP             (DES_IP             )
)
u_icmp(.rst_n              (sys_rst_n   	    ),      //复位信号,低电平有效//GMII接口//input.gmii_rx_clk        (gmii_rx_clk 	    ),      //GMII接收数据时钟         .gmii_rx_dv         (gmii_rx_dv  	    ),      //GMII输入数据有效信号       .gmii_rxd           (gmii_rxd    	    ),      //GMII输入数据                 .gmii_tx_clk        (gmii_tx_clk 	    ),      //GMII发送数据时钟//output.gmii_tx_en         (icmp_gmii_tx_en	),      //GMII输出数据有效信号       .gmii_txd           (icmp_gmii_txd	    ),      //GMII输出数据//用户接口//output.rec_pkt_done       (icmp_rec_pkt_done  ),      //以太网单包数据接收完成信号  .rec_en             (icmp_rec_en        ), 	    //以太网接收的数据使能信号				  .rec_data           (icmp_rec_data      ),      //以太网接收的数据				 	    .rec_byte_num       (icmp_rec_byte_num  ),      //以太网接收的有效字节数 单位:byte   //input.tx_start_en        (icmp_tx_start_en   ),      //以太网开始发送信号      .tx_data            (icmp_tx_data       ),      //以太网待发送数据					     .tx_byte_num        (icmp_tx_byte_num   ),      //以太网发送的有效字节数 单位:byte.des_mac            (des_mac     	    ),      //发送的目标MAC地址.des_ip             (des_ip      	    ),      //发送的目标IP地址  //output.tx_done            (icmp_tx_done	    ),      //以太网发送完成信号      .tx_req             (icmp_tx_req        )       //读数据请求信号					     
); //UDP通信
udp                                             
#(.BOARD_MAC          (BOARD_MAC          ),      //参数例化.BOARD_IP           (BOARD_IP           ),.DES_MAC            (DES_MAC            ),.DES_IP             (DES_IP             )
)
u_udp(.rst_n              (sys_rst_n          ),      //复位信号,低电平有效//GMII接口//input.gmii_rx_clk        (gmii_rx_clk        ),      //GMII接收数据时钟 .gmii_rx_dv         (gmii_rx_dv         ),      //GMII输入数据有效信号.gmii_rxd           (gmii_rxd           ),      //GMII输入数据.gmii_tx_clk        (gmii_tx_clk        ),      //GMII发送数据时钟   //output .gmii_tx_en         (udp_gmii_tx_en     ),      //GMII输出数据有效信号.gmii_txd           (udp_gmii_txd       ),      //GMII输出数据 //用户接口//outpur.rec_pkt_done       (rec_pkt_done       ),      //以太网单包数据接收完成信号 .rec_en             (udp_rec_en         ),      //以太网接收的数据使能信号.rec_data           (udp_rec_data       ),      //以太网接收的数据      .rec_byte_num       (rec_byte_num       ),      //以太网接收的有效字节数 单位:byte      //input.tx_start_en        (tx_start_en        ),      //以太网开始发送信号      .tx_data            (udp_tx_data        ),      //以太网待发送数据        .tx_byte_num        (tx_byte_num        ),      //以太网发送的有效字节数 单位:byte      .des_mac            (des_mac            ),      //发送的目标MAC地址      .des_ip             (des_ip             ),      //发送的目标IP地址    //output .tx_done            (udp_tx_done        ),      //以太网发送完成信号 .tx_req             (udp_tx_req         )       //读数据请求信号   
); //异步FIFO,实际做同步FIFO使用
async_fifo_2048x8b u_async_fifo_2048x8b (//input.rst                (~sys_rst_n	        ),      //input wire rst.wr_clk             (gmii_rx_clk        ),  	//input wire wr_clk.rd_clk             (gmii_rx_clk        ),  	//input wire rd_clk.din                (rec_data	        ),      //input wire [7 : 0] din.wr_en              (rec_en		        ),    	//input wire wr_en.rd_en              (tx_req		        ),    	//input wire rd_en//output.dout               (tx_data	        ),      //output wire [7 : 0] dout.full               (                   ),      //output wire full.empty              (                   )    	//output wire empty
);//以太网控制模块
eth_ctrl u_eth_ctrl(//input.clk            	(gmii_rx_clk	    ),      //时钟.rst_n          	(sys_rst_n		    ),      //系统复位信号,低电平有效 //ARP相关端口信号 //input.arp_rx_done    	(arp_rx_done   	    ),      //ARP接收完成信号.arp_rx_type    	(arp_rx_type   	    ),      //ARP接收类型 0:请求  1:应答.arp_tx_done    	(arp_tx_done   	    ),      //ARP发送完成信号.arp_gmii_tx_en 	(arp_gmii_tx_en	    ),      //ARP GMII输出数据有效信号 .arp_gmii_txd   	(arp_gmii_txd  	    ),      //ARP GMII输出数据//output.arp_tx_en      	(arp_tx_en     	    ),      //ARP发送使能信号.arp_tx_type    	(arp_tx_type   	    ),      //ARP发送类型 0:请求  1:应答//ICMP相关端口信号//input.icmp_tx_start_en	(icmp_tx_start_en   ),      //ICMP开始发送信号.icmp_tx_done		(icmp_tx_done	    ),      //ICMP发送完成信号.icmp_gmii_tx_en	(icmp_gmii_tx_en    ),      //ICMP GMII输出数据有效信号  .icmp_gmii_txd		(icmp_gmii_txd	    ),      //ICMP GMII输出数据 //ICMP fifo接口信号//input.icmp_rec_en       	(icmp_rec_en        ),      //ICMP接收的数据使能信号.icmp_rec_data     	(icmp_rec_data      ),      //ICMP接收的数据.icmp_tx_req       	(icmp_tx_req        ),      //ICMP读数据请求信号//output.icmp_tx_data      	(icmp_tx_data       ),      //ICMP待发送数据//UDP相关端口信号//input.udp_tx_start_en	(tx_start_en   	    ),      //UDP开始发送信号.udp_tx_done    	(udp_tx_done   	    ),      //UDP发送完成信号    .udp_gmii_tx_en 	(udp_gmii_tx_en	    ),      //UDP GMII输出数据有效信号  .udp_gmii_txd   	(udp_gmii_txd  	    ),      //UDP GMII输出数据   //UDP fifo接口信号//input.udp_rec_data		(udp_rec_data	    ),      //UDP接收的数据		.udp_rec_en			(udp_rec_en		    ),      //UDP接收的数据使能信号     .udp_tx_req			(udp_tx_req		    ),      //UDP读数据请求信号   //output .udp_tx_data		(udp_tx_data	    ),      //UDP待发送数据		//fifo接口信号//output.rec_data			(rec_data	        ),      //待发送的数据	.rec_en	        	(rec_en	            ),      //读数据请求信号 .tx_req	        	(tx_req	            ),      //接收的数据使能信号//input.tx_data	    	(tx_data	        ),      //接收的数据//GMII发送引脚  //output.gmii_tx_en     	(gmii_tx_en    	    ),      //GMII输出数据有效信号 .gmii_txd       	(gmii_txd      	    )       //GMII输出数据 
);      endmodule

(2)代码框架

3、资源消耗情况

五、下载验证

ping测试:

网口环回测试:

 

六、福利获取

后台私信   UDP协议分析表,即可获得 UDP协议分析表原件!!!!

七、工程移植、源码获取请后台私信

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com