1.MDIO協(xié)議簡介
??MAC和PHY芯片有一個(gè)配置接口,即MDIO接口。可以配置PHY芯片的工作模式以及獲取PHY芯片的狀態(tài)信息。PHY芯片內(nèi)部有一系列寄存器。用戶通過配置寄存器來配置PHY芯片的工作模式。
??FPGA通過MDIO接口對(duì)PHY芯片的內(nèi)部寄存器進(jìn)行配置。通常情況下芯片在默認(rèn)情況下也可以工作,即配置芯片不是必須的。也可通過外接特殊引腳的方式來配置PHY芯片的工作模式。
2. MDIO協(xié)議時(shí)序
??MDIO接口也被稱為SMI接口(Serial Management Interface,串行管理接口),包括ETH_MDC(數(shù)據(jù)管理時(shí)鐘,最大不超過12.5MHZ)和ETH_MDIO(數(shù)據(jù)管理輸入輸出,雙向數(shù)據(jù)線)兩條信號(hào)線。
??MDIO接口的讀寫通信協(xié)議如下圖:文章來源:http://www.zghlxwxcb.cn/news/detail-807630.html
名稱1 | 作用 |
---|---|
Preamble | 32位引導(dǎo)碼,由MAC端發(fā)送32位邏輯1,用于同步PHY芯片 |
ST(Start of Frame) | 兩位幀開始信號(hào),用01表示 |
OP(Operation Code) | 兩位操作碼,讀:10 , 寫:01 |
PHYAD | 五位PHY地址,用于表示和那個(gè)PHY芯片通訊 |
REGAD(Register Address) | 五位寄存器地址,可以表示32位寄存器 |
TA(Turnaround) | 兩位轉(zhuǎn)向。在讀命令中MDIO由MAC驅(qū)動(dòng)改為PHY驅(qū)動(dòng)。寫命令中MAC固定輸入01 |
data | 讀取PHYAD寄存器中對(duì)應(yīng)的數(shù)據(jù)或者寫入數(shù)據(jù)。高位在前低位在后 |
IDLE | 空閑狀態(tài)均為高阻態(tài) |
轉(zhuǎn)向就是MAC由發(fā)送數(shù)據(jù)變成接收數(shù)據(jù)文章來源地址http://www.zghlxwxcb.cn/news/detail-807630.html
3.MDIO程序
`timescale 1ns / 1ps
module mdio_dri(
input wire clk ,
input wire rst_n ,
input wire op_exec , //觸發(fā)開始信號(hào)
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 , //寫數(shù)據(jù)
output reg op_done , //操作完成
output reg [15:0] op_rd_data , //讀出的數(shù)據(jù)
output reg op_rd_ack , //讀應(yīng)答
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; //初始狀態(tài)
localparam PRE = 6'b000_010; //前導(dǎo)碼 32位1
localparam START = 6'b000_100; //發(fā)送幀開始加操作碼
localparam ADDR = 6'b001_000; //發(fā)送PHY地址加寄存器地址
localparam WR = 6'b010_000; //發(fā)送TA加寫入數(shù)據(jù)
localparam RD = 6'b100_000; //發(fā)送TA加接收數(shù)據(jù)
localparam Pre = 32'b1111_1111_1111_1111 ; //前導(dǎo)碼
localparam ST = 2'b01 ; //幀開始
wire mdio_in ; //mdio數(shù)據(jù)輸入
reg st_done ; //操作完成
reg [5:0] state ; //狀態(tài)機(jī)
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數(shù)據(jù)輸出
reg [9:0] clk_cnt ; //時(shí)鐘計(jì)數(shù)器
reg mdio_dir ; //mdio數(shù)據(jù)方向指示 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時(shí)鐘變化
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
eth_mdc <= 'd1;
end
else if (state != IDLE && clk_cnt[0] == 1'b0) begin
eth_mdc <= ~eth_mdc;
end
end
//寄存器 當(dāng)傳輸開始時(shí)將數(shù)據(jù)鎖存起來
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
op_code <= 'd0;
op_phy_addr_r <= 'd0;
op_reg_addr_r <= 'd0;
op_wr_data_r <= 'd0;
end
else if (op_exec == 1'b1) begin
op_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
//狀態(tài)轉(zhuǎn)移
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
state <= IDLE ;
end
else begin
case(state)
IDLE : begin
if (op_exec == 1'b1) begin
state <= PRE ;
end
end
PRE : begin
if (st_done == 1'b1) begin
state <= START ;
end
end
START : begin
if (st_done == 1'b1) begin
state <= ADDR ;
end
end
ADDR : begin
if (st_done == 1'b1 && op_code[1] == 1'b0) begin
state <= WR ;
end
else if (st_done == 1'b1 && op_code[1] == 1'b1) begin
state <= RD ;
end
end
WR : begin
if (st_done == 1'b1) begin
state <= IDLE ;
end
end
RD : begin
if (st_done == 1'b1) begin
state <= IDLE ;
end
end
endcase
end
end
//狀態(tài)輸出
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
clk_cnt <= 'd0;
mdio_out <= 1'b0;
mdio_dir <= 1'b0;
op_done <= 1'b0;
st_done <= 1'b0;
op_rd_data <= 16'b0;
end
else begin
clk_cnt <= clk_cnt + 1'b1;
op_done <= 1'b0;
case(state)
IDLE : begin
clk_cnt <= 'd0;
mdio_dir <= 'd0;
mdio_out <= 'd1;
op_rd_ack <= 1'b1;
op_done <= 1'b0;
end
PRE : begin //前導(dǎo)碼 發(fā)送32位1
mdio_dir <= 1'b1;
mdio_out <= 1'b1;
if (clk_cnt == 4 * 32 - 2) begin
st_done <= 1'b1;
end
else if (clk_cnt == 4 * 32 - 1) begin
st_done <= 1'b0;
clk_cnt <= 'd0;
end
end
START : 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 : begin
st_done <= 1'b0 ;
clk_cnt <= 'd0 ;
end
endcase
end
ADDR : begin
mdio_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 : begin
st_done <= 1'b0;
clk_cnt <= 'b0;
end
endcase
end
WR : begin
mdio_dir <= 1'b1;
case(clk_cnt)
0 : mdio_out <= 1'b1 ;
4 : mdio_out <= 1'b0 ; //寫操作 不轉(zhuǎn)向 10
8 : 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 : begin
st_done <= 1'b0 ;
clk_cnt <= 'd0 ;
mdio_dir <= 1'b0 ;
op_done <= 1'b1 ;
mdio_out <= 1'b1 ;
end
endcase
end
RD : begin
mdio_dir <= 1'b0;
case(clk_cnt)
2 : ; //等待轉(zhuǎn)向
6 : op_rd_ack <= mdio_in ; //轉(zhuǎn)向完成 應(yīng)答信號(hào)拉低代表應(yīng)答成功
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 : begin
st_done <= 1'b0 ;
clk_cnt <= 'd0 ;
mdio_dir <= 'd0 ; //高阻
mdio_out <= 'd1 ;
op_done <= 1'b1 ;
end
endcase
end
endcase
end
end
endmodule
到了這里,關(guān)于千兆以太網(wǎng)(二)——MDIO接口協(xié)議的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!