verilog除法器设计

2023-11-05

除法器原理

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

除法器设计

单独除法器设计

单步被除数位宽(信号 dividend)需比原始除数(信号 divisor)位宽多 1bit 才不至于溢出。为了便于流水,输出端需要有寄存器来存储原始的除数(信号divisor_orang_r)和被除数信息(信号 dividend_orang_r)。单步的运算结果就是得到新的 1bit 商数据(信号 merchant)和余数(信号 remainder)。为了得到最后的除法结果,新的 1bit 商数据(信号 merchant)还需要与上一周期的商结果(merchant_last)进行移位累加。单步运算单元设计如下(文件名 divider_cell.v):

module divider_cell#(
    parameter N = 5,
    parameter M = 3
    )
    (
    input  wire             clk,
    input  wire             rst_n,

    input  wire             en,
    input  wire [N-1:0]     dividend_orang,         //原始被除数
    input  wire [M-1:0]     divisor_orang,          //原始除数
    output reg  [N-1:0]     dividend_orang_r,       //原始被除数
    output reg  [M-1:0]     divisor_orang_r,        //原始除数

    input  wire [M:0]       dividend,               //本轮被除数
    input  wire [N-1:0]     merchant_last,          //上一轮商结果

    output reg              valid,                  //本轮商有效标识
    output reg  [N-1:0]     merchant,               //本轮商
    output reg  [M-1:0]     reminder                //本轮余数
    );

always@(posedge clk) begin 
    if(en) begin 
        dividend_orang_r <= dividend_orang;
        divisor_orang_r  <= divisor_orang;
    end
    else begin 
        dividend_orang_r <= 'b0; 
        divisor_orang_r  <= 'b0; 
    end
end

always@(posedge clk) begin 
    if(!rst_n) begin 
        valid <= 1'b0;
    end
    else begin 
        valid <= en;
    end
end

always@(posedge clk) begin 
    if(!rst_n) begin 
        merchant <= 'b0;
        reminder <= 'b0;
    end
    else begin 
        if(en) begin 
            if(dividend >= {1'b0, divisor_orang}) begin 
                merchant <= (merchant_last<<1) + 1'b1;
                reminder <= dividend - {1'b0, divisor_orang};
            end
            else begin 
                merchant <= merchant_last<<1;
                reminder <= dividend[M-1:0];
            end
        end
        else begin 
            merchant <= 'b0;
            reminder <= 'b0;
        end
    end
end

endmodule

流水线例化

流水线除法器能够实现流水计算,在N个周期连续计算出N个结果。
将单步计算的余数(信号 remainder)和原始被除数(信号 dividend)对应位的 1bit 数据重新拼接,作为新的单步被除数输入到下一级单步除法计算单元。其中,被除数、除数、及商的数据信息也要在下一级运算单元中传递。流水级模块例化完成除法的设计如下(文件名 pipeline_divider.v):

module pipeline_divider_top#(
    parameter N = 32,                           //被除数位宽
    parameter M = 32                            //除数位宽
    )
    (
    input  wire             clk,
    input  wire             rst_n,
    
    input  wire             en,
    input  wire [N-1:0]     dividend,
    input  wire [M-1:0]     divisor,

    output wire             valid,
    output wire [N-1:0]     merchant,
    output wire [M-1:0]     reminder
    );

    wire [N-1:0]    dividend_orang [N-1:0];     //原始被除数、除数连线,需要N条
    wire [M-1:0]    divisor_orang [N-1:0]; 

    wire [N-1:0]    valid_cell;                 //valid连线,需要N条
    wire [N-1:0]    merchant_cell [N-1:0];      //商结果,需要N条
    wire [M-1:0]    reminder_cell [N-1:0];      

divider_cell#(
    .N        ( N ),
    .M        ( M )
)u_divider_cell(
    .clk      ( clk      ),
    .rst_n    ( rst_n    ),
    .en       ( en       ),
    .dividend_orang   ( dividend   ),
    .divisor_orang    ( divisor    ),
    .dividend_orang_r ( dividend_orang[N-1] ),
    .divisor_orang_r  ( divisor_orang[N-1]  ),
    .dividend         ( { {M{1'b0}}, dividend[N-1] } ),
    .merchant_last    ( 'b0    ),
    .valid            ( valid_cell[N-1]    ),
    .merchant         ( merchant_cell[N-1] ),
    .reminder         ( reminder_cell[N-1]  )
);

genvar i;
generate 
    for(i = 0; i < N-1; i = i + 1) begin: divider_cell_pipeline
        divider_cell#(
            .N        ( N ),
            .M        ( M )
        )u_divider_cell(
            .clk      ( clk      ),
            .rst_n    ( rst_n    ),
            .en       ( valid_cell[i+1]       ),
            .dividend_orang   ( dividend_orang[i+1]   ),
            .divisor_orang    ( divisor_orang[i+1]    ),
            .dividend_orang_r ( dividend_orang[i] ),
            .divisor_orang_r  ( divisor_orang[i]  ),
            .dividend         ( {reminder_cell[i+1], dividend_orang[i+1][i]} ),
            .merchant_last    ( merchant_cell[i+1]    ),
            .valid            ( valid_cell[i]    ),
            .merchant         ( merchant_cell[i] ),
            .reminder         ( reminder_cell[i]  )
        );
    end
endgenerate

assign valid = valid_cell[0];
assign merchant = merchant_cell[0];
assign reminder = reminder_cell[0];

endmodule

非流水线除法器

这种除法器在N周期内只能完成一次除法计算,但只需要一个单步除法器。通过计数器来控制单步除法器单元的输入,从而实现移位除法计算。

module single_divider#(
    parameter N = 32,                           //被除数位宽
    parameter M = 32                            //除数位宽
    )
    (

    input  wire             clk,
    input  wire             rst_n,

    input  wire             en,
    output reg              ready,
    input  wire [N-1:0]     dividend,
    input  wire [M-1:0]     divisor,

    output reg              valid,
    output wire [N-1:0]     merchant,
    output wire [M-1:0]     reminder
    );

    reg  [ 7:0]     cnt;
    reg             busy;

//divider_cell connevtion
    wire [N-1:0]     dividend_orang_i;  
    wire [M-1:0]     divisor_orang_i;
    wire [N-1:0]     dividend_orang_o;
    wire [M-1:0]     divisor_orang_o;
    wire             en_i;
    wire             valid_o;
    wire [M:0]       dividend_i;
    wire [N-1:0]     merchant_i;
    wire [N-1:0]     merchant_o;
    wire [M-1:0]     reminder_o;


always@(*) begin 
    ready = ~busy;
end

always@(posedge clk) begin 
    if(!rst_n) begin 
        valid <= 1'b0;
    end
    else begin 
        if(cnt == N-1) begin 
            valid <= 1'b1;
        end
        else begin 
            valid <= 1'b0;
        end
    end
end

always@(posedge clk) begin 
    if(!rst_n) begin 
        cnt <= 8'd0;
    end
    else begin 
        if(cnt == N) begin 
            cnt <= 8'd0;
        end
        else if(en || busy) begin 
            cnt <= cnt + 8'd1;
        end
        else ;
    end
end

always@(posedge clk) begin 
    if(!rst_n) begin 
        busy <= 1'b0;
    end
    else begin 
        if(en) begin 
            busy <= 1'b1;
        end
        else if(cnt == N) begin 
            busy <= 1'b0;
        end
        else ;
    end
end

    assign en_i = (en || busy) && ~valid;
    assign dividend_orang_i = en? dividend : dividend_orang_o;
    assign divisor_orang_i  = en? divisor  : divisor_orang_o;
    assign dividend_i = en? {{M{1'b0}}, dividend[N-1]} : 
                        (busy && ~valid)? {reminder_o, dividend_orang_o[8'd31 - cnt]} : 'b0;
    assign merchant_i = (busy && ~valid)? merchant_o : 'b0;

    assign merchant = valid? merchant_o : 'b0;
    assign reminder = valid? reminder_o : 'b0;

divider_cell#(
    .N        ( N ),
    .M        ( M )
)u_divider_cell(
    .clk      ( clk      ),
    .rst_n    ( rst_n    ),
    .en       ( en_i     ),
    .dividend_orang   ( dividend_orang_i ),
    .divisor_orang    ( divisor_orang_i ),
    .dividend_orang_r ( dividend_orang_o ),
    .divisor_orang_r  ( divisor_orang_o ),
    .dividend         ( dividend_i ),
    .merchant_last    ( merchant_i ),
    .valid            ( valid_o ),
    .merchant         ( merchant_o ),
    .reminder         ( reminder_o )
);

endmodule

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

verilog除法器设计 的相关文章

随机推荐

  • 哈呀嗓,济南

    今天收到了泰莱区宏图三胞招聘主管的邮件 说是让联系沈经理 备注在这里以免忘记 还有就是 下午打印简历的时候潍坊新北海打电话过来 说他们公司也需要php程序员 这个也待定吧 一切还是以济南为主吧 不行再走 地形 济南市位于北纬36 40 东经
  • XXL-JOB(分布式任务调度平台)的使用(详细教程)

    概述 首先我们要知道什么是XXL JOB 官方简介 XXL JOB是一个分布式任务调度平台 其核心设计目标是开发迅速 学习简单 轻量级 易扩展 现已开放源代码并接入多家公司线上产品线 开箱即用 XXL JOB的有点特性 1 简单 支持通过W
  • Hibernate 项目查询数据报 UnknownEntityTypeException

    原因分析 1 hibernate cfg xml配置文件有没有映射实体类
  • 一文带你全面理解向量数据库

    近些年来 向量数据库引起业界的广泛关注 一个相关事实是许多向量数据库初创公司在短期内就筹集到数百万美元的资金 你很可能已经听说过向量数据库 但也许直到现在才真正关心向量数据库 至少 我想这就是你现在阅读本文的原因 如果你阅读本文只是为了简单
  • wireshark过滤器的使用

    目录 wireshark wireshark的基本使用 wireshark过滤器的区别 抓包案例 wireshark wireshark的基本使用 抓包采用 wireshark 提取特征时 要对 session 进行过滤 找到关键的stre
  • 华为云使用手册

    华为云重磅福利 云主机 海外云主机 云容器和多款云产品0元领取 华为云重磅推出云上优选 特惠来袭来迎接这个来之不易的春天 本次活动依然是给到了很低的折扣 0 7折起 活动走起 福利1 免费试用海外云主机和云原生容器网页连接 进入免费试用专区
  • CentOS安装python3.x最新版和chrome chromedriver

    之前使用selenium wire的响应拦截器获取请求头中的签名需要部署到服务器 所以得搭建一个服务器运行环境 安装过程有坑 这里记录一下 Linux平台安装需要下载源码包自己编译 下载地址 https www python org dow
  • hexo主题标签的使用

    https akilar top posts 615e2dec 这个是我看的教程 我直接复制的源码 友情链接 LrcShare 实现hexo标签的可以折叠 hexo标签的使用方法 要实现Hexo标签的可折叠 可以使用Hexo内置的foldi
  • ad中按钮开关的符号_收藏:电路图符号大全

    电子设备中有各种各样的图 能够说明它们工作原理的是电原理图 简称电路图 电路图是说明模拟电子电路工作原理的 它用各种图形符号表示电阻器 电容器 开关 晶体管等实物 用线条把元器件和单元电路按工作原理的关系连接起来 一张电路图就好像是一篇文章
  • 在SpringBoot中加入jsp

    SpringBoot官方不推荐在 SpringBoot 中使用 jsp 的 那么到底可以使用吗 答案是肯定的 不过需要导入tomcat 插件启动项目 不能再用 SpringBoot 默认 tomcat 了 一 导入SpringBoot的to
  • React实现大文件上传、react-dropzone

    React大文件上传的实现方案大致如下 使用第三方组件库实现文件上传 如react dropzone 将大文件分成多个小块 并使用XMLHttpRequest或者fetch发送分块上传请求 为了保证数据完整性 每个请求都需要携带校验码 在上
  • (0)JavaScript语法---小程序回调函数【幼儿园级教程】

    微信小程序中的回调函数 史上最简单的幼儿园基础教程 小程序的回调函数 汉字版的编码 你是不是第一次见到 总结 小程序的回调函数 在小程序包含逻辑时 回调函数几乎是无法避免 在整个使用中 发现大部分帖子都是针对有一定的基础的伙伴写的 也比较晦
  • Flink 1.11:更好用的流批一体 SQL 引擎

    许多的数据科学家 分析师和 BI 用户依赖交互式 SQL 查询分析数据 Flink SQL 是 Flink 的核心模块之一 作为一个分布式的 SQL 查询引擎 Flink SQL 提供了各种异构数据源的联合查询 开发者可以很方便地在一个程序
  • 树莓派Tools交叉编译OpenGL(mesa-12.0.5)

    以下shell命令都是在root权限下执行的 得按照顺序来 不然会报找不到包或者一些文件找不到这些话 交叉编译玩多了 自己翻来覆去 整多了后其实也就融会贯通了 有耐心就行 宗旨就是你得让它们找到的到对应文件 一般要么在环境变量里去pkg c
  • 【牛客SQL】SQL19 查找所有员工的last_name和first_name以及对应的dept_name

    题目描述 描述 有一个员工表employees简况如下 有一个部门表departments表简况如下 有一个 部门员工关系表dept emp简况如下 请你查找所有员工的last name和first name以及对应的dept name 也
  • Git如何删除本地仓库

    删除仓库 就是需要删除仓库文件夹下隐藏的 git 文件夹 进入项目所在目录 打开git bash 开始删除本地仓库 显示所有本地分支 初始化时只有一个master分支 git branch 初始化本地版本库 重新初始化一次 可以忽略 git
  • 数据结构——队列

    创建队列 塞值和拿值 当我们创建一个LinkedList的时候 就可以用来模拟队列 因为该集合里有大量操作首尾元素的方法 之后就可以在该队列里进行数据的添加和获取 但是当我们使用数组来实现时 如何创建一个队列呢 最大值怎么确定 首尾初始值怎
  • 新闻主题识别及其热点演化分析流程

    1 数据收集 收集与科技新闻相关的大量文本数据 包括新闻报道 评论 社交媒体等 2 数据预处理 对收集到的文本数据进行清洗 去重 分词 停用词过滤等处理 3 特征提取 采用TF IDF Word2Vec等技术进行文本特征提取 将文本转化为向
  • Android JNI打印logcat日志

    在 JNI 中打印日志可以使用 android log print 函数来实现 该函数是 Android NDK 提供的一个用于在本地代码中输出日志消息到 logcat 的方法 要在 JNI 中打印日志 请按照以下步骤进行操作 在你的 JN
  • verilog除法器设计

    除法器原理 和十进制除法类似 计算 27 除以 5 的过程如下所示 除法运算过程如下 1 取被除数的高几位数据 位宽和除数相同 实例中是 3bit 数据 2 将被除数高位数据与除数作比较 如果前者不小于后者 则可得到对应位的商为 1 两者做