一个完整的以太网项目系统级电路 10/100Mbps 10BASE-T ETHERENT-PHY 适合有几年工作经验的或者博士研究生 有两个版本一份是工艺是Gpdk90nm主要一份是Gpdk180nm都是有版图TOPcell都有Cadence自己家的电路 有两个锁相环模拟均衡器eqpi相位差值flash ADC带triming bgLDO比较器电平移位译码电路数字电路偏置电流源运放transDAC滤波器上周整理硬盘翻出了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 1b0; up 1b0; 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 1b0; down 1b0; end else begin fb_d1 ref_clk; down fb_d1 ~ref_clk; // 检测反馈时钟超前 end end endmodule当时用Spectre跑相位噪声仿真的时候90nm版本能做到-122dBc/Hz1MHz刚好卡着以太网的要求过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工艺下的寄生电容小均衡器的带宽能拉到60MHz180nm的只能做到30MHz所以180nm版本只能稳定跑10Mbps要跑100Mbps就得把均衡器参数改得更激进还得加一级缓冲。一个完整的以太网项目系统级电路 10/100Mbps 10BASE-T ETHERENT-PHY 适合有几年工作经验的或者博士研究生 有两个版本一份是工艺是Gpdk90nm主要一份是Gpdk180nm都是有版图TOPcell都有Cadence自己家的电路 有两个锁相环模拟均衡器eqpi相位差值flash ADC带triming bgLDO比较器电平移位译码电路数字电路偏置电流源运放transDAC滤波器接下来是带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 i0; iTRIM_W; i) begin trim_en[i] trim_in[i]; // 直接映射trim位到开关使能 end end90nm版本用了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(i0; i6; 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 1b0; end else begin mii_txd tx_data; mii_tx_en tx_en; end end endmodule最后说下版图两个版本的TOP版图我都留了注释90nm的因为线宽细密度能到70%把PLL、均衡器这些敏感模块挨得很近减少走线的寄生参数180nm的版图宽松很多留了快30%的冗余空间方便后期改参数。当初做这个项目的时候连续一个月每天熬到两点现在翻出这些文件反而觉得挺有意思——好多当初觉得过不去的坎现在回头看也就是调参数调仿真的小事。要是有同行想看完整的工程文件或者想抠细节的随时可以找我唠毕竟这玩意现在也不算啥机密项目了。