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

32位Verilog模运算模块部分计算异常问题咨询

32位Verilog模运算模块错误排查与修复

你实现的32位模运算模块仅能正确处理部分简单用例(如95 mod 12、5 mod 10),但在计算100 mod 7、255 mod 7时结果错误,核心问题出在两个关键逻辑上:

问题分析

1. start信号持续有效打断减法循环

模块中,start持续高电平时,每一个时钟上升沿都会执行temp <= A,导致减法操作被反复重置。比如测试用例里start = 1持续了100ns(对应10个时钟周期),每次时钟沿都把temp重新设为100,根本无法完成连续的temp - B循环,自然得不到正确结果。

2. done信号误触发

当前done直接由temp < B赋值,在减法过程中只要某一时刻temp小于B就会输出高电平,但这个信号没有考虑start阶段的状态,而且在减法循环未完全结束时可能提前触发,导致结果读取时机错误。

修复方案

修改后的模块代码

module mod_dp_32bit (
    input wire clk,
    input wire rst,
    input wire start,
    input wire [31:0] A,
    input wire [31:0] B,
    output reg done,
    output wire [31:0] result
);

reg [31:0] temp;
reg running; // 新增状态标记,记录是否处于减法循环中

always @(posedge clk or posedge rst) begin
    if (rst) begin
        temp <= 32'b0;
        running <= 1'b0;
        done <= 1'b0;
    end 
    else if (start) begin
        temp <= A;
        running <= 1'b1;
        done <= 1'b0; // 启动时置低done
    end 
    else if (running) begin
        if (temp >= B) begin
            temp <= temp - B;
            done <= 1'b0;
        end 
        else begin
            running <= 1'b0;
            done <= 1'b1; // 循环结束,置高done
        end
    end
end

assign result = temp;

endmodule

关键修改点

  • 新增running状态寄存器:标记模块是否处于减法计算阶段,避免start持续有效时的重置问题,同时确保减法循环完整执行。
  • 调整done信号逻辑:只有当减法循环完全结束(running置低且temp < B)时,done才会置高,避免提前触发。
  • 限制start的作用:仅在start第一次有效时初始化temp,后续时钟沿不再重复赋值。

调整测试代码

测试代码中start只需给出一个时钟周期的高电平,避免持续触发重置:

`timescale 1ns/1ns

module Mod32_TB;
  
  reg clk;
  reg rst;
  reg start;
  reg [31:0] A;
  reg [31:0] B;
  wire done;
  wire [31:0] result;

  // Instantiate mod_dp_32bit module
  mod_dp_32bit uut (
    .clk(clk),
    .rst(rst),
    .start(start),
    .A(A),
    .B(B),
    .done(done),
    .result(result)
  );

  // Clock generation
  initial begin
    clk = 0;
    forever #5 clk = ~clk;
  end

  // Test Case 1: 100 mod 7 = 2
  initial begin
    // Initialize inputs
    rst = 1;
    A = 100;
    B = 7;
    start = 0;

    // Release reset
    #10 rst = 0;

    // 仅给一个时钟周期的start信号
    #5 start = 1;
    #10 start = 0;

    // 等待done信号置高再读取结果
    wait(done);
    $display("Test Case 1 Result: 100 mod 7 = %d", result);

    // Test Case 2: 255 mod 7 = 3
    #10 A = 255;
    B = 7;
    start = 1;
    #10 start = 0;
    wait(done);
    $display("Test Case 2 Result: 255 mod 7 = %d", result);

    // Test Case 3: 95 mod 12 = 11
    #10 A = 95;
    B = 12;
    start = 1;
    #10 start = 0;
    wait(done);
    $display("Test Case 3 Result: 95 mod 12 = %d", result);

    // End simulation
    $stop;
  end

endmodule

测试代码调整点

  • 初始rst设为1,然后释放重置,符合模块的复位逻辑。
  • start仅保持一个时钟周期(10ns),确保temp只被初始化一次。
  • 使用wait(done)等待计算完成后再读取结果,避免提前读取未完成的数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:45:15