新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于Radix-2 SRT算法的无符号除法器设计与FPGA实现

发布时间:2026/9/3 4:58:47来源:尧图网络
基于Radix-2 SRT算法的无符号除法器设计与FPGA实现
简介这是一份基于 Verilog 的无符号 Radix-2 SRT 除法器设计资源适合数字逻辑、FPGA 或 IC 设计初学者用于理解基2 SRT 算法的硬件实现与仿真验证。压缩包共 6 个文件主体为 3 个 Verilog 源码文件分别承担 RTL 除法核心、辅助子模块与测试台顶层另附 README 说明、Matlab 仿真对比脚本及工程配置信息整体仅 5KB结构紧凑、便于精读与快速上手。已有 1292 人学习下载。读者可借助 RTL 主文件与测试台搭建的仿真环境观察无符号基2 SRT 除法的商数生成、余数更新和移位控制流程配套 Matlab 脚本还能辅助进行算法级与 RTL 级结果对照适合作为计算机组成原理或数字设计课程中除法器章节的课下练习资料。 做硬件除法器这件事说大不大说小不小。前阵子在调试一个RISC-V教学核指令集里要补一条无符号除法指令。一开始想直接调IP核但IP核延迟、资源、时序都不是自己控制的仿真时看不到内部状态出了问题根本没法排。于是干脆自己写一个无符号Radix-2 SRT除法器。做完之后把整个设计思路、商选择表的产生方式、还有几个踩过的坑整理出来希望对同样在折腾除法器的人有点帮助。这篇内容适合谁看如果你在做FPGA信号处理、在给CPU写除法指令、或者只是想把“除法器”这个黑盒变成自己可控的模块都可以参考。我假设读者对二进制补码、状态机、Verilog基础语法有基本了解但不需要你提前研究过除法器的各种论文。1. 为什么选Radix-2 SRT从慢速除法到快速除法1.1 除法器的真实痛点除法和加、减、乘不一样。加法器可以并行算完所有位的进位乘法器可以把部分积展开成树形结构并行压缩。但除法本质上是一个“串行试商”的过程这一拍的商选错了会直接影响下一拍的部分余数后面所有结果都得跟着错。所以除法器的速度瓶颈不在加减法本身而在“每一步的商怎么选”。传统教科书里教的恢复余数除法每拍要做一次全宽度的减法然后看结果符号决定商位是0还是1。如果余数为负还要把除数加回来“恢复”余数。这一步不仅多了一次加法而且全宽度比较器的延迟会直接落在关键路径上。不恢复余数除法省掉了恢复操作但仍然需要一个N位加法器出结果后才能判断商的符号周期照样快不了。SRT算法是另一条路它允许商位取值变成{-1, 0, 1}。这个“允许负商位”的改动看上去只是数字集合变了实际上把“每拍必须精确判断”变成了“每拍只需要大致判断”硬件上正是靠这个自由度做出速度的。1.2 SRT把“精确判断”换成“容错迭代”Radix-2 SRT除法的迭代核心是这一条w[j1] 2 * (w[j] - q[j] * D)其中w[j]是第j拍的部分余数D是除数q[j]是第j拍选出的商位只能取-1、0、1三种值。整体约束是让部分余数始终被限制在一个安全区间内一般要求|w|不超过一个跟D有关的常数。这个公式真正有意思的地方在于它不要求你把2w和D的完整大小关系比出来只要判定2w落在哪个区域就行。判定可以基于截断的高位来实现不必用全宽度比较器。打个比方传统除法像是称体重必须精确到克才知道该往哪边调整SRT像是看一眼指针大致在哪个区间就敢动手调就算调过头了下一拍还能拉回来。1.3 常见除法器方案对比方案每拍产出商位数商位集合关键路径典型用途恢复余数除法1位0/1全宽减法比较教学、低复杂度场景不恢复余数除法1位0/1全宽加法器软核CPU、简单硬件除法Radix-2 SRT1位-1/0/1截断比较加减D浮点尾数除法、通用除法器Radix-4 SRT2位-2/-1/0/1/2高位比较多路选择高性能处理器这张表能看出来基2 SRT的每拍产出商位数和普通除法一样都是1位但它把关键路径从“全宽度比较全宽度减法”缩短成了“高位截断比较加减D选择”。这个周期优势才是它被广泛用在浮点运算单元里的原因。2. 关键电路拆解商选择、数据通路与位宽设计2.1 商选择表是怎么算出来的整个SRT除法器最核心的模块就是商选择逻辑它决定一拍要选哪个q。设计目标很简单保证w[j1]不会逃出安全范围。假设我们约定每次迭代后|w| ≤ 2D这个边界不同实现不一样但思想相同。那么对于当前w如果2w比D大不少选q1是合理的如果2w比负D小不少选q-1如果2w就在中间选q0最安全。工程上不可能每个周期都把w和D做全宽度比较所以办法是只看w的高几位和D的高几位。例如w取高5位转成4位比较量D取高3位然后查一张很小的表。表里的判断条件可以用Verilog的case语句实现也可以写成一段组合逻辑判断。这里有一个特别容易搞错的地方公式里比较的是2w不是w。如果你的部分余数寄存器存的是w那做比较时要么把w左移一位再截断要么取w的高5位然后用前4位参与判表。不少人第一次写的时候直接拿w的高4位去判结果边界偏移了一位仿真就会出现偶发错误。商选择表中的阈值不一定唯一不同的阈值得到不同的表只要满足不收敛条件就行。我自己的做法是写一个Python脚本把所有可能的w截断值和D截断值枚举一遍检查在当前选择下w是否仍然落在安全范围不满足的组合直接标记出来。这样生成的表比手推边界可靠得多。2.2 部分余数寄存器与位宽选择部分余数寄存器w的位宽是整个设计的根基。因为它可能为负必须用补码表示而且因为每拍要乘2还要留出足够的进位保护位。我通常会设置w的位宽为N4其中N是除数D的位宽。比N多出来的4位里2位用来扩展符号位和整数部分2位用来降低截断误差。太少的位置会压缩商选择表的判断区间导致表设计非常别扭位置太多又浪费寄存器资源。这个值是我在32位除法器里实测比较舒服的一个折中。D的位宽可以保持N位但如果要做规格化后面会讲实际参与迭代的D要左移过所以D寄存器本身也要能容纳左移后的值。最稳妥的做法是D和w统一用N4位宽度减少位宽对齐的思考负担。2.3 商重建为什么不能直接把q塞进商寄存器很多新手做完SRT迭代后发现商不对根本原因是没有理解“商位q是冗余编码”这件事。每拍选出的q是-1或0或1它并不是最终的二进制商位不能直接塞进一个普通移位寄存器里。正确的做法是维护两个寄存器一个记录“出现过1的位置”另一个记录“出现过-1的位置”。比如第3拍选了q1那pos寄存器的第3位写1neg寄存器第3位写0如果某拍选了-1就反过来。迭代结束后真正的商等于pos减neg。这个减法需要在最后额外做一次但它的成本很低不在关键路径上完全不影响每拍的周期。如果你在做的是高基数SRT比如基4的q集合包含±2那么商重建会更复杂需要多个位的编码。基2的好处就在这里商重建只需要两个移位寄存器和一个减法器。3. 可综合实现Verilog框架与迭代状态机3.1 顶层模块和端口定义我习惯把除法器做成一个独立的模块方便在其他地方实例化。顶层端口大概是这样的module div_radix2_srt #( parameter N 32 )( input wire clk, input wire rst_n, input wire start, input wire [N-1:0] dividend, input wire [N-1:0] divisor, output reg done, output reg [N-1:0] quotient, output reg [N-1:0] remainder );start信号拉高一拍后开始运算done信号拉高表示结果有效。这种接口在总线模块里接起来很方便无论挂在CPU总线上还是FPGA的AXI-Lite上都能直接适配。内部模块我分成三块规格化预处理、迭代核心、商重建和余数调整。规格化预处理不一定在第一次做的时候就能意识到要加但它恰恰是整数除法能不能直接用SRT的关键。3.2 迭代状态机与规格化预处理SRT算法天然是“小数除法”的思路它要求被除数和除数都落在比较接近的范围内然后迭代出一串小数商位。而这里做的是无符号整数除法被除数A完全可能比除数D大几十倍所以不能直接送进迭代核心。我的做法是对D做前导零计数clz_d把D左移clz_d位让D的MSB为1这样D就落在[1,2)这个归一化区间。对被除数A也左移clz_d位让A落在同一数量级下。如果A仍然大于等于D说明商的整数部分不为0。这种情况要处理要么预先把A右移一位并在最终商的高位补1要么在状态机中多做一步处理。这一步是最容易埋坑的。因为A左移clz_d之后它的位宽可能超过了N需要把A和D都扩宽到N4甚至N5位再进迭代否则最高位被截掉结果差一截。迭代控制相对简单计数器从0跑到N每拍更新一次w。状态机有idle、compute、finish三个状态。compute阶段每个周期做一次w更新和q记录finish阶段做商重建和余数调整。之所以要把finish单独一个状态是因为最后的Qpos-neg减法需要一拍不能跟最后一步迭代挤在同一拍里。3.3 商选择模块的可综合写法商选择逻辑最直观的写法是一大段case语句。以4位截断余数加3位截断除数为示例表的基本形式可以写成always (*) begin case ({twoR_est, d_est}) // 2w明显大于0区间选1 4b0101, 4b0110, 4b0111: q 2b01; // 2w明显小于0区间选-1 4b1001, 4b1010, 4b1011: q 2b11; // 中间区域选0 default: q 2b00; endcase end这里q我用了2bit编码方便后续处理2’b01表示12’b11表示-1也就是补码-12’b00表示0。用补码表示负q后面做w更新和商重建都统一。上面这个case只是为了展示写法实际阈值不能照抄。不同位宽、不同安全区间的表项差异很大需要用脚本生成并验证。这里强烈建议做一次全边界穷举验证不要只靠手工挑选几个典型值。3.4 关键路径与时序优化思路基础版SRT每拍的关键路径是截断比较器 → 选择器选±D或0→ 加法器 → 寄存器。这条路径比全宽减法短很多因为截断比较器的逻辑深度很小选择器和加法器才是大头。如果时序还是不满足可以考虑把部分余数w用进位保存加法器CSA来表示也就是把w拆成sum和carry两个寄存器每次迭代不再做完整加法只是把新的部分积压进去。这样每拍的关键路径就缩短成一个CSA压缩器加比较器。代价是商选择逻辑要能处理两个寄存器表示的冗余值复杂度会明显上升。我的建议是第一次实现先用普通补码加非冗余w先把功能跑通再用随机测试验边界。确认算法没有任何问题之后再考虑用CSA做时序优化。一上来就上CSA出错了很难定位是算法问题还是电路问题。4. 调试实录仿真验证与常见坑4.1 商选择表边界不收敛这个问题的症状很典型仿真跑到一半部分余数突然跳到特别大的值之后所有商位都乱了最终结果差得很离谱。排查思路是打印每一拍的w、2w、q和D盯着w有没有超出安全区间。一旦发现w超出就说明当前这一拍商选错了。然后拿着这一拍的2w截断值和D截断值去对照商选择表看表里是不是给了个错误的选择。我之前遇到过一次原因是生成商选择表时没有考虑D的高位。只看2w的高位就选q在某些D比较小的边界上会选错。后来改成“2w高4位D高3位联合查表”边界情况才稳定下来。4.2 商重建值差一个LSB如果迭代过程完全没有越界但最终商总是比期望值小1或大1问题基本出在商重建的减法上。pos和neg两个寄存器都表示的是加权和它们的位权重关系取决于你把哪一拍当作二进制点后的第一位。如果迭代了N拍最后减出来还要考虑截断方向。另外如果某几拍选了q0pos和neg在该位都是0这些位置不能遗漏否则商的权重就错了。调试办法很简单写一个小的参考模型所有中间信号都导出比对pos和neg在每一拍的值。找到第一拍发生偏差的位置再去查那一步的q是否与参考模型一致。4.3 规格化移位后的输出换算混乱这个坑几乎每个做整数SRT的人都会踩一次。比如D的前导零个数是ldA左移了ld位参与迭代最后迭代余数w_final对应的是“归一化后的被除数”的余数不是原始A的余数。要想得到真实余数得把w_final右移ld位而且要考虑负数余数时的符号扩展。商的换算更隐蔽。因为它本质上是在一个缩放过的小数域里计算最后的结果可能还要根据A是否大于D做修正。我踩过最痛的一次是32位里算“5除以3”因为D的前导零很多迭代完余数寄存器里是一个2的30次方量级的大数代码写错了右移量余数输出完全不对。解决这类问题的最好办法是在状态机里专门记录预处理的移位量finish阶段再根据这个移位量做一次统一的商和余数校准不要在外围总线模块里散落着各种移位操作。4.4 验证用例与仿真脚本建议SRT除法器的验证不能只靠几组手算用例我建议分三层来测。第一层是边界用例被除数为0、除数为0需要单独判断否则迭代不收敛、被除数等于除数、被除数是除数的两倍、除数最高位为1、被除数最高位为1。第二层是随机测试用Python或者SystemVerilog的随机数生成跑上万组随机无符号数和C语言或者Python里的整数除法结果逐组比对。这一步能覆盖大部分边界组合。第三层是定向压力测试故意构造让商选择表处于临界状态的用例。怎么构造让被除数和除数的前几位相同或者让部分余数w恰好卡在滞回窗口附近。这些用例往往是随机测试覆盖不到的。我的验证脚本习惯是把所有失败用例的输入、期望输出、实际输出打到一个日志文件里然后写一个Python脚本解析自动算出差值分布。如果所有失败都是同一个差值那多半是商重建或者寄存器位宽的问题很快就能定位。最后说一个个人习惯每次修改商选择表或者位宽之后第一件事不是跑完整随机测试而是先跑一遍边界用例和上一次失败的那几个用例。因为SRT的商选择表对边界极其敏感可能你只是把截断位宽从4位改成5位之前验证通过的某些边界又变成不收敛了。保留一组历史回归用例比什么都管用。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

从“XQL出发首尔啦”说开去:技术写作必须依托真实输入 2026/9/3 5:52:57

从“XQL出发首尔啦”说开去:技术写作必须依托真实输入

根据当前输入内容,“XQL出发首尔啦” 这个项目标题无法生成符合要求的 CSDN 技术博客。原因很简单:当前任务要求产出的是一篇具备技术深度、环境搭建、代码示例、问题排查和工程建议的 CSDN 技术长文,但这次输入中没有任何技术关键词、项目说…

阅读更多 →
Python自动化脚本实战:从网页抓取到数据处理全流程解析 2026/9/3 5:52:57

Python自动化脚本实战:从网页抓取到数据处理全流程解析

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

阅读更多 →
Replit免费模式调整背后:AI编程与云IDE的成本博弈 2026/9/3 5:52:57

Replit免费模式调整背后:AI编程与云IDE的成本博弈

如果你最近关注 Replit,大概率会看到两类声音:一类是说它“变了”“免费用户越来越难用”,另一类是感叹它的 AI Agent 一键生成应用确实强。这两种感受其实指向同一件事:Replit 的免费模式正在发生结构性调整,不再是早…

阅读更多 →
基于OpenPose与行为分析的老年人跌倒检测系统:从原理到工程实践 2026/9/3 5:52:57

基于OpenPose与行为分析的老年人跌倒检测系统:从原理到工程实践

简介:本资源是一套基于OpenPose的人体姿态检测实战项目源码,面向计算机视觉初学者与智慧养老应用开发者,聚焦老年人日常行为监护场景,支持站立、坐姿、躺卧及摔倒等关键状态识别。压缩包共578个文件,含382张标注图像&a…

阅读更多 →
小电容点焊机原理与实战:DIY锂电池焊接安全指南 2026/9/3 5:52:57

小电容点焊机原理与实战:DIY锂电池焊接安全指南

最近想给手头的几个小风扇、蓝牙音箱换个电池,或者DIY个充电宝,你是不是也纠结过:用烙铁焊接电池太危险,专业点焊机又贵又占地方?市面上那些几百块的小电容点焊机,到底能不能用,是不是“玩具”&…

阅读更多 →
多级CIC滤波器Verilog实现:从原理到FPGA工程实践 2026/9/3 5:49:56

多级CIC滤波器Verilog实现:从原理到FPGA工程实践

简介:本资源是一套基于Verilog实现的多级CIC(积分梳状)滤波器完整工程,面向数字信号处理工程师、FPGA开发初学者及通信系统设计人员,解决采样率转换中高效低开销滤波器的设计与硬件实现问题。压缩包含169个文件&#x…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞