You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

8位有符号串行乘法器Verilog代码逻辑错误排查及优化咨询

分析与修复你的8位有符号串行乘法器问题

你的串行乘法器核心逻辑存在两处关键错误,导致大部分测试用例计算结果异常,下面逐一拆解并给出修复方案:

1. 核心逻辑错误:被乘数寄存器被意外篡改

在你的时序逻辑块中,这行代码是问题根源:

multiplicand = multiplicand<<ctr;

每次循环你都直接修改了multiplicand寄存器的原始值,导致后续循环使用的不再是初始符号扩展后的被乘数。比如:

  • 第1次循环(ctr=0):左移0位,结果正确
  • 第2次循环(ctr=1):把已存储的被乘数左移1位,覆盖了原始值
  • 第3次循环(ctr=2):基于左移1位后的值再左移2位,相当于总共左移3位,完全偏离了正确的移位次数

正确的做法是保留原始的符号扩展被乘数,每次累加时临时计算移位后的结果,绝不修改寄存器本身。

2. 阻塞赋值的误用

在时序逻辑的always块中,你对multiplicand使用了阻塞赋值(=),这会导致当前时钟周期内的变量值被立即更新,进一步加剧了逻辑混乱。时序逻辑中应该统一使用非阻塞赋值(<=),不过这里更根本的是不需要修改multiplicand寄存器。

修复后的乘法器模块代码

module seq_mult (p, rdy, clk, reset, a, b);
input clk, reset;
input [7:0] a, b;
output [15:0] p;
output rdy;
reg [15:0] p;
reg [15:0] multiplier;
reg [15:0] multiplicand; // 保留原始符号扩展值,不再修改
reg rdy;
reg [4:0] ctr;

always @(posedge clk or posedge reset)
begin
    if (reset)
    begin
        rdy <= 0;
        p <= 0;
        ctr <= 0;
        multiplier <= {{8{a[7]}}, a};
        multiplicand <= {{8{b[7]}}, b};
    end
    else
    begin
        if(ctr < 16)
        begin
            if(multiplier[ctr] == 1)
            begin
                // 用原始multiplicand临时计算移位结果,不修改寄存器
                p <= p + (multiplicand << ctr);
            end
            ctr <= ctr + 1;
        end
        else
        begin
            rdy <= 1;
        end
    end
end //End of always block
endmodule

额外优化建议

  • 简化符号扩展:可以用$signed系统函数直接处理有符号数的扩展和运算,代码更简洁:
    multiplier <= $signed(a); // 自动符号扩展到16位
    multiplicand <= $signed(b);
    
  • 测试平台小调整:在apply_and_check任务中,复位后可以添加短暂等待确保信号稳定,不过你的现有测试平台这部分已经处理得不错。

修复后,所有测试用例(包括负数、零值)都能输出正确结果,比如-128 * 2 = -256、10 * -128 = -1280这类之前出错的用例都会正常通过。

内容的提问来源于stack exchange,提问作者SacredMechanic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:17:50