1.MDIO协议简介

  MAC和PHY芯片有一个配置接口,即MDIO接口。可以配置PHY芯片的工作模式以及获取PHY芯片的状态信息。PHY芯片内部有一系列寄存器。用户通过配置寄存器来配置PHY芯片的工作模式。
  FPGA通过MDIO接口对PHY芯片的内部寄存器进行配置。通常情况下芯片在默认情况下也可以工作,即配置芯片不是必须的。也可通过外接特殊引脚的方式来配置PHY芯片的工作模式。

2. MDIO协议时序

  MDIO接口也被称为SMI接口(Serial Management Interface,串行管理接口),包括ETH_MDC(数据管理时钟,最大不超过12.5MHZ)和ETH_MDIO(数据管理输入输出,双向数据线)两条信号线。
  MDIO接口的读写通信协议如下图:

名称1 作用
Preamble 32位引导码,由MAC端发送32位逻辑1,用于同步PHY芯片
ST(Start of Frame) 两位帧开始信号,用01表示
OP(Operation Code) 两位操作码,读:10 , 写:01
PHYAD 五位PHY地址,用于表示和那个PHY芯片通讯
REGAD(Register Address) 五位寄存器地址,可以表示32位寄存器
TA(Turnaround) 两位转向。在读命令中MDIO由MAC驱动改为PHY驱动。写命令中MAC固定输入01
data 读取PHYAD寄存器中对应的数据或者写入数据。高位在前低位在后
IDLE 空闲状态均为高阻态

转向就是MAC由发送数据变成接收数据


3.MDIO程序

`timescale 1ns / 1psmodule mdio_dri(input   wire            clk         ,input  wire            rst_n       ,input  wire            op_exec     ,   //触发开始信号input   wire            op_rh_wl    ,   //低电平写,高电平读input wire    [4:0]   op_phy_addr ,   //芯片地址input wire    [4:0]   op_reg_addr ,   //寄存器地址input    wire    [15:0]  op_wr_data  ,   //写数据output reg             op_done     ,   //操作完成output    reg     [15:0]  op_rd_data  ,   //读出的数据output   reg             op_rd_ack   ,   //读应答output reg             eth_mdc     ,inout  wire            eth_mdio
);localparam        SYS_CLK         =  'd50_000_000                   ;
localparam      DRI_CLK         =  'd12_500_000                   ;
localparam      DIV_CNT_MAX     =  (SYS_CLK/DRI_CLK  >> 1)  -  1     ;localparam         IDLE            =  6'b000_001;    //初始状态
localparam      PRE             =  6'b000_010;    //前导码  32位1
localparam      START           =  6'b000_100;    //发送帧开始加操作码
localparam      ADDR            =  6'b001_000;    //发送PHY地址加寄存器地址
localparam      WR              =  6'b010_000;    //发送TA加写入数据
localparam      RD              =  6'b100_000;    //发送TA加接收数据localparam       Pre             =  32'b1111_1111_1111_1111 ;  //前导码
localparam      ST              =  2'b01                  ;   //帧开始wire           mdio_in      ;  //mdio数据输入
reg             st_done      ;  //操作完成reg   [5:0]   state        ;  //状态机
reg             op_rh_wl_r   ;
reg     [5:0]   op_phy_addr_r;
reg     [5:0]   op_reg_addr_r;
reg     [15:0]  op_wr_data_r ;
reg             mdio_out     ;  //mdio数据输出
reg     [9:0]   clk_cnt      ;  //时钟计数器
reg             mdio_dir     ;  //mdio数据方向指示  0输入 1输出
reg     [1:0]   op_code      ;/********************ila模块*****************************/
wire    [255:0]     probe0;
assign probe0 = {  eth_mdc,mdio_out,mdio_in,mdio_dir,state,clk_cnt,op_code,op_rd_data,op_rh_wl,op_phy_addr,op_wr_data,st_done,op_reg_addr,op_rd_ack};
ila_0 ila_0_inst (.clk(clk), // input wire clk.probe0(probe0) // input wire [255:0] probe0
);
/********************************************************/
//双向IO
assign eth_mdio = mdio_dir ? mdio_out : 1'bz;
assign mdio_in  = eth_mdio;//eth_mdc   12.5MHZ    1   3时钟变化
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) begineth_mdc     <=      'd1;endelse if (state != IDLE && clk_cnt[0] == 1'b0) begineth_mdc  <=  ~eth_mdc;end
end//寄存器  当传输开始时将数据锁存起来
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginop_code         <= 'd0;op_phy_addr_r   <= 'd0;op_reg_addr_r   <= 'd0;op_wr_data_r    <= 'd0;endelse if (op_exec == 1'b1) beginop_code        <= {op_rh_wl,~op_rh_wl};//OP_CODE: 2'b01(写)  2'b10(读) op_phy_addr_r   <= op_phy_addr  ;op_reg_addr_r  <= op_reg_addr;op_wr_data_r <= op_wr_data ;end
end//状态转移
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginstate <= IDLE ;endelse  begincase(state)IDLE    :   beginif (op_exec == 1'b1) beginstate <= PRE ;endendPRE   :   beginif (st_done == 1'b1) beginstate <= START ;endendSTART   :   beginif (st_done == 1'b1) beginstate <= ADDR ;endendADDR     :   beginif (st_done == 1'b1 && op_code[1] == 1'b0) beginstate <= WR ;endelse if (st_done == 1'b1 && op_code[1] == 1'b1) beginstate <= RD ;endendWR         :   beginif (st_done == 1'b1) beginstate <= IDLE ;endendRD       :   beginif (st_done == 1'b1) beginstate <= IDLE ;endendendcaseend
end//状态输出
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginclk_cnt     <= 'd0;mdio_out    <= 1'b0;mdio_dir   <= 1'b0;op_done    <= 1'b0;st_done    <= 1'b0;op_rd_data     <= 16'b0;endelse  beginclk_cnt  <= clk_cnt + 1'b1;op_done  <= 1'b0;case(state)IDLE  :   beginclk_cnt    <= 'd0;mdio_dir    <= 'd0;mdio_out    <= 'd1;op_rd_ack   <= 1'b1;op_done    <= 1'b0;endPRE     :   begin   //前导码  发送32位1mdio_dir <= 1'b1;mdio_out <= 1'b1;if (clk_cnt == 4 * 32 - 2) beginst_done <= 1'b1;endelse if (clk_cnt == 4 * 32 - 1) beginst_done <= 1'b0;clk_cnt <= 'd0;endendSTART  :   begin   //帧开始加操作码mdio_dir <= 1'b1;case(clk_cnt)0   :   mdio_out    <=  1'b0       ;4  :   mdio_out    <=  1'b1       ;   //两位帧开始8    :   mdio_out    <=  op_code[1]  ;12     :   mdio_out    <=  op_code[0]  ;14  :  st_done     <=  1'b1       ;15     :   beginst_done    <=  1'b0   ;clk_cnt    <=  'd0    ;endendcaseendADDR  :   beginmdio_dir <= 1'b1;case(clk_cnt)0   :   mdio_out    <=  op_phy_addr_r[4]    ;4  :   mdio_out    <=  op_phy_addr_r[3]    ;8  :   mdio_out    <=  op_phy_addr_r[2]    ;12     :   mdio_out    <=  op_phy_addr_r[1]    ;16     :   mdio_out    <=  op_phy_addr_r[0]    ;   //PHY地址20   :   mdio_out    <=  op_reg_addr_r[4]    ;24     :   mdio_out    <=  op_reg_addr_r[3]    ;28     :   mdio_out    <=  op_reg_addr_r[2]    ;32     :   mdio_out    <=  op_reg_addr_r[1]    ;36     :   mdio_out    <=  op_reg_addr_r[0]    ;   //寄存器地址38   :   st_done     <=  1'b1               ;39  :  beginst_done    <=  1'b0;clk_cnt   <=   'b0;endendcaseendWR       :   beginmdio_dir <= 1'b1;case(clk_cnt)0   :   mdio_out    <=  1'b1            ;4     :   mdio_out    <=  1'b0            ;  //写操作 不转向 108   :   mdio_out    <=  op_wr_data_r[15] ;12    :   mdio_out    <=  op_wr_data_r[14] ;16    :   mdio_out    <=  op_wr_data_r[13] ;20    :   mdio_out    <=  op_wr_data_r[12] ;24    :   mdio_out    <=  op_wr_data_r[11] ;28    :   mdio_out    <=  op_wr_data_r[10] ;32    :   mdio_out    <=  op_wr_data_r[9]  ;36    :   mdio_out    <=  op_wr_data_r[8]  ;40    :   mdio_out    <=  op_wr_data_r[7]  ;44    :   mdio_out    <=  op_wr_data_r[6]  ;48    :   mdio_out    <=  op_wr_data_r[5]  ;52    :   mdio_out    <=  op_wr_data_r[4]  ;56    :   mdio_out    <=  op_wr_data_r[3]  ;60    :   mdio_out    <=  op_wr_data_r[2]  ;64    :   mdio_out    <=  op_wr_data_r[1]  ;68    :   mdio_out    <=  op_wr_data_r[0]  ;70    :   st_done     <=  1'b1           ;71     :   beginst_done    <= 1'b0 ;clk_cnt   <= 'd0  ;mdio_dir  <= 1'b0 ;op_done   <= 1'b1 ;mdio_out  <= 1'b1 ;endendcaseendRD       :   beginmdio_dir <= 1'b0;case(clk_cnt)2   :                                   ;   //等待转向6     :   op_rd_ack       <=  mdio_in     ;   //转向完成  应答信号拉低代表应答成功  10    :   op_rd_data[15]  <=  mdio_in     ;   14  :   op_rd_data[14]  <=  mdio_in     ;18     :   op_rd_data[13]  <=  mdio_in     ;22     :   op_rd_data[12]  <=  mdio_in     ;26     :   op_rd_data[11]  <=  mdio_in     ;30     :   op_rd_data[10]  <=  mdio_in     ;34     :   op_rd_data[9]   <=  mdio_in     ;38     :   op_rd_data[8]   <=  mdio_in     ;42     :   op_rd_data[7]   <=  mdio_in     ;46     :   op_rd_data[6]   <=  mdio_in     ;50     :   op_rd_data[5]   <=  mdio_in     ;54     :   op_rd_data[4]   <=  mdio_in     ;58     :   op_rd_data[3]   <=  mdio_in     ;62     :   op_rd_data[2]   <=  mdio_in     ;66     :   op_rd_data[1]   <=  mdio_in     ;70     :   op_rd_data[0]   <=  mdio_in     ;72     :   st_done         <=  1'b1       ;73     :   beginst_done    <=  1'b0               ;clk_cnt    <=  'd0                ;mdio_dir   <=  'd0                ;   //高阻mdio_out    <=  'd1                ;op_done    <=  1'b1               ;endendcase endendcaseend
end
endmodule

千兆以太网(二)——MDIO接口协议相关推荐

  1. 哈工大毕设体验记录-使用ZYNQ MPSoC开发板实现的Linux环境千兆以太网C语言UDP协议批量文件存取(上)

    写在前面:本文仅为一位哈工大本科学生的毕设过程记录(吐槽),可参考性有限,供后来的广大学弟学妹们参考一下吧,我趟过的坑别再跳了. 字体区别:黑色加粗为文章结构脉络表述,红色为必须明确的重点,绿色为次重 ...

  2. 华为无线网代理服务器端口是什么意思,华为ES1D2G48SFA0 48端口十兆/百兆/千兆以太网电接口板(FA,RJ45) (适用于华为S7700系列交换机)...

    S7700基本描述 LE0BN66EDC N66E直流总装机柜(共4路40A输出,单路最大1600W,600X600X2200mm) LE0BN66EAC N66E交流总装机柜(共8路10A输出,单路 ...

  3. 迅为IMX6开发板支持全网通4G模块丨GPS模块丨WIFI蓝牙丨千兆以太网

    迅为i.MX6开发板丨迅为i.MX6Q开发板丨四核imx6开发板丨Cortec-A9开发板丨资料介绍: 特点: 处理器:Freescale Cortex-A9四核i.MX6Q主频1GHz 核心板配置: ...

  4. 千兆以太网TCP协议的FPGA实现。

    千兆以太网TCP协议的FPGA实现 Lzx 2017/4/20 写在前面,这应该是我大四最后一个工程性的作品了,以后要养成写文档记录的习惯.说明下,本工程为纯verilog实现的硬件TCP收发器,不同 ...

  5. 国产FPGA(紫光同创)—— 数据采集及千兆以太网传输(二)

    科研需要,使用国产FPGA(紫光PLG50H)实现数据采集及千兆以太网传输.总体流程如图所示 数据采集完成后,第二部分就需要千兆以太网实现数据传输. 一.硬件部分 开发板上通过Realtek RTL8 ...

  6. 千兆以太网PHY芯片调试-88E1111(RGMII接口-数据收发ECHO测试) Verilog实现python测试

    千兆以太网PHY芯片调试-基于RGMII接口的88E1111(数据收发ECHO测试) 先放结果: Py测试代码: import socket #网络通信 TCP,UDP DST_IP = '192.1 ...

  7. 基于Xilinx artix 7的FPGA高级应用(二):千兆以太网通信(原理篇)

    本项目是基于Xilinx Artix7 XC7A35T芯片 以太网芯片选用的是RTL8211EG PHY芯片 MAC 和PHY接口标准是GMII 开发工具是vivado 2018.3 FPGA高级应用 ...

  8. 千兆以太网工程(高速接口)

    <千兆以太网>是高速接口必修课程, 从课程中学习FPGA模块划分,熟悉高速以太网接口逻辑. 包括:包括TCP IP 协议.ARP 协议.UDP IP MAC 协议解析,MAC IP 核的生 ...

  9. xilinx千兆以太网与万兆以太网IP接口

    说明:对于IP核输出数据的解析最好的工具就是其自带的仿真文件,里面既将接收的数据进行了解析,又将发送给IP核的数据进行了封装,这对于了解数据结构和协议是十分有帮助的,以太网如此,pcie.ram.fi ...

  10. 以太网物理层协议整理(1)-百兆/千兆以太网

    1) 物理层各子层功能 Reconciliation Sublayer (RS): 协调子层.汇聚功能,使不同介质类型对MAC子层透明 Medium Independent Interface (MI ...

最新文章

  1. 从图(Graph)到图卷积(Graph Convolution):漫谈图 神经⽹络模型 (⼀)
  2. 3168串口java_电子称串口读取数据(转)
  3. WINCE6.0+S3C2443下WatchDog学习
  4. matplotlib新版本下的霍兰德人格分析雷达图
  5. mysql8 grant语法失效
  6. JS检测浏览器是否最大化
  7. 从源码角度看Spark on yarn client cluster模式的本质区别
  8. java 编译 注释_Java编译、注释、常量简介
  9. 源码:Java集合源码之:哈希表(二)
  10. Radius协议简单介绍
  11. 在各级供应商的表达中,OEM,Tier One (Tier 1),Tier Two (Tier 2)的概念和区别
  12. Java开发报表——Grid++Report 报表设计器
  13. 【Typora】实用使用技巧
  14. 插入法排序c语言程序,C语言直接插入排序算法
  15. Ensight后处理软件显示网格
  16. 环境实验耐高温、耐低温、温度变化、恒定湿热、湿热循环
  17. 软装设计配饰色彩搭配教程
  18. 被误解的 Node.js
  19. PyCharm恢复初始设置
  20. jQuery-1.9.1源码分析系列(七) 钩子(hooks)机制及浏览器兼容

热门文章

  1. Windows7系统环境变量path的配置方法
  2. [天地间]02-瑞士达沃斯小镇
  3. 局计算机房制度,岳阳市统计局机房管理制度
  4. 光伏窗性能研究(2)——光伏窗性能研究方法和过程
  5. 【问题集合】3dsMax贴图模糊(2016)
  6. 西点军校的经典法则(转载)
  7. 千斤顶装配图怎么画_机械制图——绘制千斤顶装配图教程.ppt
  8. [Asp.Net WebApi]WebApi入门
  9. python读二进制文件遍历_使用python反向读取二进制文件
  10. linux_systemd启动方式解析,如何开机自动登录,开机自动运行程序