通信协议之MDIO读写的FPGA实现
介绍
MAC与PHY之间的通信通过了MDIO的接口
与PHY芯片的通信则通过MAC(Media Access Control)控制器来实现。MAC控制器与PHY芯片之间的通信通常包括两部分:
1.数据传输接口
:比如MII(Media Independent Interface)、RMII(Reduced Media Independent Interface)、GMII(Gigabit Media Independent Interface)等,用于传输实际的数据包。
2.管理接口
:MDIO接口和MDC(Management Data Clock)用于对PHY芯片进行配置、状态监控和管理。通过MDIO接口,MAC控制器可以访问PHY芯片的寄存器,读取和修改PHY的工作模式、状态等信息。
MDIO接口的作用
MDIO接口是标准的IEEE 802.3规范定义的,用于在MAC和PHY之间进行管理和配置的低速控制通道。其主要功能包括:
- 配置PHY寄存器:通过MDIO接口,可以设置PHY的工作模式(如速度、双工模式等)。
- 读取PHY状态:MAC可以通过MDIO接口查询PHY的状态,如链路是否建立、连接速率等。
工作原理
MDIO接口由两条信号线组成: - MDC(Management Data Clock):时钟信号,由MAC控制器生成,用于同步MDIO数据传输。
- MDIO(Management Data Input/Output):双向数据线,用于传输PHY寄存器地址、数据等信息。
通过MDIO接口,MAC控制器可以在PHY芯片的多个寄存器之间进行读写操作,从而实现对PHY的管理。
MDIO接口的传输格式:
Preamble:32 位前导码,由 MAC 端发送 32 位逻辑“1”,用于同步 PHY 芯片。
ST(Start of Frame):2 位帧开始信号,用 01 表示。
OP(Operation Code):2 位操作码,读:10 写:01。
PHYAD(PHY Address):5 位 PHY 地址,用于表示与哪个 PHY 芯片通信,因此一个 MAC 上可以连
接多个 PHY 芯片。
REGAD(Register Address):5 位寄存器地址,可以表示 32 个寄存器。
TA(Turnaround):2 位转向,在读命令中,MDIO 在此时由 MAC 驱动改为 PHY 驱动,在第一个 TA
位,MDIO 引脚为高阻状态,第二个 TA 位,PHY 将 MDIO 引脚拉低,准备发送数据;在写命令中,不需
要 MDIO 方向发生变化,MAC 固定输出 2’b10,随后开始写入数据。
DATA:16 位数据,在读命令中,PHY 芯片将对应的 PHYAD 的 REGAD 寄存器的数据写到 DATA 中;
在写命令中,PHY 芯片将接收到的 DATA 写入 REGAD 寄存器中。需要注意的是,在 DATA 传输的过程中,
高位在前,低位在后。
IDLE:空闲状态,此时 MDIO 为无源驱动,处于高阻状态,但一般用上拉电阻使其上拉至高电平。
其实不过是读还是写,都是在时钟的上升沿完成采样,在下降沿完成对数据的更新。只是不同的是,读数据需要将后面的控制权切换给PHY芯片,而写是完整的MAC控制。
verilog代码
mdo_rw_test.v — top
module mdio_rw_test(
input sys_clk ,
input sys_rst_n,
//MDIO接口
output eth_mdc , //PHY管理接口的时钟信号
inout eth_mdio , //PHY管理接口的双向数据信号
output eth_rst_n, //以太网复位信号
input touch_key, //触摸按键
output [1:0] led //LED连接速率指示
);
//wire define
wire op_exec ; //触发开始信号
wire op_rh_wl ; //低电平写,高电平读
wire [4:0] op_addr ; //寄存器地址
wire [15:0] op_wr_data ; //写入寄存器的数据
wire op_done ; //读写完成
wire [15:0] op_rd_data ; //读出的数据
wire op_rd_ack ; //读应答信号 0:应答 1:未应答
wire dri_clk ; //驱动时钟
//硬件复位
assign eth_rst_n = sys_rst_n;
//MDIO接口驱动
mdio_dri #(
.PHY_ADDR (5'h04), //PHY地址 3'b100
.CLK_DIV (6'd10) //分频系数
)
u_mdio_dri(
.clk (sys_clk),
.rst_n (sys_rst_n),
.op_exec (op_exec ),
.op_rh_wl (op_rh_wl ),
.op_addr (op_addr ),
.op_wr_data (op_wr_data),
.op_done (op_done ),
.op_rd_data (op_rd_data),
.op_rd_ack (op_rd_ack ),
.dri_clk (dri_clk ),
.eth_mdc (eth_mdc ),
.eth_mdio (eth_mdio )
);
//MDIO接口读写控制
mdio_ctrl u_mdio_ctrl(
.clk (dri_clk),
.rst_n (sys_rst_n ),
.soft_rst_trig (touch_key ),
.op_done (op_done ),
.op_rd_data (op_rd_data),
.op_rd_ack (op_rd_ack ),