FPGA时钟管理实战:MMCM与Clocking Wizard配置详解

发布时间:2026/10/7 4:44:59
FPGA时钟管理实战:MMCM与Clocking Wizard配置详解 刚接触FPGA的时候十个人有九个会在时钟上卡一下。板子上的晶振一般是50M、100M这种固定频率但工程里DDR要200M、串口要50M、像素时钟要74.25M总不能买一堆晶振挨个换。Xilinx的Clocking Wizard加上内部的MMCMMixed-Mode Clock Manager就是专门干这个的——倍频、分频、相位偏移、占空比调整全在一个IP核里配好省掉你自己写原语和算分频系数的时间。这篇东西面向的是刚把Vivado装好、还没怎么用过IP核的新手。我会从MMCM到底是什么讲起再手把手走一遍Clocking Wizard的配置流程最后把我实际跑工程时踩过的那些坑频率算不出来、locked信号不拉高、仿真没波形之类的一并列出来。内容不深但每一步都能直接照着做配置完不是只在仿真里能转下到板子上也能稳定跑。1. 为什么要用Clocking Wizard而不是自己写原语1.1 先搞清楚MMCM和PLL是干嘛的FPGA里的时钟资源分两大派PLL锁相环和MMCM混合模式时钟管理器。PLL是纯模拟电路做倍频分频MMCM是在PLL的基础上加了数字相位调整、动态重配置、更精细的占空比控制说人话就是——MMCM比PLL更“聪明”能干更多细活。7系列以及更新的Xilinx FPGA里MMCM基本是主力PLL反而用得少了。MMCM内部大致分三段最前面是输入分频器D中间是压控振荡器VCO做倍频M后面是一堆输出分频器O。最终输出频率的关系可以简化成输出频率 输入频率 × M / (D × O)其中M、D、O都只能是整数输出分频器部分支持半整数所以输出频率不能是任意值它必须满足这个整数分频关系同时VCO的实际频率得落在器件的合法范围内。拿Artix-7来说VCO范围大概是600MHz到1200MHz速度等级不同略有差异你配IP的时候如果VCO超出这个范围Vivado会直接报错这就是很多新手第一次配MMCM就卡住的原因——你想要的频率组合根本不满足器件约束。1.2 用Clocking Wizard帮你算这些系数你说的“配置MMCM”在Xilinx的流程里其实就是调Clocking Wizard这个IP核。它的价值在于你只需要告诉它输入时钟多少、想要哪些输出时钟、每个输出要不要偏移相位它会自动去枚举D、M、O的组合找出满足VCO范围的那一套参数。如果不用这个IP你得自己去Xilinx手册里查每个系列的VCO范围手动算分频系数再用MMCME2_ADV原语一行一行地例化。新手第一次干这事十有八九会翻车不是M和D放大了导致VCO超限就是输出分频选了个没法实现的值。而Clocking Wizard把这些全部包装成了图形界面参数合法性和时序检查它会自动帮你做这就是“5分钟搞定”的信心来源。我自己刚开始学的时候也走过弯路总想着“用原语是不是更底层更厉害”实际到项目里根本没必要。以前排队的经验是只要不是做那种对时钟质量有变态要求的超高速接口Clocking Wizard生成的MMCM配置已经经过了Xilinx官方验证时序收敛、抖动性能都有保障直接用就行。1.3 选PLL还是选MMCM怎么判断Clocking Wizard的第一页就让你选PLL还是MMCM。很多新手在这直接懵。我的建议很简单粗暴默认选MMCM。如果你的需求就是最普通的时钟生成——输入100M输出200M和50MPLL和MMCM都能干效果也差不多。但一旦你涉及下面任意一条就必须上MMCM需要输出时钟相位精确偏移比如源同步接口里数据时钟移相90度需要动态调整输出频率或相位配合DRP端口需要两个输出时钟之间有特定的相位关系输入输出频率组合比较刁钻PLL的整数分频不够用另外要注意一个MMCM能提供最多7路输出时钟但实际能同时使用多少路还取决于你用的封装和引脚资源。PLL的输出路数少一些。大多数入门板卡上的时钟资源足够你折腾不用太担心数量不够的问题。总结一下MMCM是7系列里最常用的时钟资源Clocking Wizard是配它的正规姿势。下一节开始我把配置前要理清的参数和实际步骤一起讲。2. 打开配置界面之前先把这3个参数理清楚2.1 输入时钟频率你板子上晶振到底是多大这是配置MMCM的第一步也是最多人填错的地方。Clocking Wizard界面里有一个“Input Clock Information”区域你得把这颗输入时钟的频率填准。填错了整个分频倍频关系全歪后面所有输出时钟都是错的。怎么看自己的板子输入频率简单翻板卡原理图找晶振那颗器件旁边的丝印或者元件标号一般会标“50MHz”或者“100MHz”。常见的入门开发板比如黑金、正点原子的Artix-7板卡系统时钟大多是50M或100M。也有一些板子用33.333M、125M这些频率都是为了某个特定用途比如网络接口选的。如果输入时钟是差分信号比如LVDS的时钟对在配置界面要选“Differential”同时确定好是“clock capable pin”还是普通的“MRCC/SRCC”引脚。我刚学的时候没注意这个直接把差分时钟当单端填结果下板以后MMCM输入引脚根本没有时钟进来locked死活不拉高。还要注意输入频率的范围。MMCM输入端的合法频率范围一般是10MHz到800MHz这个量级具体看器件型号和速度等级但板载晶振通常不会超出这个范围所以只要你不是外接一些奇奇怪怪的信号基本不用操心上限下限的问题。2.2 输出时钟频率先确定你到底需要几路配置MMCM之前最忌讳的就是一边开界面一边想“那我就随便先配一个”。打开Clocking Wizard之前我建议你把整个工程需要的时钟频率列个清单不仅列出频率还要列出每一路时钟用在哪里逻辑时钟、DDR接口、串口、视频像素时钟是否需要相位偏移比如DDR需要90度偏移做数据选通占空比是否有特殊要求默认50%大多数场景都够为什么这样做因为MMCM的输出分频器数量有限你如果配完了发现还缺一路时钟虽然可以再加一个MMCM一个器件里MMCM数量也是有限的7系列大概有几十个但时钟资源不能这么浪费不如第一次就规划好。以我常用的一个工程为例输入100M我需要200M给DDR接口、50M给逻辑主时钟、25M给低速外设接口、125M给以太网RGMII接口这个比较特殊因为RGMII需要125M的参考时钟。这种需求最好在打开IP核之前就写在纸上配的时候直接往里填。2.3 相位偏移和占空比什么时候需要动新手最容易忽略的就是“Phase”这个输入框。它默认是0度对于绝大多数内部逻辑时钟来说0度就够了。但是以下几种场景你必须用到相位偏移DDR接口DDR数据的读写需要时钟有90度或180度的偏移因为要和数据眼图中心对齐源同步接口SPI、I2S这类接口数据在时钟边沿附近变化最好把采样时钟偏移半个周期避免采到数据跳变沿ADC/DAC的采样时钟为了满足建立保持时间经常需要微调时钟相位占空比方面默认50%别乱动。只有在像PWM调制、某些串行协议中才需要特殊的占空比比如30%、70%这种。MMCM对占空比的调整范围有限不是所有频率组合都能配出你想要的占空比Vivado会在界面上实时检查如果配不了会直接提示。我见过一个比较典型的坑有人为了让I2S采样时钟避开数据边沿直接把占空比改成40%结果时序约束检查时发现数据采样窗口反而变差了。后来我实际调的时候发现与其改占空比不如用相位偏移0度改到90度问题直接解决。记住占空比影响的是高低电平的绝对时间相位影响的是整个时钟波形相对于参考点的时间偏移这俩解决的是不同的问题别混用。梳理完这3个参数你就可以打开Vivado开始配Clocking Wizard了。下面我按实际界面一步步来照着点就行。3. 实操Clocking Wizard的MMCM配置照着点就行3.1 在Vivado里创建Clocking Wizard IP核先确保你已经把工程建好并选好了器件型号比如xc7a35tcsg324-1。然后在Vivado左侧流程导航器点“IP Catalog”在搜索框输入“clocking wizard”回车能看到两个结果一个叫“Clocking Wizard”另一个带“(DRP)”字样的是支持动态重配置的版本。新手先用不带DRP的就行DRP是后面进阶再学的东西。双击打开后会弹出“Customize IP”窗口里面大概有4到5个页签。第一次打开默认停在第一页“Clocking Options”你在左边能看到“Component Name”默认叫“clk_wiz_0”可以改成有意义的名字比如“clk_gen_pll”这样后面例化的时候代码更直观。第一页的“Clocking Features”区域有两个重要选项上面是“MMCM”下面是“PLL”。默认勾选MMCM我们这里也用MMCM不用改。下面有个“Input Clock Information”填你板子上的输入频率。比如你的系统时钟是100MHz就填100。第一个容易踩坑的地方是“Source”下拉框这里要选“Single ended clock capable pin”还是“Global buffer”。如果你输入时钟是直接来自板载晶振引脚选“Single ended clock capable pin”没问题如果你的输入时钟是来自别的逻辑生成的转全局时钟选“Global buffer”。大部分入门场景选前者就行。还有一个“Clock Monitor”选项新手别勾。它的作用是当时钟丢失时输出一个报警信号需要额外的逻辑配合而且误报的概率也不小我遇到过板子晶振正常但MMCM报了时钟丢失排查半天发现是电压纹波太大导致时钟沿抖动超标。不是必要场景就别开。3.2 配置输出时钟频率、相位、占空比一次填完“Clocking Options”这一页设置好输入后点下一个页签“Output Clocks”。这里是核心页面界面上会显示4个默认的输出时钟槽位标着“clk_out1”到“clk_out4”。你先勾上需要的输出端口然后对应填频率和相位。举一个实际例子。输入100MHz我需要三路输出200MHz主时钟、50MHz逻辑时钟、25MHz外设时钟。具体这样填clk_out1勾选“Output Clock”频率填200单位默认MHz相位0度占空比50%clk_out2勾选频率填50相位0度占空比50%clk_out3勾选频率填25相位0度占空比50%填完以后Vivado会自动在页面底部显示计算出来的VCO频率和分频系数。比如输入100M它可能自动算了D1、M20VCO2000MHz不对2000MHz超了7系列的范围了。这里Vivado会继续调整组合我实际配置时的结果是D1、M10VCO1000MHz然后clk_out1用O5分频得到200Mclk_out2用O20分频得到50Mclk_out3用O40分频得到25M。这些参数你不用自己算但最好能看懂界面显示的含义方便出问题时排查。如果填了一个无法实现的频率组合Vivado会在对应输出旁边标红并提示类似“Value out of range”或者“Cannot achieve this frequency with current input”。这时候别死磕检查一下是不是输入频率填错了或者换一组输出频率值试试。比如我之前配一个125M的以太网时钟输入是33.333M怎么填都报错后来发现是因为VCO频率想刚好落在1000MHz的时候分频输出细粒度不够差一点。换一个M/D组合就成功了。这个页面还有一个“Jitter Optimization”下拉框默认是“Balanced”保持不动就行。如果你在做高速接口比如PCIe、千兆以太网可以对输出时钟选择“Minimize Output Jitters”如果你更关注输入噪声抑制就选“Maximize Input Jitter Filtering”。这是个性能倾向性选项不影响功能正确性。“Output Clocks”页面下方有个“Clocking Feedback”区域默认是“Auto”不用动。它控制的是MMCM反馈路径用内部反馈还是外部反馈新手不需要关心自动选择就好。3.3 添加复位、锁定信号以及生成IPOutput Clocks页面配完后切到下一个页签“Port Renaming”。你不需要在这里改什么但要看一眼里面列出来的端口clk_in1、clk_out1、clk_out2、locked、reset。locked是必须用到的它表示MMCM输出时钟已经稳定可以安全使用了。reset是可选的但建议至少保留一个外部复位输入。如果不需要复位可以不勾选“Reset”端口IP内部会把复位信号固定为无效状态。我建议第一次用还是勾上方便上板调试时手动复位整个时钟系统。再往后有个“Dynamic Reconfig”页签默认不勾。新手别碰这个功能一般应用在需要在线调整时钟频率/相位的场景比如动态变频的DDR控制器或者需要对时钟相位实时校准的接口。开DRP端口会让IP多出一堆AXI-Lite接口代码量直接翻倍没必要。这几个页签设置完点最下方的“OK”Vivado会弹出一个生成IP的对话框框点击“Generate”等待几秒到几十秒取决于工程规模和机器性能IP就生成好了。之后你可以在“Sources”面板的“IP Sources”下面看到这个clk_wiz_0的条目展开能看到它的实例化模板“clk_wiz_0.veo”。3.4 生成Example Design直接跑仿真看波形这一步非常推荐新手做。在Sources窗口右键点击“clk_wiz_0”选择“Open IP Example Design...”。Vivado会弹个对话框问你要把示例工程放在哪选个路径它会自动创建并打开一个独立的工程里面包含了这个时钟IP的测试平台testbench。这个Example Design就是我配置时钟后第一手验证的地方。点一下“Run Simulation”——Behavioral Simulation等待仿真跑起来你会在波形窗口看到类似这样的结果clk_in1是100MHz的方波周期10nsclk_out1是200MHz的方波周期5nsclk_out2是50MHz的方波周期20nslocked信号在复位释放后大概几个微秒内拉高这里有两个现象新手要留意第一locked不是上电立刻拉高的它需要一段时间去锁定这个时间一般是几微秒到几十微秒取决于输入频率和MMCM的环路参数第二在locked拉高之前输出时钟可能已经开始翻转了但是频率不一定准所以外部逻辑千万别拿输出时钟做任何存储或状态判断必须等locked信号拉高再开始工作。我第一次看到locked迟迟不拉高时吓了一跳以为是IP配置错了。后来查手册才知道MMCM的锁定过程本来就需要一段时间。如果你的locked一直不拉高重点检查输入时钟的仿真激励文件里有没有正确生成时钟很多仿真跑不起来都是testbench里忘了写initial begin clk0; forever #5 clk~clk; end这样的语句。Example Design仿真通过之后就可以关掉这个示例工程回到你自己的主工程开始例化IP了。3.5 在顶层模块里例化Clocking Wizard回到你的主工程在源码里右键点击“clk_wiz_0”选择“Instantiation Template”可以打开一个后缀是.veo的模板文件里面就是Verilog仿真和综合用的实例化代码。直接复制到你的顶层模块里改一下端口连接就行。我以一个典型写法为例假设顶层模块的端口有输入系统时钟 sys_clk_100m输入复位按键 rst_n低有效输出时钟给逻辑使用的 clk_50m以及其他模块需要的时钟那么例化代码大概是这样的clk_wiz_0 u_clk_wiz_0 ( .clk_out1 (clk_200m), // 200MHz给DDR或高速逻辑 .clk_out2 (clk_50m), // 50MHz主逻辑时钟 .clk_out3 (clk_25m), // 25MHz低速外设时钟 .locked (clk_locked), // MMCM锁定信号高有效 .clk_in1 (sys_clk_100m), // 输入时钟 .reset (~rst_n) // 复位信号高有效 );注意三件事第一端口名要以你生成的IP模板里为准不同Vivado版本可能有细微差异。比如有些版本的reset端口叫“reset”而不是“resetn”我见过模板里叫“reset”的也见过叫“clk_reset”的。用Generate Output Products后弹出的模板一定以那个文件里的实际名字来连接。第二如果你的复位按键是低有效按下为0连接reset端口时要取反写成 ~rst_n。我第一次偷懒直接接了rst_n结果上板后发现MMCM被一直复位locked永远为低排查了大半天。第三locked信号别只连一个LED看着玩。工程里最好用locked做一个复位释放逻辑在locked拉高之前所有模块的复位都保持有效等locked拉高后再释放复位。这样能避免逻辑在上电瞬间跑到一个中间状态。这个做法大家可以参考不是必须但能省很多debug时间。4. 常见问题与排查技巧实录4.1 locked信号拉不高先检查这4件事locked拉不高是所有MMCM配置里遇到最多的问题。我分情况说。第一种仿真里locked一直为0。优先检查输入时钟是不是真的产生了。很多人testbench里忘了写时钟翻转语句或者写的时钟频率和IP里填的频率不一致MMCM在里面一直在等输入沿自然锁定不了。这个最好排查加个initial块生成时钟就行。第二种上板后locked为0示波器能看到输入时钟有波形。那要检查输入时钟的电平标准IOSTANDARD和引脚位置对不对。很多开发板的晶振是接到FPGA的MRCC或SRCC专用时钟引脚上的如果你约束文件里把这个输入时钟约束到了普通IO即使引脚号写对了时钟信号也能进来有些器件普通IO能接时钟但MMCM的输入源选择可能就错了。正确做法是把输入时钟约束到器件手册标注的MRCC引脚上并且设置好IOSTANDARD一般是LVCMOS33或LVDS25。第三种上电后locked拉高了但一跑业务逻辑就掉。这种情况往往是MMCM输出时钟驱动的逻辑太复杂时序没有收敛复位释放时机不对。常见方案是把locked接的复位释放逻辑做一个同步处理防止释放瞬间产生毛刺。第四种输入时钟电压纹波太大或者频率不稳。我用过一个第三方开发板上面那颗晶振质量一般配了MMCM之后locked经常在系统负载高的时候掉下来。后来换了一个更干净的低噪声电源给晶振供电就稳定了。这种问题比较隐蔽如果排查完前三种还没解决可以考虑测一下电源纹波。4.2 输出频率和配置值对不上是哪里出错了这个问题也很典型。配置界面填的是200M但示波器看输出只有100M或者用计数器测出来的波特率是预期的一半甚至四分之一。先别怀疑IP坏了99%的情况是你的逻辑写错了。最常见的是把MMCM的输出直接接到了普通逻辑然后这个逻辑再加上BUFG又回环成全局时钟时钟树被分叉导致采样错乱。正确的接法是MMCM的输出时钟在IP内部已经接好了BUFG或者全局时钟网络你只需要把它直接连到逻辑的时钟输入即可。还有一个容易被忽略的地方如果你在约束文件里对某个时钟端口写了create_clock而这个时钟经过MMCM后产生了新的时钟Vivado会自动推导出生成时钟Generated Clock在时序报告中能看到。如果你的约束里手写了一个生成的时钟约束而且频率和MMCM的输出不一致Vivado会以两边约束里更严格的那一个计算时序可能导致奇怪的时序违规。新手阶段不要手写Generated Clock约束让工具自动从MMCM配置去推。另外如果你用逻辑自己写了个分频器再拿去当时钟用也会出现“看起来频率对不上”的情况这在Xilinx的警告报告中会提示“Clock has no driver”或者“Multi-driven clock”。解决方式是尽量不要用逻辑分频去产生时钟要么再用一个PLL/MMCM要么把分频后的信号当作普通数据信号用时钟使能的方式处理而不是当作真正的时钟。4.3 仿真中MMCM输出没波形怎么排查仿真里MMCM输出没有波形除了前面说的输入时钟没搞定之外还有一个原因Vivado的仿真库没加载完整。第一次创建Example Design跑仿真时一般没问题但如果是在主工程里直接跑仿真工程设置里的仿真库可能没有包含Xilinx的Unisim库导致MMCM模型没被正确加载仿真波形直接为空白。排查方法是看仿真窗口底部的Tcl控制台如果有大量类似“ERROR: Failed to load module: unisims”或者找不到glbl模块的报错就去Simulation设置里把Xilinx仿真库添加上然后在顶层测试平台里加上glbl模块的例化一般在模板里会带上。还有一个容易踩的坑在testbench里给MMCM的输入时钟做force然后观察不到输出。force在行为仿真下通常会正常工作但我遇到过一个情况在工程里同时给“clk_in1”写了force又在IP内部接了另一个时钟网络结果产生多驱动冲突输出没有。后来把force去掉、直接用真实的时钟约束来跑问题就正常了。仿真时尽量用真实时钟源少用force。4.4 综合和实现阶段报MMCM相关错误怎么处理在综合或实现阶段MMCM相关的错误一般集中在这几类第一类引脚约束和时钟端口不匹配。错误提示类似“The clock pin xx is not a clock capable pin”。解决办法是查一下该引脚是不是MRCC/SRCC如果是普通IO就别硬接时钟。第二类“Mandel/No valid MMCM setting for this input/output frequency combination”。这就是频率组合无解。回到IP配置界面换一组M/D组合或者调整输出频率。有些频率确实没法用同一个MMCM同时满足比如输入100M想同时得到30M和70M这俩加起来不是100的整数倍关系会有一个输出达不到。这时候可以考虑用两个MMCM或者改DS——如果输出时钟是给外部接口用的看能不能调整接口工作频率。第三类在实现阶段出现“The MMCM is unconstrained”或者时钟输入端口没有时序约束。解决办法是给输入时钟添加create_clock约束例如create_clock -period 10.000 -name sys_clk [get_ports clk_in1]这样综合工具才会去分析MMCM输出时钟的时序路径。如果不加这个约束MMCM的输出时钟就会被当成无约束时钟时序分析全跳过虽然实现能跑完但上板后随机出问题。4.5 我调MMCM时用过的几个小技巧最后分享几个我在实际项目里摸索出来的习惯不算什么高深技术但很管用。第一个把所有经过MMCM的时钟在约束文件里显式命名。比如create_clock给输入时钟取名为“clk_100m”然后MMCM生成的两个输出时钟会自动叫“clk_100m_clk_wiz_0”之类的名字时序报告里看起来会很清晰。如果你配多个MMCM名字会更多不命名的话后期看时序报告很痛苦。第二个把locked信号作为系统级复位的主控。很多参考设计的复位逻辑是“上电立即释放复位”结果逻辑在时钟还没锁定时就开始跑出现随机乱码。我都改成“内部产生一个reset_async_n然后同时被locked和外部按键复位控制”例化代码里写一个同步复位释放逻辑能省去大量上板调试时间。第三个MMCM输出时钟尽量少做跨时钟域连接。虽然MMCM的多路输出来自同一个VCO理论上它们之间是同步的但不同输出时钟之间如果没有约束和同步处理还是会有相位偏差和抖动问题。如果两路时钟之间要交互数据建议加FIFO或打拍同步别裸连。第四个当你改了输入时钟频率MMCM的M/D参数可能会自动重算。如果Vivado提示需要更新IP的全局状态记得在IP配置界面里点一下重新生成然后在约束里也同步更新period不然实现时会用旧的约束去分析新的时钟导致时序异常。5. 进阶动态相位调整、时钟监控还有哪些玩法Clocking Wizard除了基础的分频倍频其实还有几个功能是很多项目里用得上的。虽然新手阶段不需要全部掌握但你至少要知道有这些选项等后面做复杂工程时能想起来用。一个比较实用的是输出时钟的“相位对齐”功能。在Output Clocks页面里每路输出可以设置和某一路参考时钟对齐或者和输入时钟对齐这在设计高速ADC采样、DDR接口时非常关键。我之前做一个ADC采集模块采样时钟和逻辑时钟来自同一个MMCM由于输出路径上BUFG延迟不一致采样数据总有建立保持违规。后来我在Clocking Wizard里把采样时钟的输出相位设成跟主时钟对齐并启用“Match相关选项时序问题直接消失。另一个是前面提过的“DRP”动态重配置。这个功能让FPGA在运行过程中改变MMCM的输出频率常见于软件无线电里的变频设计或者一些需要在线调整采样率的采集系统。实现方式也不复杂通过一组寄存器和AXI-Lite接口把新的分频系数写进MMCM的配置寄存器即可。虽然我不建议新手一上来就玩这个但当你有处理“同一块硬件兼容多种通信速率”的需求时DRP几乎是唯一方案。还有一个容易被我忽略的功能是“Clock Monitor”我刚才说新手别开但如果你的系统部署在工业现场输入晶振老化或者电源波动大导致时钟丢失这个模块会在时钟异常时直接拉低locked并产生一个中断信号给逻辑可以做到实时告警。我后来在几个需要长期运行的采集设备上开了这个功能确实抓到了两次晶振老化导致的掉时钟问题。但是要注意时钟丢失检测本身就依赖一个参考时钟如果整个系统所有时钟都断了告警信号也就没有意义了实际用的时候通常跳过一个稳定的低速参考时钟来做监测基准。写在最后Clocking Wizard的MMCM配置说白了就是“输入频率输出频率相位关系”这三个信息其余全部交给工具。刚开始学的时候不要怕界面选项多默认值不动就行先把最基础的时钟生成跑通。等你用了一段时间发现时序报告里出现时钟相关的问题再倒过头去研究MMCM的原理、VCO范围和分频结构比一上来就啃UG472手册要快得多。这几年我帮不少新人看过板卡他们第一次配MMCM遇到的各种奇怪问题归根结底都是没先想清楚“输入是什么、输出要什么”就直接开配。所以最好的办法就是动手之前把你板卡上的晶振频率和工程里需要的所有时钟整理成一张表然后照着表去填界面。按这个流程来5分钟配完真的不难。