欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 以太网通信--读取物理层PHY芯片的状态

以太网通信--读取物理层PHY芯片的状态

2025/2/6 12:46:50 来源:https://blog.csdn.net/qq_44830822/article/details/144718067  浏览:    关键词:以太网通信--读取物理层PHY芯片的状态

PHY芯片通过MDIO接口进行读写,框图如下所示:

原理很简单,就是按照时序将PHY芯片的指定寄存器信息读出或者写入。

MDC时钟需要输出到PHY芯片,一般不低于80MHz。

MDIO是双向接口,FPGA读出状态信息时为输入,FPGA写入控制信息时为输出。

基本时序如下:(来源正点原子)

编码:(使用状态机实现对PHY芯片0x11地址的特殊寄存器的状态读操作)

module mdio_interface (input wire        clk,         // FPGA涓绘椂閽?input wire        reset_n,     // 澶嶄綅淇″彿锛屼綆鏈夋晥output reg        mdc,         // MDC鏃堕挓	涓嶈秴杩?12.5MHz 80nsinout              mdio         // MDIO鍙屽悜鏁版嵁绾?
);reg [2:0] clk_div;
always @ (posedge clk or negedge reset_n) beginif (!reset_n) beginclk_div <= 3'd0;end else if (clk_div == 3'd3) beginclk_div <= 3'd0;end else beginclk_div <= clk_div + 1;end
endalways @ (posedge clk or negedge reset_n) beginif (!reset_n) beginmdc <= 0;end else if (clk_div == 3'd2) begin		//120ns鍛ㄦ湡mdc <= ~mdc;end else beginmdc <= mdc;end
endreg mdio_dir;	//0璇?1鍐?
reg mdio_out;	//
assign mdio = mdio_dir ? mdio_out : 1'bz;parameter IDLE = 8'b00000001;
parameter PREAMBLE = 8'b00000010;	//鍙戦??32浣?1 鍓嶅鐮?
parameter START = 8'b00000100;
parameter OPCODE = 8'b00001000;
parameter PHYADDR = 8'b00010000;
parameter REGADDR = 8'b00100000;
parameter TURNDIR = 8'b01000000;
parameter READ = 8'b10000000;reg [7:0] state,next_state;
reg [7:0] cnt;
always @ (posedge mdc or negedge reset_n) beginif (!reset_n) beginstate <= IDLE;end else beginstate <= next_state;end
endinitial beginnext_state = IDLE;
endalways @ (*) begincase (state)IDLE:		next_state = PREAMBLE;PREAMBLE:	if (cnt == 8'd32) beginnext_state = START;end else beginnext_state = PREAMBLE;endSTART:		if (cnt == 8'd34) beginnext_state = OPCODE;end else beginnext_state = START;endOPCODE:		if (cnt == 8'd36) beginnext_state = PHYADDR;end else beginnext_state = OPCODE;endPHYADDR:	if (cnt == 8'd41) beginnext_state = REGADDR;end else beginnext_state = PHYADDR;endREGADDR:	if (cnt == 8'd46) beginnext_state = TURNDIR;end else beginnext_state = REGADDR;endTURNDIR:	if (cnt == 8'd48) beginnext_state = READ;end else beginnext_state = TURNDIR;endREAD:		if (cnt == 8'd65) beginnext_state = IDLE;end else beginnext_state = READ;endendcase
endreg [15:0] data_out; 
always @ (posedge mdc or negedge reset_n) beginif (!reset_n) begincnt <= 8'd0;mdio_dir <= 1'd0;mdio_out <= 1'd0;data_out <= 16'd0;end else begincase(state)IDLE:		begincnt <= 8'd0;mdio_dir <= 1'd0;mdio_out <= 1'd0;data_out <= 16'd0;end PREAMBLE:	begincnt <= cnt + 1;mdio_dir <= 1'd1;	//鍙戦?佸墠瀵肩爜锛屽啓32浣?1mdio_out <= 1'd1;endSTART:		begincnt <= cnt + 1; mdio_out <= (cnt == 8'd33 ? 0 : 1);		//鍥哄畾01endOPCODE:		begincnt <= cnt + 1;mdio_out <= (cnt == 8'd35 ? 1 : 0);		//璇?10 鍐?01endPHYADDR:	begincnt <= cnt + 1;case (cnt) 8'd37:	mdio_out <= 0;8'd38:	mdio_out <= 0;8'd39:	mdio_out <= 1;8'd40:	mdio_out <= 0;8'd41:	mdio_out <= 0;endcaseendREGADDR:	begincnt <= cnt + 1;case (cnt) 8'd42:	mdio_out <= 1;	//10001瀵勫瓨鍣?8'd43:	mdio_out <= 0;8'd44:	mdio_out <= 0;8'd45:	mdio_out <= 0;8'd46:	mdio_out <= 1;endcaseendTURNDIR:	begin		//璇籞0 鍐?10cnt <= cnt + 1;mdio_out <= (cnt == 8'd47 ? 1'bz : 0);endREAD:		beginmdio_dir <= 1'd0;cnt <= cnt + 1;data_out <= {data_out[14:0],mdio};endendcaseend
endila_1 ila1 (.clk(clk), // input wire clk.probe0(state), // input wire [7:0]  probe0  .probe1(cnt), // input wire [7:0]  probe1 .probe2(next_state), // input wire [7:0]  probe2.probe3(data_out),.probe4(mdio), // input wire [0:0]  probe4 .probe5(mdio_out) // input wire [0:0]  probe5
);endmodule

仿真截图:

可以看出,前32位前导码均为1,在cnt==33时,下两个时钟周期为01即start信号,在cnt==35时,下两个周期即OPCODE信号为10,即读操作,PHY物理地址为00100,这和芯片设计有关,寄存器地址是10001,选取的是特殊寄存器地址,读出的数据是0xbc40。

该寄存器的高四位为1011,高两位对应10即1000Mbps,验证:

链路速率确实为1Gbps,包括

链路实时状态位为1,连接状态。没问题。

代码只实现了读操作,写操作是一样的,有待读者自己完善。

接下来要实现ARP、UDP等通信协议。

 

版权声明:

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

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