基于Gpdk90nm/180nm工艺的10/100Mbps以太网PHY芯片系统级电路与版图设计
一个完整的以太网项目,系统级电路 10/100Mbps 10BASE-T ETHERENT-PHY 适合有几年工作经验的或者博士研究生 有两个版本,一份是工艺是Gpdk90nm(主要),一份是Gpdk180nm,都是有版图(TOP,cell都有),Cadence自己家的电路 有两个锁相环,模拟均衡器eq,pi相位差值,flash ADC,带triming bg,LDO,比较器,电平移位,译码电路,数字电路,偏置电流源,运放,trans,DAC,滤波器

上周整理硬盘翻出了10/100Mbps以太网PHY的老项目备份,本来以为早就随旧电脑一起丢了,结果Cadence的工程文件还安安稳稳躺在加密分区里——这算是我刚入行第二年啃下的最磨人的项目了,今天刚好拿出来唠唠。

这个项目是给工业低成本以太网方案做的,分GPDK90nm和GPDK180nm两个版本,全流程从电路设计到版图落地都用的Cadence工具,连顶层和单元库版图都给齐了,当初做的时候特意留了冗余,现在改改参数还能直接用。受众本来就是给有几年经验的工程师或者博士准备的,毕竟里面不少模块要是没点实际调流片的经验,光看论文真容易踩坑。

先从最头疼的两个锁相环说起吧:一个给发送端提供同步时钟,一个给接收端做采样时钟。当初一开始只做了一个PLL,结果接收端采样的时候总跟发送端时钟不同步,眼图直接糊成一片,后来补了带反馈环路的第二个PLL才搞定。贴个当时简化版鉴频鉴相器的数字代码片段:
// 适配10/100Mbps的PFD数字核心
module pfd_core(
input wire ref_clk,
input wire fb_clk,
input wire rst_n,
output reg up,
output reg down
);
reg ref_d1, fb_d1;
always @(posedge ref_clk or negedge rst_n) begin
if(!rst_n) begin
ref_d1 <= 1'b0;
up <= 1'b0;
end else begin
ref_d1 <= fb_clk;
up <= ref_d1 & ~fb_clk; // 检测参考时钟超前
end
end
always @(posedge fb_clk or negedge rst_n) begin
if(!rst_n) begin
fb_d1 <= 1'b0;
down <= 1'b0;
end else begin
fb_d1 <= ref_clk;
down <= fb_d1 & ~ref_clk; // 检测反馈时钟超前
end
end
endmodule
当时用Spectre跑相位噪声仿真的时候,90nm版本能做到-122dBc/Hz@1MHz,刚好卡着以太网的要求过,180nm版本因为器件匹配差,只能做到-110dBc/Hz,不过胜在成本低,给低端项目用刚好。

然后是接收端的模拟均衡器,说白了就是给网线损耗掉的高频信号“补妆”,长网线跑100Mbps的时候要是没这个,接收端看到的信号直接糊成马赛克。我当时用的是连续时间线性均衡器,核心用了两级运放放增益,贴个简化的Verilog-A模型:
// 适配PHY的两级运放模型
module ctle_opamp(
electrical vin_p, vin_n,
electrical vout,
electrical vdd, vss
);
parameter real A0 = 58; // 开环增益dB
parameter real GBW = 950e6;// 增益带宽积,刚好压着100Mbps的采样率
real av, gm1, ro1;
analog begin
av = 10 ** (A0 / 20);
gm1 = 2 * GBW / av;
ro1 = 10e3; // 输出电阻固定
I(vin_p, vin_n) <+ 0;
I(vout, vss) <+ gm1 * V(vin_p, vin_n) - V(vout, vss)/ro1;
end
endmodule
当时调这个的时候踩了个大坑:90nm工艺下的寄生电容小,均衡器的带宽能拉到60MHz,180nm的只能做到30MHz,所以180nm版本只能稳定跑10Mbps,要跑100Mbps就得把均衡器参数改得更激进,还得加一级缓冲。

一个完整的以太网项目,系统级电路 10/100Mbps 10BASE-T ETHERENT-PHY 适合有几年工作经验的或者博士研究生 有两个版本,一份是工艺是Gpdk90nm(主要),一份是Gpdk180nm,都是有版图(TOP,cell都有),Cadence自己家的电路 有两个锁相环,模拟均衡器eq,pi相位差值,flash ADC,带triming bg,LDO,比较器,电平移位,译码电路,数字电路,偏置电流源,运放,trans,DAC,滤波器

接下来是带trim的带隙基准和LDO,这俩是整个PHY的“后勤保障”,模拟电路对电源和基准电压敏感得要死。先看trim译码的代码,当时为了兼容两个工艺版本,特意做了可配置位宽:
// 6/4位可选的带隙基准trim译码器
module bg_trim_dec #(
parameter TRIM_W = 6
)(
input wire [TRIM_W-1:0] trim_in,
output reg [TRIM_W-1:0] trim_en
);
always @(*) begin
trim_en = '0;
for(int i=0; i<TRIM_W; i++) begin
trim_en[i] = trim_in[i]; // 直接映射trim位到开关使能
end
end
90nm版本用了6位trim,能把带隙的温漂控制在10ppm/℃以内,180nm只用4位就够了,毕竟工艺本身的误差就大,没必要浪费多余的trim位。当时调LDO的时候,为了把纹压控制在10mV以内,特意用了电流镜做误差放大器,仿真的时候跑了快一下午,电脑风扇转得跟直升机似的,最后流片实测才8mV,刚好达标。

还有6位flash ADC,接收端把模拟信号转成数字信号的核心,当时为了省面积没用流水线ADC,直接用了比较器阵列,贴个例化的代码片段:
// 6位flash ADC比较器阵列
module flash_adc_6b(
input wire adc_in,
input wire [5:0] ref_array,
output reg [5:0] adc_out
);
genvar i;
generate
for(i=0; i<6; i++) begin : comp_loop
comp_with_trim u_comp(
.vin_p(adc_in),
.vin_n(ref_array[i]),
.trim_en(trim_array[i]),
.vout(adc_out[i])
);
end
endgenerate
这里每个比较器都带了trim校准偏移,不然90nm工艺下的比较器偏移能到15mV,直接把ADC的线性度干到只剩3位,加了trim之后能拉到5.5位,刚好满足100Mbps的采样要求。180nm版本的比较器偏移更大,只能做到5位线性度,眼图稍微差一点,但也能用。

剩下的电平移位、译码电路、偏置电流源这些模块就不一一细说了,反正都是当时抠细节抠出来的:比如电平移位电路用来把3.3V的数字信号转成1.2V的模拟电路电平,当时一开始用电阻分压,结果速度跟不上100Mbps的速率,后来改成CMOS传输门结构才搞定;偏置电流源用了带温度补偿的电流镜,把温漂控制在0.1%以内。
整个项目的数字电路部分都是用Verilog写的,包括MII接口、编码解码模块,当时调试MII发送模块的时候,差点被时钟域交叉搞疯——tx_clk和系统时钟不同步的时候,发送的数据直接错位成乱码,后来加了异步FIFO才搞定,贴个简化的MII发送代码:
// 简化MII发送模块
module mii_tx(
input wire tx_clk,
input wire rst_n,
input wire [3:0] tx_data,
input wire tx_en,
output reg [3:0] mii_txd,
output reg mii_tx_en
);
always @(posedge tx_clk or negedge rst_n) begin
if(!rst_n) begin
mii_txd <= '0;
mii_tx_en <= 1'b0;
end else begin
mii_txd <= tx_data;
mii_tx_en <= tx_en;
end
end
endmodule
最后说下版图,两个版本的TOP版图我都留了注释,90nm的因为线宽细,密度能到70%,把PLL、均衡器这些敏感模块挨得很近,减少走线的寄生参数;180nm的版图宽松很多,留了快30%的冗余空间,方便后期改参数。
当初做这个项目的时候,连续一个月每天熬到两点,现在翻出这些文件反而觉得挺有意思——好多当初觉得过不去的坎,现在回头看也就是调参数调仿真的小事。要是有同行想看完整的工程文件,或者想抠细节的,随时可以找我唠,毕竟这玩意现在也不算啥机密项目了。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)