FPGA时钟分频器设计:从计数器到时钟使能的工程实践
简介这是一份面向FPGA初学者与数字电路学习者的Verilog时钟分频器设计资料围绕如何将高频时钟转换为任意指定频率这一核心问题展开适合需要掌握分频器原理、时序约束与综合流程的开发者参考。压缩包共155个文件约971KB包含Verilog源码、UCF管脚约束文件、时钟约束文件以及综合与实现过程产生的日志、报告、网表、比特流等工程文件完整覆盖从代码编写到布局布线的全流程。资源中div_int等源文件展示了分频系数参数化、计数器更新与输出时钟翻转的具体实现可帮助读者理解任意分频的写法并借助约束文件学习I/O分配与时序优化。目前已有1731人学习下载可作为模板直接移植到自己的FPGA项目中快速搭建可复用的分频模块。1. 时钟分频器为什么你的第一个分频器上板就翻车很多人第一次写时钟分频器逻辑仿真波形完美一上板就翻车——要么输出时钟抖动得没法看要么后级电路直接跑飞。问题不在代码写错了而在于把「分频」当成了一个纯计数问题。时钟分频器的本质不是数数而是在用触发器搭建一个受控的相位延迟链每一级触发器的输出都是对前一级的重新采样。当你用计数器分频时输出时钟是由组合逻辑比较产生的这条路径上任何一点毛刺都会被后级当成有效边沿。真正能上板的分频器要么用触发器直接翻转输出要么用时钟使能信号代替生成新时钟。搞懂这个区别是从「仿真能跑」到「硬件能跑」的分水岭也是理解时序逻辑设计的第一道门槛。2. 分频器的底层机制从计数器到相位累加2.1 偶数分频为什么天然比奇数分频简单偶数分频的核心机制是「对称翻转」。假设输入时钟 50 MHz要得到 25 MHz只需要在输入时钟的每个上升沿让输出寄存器翻转一次。因为 50 MHz 的周期是 20 ns每 10 ns 翻转一次输出周期正好是 20 ns占空比 50%。这个过程中没有任何组合逻辑参与判断输出完全由触发器驱动毛刺无从产生。用计数器实现偶数分频时常见的写法是计数到 N/2-1 时翻转输出并清零计数器。这里有一个容易被忽略的细节计数器本身的值不需要参与输出逻辑它只负责告诉触发器「什么时候该翻转」。换句话说计数器是控制通路输出寄存器是数据通路两者分离才能保证输出干净。// 偶数分频参数化实现DIV_N 必须为偶数 module even_divider #( parameter DIV_N 4 // 分频比输出频率 输入频率 / DIV_N )( input wire clk_in, input wire rst_n, output reg clk_out ); // 计数器位宽根据分频比自动计算 localparam CNT_W $clog2(DIV_N); reg [CNT_W-1:0] cnt; always (posedge clk_in or negedge rst_n) begin if (!rst_n) begin cnt 0; clk_out 0; end else if (cnt DIV_N/2 - 1) begin cnt 0; clk_out ~clk_out; // 每到一半就翻转 end else begin cnt cnt 1b1; end end endmodule这段代码里cnt只负责计数clk_out只在计满一半时翻转。DIV_N/2 - 1这个比较值是组合逻辑但它只驱动计数器的清零和输出的翻转使能不直接参与输出赋值。综合工具会把比较逻辑和触发器放在同一个时序路径上只要输入时钟频率不超过触发器的建立保持时间要求输出就是干净的。参数说明DIV_N是分频比必须是偶数CNT_W用$clog2自动计算避免手动指定位宽导致综合警告。如果DIV_N4计数器在 0 和 1 之间循环clk_out每两个输入周期翻转一次输出频率是输入的 1/4。2.2 奇数分频的占空比难题与双沿采样奇数分频之所以麻烦是因为无法用单个计数器在整数个输入周期内完成对称翻转。比如 3 分频输入 3 个周期输出 1 个周期但 3 是奇数找不到一个整数点让输出在高电平和低电平各停留 1.5 个输入周期。常见的实现思路是用两个计数器分别在上半周期和下半周期计数或者用输入时钟的上升沿和下降沿分别触发两个寄存器再把它们的输出做逻辑组合。双沿采样方案的核心机制是用上升沿计数器产生一个提前半个周期的信号用下降沿计数器产生另一个信号两者相或或相与后得到 50% 占空比的输出。这种做法的代价是引入了下降沿触发的触发器对时钟质量要求更高但在大多数 FPGA 器件里时钟资源支持双沿触发所以是可实现的。// 奇数分频3 分频占空比 50% module odd_divider #( parameter DIV_N 3 // 必须为奇数 )( input wire clk_in, input wire rst_n, output wire clk_out ); localparam CNT_W $clog2(DIV_N); reg [CNT_W-1:0] cnt_pos, cnt_neg; reg clk_pos, clk_neg; // 上升沿计数计到 (DIV_N-1)/2 时翻转 always (posedge clk_in or negedge rst_n) begin if (!rst_n) begin cnt_pos 0; clk_pos 0; end else if (cnt_pos DIV_N - 1) begin cnt_pos 0; clk_pos ~clk_pos; end else begin cnt_pos cnt_pos 1b1; if (cnt_pos (DIV_N-1)/2) clk_pos ~clk_pos; end end // 下降沿计数相位滞后半个输入周期 always (negedge clk_in or negedge rst_n) begin if (!rst_n) begin cnt_neg 0; clk_neg 0; end else if (cnt_neg DIV_N - 1) begin cnt_neg 0; clk_neg ~clk_neg; end else begin cnt_neg cnt_neg 1b1; if (cnt_neg (DIV_N-1)/2) clk_neg ~clk_neg; end end assign clk_out clk_pos | clk_neg; // 两个半周期信号相或 endmodule这段代码里clk_pos在上升沿域产生一个占空比非 50% 的信号clk_neg在下降沿域产生一个相位滞后半个输入周期的信号。两者相或之后高电平时间被补齐输出占空比接近 50%。注意cnt_pos和cnt_neg的翻转条件不同clk_pos在计数到(DIV_N-1)/2时提前翻转一次计满时再翻转一次这样它的高电平时间比低电平时间多半个输入周期。clk_neg同理但整体滞后半个周期。相或之后多出来的半个周期被另一个信号补上。2.3 为什么推荐用时钟使能代替分频时钟在 FPGA 设计里直接用一个分频后的时钟去驱动后级触发器会引入时钟偏斜和时序收敛问题。因为分频时钟是由普通逻辑资源产生的它到后级触发器的路径延迟不可控而专用时钟网络走的是全局时钟树偏斜在皮秒级。常见的做法是保持系统时钟统一用分频器产生一个使能信号后级电路在使能有效时才更新状态。// 时钟使能生成每 DIV_N 个周期产生一个使能脉冲 module clk_enable #( parameter DIV_N 4 )( input wire clk, input wire rst_n, output reg en ); localparam CNT_W $clog2(DIV_N); reg [CNT_W-1:0] cnt; always (posedge clk or negedge rst_n) begin if (!rst_n) begin cnt 0; en 0; end else if (cnt DIV_N - 1) begin cnt 0; en 1b1; end else begin cnt cnt 1b1; en 1b0; end end endmodule这个模块的输出en只在每个分频周期的最后一个系统时钟周期拉高。后级电路用if (en) begin ... end来更新状态所有触发器仍然由同一个系统时钟驱动。这样做的好处是时序分析只需要分析一个时钟域不需要为分频时钟单独约束后级电路的建立保持时间余量更大综合工具不会因为时钟门控产生额外的时钟域交叉问题。参数说明DIV_N是使能脉冲的间隔周期数可以是任意正整数。en的脉冲宽度是一个系统时钟周期后级电路需要在en有效的那个周期内完成状态更新。如果后级逻辑较复杂可以把en展宽或者用状态机配合。3. 从 RTL 到门级分频器综合后到底变成了什么3.1 触发器翻转与计数器比较的硬件映射写 RTL 的时候cnt DIV_N/2 - 1看起来是一条判断语句综合之后它变成什么常见的实现思路是综合工具会推断出一个比较器把计数器的每一位和常数做异或或同或再通过一棵与门树汇聚成使能信号。对于 4 分频比较值是 1计数器只有 1 位比较逻辑退化成一根线几乎不消耗资源。对于 1024 分频比较值是 511计数器 10 位比较器需要 10 个同或门加一棵与门树面积不可忽略。这也是为什么大分频比的分频器推荐用「计数到最大值自动回绕」而不是「计数到中间值翻转」。前者只需要判断计数器是否全 1综合工具可以用进位链直接实现后者需要和任意常数比较面积和延迟都更大。// 大分频比优化用回绕判断代替常数比较 module large_divider #( parameter DIV_N 1024 )( input wire clk_in, input wire rst_n, output reg clk_out ); localparam CNT_W $clog2(DIV_N); reg [CNT_W-1:0] cnt; always (posedge clk_in or negedge rst_n) begin if (!rst_n) begin cnt 0; clk_out 0; end else if (cnt DIV_N - 1) begin cnt 0; clk_out ~clk_out; // 计满整个周期才翻转 end else begin cnt cnt 1b1; end end endmodule这段代码和偶数分频的区别在于翻转条件是cnt DIV_N - 1而不是DIV_N/2 - 1。这样输出频率是输入的 1/(2DIV_N)占空比仍然是 50%但计数器只需要判断全 1 状态。综合工具会把cnt DIV_N - 1优化成进位链的溢出信号面积比常数比较器小得多。代价是分频比变成了 2DIV_N如果需要奇数分频比这个技巧不适用。3.2 复位策略同步复位还是异步复位分频器的复位策略直接影响上板后的行为。异步复位在复位信号有效时立即清零计数器和输出不依赖时钟但释放时如果和时钟边沿太近可能产生亚稳态。同步复位在时钟边沿采样复位信号释放时不会产生亚稳态但需要复位信号保持足够长时间。常见的做法是分频器内部用异步复位、同步释放。复位信号先经过两级触发器同步到目标时钟域再作为分频器的异步复位输入。这样既保证了复位立即生效又避免了释放时的亚稳态。// 异步复位同步释放 module reset_sync ( input wire clk, input wire rst_async_n, output wire rst_sync_n ); reg rst_meta, rst_sync; always (posedge clk or negedge rst_async_n) begin if (!rst_async_n) begin rst_meta 0; rst_sync 0; end else begin rst_meta 1b1; rst_sync rst_meta; end end assign rst_sync_n rst_sync; endmodule这个模块的输出rst_sync_n在复位有效时立即拉低复位释放时经过两个时钟周期的同步才拉高。分频器的复位端口接这个同步后的复位信号就能避免释放时的亚稳态。注意rst_meta和rst_sync的初值都是 0复位有效时它们被强制为 0复位释放后第一个时钟沿rst_meta变 1第二个时钟沿rst_sync变 1输出才释放。3.3 时序约束分频时钟需要额外约束吗如果分频器输出的是时钟信号并且后级触发器直接用这个时钟那么需要为分频时钟创建 generated clock 约束。如果分频器输出的是使能信号后级触发器仍然用系统时钟那么不需要额外的时钟约束只需要保证使能信号的路径延迟满足建立保持时间。常见的做法是在综合脚本里用create_generated_clock命令为分频时钟指定源时钟和分频比。如果不加这条约束综合工具会把分频时钟当成普通信号时序分析会遗漏跨时钟域路径上板后可能出现亚稳态或数据丢失。# 为分频时钟创建 generated clock 约束 create_clock -name clk_in -period 20 [get_ports clk_in] create_generated_clock -name clk_div -source [get_ports clk_in] \ -divide_by 4 [get_pins even_divider_inst/clk_out]这段约束告诉综合工具clk_div是从clk_in分频得到的分频比是 4。工具会自动计算clk_div的周期和相位关系并对跨时钟域路径做时序分析。如果不加这条约束工具会把clk_div当成普通数据信号跨时钟域路径的建立保持时间不会被检查。4. 避坑与排查分频器上板后不工作的常见原因4.1 输出时钟抖动大后级电路随机出错现象仿真波形干净上板后用示波器看输出时钟边沿有明显的振铃和抖动后级电路偶尔跑飞。原因分频器的输出直接来自组合逻辑比较器比较器的毛刺被后级当成有效边沿。或者输出信号没有走专用时钟网络而是走了普通布线资源延迟不可控。解决把输出改成寄存器直接翻转不要用组合逻辑产生时钟。如果必须用组合逻辑在输出端加一级触发器打拍。在 FPGA 里把输出信号分配到全局时钟引脚或者用时钟缓冲器原语。4.2 奇数分频占空比不是 50%后级电路时序余量不足现象奇数分频器输出频率正确但占空比是 33% 或 67%后级触发器的建立保持时间余量变小高频时出错。原因单计数器实现奇数分频时输出在高电平和低电平停留的周期数不相等。比如 3 分频高电平 1 个周期低电平 2 个周期占空比 33%。解决用双沿采样方案上升沿和下降沿各产生一个信号相或后得到 50% 占空比。或者用状态机在输出端做对称翻转但状态机的时钟频率需要是输入时钟的 2 倍。4.3 大分频比时计数器位宽不够综合后行为异常现象分频比设为 1000仿真时输出频率正确上板后输出频率是预期的两倍或完全不对。原因计数器位宽用$clog2(DIV_N)计算时如果DIV_N不是 2 的幂$clog2返回的是向上取整的位宽但计数器最大值是DIV_N-1不会溢出。问题出在比较器的常数被截断比如DIV_N1000$clog2(1000)1010 位计数器最大 1023比较值 999 在范围内不会截断。但如果手动指定位宽为 8 位比较值 999 被截断成 231分频比就错了。解决用$clog2自动计算位宽不要手动指定。如果综合工具不支持$clog2用$clog2的等价函数或者手动计算最小位宽。4.4 复位释放时产生亚稳态分频器输出随机翻转现象上电后分频器输出不稳定偶尔多翻转一次或少翻转一次复位释放后需要很长时间才稳定。原因复位信号是异步的释放时和时钟边沿太近触发器的复位端口产生亚稳态导致计数器和输出寄存器的初值不确定。解决用异步复位同步释放电路复位信号先经过两级触发器同步到目标时钟域再作为分频器的复位输入。这样复位释放时不会产生亚稳态。4.5 分频时钟没有加时序约束跨时钟域路径时序违规现象分频器输出时钟驱动后级电路综合报告没有时序违规但上板后数据偶尔出错。原因分频时钟没有创建 generated clock 约束综合工具把它当成普通信号跨时钟域路径的建立保持时间没有被检查。解决在综合脚本里用create_generated_clock为分频时钟创建约束指定源时钟和分频比。如果分频器输出的是使能信号不需要额外约束但需要保证使能信号的路径延迟满足时序要求。5. 设计取舍什么时候该用分频器什么时候该用使能分频器和时钟使能是两种不同的设计思路选择哪一种取决于后级电路的需求和器件的时钟资源。分频器直接产生一个新时钟后级电路用这个时钟驱动触发器优点是代码直观后级电路不需要修改缺点是引入了新的时钟域需要额外的时序约束而且分频时钟的偏斜和抖动会影响后级电路的时序余量。时钟使能保持系统时钟统一后级电路在使能有效时更新状态优点是时序分析简单只有一个时钟域缺点是后级电路需要修改每个触发器都要加使能条件。在 FPGA 设计里常见的做法是低速逻辑用时钟使能高速逻辑用专用时钟管理单元。比如 50 MHz 系统时钟下需要 1 kHz 的采样率用时钟使能产生 1 kHz 的脉冲后级 ADC 接口在脉冲有效时采样。如果后级电路是一个独立的模块接口时钟必须是 1 kHz那就用分频器产生 1 kHz 时钟但要在模块边界加异步 FIFO 或者握手信号做跨时钟域处理。我一般会这么理解分频器是「造一个新时钟」时钟使能是「在旧时钟上开一扇窗」。造新时钟的代价是时钟树资源、时序约束和跨时钟域处理开窗的代价是后级电路需要感知使能信号。对于大多数中小规模设计时钟使能是更安全的选择因为时序收敛更容易调试也更简单。只有在后级电路必须用独立时钟驱动或者分频比非常大、使能脉冲太窄导致后级电路来不及响应时才考虑用分频器。从那以后我每次写分频器都会先问自己后级电路到底需要一个新时钟还是只需要一个「什么时候该动」的信号如果是后者我强制自己走一遍时钟使能的方案把分频器留到真正需要独立时钟域的场合。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

HALCON语义分割实战:金属表面缺陷像素级检测与部署全流程

HALCON语义分割实战:金属表面缺陷像素级检测与部署全流程

去年下半年接了一个某金属冲压件表面缺陷检测的评估项目,甲方要求不只是框出缺陷位置,还得把缺陷的轮廓给精确抠出来,为后续的缺陷面积统计提供依据。一开始我想着用传统算法走阈值分割加形态学处理,结果试了十几种打光方案&#…

2026/10/17 7:59:15 阅读更多 →
ZC706与ADRV9009开发实战:HDL、SDK与no-os工程搭建与调试

ZC706与ADRV9009开发实战:HDL、SDK与no-os工程搭建与调试

简介:本资源为基于Xilinx ZC706开发板与ADI ADRV9009高性能接收器的完整工程包,面向FPGA开发者、嵌入式工程师及高速信号处理研究者,解决从HDL接口设计到no-os裸机SDK开发的协同实现问题。压缩包共约2000个文件,整体201.1MB&#…

2026/10/17 7:59:15 阅读更多 →
Hive开窗函数over()实战指南:从原理到性能调优

Hive开窗函数over()实战指南:从原理到性能调优

1. 开窗函数不是“窗口”,而是数据透视的杠杆你刚接触Hive时,看到over()这个写法,第一反应可能是:“这不就是个括号吗?跟sum()、count()一起用,难道只是语法糖?”——我当年也是这么想的&#x…

2026/10/17 7:59:15 阅读更多 →

最新新闻

从傅里叶级数到傅里叶变换:非周期信号的频谱密度推导与实战

从傅里叶级数到傅里叶变换:非周期信号的频谱密度推导与实战

1. 从“非周期”这三个字说起1.1 信号分析里最常被跳过的一个动机问题我当年学“信号与系统”这门课,第一次对傅里叶变换产生困惑就是在教材的章节标题上:前面还在讲“周期信号的傅里叶级数”,后面突然跳到“非周期信号的傅里叶变换”。老师在…

2026/10/17 15:14:52 阅读更多 →
AI数学基础全解析:从线性代数到梯度下降的深度学习必备知识

AI数学基础全解析:从线性代数到梯度下降的深度学习必备知识

简介:这是一份关于人工智能数学基础的英文原版电子书,源自 Hala Nelson 撰写的《Essential Math for AI》,由 O’Reilly 于 2023 年出版。全书面向数据、商业领域以及数学背景较薄弱的读者,将线性代数、微积分、概率统计等核心数学…

2026/10/17 15:14:52 阅读更多 →
基于kNN的单分类异常检测:原理、Matlab代码与调参实战

基于kNN的单分类异常检测:原理、Matlab代码与调参实战

开头先聊一个场景。某设备厂商的现场监测项目里,工程师手里攒了上千条正常运行数据,但故障样本几乎没有——设备常年稳定运行,故障数据只能靠运气碰。这时候传统分类器根本训不了,因为二分类需要正负两类样本,而眼前只…

2026/10/17 15:14:52 阅读更多 →
基于Kafka构建延迟队列、重试队列与死信队列的生产级方案

基于Kafka构建延迟队列、重试队列与死信队列的生产级方案

Kafka 本身没有原生提供延迟消息、死信队列和重试队列,但借助它的分区机制、消费位移模型和 topic 存储能力,完全能搭出一套能上生产环境的队列体系。这篇文章我把这套方案的设计思路、核心配置和踩坑记录完整写出来,给同样被消息可靠性困扰的…

2026/10/17 15:14:52 阅读更多 →
airllm实战:低显存显卡也能轻松运行大语言模型

airllm实战:低显存显卡也能轻松运行大语言模型

如果你最近在折腾大语言模型的本地部署,肯定踩过显卡显存不足的坑。想跑一个像样的开源模型,动辄就要几十GB显存,普通显卡根本扛不住。我最近试了一个叫airllm的项目,它解决的就是这个痛点。airllm是一个专注于低资源环境下运行大…

2026/10/17 15:14:52 阅读更多 →
PLC与组态王机械手控制:从硬件接线到HMI交互的完整闭环实现

PLC与组态王机械手控制:从硬件接线到HMI交互的完整闭环实现

简介:本资源是一份面向电气自动化、工业控制类专业本科生的毕业设计完整文档,聚焦PLC与组态软件协同实现机械手自动控制的工程实践。内容覆盖机械手工作原理与功能需求分析、S7-200 PLC下位机设计(含I/O分配、顺序功能图、外围接线图及梯形图…

2026/10/17 15:13:51 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →