从零开始设计riscv cpu记录之五
📅 2026/7/11 2:38:17
👁️ 阅读次数
📝 编程学习
一、在测试mulhsu不通过,其余的mul 、mulh、 mul都通过,这是为什么?
| 指令 | 含义 |
|---|---|
| mulh | 有符号 × 有符号,取高 32 位 |
| mulhsu | 有符号 × 无符号,取高 32 位 |
| mulhu | 无符号 × 无符号,取高 32 位 |
| mul | 有符号/无符号 × 有符号/无符号,取低 32 位 |
二、对我来说,是认知之外的原因
三、ex.v中乘法的实现,分成散步
第一步,先取到操作数的有符号格式:
wiresigned[`DW-1:0]op1_signed=$signed(op1_i);wiresigned[`DW-1:0]op2_signed=$signed(op2_i);第二步,按照表格中规定的计算乘积,比如mul,无符号相乘,就是op1_i * op2_i,其他的方法也一样:
wire[`DW*2-1:0]mul_result=op1_i*op2_i;wire[`DW*2-1:0]mulh_result=op1_signed*op2_signed;wire[`DW*2-1:0]mulhsu_result=op1_signed*op2_i第三步,取32位,高32位或低32位
`INST_MUL:begin reg_wdata_o=mul_result[31:0];end `INST_MULH:begin reg_wdata_o=mulh_result[63:32];end `INST_MULHSU:begin reg_wdata_o=mulhsu_result[63:32];end `INST_MULHU:begin reg_wdata_o=mul_result[63:32];四、思路清晰,感觉不会出错,但是忽略了verilog的乘法规则
五、mulhsu的错误原因:mulhsu要求的是有符号数 × 无符号数,但op1_signed * op2_i这种写法在 Verilog 里会被当成无符号 × 无符号来算。
六、Verilog 的混合符号乘法规则
Verilog 规定:一个表达式里只要有一个操作数是无符号的,整个表达式就按无符号运算处理。
七、正确做法:
wire[`DW*2-1:0]mulhsu_result=$signed({{32{op1_i[31]}},op1_i})*$signed({32'b0,op2_i});含义:
{{32{op1_i[31]}}, op1_i}
把op1_i按有符号数符号扩展到 64 位。{32'b0, op2_i}
把op2_i按无符号数零扩展到 64 位。两个 64 位数相乘,取高 32 位,就是
mulhsu的正确结果。
八、改完之后测试结果PASS
编程学习
技术分享
实战经验