文档详情

通过MDIO接口管理PHY芯片的验证设计方案

ji****81
实名认证
店铺
DOCX
801.25KB
约25页
文档ID:272420667
通过MDIO接口管理PHY芯片的验证设计方案_第1页
1/25

       通过MDIO接口管理PHY芯片的验证设计方案                       作者:没落骑士一、前言本文设计思想采用明德扬至简设计法以太网这一高效实用的数据传输方式应用于各个领域,如网络交换设备,高速网络相机等虽然各FPGA厂商都提供MAC IP核,但大多收费,有时无法破解不同厂家之间无法移植,而且为了通用性考虑牺牲了效率,因此自己动手写一个以太网MAC是个不错的选择本博文讨论通过MDIO接口管理PHY芯片来验证其正确工作,为在此基础上设计MAC逻辑开个头PHY芯片采用RTL8211EGVB,选用GMII接口与MAC连接下面我们来开始第一步,在此之前明确设计目的:检测PHY芯片是否完成自动协商 链路速率是否达到1000M所以要从datasheet中了解到芯片引脚 寄存器地址 接口时序二、设计分析管理帧格式如下:读写操作时序:MDC为MAC驱动时钟信号,MDIO是串行数据总线,需要连接上拉电阻保证idle状态下高电平其中前导码包含32个比特“1”,PHY地址根据芯片引脚连接而定,此处为01.turn around域是为了防止读操作时数据冲突,在读操作过程中MAC和PHY均在第1比特处进入高阻态,PHY在第2比特处驱动MDIO接口为低电平以占据总线控制权。

注意两点:第一如果时钟信号在读写操作后停止,时钟必须保证至少7个时钟周期持续翻转且MDIO高电平从而保证之前的操作完成故在设计中可以等待一段时间后再拉低时钟使能信号第二两个操作之间至少一个idle比特正确驱动接口时序需要关注AC characterisics.很明显MAC驱动总线时,在MDC下降沿更新数据而PHY驱动总线时,MDC上升沿后更新数据根据datasheet中的timing参数设定MDC时钟周期是800ns,MAC接收PHY数据时下降沿采样接下来关注要访问的内部寄存器地址,首先读取PHY寄存器数据以检测其工作状态,若发现异常再考虑写入数据这里读取基本模式状态寄存器0X01的bit5,若为1说明自动协商完成第二个寄存器是PHY特定状态寄存器0X11中的[15:14]和13,分别是当前速率和全/半双工通信模式若检测到自动协商完成,且工作在1000M全双工模式下,说明工作正确三、硬件架构与状态机设计所有准备工作完成,现在开始设计按照“自顶向下”设计原则,规划好整体结构和模块间接口,再设计内部状态机一步步实现逻辑功能Mdio_ctrl模块负责完成PHY芯片的配置与检测逻辑,Mdio接口模块完成读写操作时序。

此处仅通过读操作简单检测PHY状态,暂不进行配置,故两模块工作状态跳转如图所示:剩下的工作就是把两个状态机实现出来,非常简单有需要的朋友可以参考一下,关于芯片的具体参数详见:Realtek RTL8211E(G)-VB(VL)-CG Datasheet 1.8.上代码!四、代码编写MDIO控制模块:`timescale 1ns / 1psmodule mdio_ctrl(input clk,//100Minput rst_n,input en,output reg chk_result =0,output reg chk_vld =0,input rdy,output reg rd_en =0,output reg [5-1:0] phy_addr =0,output reg [5-1:0] reg_addr =0,input [16-1:0] rd_data,input rd_vld);parameter MS_CYC = 100_000;localparam IDLE = 0 ;localparam WAIT = 1 ;localparam RD_PHY = 2 ;localparam CHECK = 3 ;localparam WAIT_MS = 10;localparam BMSR = 5'h01,PHYSR = 5'h11;reg [4-1:0] state_c = 0,state_n = 0;wire idle2wait,wait2rd_phy,rd_phy2check,check2idle,check2wait;wire link_up;reg [16-1:0] rd_memory [0:1];reg [ (17-1):0] ms_cnt =0 ;wire add_ms_cnt ;wire end_ms_cnt ;reg [ (4-1):0] wait_cnt =0 ;wire add_wait_cnt ;wire end_wait_cnt ;reg [ (2-1):0] rd_cnt =0 ;wire add_rd_cnt ;wire end_rd_cnt ;reg [ (2-1):0] rdata_cnt =0 ;wire add_rdata_cnt ;wire end_rdata_cnt ;wire [5*2-1:0] registers;reg rd_finish = 0;initial beginrd_memory[0] = 0;rd_memory[1] = 0;endalways @(posedge clk or negedge rst_n) beginif (rst_n==0) beginstate_c endelse beginstate_c endendalways @(*) begincase(state_c)IDLE :beginif(idle2wait)state_n = WAIT ;elsestate_n = state_c ;endWAIT :beginif(wait2rd_phy)state_n = RD_PHY ;elsestate_n = state_c ;endRD_PHY :beginif(rd_phy2check)state_n = CHECK ;elsestate_n = state_c ;endCHECK :beginif(check2idle)state_n = IDLE ;else if(check2wait)state_n = WAIT ;elsestate_n = state_c ;enddefault : state_n = IDLE ;endcaseendassign idle2wait = state_c==IDLE && (en);assign wait2rd_phy = state_c==WAIT && (end_wait_cnt);assign rd_phy2check = state_c==RD_PHY && (end_rdata_cnt);assign check2idle = state_c==CHECK && (link_up);assign check2wait = state_c==CHECK && (!link_up);assign link_up = rd_memory[0][5] == 1'b1 && rd_memory[1][15:13] == 3'b10_1;//auto_nego && gigabit && full_duplex//计数器always @(posedge clk or negedge rst_n) beginif (rst_n==0) beginms_cnt endelse if(add_ms_cnt) beginif(end_ms_cnt)ms_cnt elsems_cnt endendassign add_ms_cnt = (state_c == WAIT);assign end_ms_cnt = add_ms_cnt && ms_cnt == (MS_CYC)-1 ;//100MHZ时钟100_000always @(posedge clk or negedge rst_n) beginif (rst_n==0) beginwait_cnt endelse if(add_wait_cnt) beginif(end_wait_cnt)wait_cnt elsewait_cnt endendassign add_wait_cnt = (end_ms_cnt);assign end_wait_cnt = add_wait_cnt && wait_cnt == (WAIT_MS)-1 ;always @(posedge clk or negedge rst_n) beginif (rst_n==0) beginrd_cnt endelse if(add_rd_cnt) beginif(end_rd_cnt)rd_cnt elserd_cnt endendassign add_rd_cnt = (state_c == RD_PHY && rdy && !rd_finish);assign end_rd_cnt = add_rd_cnt && rd_cnt == (2)-1 ;always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginrd_finish endelse if(end_rd_cnt)beginrd_finish endelse if(state_c == CHECK)rd_finish endalways @(posedge clk or negedge rst_n) beginif (rst_n==0) beginrdata_cnt endelse if(add_rdata_cnt) beginif(end_rdata_cnt)rdata_cnt elserdata_cnt endendassign add_rdata_cnt = (rd_vld);assign end_rdata_cnt = add_rdata_cnt && rdata_cnt == (2)-1 ;//接口信号逻辑always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginrd_en phy_addr reg_addr endelse if(add_rd_cnt)beginrd_en phy_addr reg_addr endelse beginrd_en phy_addr reg_addr endendassign registers = {BMSR,PHYSR};//5'h01,5'h11always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginrd_memory[0] rd_memory[1] endelse if(add_rdata_cnt)beginrd_memory[rdata_cnt] endend//用户侧输出检测结果always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginchk_vld endelse if(state_c ==。

下载提示
相似文档
正为您匹配相似的精品文档