ci mdio.v

This commit is contained in:
yunlongLi 2024-11-13 09:18:02 +08:00
parent 54474aa1df
commit 3d8c285ac0
1 changed files with 263 additions and 0 deletions

263
protocol/mdio.v Normal file
View File

@ -0,0 +1,263 @@
//==========================================================
//--Author : colonel
//--Date : 11-11
//--Module : mdio
//--Function: mdio contains the send and receiver
//--Ref: https://blog.csdn.net/yingyu12345/article/details/126129452
//==========================================================
module MDIO(
//==========================< 端口 >=========================
input rst,
input clk,
output reg mdc,
inout mdio,
input start , //开始传输标志 高电平有效结束传输后拉低
input [1:0] opcode ,
input [4:0] phy_addr , //phy address
input [4:0] reg_addr , //phy register address
input [15:0] write_data , //write smi data
output reg [15:0] phy_reg , //read smi data
output reg transfer_end //write or read finished
);
//==========================< 信号 >=========================
reg mdio_oe;
reg mdio_out;
wire mdio_in;
assign mdio = mdio_oe ? mdio_out : 1'bz ;// MDIO数据输出或高阻, 0-READ,1-WRITE
assign mdio_in = mdio;
//产生MDC 时钟
parameter NUM=49; //50M/100=500k
reg [5:0] cnt;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
cnt<=0;
mdc<=0;
end
else if (cnt==NUM)
begin
cnt<=0;
mdc<=mdc+1;
end
else
begin
cnt<=cnt+1;
end
end
//数据流上升沿有效
parameter preamble = 8'b00000001;
parameter st = 8'b00000010;
parameter op = 8'b00000100;
parameter phyad = 8'b00001000;
parameter regad = 8'b00010000;
parameter ta = 8'b00100000;
parameter data = 8'b01000000;
parameter idle = 8'b10000000;
//检测上升沿产生开始传输脉冲
reg start_next;
wire start_edge;
always @(posedge mdc or negedge rst)
begin
if(!rst)
begin
start_next<=0;
end
else
start_next<=start;
end
assign start_edge=!start_next & start;
//状态转移
reg [7:0] state,state_next;
always @(posedge mdc or negedge rst )
begin
if(!rst)
begin
state<=idle;
end
else if(start_edge)
begin
state<=preamble;
end
else
state<=state_next;
end
//接口数据缓存
reg [1:0] st_code; //mdio start code
reg [1:0] ta_code ; //mdio write code
reg [1:0] op_code;
reg [4:0] regaddr;
reg [4:0] phyaddr;
reg [15:0] writedata;
reg [7:0] counter;
always @(posedge mdc or negedge rst)
begin
if(!rst)
begin
counter<=0;
end
else if(counter==64)
begin
counter<=0;
transfer_end<=1;
end
else if(state!=idle)
begin
transfer_end<=0;
counter<=counter+1;
end
end
always @(negedge mdc)
begin
state_next<=state;
case(state)
preamble:
begin
st_code<= 2'b01 ;
ta_code<= 2'b10 ;
op_code<=opcode;//缓存
regaddr<=reg_addr;
phyaddr<=phy_addr;
writedata<=write_data;
mdio_oe<=1;
mdio_out<=1;
if(counter==31)
begin
state_next<=st;
end
end
st:
begin
mdio_oe<=1;
mdio_out<=st_code[1];
st_code<=st_code<<1;
if(counter==33)
begin
state_next<=op;
end
end
op:
begin
mdio_oe<=1;
mdio_out<=op_code[1];
op_code<=op_code<<1;
if(counter==35)
begin
state_next<=phyad;
end
end
phyad:
begin
mdio_oe<=1;
mdio_out<=phyaddr[4];
phyaddr<=phyaddr<<1;
if(counter==40)
begin
state_next<=regad;
end
end
regad:
begin
mdio_oe<=1;
mdio_out<=regaddr[4];
regaddr<=regaddr<<1;
if(counter==45)
begin
state_next<=ta;
end
end
ta:
begin
if(opcode==2'b10)
begin
mdio_oe<=0;
if(counter==47)
begin
state_next<=data;
end
end
if(opcode==2'b01)
begin
mdio_oe<=1;
mdio_out<=ta_code[1];
ta_code<=ta_code<<1;
if(counter==47)
begin
state_next<=data;
end
end
end
data:
begin
if(opcode==2'b10)//读取
begin
mdio_oe<=0;
//读取放到外面
if(counter==63)
begin
state_next<=idle;
end
end
if(opcode==2'b01)//写入
begin
mdio_oe<=1;
mdio_out<=writedata[15];
writedata<=writedata<<1;
if(counter==63)
begin
state_next<=idle;
end
end
end
idle:
begin
mdio_oe<=0;
if(counter==64)
begin
state_next<=idle;
end
end
default:
begin
state_next<=idle;
end
endcase
end
//读取数据
always @(posedge mdc or negedge rst )
begin
if(!rst)
begin
phy_reg<=0;
end
else if(state_next==data )
begin
phy_reg<={phy_reg[14:0],mdio_in};
end
else
phy_reg<=phy_reg;
end
endmodule