RGMII_PHY测试笔记1 基于开发板MiS603-X25
作者:汤金元
日期:20150817
公司:南京米联电子科技有限公司
博客:http://blog.chinaaet.com/detail/46639
论坛:www.osrc.cn
网店:http://osrc.taobao.com
网络通信对于本人来说一直很神秘,没有搞过10M网络,也没有搞过100M网络,更没有搞过千兆网络,更不要说RGMII了。但是今天本人成功了,实现0到RGMII突破。如果,兄弟你觉得有难度,我告诉你,你也行的,下面就开始见证本人徒步学习RGMII千兆网络部分的苦逼经历。今天主要完成PHY的测试。
何为RGMII ?
RGMII(Reduced Gigabit Media Independent Interface)是Reduced GMII(吉比特介质独立接口)。RGMII均采用4位数据接口,工作时钟125MHz,并且在上升沿和下降沿同时传输数据,因此传输速率可达1000Mbps。同时兼容MII所规定的10/100 Mbps工作方式,支持传输速率:10M/100M/1000Mb/s ,其对应clk 信号分别为:2.5MHz/25MHz/125MHz。RGMII数据结构符合IEEE以太网标准,接口定义见IEEE 802.3-2000。
采用RGMII的目的是降低电路成本,使实现这种接口的器件的引脚数从25个减少到14个。
RGMII接口定义?
发送器:
◎ GTX_CLK——吉比特TX..信号的时钟信号(125MHz)
◎ TXD[3..0]——被发送数据
◎ TX_CTL——发送控制
注:在千兆速率下,向PHY提供GTX_CLK信号,TXD、TXEN、TXER信号与此时钟信号同步。否则,在10/100M速率下,PHY提供 TXCLK时钟信号,其它信号与此信号同步。其工作频率为25MHz(100M网络)或2.5MHz(10M网络)。
接收器:
◎ RX_CLK——接收时钟信号(从收到的数据中提取,因此与GTXCLK无关联)
◎ RXD[3..0]——接收数据
◎ RX_CTL——接收控制
◎ COL——冲突检测(仅用于半双工状态)
◎ CRS——载波监听
管理配置(控制和状态信息):
◎ MDC——配置接口时钟
◎ MDIO——配置接口I/O
RGMII接口相对于GMII接口,在TXD和RXD上总共减少8根数据线。
RGMII通信时序?
发送器:
◎ TX_CLK
吉比特TX..信号的时钟信号(125MHz)
◎ TXD[3..0]
发送数据
TX_CLK高电平输出数据低4位,低电平输出数据高四位。
◎ TX_CTL
—发送控制
TX_CLK高电平期间为1表示发送使能,TX_CLK低电平期间为1表示发送正确
接收器:
◎ RX_CLK
吉比特RX..信号的时钟信号(125MHz)
◎ RXD[3..0]
接收数据
RX_CLK高电平接收数据低4位,低电平接收数据高四位。
◎ RX_CTL
—接收控制
RX_CLK高电平期间为1表示接收使能,RX_CLK低电平期间为1表示接收正确
TX_CTL和RX_CTL是数据同步机制,可以理解为同步信号
RGMII 硬件方案-VSC8601
VITESSE公司的VSC8601是一颗支持10/100/1000M PHY的RGMII MAC接口芯片,此芯片价格便宜,淘宝价格大概十几元一颗,另外封装是TQFP64 封装,只有64个PIN外围简单,焊接调试方便,功耗低,支持3.3V的IO接口,算是RGMII方案中首选无二的IC了。
VSC8601应用方案
RGMII 硬件接口
硬件电路原理图
由于时钟速度125MHZ 双边沿采样,对硬件要求很高,PCB必须等长布线
好了,具备这些硬件知识就可以设计程序了。
一下本人把一些设计要点列出来,读者具体看程序
1、产生至少1MS 复位信号,如果没有产生这个信号,那么PHY芯片不会工作
//generate PHY reset signal
reg[22:0]rgmii_rst_cnt=0;
assign rgmii_rst_n_o=rgmii_rst_cnt[22];
always @(posedge CLK_50MHZ_i)begin
if(!rgmii_rst_cnt[22])rgmii_rst_cnt<=rgmii_rst_cnt+1'b1;
End
2、为了实现上下沿都进行采样,关于一些原语的基础知识
ILOGIC2资源
图ILOGIC2逻辑框图,它可支持以下功能。
边沿触发D型触发器。
IDDR(NONE、C0或C1)模式。
锁存器。
异步/组合逻辑。
(1) 异步/组合逻辑。
当有下列情况之一时,软件会自动生成组合通路,使输入驱动器与FPGA内部逻辑资源直接连接。
FPGA的输入数据与内部逻辑直接相连,而没有用寄存器。
“打包I/O寄存器/锁存器到IOB中”的属性设置为OFF。
(2) IDDR模式。
Spartan-6器件的ILOGIC2中有专用寄存器来实现输入双倍数据速率(DDR)寄存器。可以通过例化IDDR2的原语来使用此功能。
DDR2的属性DDR_ALIGNMENT有3种模式:NONE、C0和C1。
在NONE模式下,输入DDR时序如图2-40所示。寄存器在C0上升沿将输入数据D寄存到Q0,C1上升沿将下一输入数据D寄存到Q1。
图2-40 DDR_ALIGNMENT=NONE时输入DDR时序示意图
在某些情况下,输入数据必须同步到一个时钟域里,通常C0同步。但是在频率比较高的情况下,这种同步相对比较困难,因为有效时间仅为时钟周期的一半(50%占空比的情况下)。Spartan-6器件中的IDDR2包含了专用的逻辑,可以在ILOGIC2内部进行时钟域的同步。
当DDR_ALIGNMENT为C0(或C1),信号Q0(Q1)在C1(C0)再次寄存,通过内部互联将输入数据同步到同一时钟域。时序图如图2-41所示。
图2-41 DDR_ALIGNMENT=C0\C1 的输入DDR
IDDR 的原语如图2-42 所示。
图2-42 IDDR2 的原语
OLOGIC2 资源
如图2-43所示,OLOGIC2主要由两部分组成,分别是输出数据路径和三态控制路径。
这两个部分可以配置成以下模式。
边沿触发D 型触发器。
DDR 模式(NONE、C0 或C1 同步方式)。
电平敏感锁存器。
异步/组合逻辑。
图2-43 OLOGIC2 逻辑模块
(1) 组合数据输出和三态控制路径。
当有下列情况之一时,软件会自动生成组合通路,将FPGA 内部数据直接输出到输出驱动器或驱动器的控制端。
“打包I/O 寄存器/锁存器到IOB 中”的属性设置为OFF。
(2) ODDR模式。
Spartan-6器件的OLOGIC2中具有专用寄存器,用来实现DDR输出寄存器。例化ODDR2原语可以使用此功能。当使用OLOGIC2时,会自动使用多路复用器,多路复用器的控制端产生于时钟信号,不需要手动控制。ODDR2 有两个时钟输入,相位差180°。
ODDR2 支持以下操作模式。
NONE 模式:允许设计人员在C0 和C1 时钟的上升沿将两个数据通过DDR多路复用器送
至输出引脚,如图2-44所示。·
图2-44 DDR_ALIGNMENT=NONE 下的ODDR2
C0模式:在时钟C0上升沿时,将两个数据通过DDR多路复用器送至输出引脚。
C1模式:在时钟C1上升沿时,将两个数据通过DDR多路复用器送至输出引脚。
ODDR原语如图2-45所示。
图2-45 ODDR原语
原语应用-双边沿采样
//use IDDR2 sample data with poseadge and negadge
IDDR2 #(
.DDR_ALIGNMENT("C0"),
.INIT_Q0(1'b0),
.INIT_Q1(1'b0),
.SRTYPE("SYNC")
)
Iddr2_0(
.Q0(gmii_rxd[4]), // 1-bit output captured with C0 clock
.Q1(gmii_rxd[0]), // 1-bit output captured with C1 clock
.C0(rgmii_rxclk_n), // 1-bit clock input
.C1(rgmii_rxclk_i), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D(rgmii_rxd_i[0]), // 1-bit ddr data input
.R(1'b0), // 1-bit reset input
.S(1'b0) // 1-bit set input
);
原语应用双边沿输出
//usb ODDR2 output data with posadge and neadge
assign rgmii_txdv_o = gmii_txdv;
ODDR2 #(
.DDR_ALIGNMENT("C0"), // Sets output alignment to "NONE", "C0" or "C1"
.INIT(1'b0), // Sets initial state of the Q output to 1'b0 or 1'b1
.SRTYPE("ASYNC") // Specifies "SYNC" or "ASYNC" set/reset
)
ODDR2_0 (
.Q(rgmii_txd_o[0]), // 1-bit DDR output data
.C0(rgmii_txclk), // 1-bit clock input
.C1(rgmii_txclk_n), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D0(gmii_txd[0]), // 1-bit data input (associated with C0)
.D1(gmii_txd[4]), // 1-bit data input (associated with C1)
.R(1'b0), // 1-bit reset input
.S(1'b0) // 1-bit set input
);
为了实现数据的发送和接收的对比需要准备2块MIS603开发板
测试数据发送:
原理:发送数据从0~255 不停循环
//计数器循环累加,当gmii_txdv_cnt[8]为0时将数据输出
reg [8:0]gmii_txdv_cnt;
assign gmii_txd_ts = gmii_txdv_cnt[8] ? 7'd0 : gmii_txdv_cnt[7:0];
//数据有效标志
assign gmii_txdv_ts = ((~gmii_txdv_cnt[8])||(gmii_txdv_cnt==256)||(gmii_txdv_cnt==257)) ? 1'b1 : 1'b0;
//循环计数器
always @(posedge rgmii_txclk_ts)
if(~rst_n)begin
gmii_txdv_cnt <= 9'd0;
end
else begin
gmii_txdv_cnt <= gmii_txdv_cnt +1'b1;
end
测试数据接收对比:
原来采用了一个状态机首先识别0x55 识别2个0x55后,后面就是有效数据,如果是从0~255不停累加就代表正确。
reg [7:0]gmii_rxd_next;
//比较数据
assign rxd_error= (rxd_s==2'd2) ? ((gmii_rxd_next==gmii_rxd_ts) ? 1'b0 : 1'b1 ) : 1'b0;
reg [1:0] rxd_s;
//下一个数据被比较数据准备
always @(posedge rgmii_rxclk_ts)begin
if((~rst_n)||(gmii_rxdv_ts!=2'b11))begin
gmii_rxd_next<=8'd1;
rxd_s<=2'd0;
end
else if(gmii_rxdv_ts==2'b11)begin
case(rxd_s)
0:
if(gmii_rxd_ts==8'h55)//接收第一个55
rxd_s <= rxd_s + 1'b1;//0x55
1:
if(gmii_rxd_ts==8'h55)//接收第二个55
rxd_s <= rxd_s + 1'b1;
else
rxd_s <= 2'd0;
2: begin //计算下一个比较数据
gmii_rxd_next <= gmii_rxd_ts+1'b1;
if(gmii_rxd_ts==8'd255)
rxd_s <= 2'd0;
end
endcase
end
end
测试结果:
PHY板对板测试,48小时以上没有任何错误。
源码下载地址:
http://pan.baidu.com/s/1pwSnc