概述

管理MII接口的MDIO接口是一个双线的串行接口,用来对PHY芯片等物理层信息进行操作管理

MDIO
MDIO(Management Data Input/Output),对G比特以太网而言,串行通信总线称为管理数据输入输出 (MDIO)。
MDIO由两根线组成,MDC线是数据的随路时钟,最高速率可达几MHz(各PHY芯片有异)。MDIO线是数据的输入输出双向总线,数据是与MDC时钟同步的。
MDIO前后有两种协议, 包括之前的Clause22 以及之后为了弥补Clause22 寄存器空间不足而出的Clause45, Clause 45 向前兼容Clause 22。

Clause 22

Clause 22 的时序图如下:


STA:Station Management
MMD:MDIO Managed Device

PRE:帧前导码,为32个连续“1”比特。
ST:帧开始标志, Clause22 的开始标志为比特“01”。
OP:操作码,CL22中比特“10”表示此帧为一读操作帧,比特“01”表示此帧为一写操作帧。
PHYAD:MMD的物理地址,5个比特,每个MMD都把自己的地址与这5个比特进行比较,若匹配则响应后面的操作,若不匹配,则忽略掉后面的操作。
REGAD:用来选MMD的32个寄存器中的某个寄存器的地址。
TA:状态转换域,若为读操作,则第一比特时MDIO为高阻态,第二比特时由MMD使MDIO置“0”。若为写操作,则MDIO仍由STA控制,连续输出“10”两个比特。
DATA:帧的寄存器的数据域,16比特,若为读操作,则为MMD送到STA的数据,若为写操作,则为STA送到MMD数据。
IDLE:帧结束后的空闲状态,此时MDIO无源驱动,处高阻状态。

Clause 45

Clause 45 的时序图如下:

STA:Station Management
MMD:MDIO Managed Device

PRE:帧前导码,为32个连续“1”比特。
ST:帧开始标志, 为了区别CL22,Clause45 的开始标志为比特“00”。
OP:操作码,Clause45有4种操作码,比特“00”表示设置当前寄存器地址,比特“01”表示写当前寄存器。比特“10”表示读当前寄存器,比特“11”表示读当前寄存器读完后把当前寄存器的值加1,用于顺序读。
PRTAD:Port Address,端口地址, 也称物理地址。
DEVAD:器件地址,CL45新增概念,各值与器件对应如下。

REGAD:用来选MMD的65536个寄存器中的某个寄存器的地址。
TA:状态转换域,若为读操作,则第一比特时MDIO为高阻态,第二比特时由MMD使MDIO置“0”。若为写操作,则MDIO仍由STA控制,连续输出“10”两个比特。
DATA:帧的寄存器的数据域,16比特,若为读操作,则为MMD送到STA的数据,若为写操作,则为STA送到MMD数据。
IDLE:帧结束后的空闲状态,此时MDIO无源驱动,处高阻状态。

Problems with the MDIO
当MDIO通信出现问题,可依次检查以下方面

确保MDC工作在合适的频率
确保MDC以及MDIO有上拉
PHYAD(PRTAD)没有搞错。
MMD 没有处于复位状态。
适当调整MDC的相位。
有些MMD要求帧与帧之间一定要用高阻态分隔
STA MDIO 接口 Verilog 代码如下

 `timescale 1ns / 1ps//// Company: // Engineer: // // Create Date: 2019/08/12 10:39:51// Design Name: // Module Name: eth_mdio_interface// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:  //      //module eth_mdio_interface #(parameter MDC_DIVISOR = 100      MDC frequency is clk_i / MDC_DIVISOR.  )(input               clk_i,input               rstn_i,input               clause_sel_i,1 : Clause 45;  0 : Clause 22;output  reg         ready_o,input               valid_i,input   [1:0]       cmd_i,input   [25:0]      addr_i,      Cl45: PHY Addr(5 bit) + Devices Addr(5 bit) + Reg Addr(16 bit); Cl22 : PHY Addr(5 bit) + Reg Addr(5 bit) + invalid(16 bit)//input   [15:0]      wdata_i,  output  reg         rdata_vld_o,output  reg [15:0]  rdata_o,output  reg         mdc_o,input               mdio_i,output  reg         mdio_o,output  reg         mdio_oen_o);localparam  WR_CMD = 2'b01;localparam  RD_CMD = 2'b11; localparam  RD_INC = 2'b10;  not supported//---------------------------------------------------------------------------------------------------// Function - Calculates the log2ceil of the input value//---------------------------------------------------------------------------------------------------function integer log2ceil;input integer val;integer i;begini = 1;log2ceil = 0;while (i < val) beginlog2ceil = log2ceil + 1;i = i << 1; endendendfunction  localparam P_MDC_DIVIDE_BITS = log2ceil(MDC_DIVISOR) - 1;    // Need to count to (MDC_DIVISOR/2) - 1   reg [P_MDC_DIVIDE_BITS-1:0] mdc_divide;  reg mdc_tick;     reg mdc_sample;   Divide clock to make MDIO clock  always @(posedge clk_i, negedge rstn_i) if(!rstn_i)mdc_divide <= 0;else if(mdc_divide == 0)      mdc_divide <= (MDC_DIVISOR/2) - 1'b1;else mdc_divide <= mdc_divide - 1'b1;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)    mdc_o <= 1'b0;else if(mdc_divide == 0)mdc_o <= ~mdc_o;Data is output on mdc_tick. Delay it slightly from the clock to ensure setup and hold timing is metSample read data just before rising edge of MDCalways @(posedge clk_i, negedge rstn_i)if(!rstn_i) beginmdc_tick <= 1'b0;mdc_sample <= 1'b0;endelse beginmdc_tick <= ~mdc_o & (mdc_divide==(MDC_DIVISOR/2) - (MDC_DIVISOR/4));mdc_sample <= ~mdc_o & (mdc_divide==2);endwire   [4:0]    cl45_phy_addr = addr_i[25:21];           wire   [4:0]    cl45_dev_addr = addr_i[20:16];           wire   [15:0]   cl45_reg_addr = addr_i[15:0];          wire   [4:0]    cl22_phy_addr = addr_i[25:21];              wire   [4:0]    cl22_reg_addr = addr_i[20:16];                                                                           reg    [3:0]    state;localparam      ST_PREAMBLE1        = 4'd0;localparam      ST_IDLE1            = 4'd1;localparam      ST_WR_ADDR_CL45     = 4'd2;localparam      ST_IDLE2            = 4'd3;localparam      ST_PREAMBLE2        = 4'd4;localparam      ST_REWR_ADDR_CL45   = 4'd5;localparam      ST_WR_ADDR_CL22     = 4'd6;localparam      ST_WR_DATA          = 4'd7;localparam      ST_RD_DATA          = 4'd8;wire  preamble_set_done;wire  wr_addr_cl45_done;wire  wr_addr_cl22_done;wire  rewr_addr_cl45_done;wire  wr_data_done;wire  rd_data_done;reg   wr_rdn_en;reg   cmd_pending;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)state <= ST_IDLE1;else  case (state)ST_IDLE1               :   if(cmd_pending && mdc_tick)state <= ST_PREAMBLE1; else state <= ST_IDLE1;ST_PREAMBLE1           :   if(preamble_set_done)     state <= clause_sel_i? ST_WR_ADDR_CL45 : ST_WR_ADDR_CL22;else state <= ST_PREAMBLE1;                              ST_WR_ADDR_CL45        :   if(wr_addr_cl45_done)state <= ST_IDLE2;else state <= ST_WR_ADDR_CL45;ST_IDLE2               :   if(mdc_tick)    state <= ST_PREAMBLE2;else state <= ST_IDLE2;                           ST_PREAMBLE2           :   if(preamble_set_done)state <= ST_REWR_ADDR_CL45;else state <= ST_PREAMBLE2;ST_REWR_ADDR_CL45      :   if(rewr_addr_cl45_done)state <= wr_rdn_en? ST_WR_DATA : ST_RD_DATA;  else state <= ST_REWR_ADDR_CL45;ST_WR_ADDR_CL22        :   if(wr_addr_cl22_done)state <= wr_rdn_en? ST_WR_DATA : ST_RD_DATA;   else state <= ST_WR_ADDR_CL22;                          ST_WR_DATA             :   if(wr_data_done)                               state <= ST_IDLE1;else state <= ST_WR_DATA;                                 ST_RD_DATA             :   if(rd_data_done)   state <= ST_IDLE1;else state <= ST_RD_DATA;       default                :   state <= ST_IDLE1;endcasewire latch_en;assign latch_en = (ready_o && valid_i);  wait mdc_tick to startalways @(posedge clk_i, negedge rstn_i)if(!rstn_i)cmd_pending <= 1'b0;else if(latch_en)cmd_pending <= 1'b1;else if(mdc_tick)cmd_pending <= 1'b0;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)wr_rdn_en <= 1'b0;else if(latch_en)wr_rdn_en <= (cmd_i == WR_CMD);reg [5:0]  preamble_cnt;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)preamble_cnt <= 6'b0;else if(state != ST_PREAMBLE1 && state != ST_PREAMBLE2)   preamble_cnt <= 6'b0; else if(mdc_tick)preamble_cnt <= preamble_cnt + 6'b1;assign preamble_set_done = (preamble_cnt == 6'd31) && mdc_tick;reg [5:0] wr_addr_cl45_cnt;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)wr_addr_cl45_cnt <= 6'b0;else if(state != ST_WR_ADDR_CL45)wr_addr_cl45_cnt <= 6'b0;else if(mdc_tick)wr_addr_cl45_cnt <= wr_addr_cl45_cnt + 6'b1;assign wr_addr_cl45_done = (wr_addr_cl45_cnt == 6'd31) && mdc_tick; reg [4:0] rewr_addr_cl45_cnt;  always @(posedge clk_i, negedge rstn_i)if(!rstn_i)rewr_addr_cl45_cnt <= 5'b0;else if(state != ST_REWR_ADDR_CL45)      rewr_addr_cl45_cnt <= 5'b0;else if(mdc_tick)rewr_addr_cl45_cnt <= rewr_addr_cl45_cnt + 5'b1;assign rewr_addr_cl45_done = (rewr_addr_cl45_cnt == 5'd13) && mdc_tick;reg [4:0] wr_addr_cl22_cnt;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)wr_addr_cl22_cnt <= 5'b0;else if(state != ST_WR_ADDR_CL22)wr_addr_cl22_cnt <= 5'b0;else if(mdc_tick)wr_addr_cl22_cnt <= wr_addr_cl22_cnt + 5'b1;assign wr_addr_cl22_done = (wr_addr_cl22_cnt == 5'd13) && mdc_tick;reg [4:0] wr_data_cnt;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)wr_data_cnt <= 5'b0;else if(state != ST_WR_DATA)wr_data_cnt <= 5'b0;else if(mdc_tick)wr_data_cnt <= wr_data_cnt + 5'b1;assign wr_data_done = (wr_data_cnt == 5'd17) && mdc_tick;reg [4:0] rd_data_cnt;always @(posedge clk_i, negedge rstn_i)if(!rstn_i)rd_data_cnt <= 5'b0;else if(state != ST_RD_DATA)rd_data_cnt <= 5'b0;else if(mdc_tick)rd_data_cnt <= rd_data_cnt + 5'b1;assign rd_data_done = (rd_data_cnt == 5'd17) && mdc_tick; always @(posedge clk_i, negedge rstn_i)if(!rstn_i)ready_o = 1'b0;else ready_o = (state == ST_IDLE1) && (!valid_i) && (!cmd_pending);reg [1:0] op_code_cl45;always @(*)case (cmd_i)WR_CMD : op_code_cl45 = 2'b01;RD_CMD : op_code_cl45 = 2'b11;RD_INC : op_code_cl45 = 2'b10;default : op_code_cl45 = 2'b11;endcasereg [1:0] op_code_cl22;always @(*)case (cmd_i)WR_CMD : op_code_cl22 = 2'b01;RD_CMD : op_code_cl22 = 2'b10;default : op_code_cl22 = 2'b11;endcasereg [31:0] first_wraddr_sfr_cl45;always @(posedge clk_i)if(latch_en)first_wraddr_sfr_cl45 <= {2'b00, 2'b00, cl45_phy_addr, cl45_dev_addr, 2'b10, cl45_reg_addr};else if((state == ST_WR_ADDR_CL45) && mdc_tick)first_wraddr_sfr_cl45 <= {first_wraddr_sfr_cl45[30:0], 1'b0};reg [13:0] second_wraddr_sfr_cl45;always @(posedge clk_i)if(latch_en)second_wraddr_sfr_cl45 <= {2'b00, op_code_cl45, cl45_phy_addr, cl45_dev_addr};else if((state == ST_REWR_ADDR_CL45) && mdc_tick)second_wraddr_sfr_cl45 <= {second_wraddr_sfr_cl45[12:0], 1'b0};reg [13:0]  wraddr_sfr_cl22;always @(posedge clk_i)  if(latch_en)wraddr_sfr_cl22 <= {2'b01, op_code_cl22, cl22_phy_addr, cl22_reg_addr};else if((state == ST_WR_ADDR_CL22) && mdc_tick)wraddr_sfr_cl22 <= {wraddr_sfr_cl22[12:0], 1'b0};reg [17:0] wrdata_sfr;always @(posedge clk_i)if(latch_en)wrdata_sfr <= {2'b10, wdata_i};else if((state == ST_WR_DATA) && mdc_tick)      wrdata_sfr <= {wrdata_sfr[16:0], 1'b0};reg [15:0] rddata_sfr;always @(posedge clk_i)if((state == ST_RD_DATA) && mdc_sample)  rddata_sfr <= {rddata_sfr[14:0], mdio_i};always @(posedge clk_i, negedge rstn_i)if(!rstn_i)mdio_o <= 1'b0;else case (state)ST_WR_ADDR_CL45    : mdio_o <= first_wraddr_sfr_cl45[31];ST_REWR_ADDR_CL45  : mdio_o <= second_wraddr_sfr_cl45[13];ST_WR_ADDR_CL22    : mdio_o <= wraddr_sfr_cl22[13];ST_WR_DATA         : mdio_o <= wrdata_sfr[17];default            : mdio_o <= 1'b1;endcasealways @(posedge clk_i, negedge rstn_i)if(!rstn_i)mdio_oen_o <= 1'b1;else mdio_oen_o <= (state != ST_RD_DATA)&&(state != ST_IDLE1)&&(state != ST_IDLE2);always @(posedge clk_i, negedge rstn_i)if(!rstn_i) beginrdata_vld_o <= 1'b0;rdata_o <= 16'b0;endelse if(rd_data_done) beginrdata_vld_o <= 1'b1;rdata_o <= rddata_sfr;endelse beginrdata_vld_o <= 1'b0;rdata_o <= rdata_o;endendmodule


实际使用时抓取的波形


————————————————
原文链接:https://blog.csdn.net/yhs18200259681/article/details/99652701

PHY之MDIO解析相关推荐

  1. Linux 网卡驱动 PHY Mac MDIO kernel 驱动讲解 (未完待续)

    前言 会从网卡的硬件结构讲解,然后再到 kernel 驱动调用的讲解 我用Xilinx Zu2cg开发板的实际举例,一般嵌入式设备肯定会预留网口,用作调试开发,组网通讯使用,那么开发板的意义在哪 意义 ...

  2. Linux系统网卡驱动phy工作原理解析

    Linux网卡驱动架构 MAC控制器驱动是芯片厂商集成在SDK中 比如三星控制器.ATMEL控制器,这部分驱动厂商已经写好了, linux下自带通用phy驱动phy_device.c(phy层协议是通 ...

  3. 以太网PHY 开发与解析

    目录 1.PHY芯片介绍 1.1 芯片引脚定义和说明 1.2 PHY芯片功能说明 1.3 供电管理 1.4 寄存器说明 1.4.1 控制寄存器 1.4.2 状态寄存器 1.4.3 PHY ID寄存器 ...

  4. 【NanoPi T2】 5.uboot gmac网卡驱动(1) - mac控制器,phy芯片,rgmii协议

    1.mac控制器,phy芯片,rgmii协议 2.寄存器介绍 3.驱动源码解析 4.nanopi t2 移植rtl8211e网卡驱动(首发) 硬件构成部分 以太网卡或者是ARM开发板的网络部分通常由M ...

  5. PHY驱动调试之 --- PHY控制器驱动(二)

    1. 前言 内核版本:linux 4.9.225,以freescale为例. 2. 概述 PHY芯片为OSI的最底层-物理层(Physical Layer),通过MII/GMII/RMII/SGMII ...

  6. emac接口与phy交互

    nuc970的emac接口 nuc970的EMAC以太网接口与PHY芯片之间的数据交换是通过MII(Media Independent Interface)或RMII(Reduced Media In ...

  7. 千兆网络PHY芯片 RTL8211E的实践应用(自我总结篇)

    这篇算是对FPGA做千兆以太网的电路搭建这一块儿的最全的扫盲篇了吧,废话不多说,直接上干货. 一.千兆以太网的系统搭建 1.硬件系统搭建 以太网MAC模块负责实现以太网MAC子层的功能,完成802.3 ...

  8. 【驱动】以太网扫盲(三)PHY的控制器驱动框架分析

    1. 概述 PHY芯片为OSI的最底层-物理层(Physical Layer),通过MII/GMII/RMII/SGMII/XGMII等多种媒体独立接口(介质无关接口)与数据链路层的MAC芯片相连,并 ...

  9. phy 驱动与 switch 驱动

    phy 驱动与 switch 驱动 phy 驱动 phy 与 cpu 的硬件连接 一般为 MAC-PHY 模式: ----------- | CPU | RGMII/| ------| MII --- ...

  10. MDIO/MDC接口

    http://xiaominwzj.blog.163.com/blog/static/24192202220153201132715/ MDIO接口,MAC与PHY间的管理接口(MII是数据接口),有 ...

最新文章

  1. 应用 | 红黄蓝的虐童惨案,其实可以用机器学习等技术来避免
  2. pandas基于条件判断更新dataframe中所有数据列数值内容的值(Conditionally updating all values in pandas Dataframe )
  3. 信息系统运维安全管理规定(可作为范文参考)
  4. poj3273---Monthly Expense
  5. Unable to find the ncurses libraries的解决办法
  6. enum in c language
  7. 第三篇:服务消费者(Feign)(Finchley版本)V2.0_dev
  8. 调账成功 对账失败处理流程反思
  9. [DFS|回溯法] leetcode 17 电话号码的字母组合
  10. dp在约会上是什么意思_dp是什么意思网络术语 饭圈为什么喜欢用缩写
  11. IDEA怎么设置背景图片
  12. Cloudflare DDNS梅林插件代码
  13. 字典(JSON)数据写入文件并换行,Python
  14. OBJECTS IN SEMANTIC TOPOLOGY
  15. Ubuntu部署TeamTalk文档
  16. npm install 安装软件,出现 operation not permitted, mkdir
  17. Java发送网易企业邮箱邮件
  18. 7.3 向量的数量积与向量积
  19. SQL Prompt 4试用
  20. 关于tp-link wr740 v4的刷机救砖的办法(非线刷解决)恢复原版的

热门文章

  1. Mixly 软件的基本应用
  2. SpringBoot整合editormd富文本编辑器
  3. 计算机应用基础教案 电子书,计算机应用基础教案(全套)-20210511075659.pdf-原创力文档...
  4. 视频教程-网页设计速成之Dreamweaver-Dreamweaver
  5. 【硬件】详解电流采样电路
  6. Cry with DX11
  7. 卡巴斯基蓝屏问题处理
  8. 布线工程-认识光纤和光缆
  9. 1.1、信息化和信息系统
  10. 区块链技术驱动商业银行开展供应链金融业务的创新路径