news 2026/4/15 17:22:44

tinyriscv执行模块讲解3(除法运算2)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
tinyriscv执行模块讲解3(除法运算2)

写在前面

  • 前面执行模块对于除法计算只做流水线控制和参数传递,具体的除法计算由DIV除法模块来完成。该模块作者使用试商法实现,所以在开始前先了解下试商法怎么进行除法计算。
    有VIP的同学可以看一下这篇文章,可能会讲解得更加详细:https://blog.csdn.net/m0_71078397/article/details/126610918

  • 试商法是一种用于除法运算的算法,特别适用于硬件实现(如FPGA、CPU等)。它的核心思想是通过试探和修正的方式逐位确定商的值。

  • 基本公式:
    被除数 ÷ 除数 = 商 … 余数

  • 基本思想:从最高位开始,每次确定商的一位。
    1、猜测当前位的商值
    2、用猜测值乘以除数
    3、比较乘积与被除数(或当前余数)
    4、根据比较结果调整商值

  • 十进制举例(100 / 7):

  • 二进制举例(100 / 7):

    call in:作者为什么说除法至少需要33个时钟周期。这里试商法对于32位数的除法而言需要迭代处理32次,即每一位都需要迭代一次。

1、RISC-V32位除法指令

DIV:有符号除法(商) DIVU:无符号除法(商) REM:有符号取余(余数) REMU:无符号取余(余数)

2、除法模块接口定义

input wire clk,input wire rst,// from exinput wire[`REG_BUS]dividend_i,// 被除数input wire[`REG_BUS]divisor_i,// 除数input wire start_i,// 开始信号,运算期间这个信号需要一直保持有效input wire[2:0]op_i,// 具体是哪一条指令input wire[`REG_ADDR_BUS]reg_waddr_i,// 运算结束后需要写的寄存器// to exoutput reg[`REG_BUS]result_o,// 除法结果,高32位是余数,低32位是商output reg ready_o,// 运算结束信号output reg busy_o,// 正在运算信号output reg[`REG_ADDR_BUS]reg_waddr_o// 运算结束后需要写的寄存器

该模块只和执行模块交换数据,所以接口只用定义与执行模块数据交换即可。

3、除法器状态机状态定义

// 状态定义localparam STATE_IDLE=4'b0001;//空闲localparam STATE_START=4'b0010;//开始localparam STATE_CALC=4'b0100;//计算中localparam STATE_END=4'b1000;//结束

4、中间运算变量

reg[`REG_BUS]dividend_r;//被除数reg[`REG_BUS]divisor_r;//除数reg[2:0]op_r;//指令reg[3:0]state;//状态机状态reg[31:0]count;reg[`REG_BUS]div_result;//除法结果reg[`REG_BUS]div_remain;//除法结果余数reg[`REG_BUS]minuend;//余数reg invert_result;//结果的补码形式wire op_div=(op_r==`INST_DIV);wire op_divu=(op_r==`INST_DIVU);wire op_rem=(op_r==`INST_REM);wire op_remu=(op_r==`INST_REMU);

5、试商法除法的核心计算部分

wire[31:0]dividend_invert=(-dividend_r);//等价于dividend_invert = ~dividend_r + 32'b1wire[31:0]divisor_invert=(-divisor_r);//取二进制补码wire minuend_ge_divisor=minuend>=divisor_r;//比较部分余数 minuend 是否大于等于除数 divisor_rwire[31:0]minuend_sub_res=minuend-divisor_r;//wire[31:0]div_result_tmp=minuend_ge_divisor?({div_result[30:0],1'b1}): ({div_result[30:0], 1'b0});//若部分余数大于等于除数,则余数更新为余数减除数的差值,否则余数不变wire[31:0]minuend_tmp=minuend_ge_divisor?minuend_sub_res[30:0]:minuend[30:0];

div_result_tmp:在余数大于等于除数时,在对应位上商1,否则商0。

6、除法状态机

1. 复位

if(rst==`RESET_EN)begin state<=STATE_IDLE;ready_o<=`DIV_RESULT_NOT_READY;//除法结果是否完成result_o<=`ZERO_WORD;//存储最终的除法结果(商或余数)div_result<=`ZERO_WORD;//存储计算过程中的商div_remain<=`ZERO_WORD;op_r<=3'h0;reg_waddr_o<=`ZERO_WORD;//除法结果-写地址dividend_r<=`ZERO_WORD;divisor_r<=`ZERO_WORD;minuend<=`ZERO_WORD;//存储当前的部分余数(被减数)invert_result<=1'b0;// 结果取反标志busy_o<=`FALSE;//除法器是否正在工作count<=`ZERO_WORD;//控制32次迭代的计数器end

2. 空闲状态

STATE_IDLE:beginif(start_i==`DIV_START)begin op_r<=op_i;dividend_r<=dividend_i;divisor_r<=divisor_i;reg_waddr_o<=reg_waddr_i;state<=STATE_START;busy_o<=`TRUE;endelsebegin op_r<=3'h0;reg_waddr_o<=`ZERO_WORD;dividend_r<=`ZERO_WORD;divisor_r<=`ZERO_WORD;ready_o<=`DIV_RESULT_NOT_READY;result_o<=`ZERO_WORD;busy_o<=`FALSE;end end

当接收到开始信号时,将参与运算的变量进行初始化,并对外发出“忙”信号(busy_o),后将状态机状态切换位开始状态。
3、开始状态

STATE_START:beginif(start_i==`DIV_START)begin// 除数为0if(divisor_r==`ZERO_WORD)beginif(op_div|op_divu)begin result_o<=32'hffffffff;//若指令为除法运算则返回全1--无限大endelsebegin result_o<=dividend_r;//若为取余数运算则返回取余本身end ready_o<=`DIV_RESULT_READY;//完成计算state<=STATE_IDLE;busy_o<=`FALSE;// 除数不为0endelsebegin busy_o<=`TRUE;count<=32'h40000000;//计数器初始化--第31位为1,右移32位后为0state<=STATE_CALC;//状态机切换为计算div_result<=`ZERO_WORD;div_remain<=`ZERO_WORD;// DIV和REM这两条指令是有符号数运算指令if(op_div|op_rem)begin// 被除数求补码if(dividend_r[31]==1'b1)begin//被除数为负数时取二进制补码dividend_r<=dividend_invert;minuend<=dividend_invert[31];endelsebegin minuend<=dividend_r[31];end// 除数求补码if(divisor_r[31]==1'b1)begin divisor_r<=divisor_invert;end endelsebegin minuend<=dividend_r[31];end// 运算结束后是否要对结果取补码if((op_div&&(dividend_r[31]^divisor_r[31]==1'b1))//异或运算,若除数与被除数符号不同则为1,标记结果符号为负号||(op_rem&&(dividend_r[31]==1'b1)))begin invert_result<=1'b1;endelsebegin invert_result<=1'b0;end end endelsebegin state<=STATE_IDLE;result_o<=`ZERO_WORD;ready_o<=`DIV_RESULT_NOT_READY;busy_o<=`FALSE;end end

执行操作:
1、处理除数为0的情况(除法计算返回全1,取余运算返回本身)。
2、除数不为0,初始化迭代计数器(count <= 32’h40000000),将状态切换为计算状态。
3、对于操作数中存在负数情况时,对其取补码。
4、判断运算结果的符号,并标记(invert_result )。

4、计算状态

STATE_CALC:beginif(start_i==`DIV_START)begin dividend_r<={dividend_r[30:0],1'b0};//被除数左移一位div_result<=div_result_tmp;//保存运算中间结果count<={1'b0,count[31:1]};//计数器右移if(|count)begin minuend<={minuend_tmp[30:0],dividend_r[30]};endelsebegin state<=STATE_END;if(minuend_ge_divisor)begin div_remain<=minuend_sub_res;endelsebegin div_remain<=minuend;end end endelsebegin state<=STATE_IDLE;result_o<=`ZERO_WORD;ready_o<=`DIV_RESULT_NOT_READY;busy_o<=`FALSE;end end

结合计算部分迭代32次,完成计算。
5、完成状态

STATE_END:beginif(start_i==`DIV_START)begin ready_o<=`DIV_RESULT_READY;state<=STATE_IDLE;busy_o<=`FALSE;if(op_div|op_divu)beginif(invert_result)begin result_o<=(-div_result);endelsebegin result_o<=div_result;end endelsebeginif(invert_result)begin result_o<=(-div_remain);endelsebegin result_o<=div_remain;end end endelsebegin state<=STATE_IDLE;result_o<=`ZERO_WORD;ready_o<=`DIV_RESULT_NOT_READY;busy_o<=`FALSE;end end

结合符号标记(invert_result)和指令为结果输出赋值,并向执行模块发送完成信号。

https://gitee.com/liangkangnan/tinyriscv

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 3:58:29

MusicFree插件进阶指南:从入门到精通的实战教程

想要打造专属音乐空间&#xff0c;让MusicFree插件成为你的得力助手吗&#xff1f;无论你是初次接触插件的新手&#xff0c;还是想要深入挖掘插件潜力的进阶用户&#xff0c;这篇指南都将为你提供实用技巧和深度解析。MusicFree插件生态通过模块化设计&#xff0c;让你能够轻松…

作者头像 李华
网站建设 2026/4/12 21:03:35

IBM推出开源智能体CUGA 任务完成率超五成

IBM研究人员发布了一款名为CUGA的开源智能体&#xff0c;旨在实现复杂企业工作流程的自动化&#xff0c;根据不同任务类型&#xff0c;其准确完成率约为50%。CUGA是"可配置通用智能体"的缩写。根据其在AI平台HuggingFace上的介绍&#xff0c;该软件通过"多智能体…

作者头像 李华
网站建设 2026/4/14 23:51:39

Java毕设项目推荐-基于JavaWeb的家装一体化平台室内设计、装修施工、建材选购、软装搭配、后期维护于一体的专业化家装服务平台【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/15 3:39:18

Java毕设项目推荐-基于SpringBoot+Vue的汽配销售管理系统基于JavaWeb的汽配销售管理系统【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/9 13:44:15

PHP转Go必看!GoFrame框架详解+30分钟搭建CRUD API(附代码步骤)

最近贼有意思&#xff0c;发现了一个账号&#xff0c;专门发PHP转Go的帖子&#xff0c;哎呦喂&#xff0c;这不正是我3年前做的事情吗&#xff1f;哈哈。 尤其看到他写的安利GoFrame教程的文章&#xff0c;有点刺激到我了&#xff0c;一看他就没我用的多&#xff0c;用的溜&…

作者头像 李华