FPGA自编AXI4 Slave核:从XDMA到自定义IP的实战指南
简介这份资源面向FPGA与PCIe接口开发的中高级工程师聚焦XDMA核与AXI4协议数据读写链路中的关键一环——自编AXI4 Slave核的设计与实现解决AXI4事务与AXI4-Stream数据流之间协议转换、宽度匹配、流控与错误响应等实际问题。压缩包共15个文件约25KB以tcl脚本、Verilog源码、C与头文件为主另含mdd、makefile、sv及xml等覆盖IP打包、综合仿真、驱动与示例设计等用途目录按bd、hdl、drivers、xgui等模块组织便于快速集成到Vivado工程。目前已有5190人学习下载读者可从中获得可复用的Slave核RTL实现、IP封装脚本与测试平台理解FIFO缓冲、事务同步及流开始结束信号生成思路为高性能低延迟PCIe系统开发提供参考。1. 从 XDMA 到自编 AXI4 Slave为什么现成 IP 不够用手里有一块 FPGA 开发板PC 端要跑大数据吞吐XDMA 核一挂上AXI4 总线上立刻多出一堆读写请求。这时候你会发现一个尴尬的事XDMA 的 AXI4 Master 接口是现成的但你要挂的那个从设备——比如一块自定义的片上缓存、一组寄存器阵列、或者一个流式数据搬运通道——市面上根本没有刚好合适的 IP。Vivado 里倒是有 AXI4 的 Slave 模板但那个模板是给寄存器读写用的突发长度、Outstanding 能力、数据位宽全被写死稍微改一点就要动它的状态机改到最后还不如自己写一个。这就是这篇要聊的事在 XDMA 核已经跑通 PCIe 链路的前提下自己用 Verilog 写一个 AXI4 Slave 核接在 XDMA 的 M_AXI 接口上实现 PC 端到 FPGA 内部存储的稳定读写。适合两类人一类是已经调通了 XDMA 基础回环、想往里面塞自定义逻辑的另一类是被 AXI4 协议时序折腾过、想找一个能直接改的 Slave 参考实现。AXI4 和 AXI-Stream 的区别这里不展开但记住一点XDMA 的 M_AXI 是完整 AXI4带地址通道不是 Stream别搞混。2. AXI4 Slave 核的接口拆解与状态机设计2.1 五个通道到底谁先谁后AXI4 的五个通道——AW写地址、W写数据、B写响应、AR读地址、R读数据——协议里说它们相互独立但实际做 Slave 的时候读写通道之间的优先级和握手顺序直接决定会不会死锁。我一般把写通道和读通道做成两套独立的状态机写通道内部再分 AW 和 W 的会合逻辑。写通道的核心问题是AW 和 W 谁先到协议允许任意顺序所以 Slave 必须能缓存先到的那个。常见做法是用两个小 FIFO一个存 AW 的地址和突发信息一个存 W 的数据然后状态机从两个 FIFO 里同时取凑齐一笔就写一次存储。读通道相对简单AR 到了之后直接按突发长度连续吐 R 数据就行但要注意 R 的 LAST 信号必须跟 AR 的突发长度严格对齐差一个周期 PC 端就报错。注意XDMA 的 M_AXI 接口默认 Outstanding 能力不低如果你的 Slave 没有反压机制读请求堆多了会把 R 通道堵死。建议在 AR 通道加一个深度 4 到 8 的 FIFO 做缓冲。2.2 状态机怎么写才不翻车下面是我常用的写通道状态机骨架用三段式写法状态编码用独热码方便时序收敛。这段代码可以直接放进 Vivado 里综合接口信号名跟 XDMA 的 M_AXI 对得上。// 写通道状态机IDLE - GET_AW - GET_W - WRITE - RESP // 假设存储侧是一个简单双口 RAM 接口 localparam S_IDLE 4b0001; localparam S_GET_AW 4b0010; localparam S_GET_W 4b0100; localparam S_WRITE 4b1000; localparam S_RESP 4b10000; // 实际用 5 位这里示意 reg [4:0] cur_state, nxt_state; reg [31:0] aw_addr_reg; reg [7:0] aw_len_reg; reg [2:0] aw_size_reg; reg [1:0] aw_burst_reg; reg aw_valid_reg; reg [31:0] w_data_reg; reg [3:0] w_strb_reg; reg w_last_reg; always (posedge clk or negedge rst_n) begin if (!rst_n) cur_state S_IDLE; else cur_state nxt_state; end always (*) begin nxt_state cur_state; case (cur_state) S_IDLE: begin if (s_axi_awvalid s_axi_wvalid) nxt_state S_WRITE; // 地址和数据同时到直接写 else if (s_axi_awvalid) nxt_state S_GET_AW; // 先到地址 else if (s_axi_wvalid) nxt_state S_GET_W; // 先到数据 end S_GET_AW: begin if (s_axi_wvalid) nxt_state S_WRITE; end S_GET_W: begin if (s_axi_awvalid) nxt_state S_WRITE; end S_WRITE: begin if (w_last_reg) nxt_state S_RESP; end S_RESP: begin if (s_axi_bready) nxt_state S_IDLE; end default: nxt_state S_IDLE; endcase end这段状态机的逻辑说明IDLE 状态同时检测 AW 和 W 的 valid谁先到就进对应的缓存状态等另一个也到了再进 WRITE。WRITE 状态里每写一个数据就判断 w_last如果是最后一拍就跳 RESP 发 B 响应。参数方面aw_len_reg 存的是突发长度减一AXI4 的 INCR 模式下实际传输拍数是 len1这个减一操作在接收 AW 的时候就要做掉不然后面地址计算会多算一拍。2.3 地址对齐和 4K 边界AXI4 协议里有一条硬规矩一笔突发不能跨 4KB 边界。XDMA 作为 Master 一般会遵守但你自己写 Slave 的时候如果地址计算逻辑有 bug比如把 aw_addr_reg 直接累加而不检查低位就可能出现跨边界访问。我的做法是在 WRITE 状态里每拍检查当前地址的低 12 位如果加上传输宽度之后超过 0xFFF就提前拉高 B 响应的错误标志——虽然 XDMA 不一定理你但至少仿真波形里能一眼看出来。地址对齐还有一层aw_size_reg 表示每拍传输的字节数2b10 是 4 字节2b11 是 8 字节。如果你的存储侧位宽是 64 位而 AXI 数据位宽是 32 位就要做位宽转换这个转换逻辑放在 WRITE 状态里做不要放到状态机外面否则时序会很难看。3. 把 Slave 核挂到 XDMA 上地址映射与位宽匹配3.1 地址窗口怎么划XDMA 核的 M_AXI 接口出来之后地址空间是 PC 端 BAR 映射过来的。假设你在 Vivado 里给 XDMA 配了 1MB 的 BAR 空间那 Slave 核能看到的地址范围就是 0x0000_0000 到 0x000F_FFFF。我一般把这段空间再切一刀低 512KB 给寄存器组高 512KB 给数据缓存。寄存器组用一个小型的 AXI4-Lite Slave 处理数据缓存用上面那个完整 AXI4 Slave 处理。地址译码的逻辑很简单在 AW 通道的 valid 握手时判断地址高位// 地址译码根据 aw_addr_reg 的 bit19 区分寄存器区和数据区 wire sel_reg (aw_addr_reg[19] 1b0); wire sel_mem (aw_addr_reg[19] 1b1); // 只有选中对应区域时才拉高该区域的 awready assign reg_awready sel_reg ? s_axi_awready : 1b0; assign mem_awready sel_mem ? s_axi_awready : 1b0;这里有个坑两个 Slave 的 awready 不能同时拉高否则 XDMA 会收到两个响应行为未定义。用地址位做互斥是最稳妥的别用优先级编码器那个在高速时序下容易出毛刺。3.2 位宽不匹配怎么办XDMA 的 M_AXI 数据位宽常见的是 64 位或 128 位而你的内部存储可能是 32 位。位宽转换有两种做法一种是写一个专门的位宽转换模块把 64 位拆成两个 32 位另一种是在 Slave 状态机里直接处理用 w_strb 信号控制哪些字节有效。我倾向于第二种因为少一层模块少一层时序压力。具体做法是在 WRITE 状态里判断 w_strb如果当前拍只有低 32 位有效就只写低 32 位如果高 32 位也有效就分两拍写。但这样会拉长写周期如果 XDMA 的写吞吐要求高还是老老实实加一个异步 FIFO 做位宽转换。提示位宽转换模块的 FIFO 深度建议至少 16因为 XDMA 的突发长度可能到 256深度太小会频繁反压反而降低吞吐。3.3 读写通道的仲裁当读通道和写通道同时有请求时存储侧只有一个端口必须仲裁。我的做法是给写通道更高优先级因为写响应 B 如果迟迟不发PC 端的写事务会堆积最终导致驱动层超时。读通道可以稍微等一等R 数据的延迟对 PC 端来说通常比写响应更宽容。仲裁逻辑用一个简单的优先级选择器// 存储侧端口仲裁写优先 assign mem_wr_en (cur_state S_WRITE); assign mem_rd_en (cur_state S_RESP) ? 1b0 : ar_valid_reg; // 当写状态机活跃时读请求被挂起这段逻辑的意思是只要写状态机不在 IDLE读请求就不放行。实际项目中如果读写比例接近 1:1这种策略会导致读吞吐下降这时候就要改成轮询仲裁。轮询仲裁的实现稍微复杂一点需要一个 last_grant 寄存器记录上次谁被服务。4. 仿真验证与上板调试从波形到眼图4.1 Testbench 怎么搭才像真的自己写 Slave 核Testbench 不能只发几笔单次读写就完事。XDMA 的行为特点是突发长度不固定、Outstanding 深度大、读写交织。我一般用 SystemVerilog 写一个简单的 AXI4 Master BFM随机生成突发长度1 到 16 拍、随机地址4KB 对齐、随机读写比例。// 简化的 AXI4 Master 激励随机突发 task automatic send_write(input [31:0] addr, input [7:0] len); // 拉高 awvalid等待 awready s_axi_awaddr addr; s_axi_awlen len; s_axi_awvalid 1b1; wait (s_axi_awready); (posedge clk); s_axi_awvalid 1b0; // 发数据 for (int i 0; i len; i) begin s_axi_wdata $random; s_axi_wstrb 8hFF; s_axi_wlast (i len); s_axi_wvalid 1b1; wait (s_axi_wready); (posedge clk); end s_axi_wvalid 1b0; // 等 B 响应 wait (s_axi_bvalid); (posedge clk); s_axi_bready 1b1; (posedge clk); s_axi_bready 1b0; endtask这个 task 的关键参数是 len它决定突发拍数。仿真的时候把 len 从 0 到 15 都跑一遍重点看 wlast 和 bvalid 的时序关系。如果 bvalid 在 wlast 之前就拉高了说明状态机跳转条件写错了。4.2 ILA 抓什么信号上板之后Vivado 的 ILA 是唯一的黑匣子。我一般抓这几组信号s_axi_awvalid/awready、s_axi_wvalid/wready/wlast、s_axi_bvalid/bready、s_axi_arvalid/arready、s_axi_rvalid/rready/rlast。触发条件设在 awvalid 和 wvalid 同时为高的那拍这样能抓到一笔完整的写事务。抓到的波形重点看三个地方第一awready 和 wready 有没有同时拉高导致数据错位第二bvalid 的持续时间够不够长XDMA 的 bready 有时候会延迟几个周期才来第三rlast 和 arlen 是否匹配差一拍就会导致 PC 端读到的数据错位。注意ILA 的采样深度有限如果抓 256 拍突发的读事务深度至少设 4096否则看不到 rlast。4.3 性能瓶颈在哪上板跑通之后用 PC 端的测试程序跑一个 1GB 的连续读写看实际带宽。如果带宽远低于 XDMA 的理论值先查 Slave 的反压频率。反压太频繁说明存储侧带宽不够要么加 FIFO 深度要么提高存储时钟频率。另一个常见瓶颈是位宽转换64 位转 32 位如果每拍都转吞吐直接减半这时候要考虑用位宽转换 FIFO 做批量转换。5. 避坑与排查那些让我重写过三次的细节5.1 坑一awready 和 wready 同时拉高导致数据丢失现象仿真波形里看到 awready 和 wready 在同一拍拉高但存储侧只写进去了一拍数据后面几拍全丢了。原因状态机在 IDLE 状态同时判断 awvalid 和 wvalid如果两个同时为高就直接跳 WRITE但跳转的那一拍没有把 aw 的地址信息锁存下来导致 WRITE 状态里用的地址是上一笔的残留值。解决在 IDLE 跳 WRITE 的那一拍用组合逻辑把 awaddr 和 wdata 同时打入寄存器或者改成先跳 GET_AW 再跳 WRITE多一个周期但逻辑清晰。我后来统一改成后者宁可多一拍也不冒这个险。5.2 坑二B 响应提前拉高导致 PC 端报错现象PC 端驱动打印 unexpected completionILA 波形显示 bvalid 在 wlast 之前就拉高了。原因状态机在 WRITE 状态里判断 wlast 的条件写成了 wvalid wready但 wready 是存储侧给的如果存储侧提前拉高 wreadywlast 还没到就误判了。解决wlast 的判断必须用 wvalid wready s_axi_wlast 三个条件与缺一不可。另外 B 响应的 bresp 要固定给 2b00OKAY除非你真的要报错否则 XDMA 收到 SLVERR 会直接断链路。5.3 坑三读通道 rlast 与 arlen 不匹配现象PC 端读回来的数据整体偏移了 4 个字节或者最后几个字节是 0。原因AR 通道的 arlen 是突发长度减一但 R 通道的 rlast 是在第 arlen1 拍拉高。如果状态机里用 arlen 直接计数就会少发一拍或者多发一拍。解决在 AR 握手时把 arlen 锁存到 arlen_regR 状态里用一个计数器从 0 计到 arlen_reg计数器等于 arlen_reg 时拉高 rlast。计数器位宽要够arlen 最大 255所以计数器至少 8 位。5.4 坑四跨时钟域导致数据错位现象XDMA 的时钟和存储侧时钟不同频上板后偶尔读到错误数据仿真却没问题。原因AW/W/AR/R 通道的信号没有做跨时钟域同步亚稳态导致握手失败。解决在 XDMA 和 Slave 之间加异步 FIFO或者用双寄存器同步器处理 valid/ready 信号。注意 ready 信号跨时钟域要用脉冲同步器不能简单打两拍。5.5 坑五4KB 边界检查漏掉了写通道现象PC 端连续写 8KB 数据前 4KB 正常后 4KB 全错。原因地址译码只检查了读通道的 4KB 边界写通道的地址累加逻辑没有做边界判断导致第二笔突发跨了 4KB 边界但 Slave 没有报错数据写到了错误的存储位置。解决在 WRITE 状态里每拍检查 aw_addr_reg[11:0] 传输字节数是否超过 0x1000超过就拉高 bresp 的 SLVERR 并提前结束突发。虽然 XDMA 不一定会重试但至少不会静默写错。6. 进阶技巧用 AXI-Stream 做数据旁路Slave 核跑通之后如果数据不需要落到存储而是直接转发给另一个模块处理可以在 Slave 内部加一个 AXI-Stream 旁路通道。具体做法是在 WRITE 状态里判断地址是否落在旁路窗口如果是就不写存储直接把 wdata 推到 m_axis_tdata 上同时拉高 m_axis_tvalid。读通道同理从 s_axis_tdata 取数据填到 rdata 上。这个旁路通道的握手逻辑要注意AXI-Stream 的 tready 是反压信号如果下游模块没准备好Slave 必须把 wready 拉低否则数据就丢了。我一般用一个深度 8 的 FIFO 做缓冲FIFO 满的时候拉低 wready这样既能吸收突发又不会丢数据。验证旁路通道是否正常最简单的办法是在 PC 端发一笔写事务地址落在旁路窗口然后在 ILA 里看 m_axis_tvalid 和 m_axis_tdata 是否跟 wdata 一致。如果 tvalid 拉高了但 tdata 是旧值说明 FIFO 的读使能时序有问题检查 fifo_rd_en 是不是在 tvalid 之前就拉高了。从那以后我每次写完 Slave 核都会先用一个 1KB 的随机数据做回环测试PC 端写进去再读出来逐字节比对。这个习惯帮我省掉了至少三次上板后才发现数据错位的返工。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

系统缩放导致页面错位?前端适配DPR与响应式布局实战

系统缩放导致页面错位?前端适配DPR与响应式布局实战

1. 缩放比例到底动了什么手脚很多人第一次遇到这个问题,场景都差不多:自己电脑上开发时页面工工整整,换到同事的笔记本上一看,要么整体变小挤在左上角,要么元素错位、弹窗跑到屏幕外面去了。第一反应往往是"浏览器…

2026/10/17 12:19:03 阅读更多 →
Pillow图像处理实战:从像素操作到图形学核心概念

Pillow图像处理实战:从像素操作到图形学核心概念

1. 项目概述1.1 从图像处理到图形学:Pillow到底能做什么如果你刚接触计算机图形学,又不想一上来就啃OpenGL、DirectX那种庞然大物,那么Pillow是一个非常合适的切入点。Pillow(PIL分支的延续版本)是Python生态里最老牌、…

2026/10/17 14:04:34 阅读更多 →
Oracle分批查询实践:从ROWNUM到keyset分页与批量DML优化

Oracle分批查询实践:从ROWNUM到keyset分页与批量DML优化

做 Oracle 开发或者 DBA 的,迟早会遇到一个场景:一张上千万行的核心表,业务说要按时间导出全部明细,或者要一次性把历史数据按状态批量刷掉。我早年接手一个报表接口,某次运营导出近三个月订单,接口直接卡死…

2026/10/16 10:37:29 阅读更多 →

最新新闻

数据结构链表实战:一元稀疏多项式计算与C语言实现

数据结构链表实战:一元稀疏多项式计算与C语言实现

这几年我带过不少学生做数据结构上机题,要说哪道题最容易被低估,一元稀疏多项式的计算绝对排得上号。这道题来自某高校的数据结构课程上机环节,题面看起来只是“计算两个多项式之和/积”,但实际做起来牵扯到链表的设计、有序插入、…

2026/10/17 14:05:57 阅读更多 →
Dify PDF解析实战:提升RAG知识库召回率的完整方案

Dify PDF解析实战:提升RAG知识库召回率的完整方案

"dify-pdf"并不是官方仓库里那种开箱即用的插件,至少在我折腾这套方案的阶段,官方知识库还没有一个能同时搞定扫描件、多栏排版和表格还原的PDF解析器。它更像是我围绕Dify平台沉淀下来的一套组合拳:知识库上传负责基础解析&#x…

2026/10/17 14:05:57 阅读更多 →
Spring Boot注册功能开发指南:用户表设计、密码加密与接口幂等性

Spring Boot注册功能开发指南:用户表设计、密码加密与接口幂等性

从“Javaspringboot 后端注册”这个标题出发,很多刚入行的小伙伴会觉得这不就是一个注册接口嘛,用户名密码存进去就完事了。但真到项目里落地,或者面试被问到细节的时候,你才会发现,一个看起来平平无奇的注册功能&…

2026/10/17 14:05:57 阅读更多 →
Claude Code 接入 11 个 MCP 服务器:从 AI 助手到真正开发同事

Claude Code 接入 11 个 MCP 服务器:从 AI 助手到真正开发同事

说实话,我第一次看到“Claude Code 一站式体验:11 个 MCP 服务器赋能 AI”这个标题时,心里是有点嘀咕的——MCP 服务器这东西,到底是真的能干活,还是又一轮配置折腾?直到我花了一周时间,在一台测…

2026/10/17 14:05:57 阅读更多 →
Flink手动维护Kafka Offset全解析:原理、实操与踩坑指南

Flink手动维护Kafka Offset全解析:原理、实操与踩坑指南

干这行久了,一定会遇到“Flink手动维护kafka的offset”这种需求。大多数情况下Flink的Kafka connector会自动帮你把消费位点交给checkpoint管理,恢复、重启都很省心,但总有那么几个场景跑不脱手动维护:比如任务从没开checkpoint&a…

2026/10/17 14:05:57 阅读更多 →
STM32+PT100温度采集系统:从恒流源电路到ADC插值计算的完整方案

STM32+PT100温度采集系统:从恒流源电路到ADC插值计算的完整方案

简介:基于STM32单片机与PT100铂电阻的温度采集系统资料包,整合程序源码、原理图与全套开发文档,适用于嵌入式初学者及从事工业温度监测项目开发的工程师。整个压缩包共277个文件,大小约18.09MB,主要包含62个C源文件、5…

2026/10/17 14:04:56 阅读更多 →

日新闻

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 阅读更多 →