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

Verilog 4-bit by 4-bit加法移位乘法器仿真结果始终为0求助

4-bit乘法器仿真结果始终为0的问题排查与修正

你的代码存在多处逻辑错误,导致乘法计算无法正常执行,以下是具体问题和修正方案:

核心错误点

1. 状态机状态更新逻辑错误

第一个always块直接将复位后的state强制赋值为START,完全忽略了next_state的状态转移逻辑,导致状态机无法按照预期流程(IDLE→START→LSB→ADD/SHIFT→...→DONE)运行,直接卡死在START或混乱跳转。
修正:将状态更新改为跟随next_state:

always @(posedge clk, negedge rstn)
begin
    if(!rstn)
    begin
        state <= IDLE;
    end
    else
    begin
        state <= next_state; // 替换原有的state <= START
    end
end

2. LSB判断使用原始输入而非寄存器值

在LSB状态中,你判断的是输入b[0],但实际应该判断移位后的寄存器r_multiplier[0]——乘法过程中乘数是不断右移的,每次要看当前寄存器的最低位决定是否加被乘数。
修正:

LSB:
begin
    if(r_multiplier[0]) // 替换b[0]
        next_state = ADD;
    else
        next_state = SHIFT;
end

3. START状态重复初始化寄存器

每次进入START状态都重新赋值r_multiplicant = a和r_multiplier = b,会在乘法循环的每次START跳转时覆盖之前移位后的值,导致计算重置。应该只在**首次启动(从IDLE进入START)**时初始化寄存器,同时重置r_count和r_product。
修正:

START:
begin
    // 仅从IDLE进入时初始化
    if(state == IDLE) begin
        r_multiplicant <= {4'b0, a}; // 扩展为8位,避免左移丢失高位
        r_multiplier <= b;
        r_product <= 8'b0;
        r_count <= 4;
    end
    // 状态转移逻辑
    if(r_count != 0)
        next_state = LSB;
    else
        next_state = DONE;
end

4. DONE状态错误使用assign语句

在时序always块中不能使用assign,这是语法错误,应该直接用非阻塞赋值将r_product赋值给result,同时设置done信号。
修正:

DONE:
begin
    result <= r_product;
    done <= 1'b1;
end

同时在IDLE状态重置done信号:

IDLE:
begin
    done <= 1'b0;
end

5. r_count递减时机错误

原代码在LSB状态递减r_count,应该在完成一次移位操作后递减,确保每次循环计数正确。
修正:将递减逻辑移到SHIFT状态:

SHIFT:
begin
    r_multiplicant <= r_multiplicant << 1;
    r_multiplier <= r_multiplier >> 1;
    r_count <= r_count - 1; // 移位后递减计数
end

6. 测试平台信号时序问题

测试平台中start拉高后10ns才赋值a和b,此时模块已进入START状态,采样的是a/b的初始值0,导致计算结果为0。应该在start拉高前设置好a/b,且每次测试新乘数时,需拉低start再重新拉高触发计算。
修正后的测试平台:

`timescale 1ns / 1ps

module tb_multi_8bit();

    reg clk;
    reg rstn;
    reg start;
    reg [3:0] a;
    reg [3:0] b;
    
    wire [7:0] result;
    wire done;

    always #10 clk = ~clk;
    
    multi_8bit test(
        .clk(clk),
        .rstn(rstn),
        .start(start),
        .a(a),
        .b(b),
        .result(result),
        .done(done)
    );

    initial
    begin
        clk = 0; rstn = 1; start = 0; a = 4'b0; b = 4'b0;
        #15 rstn = 0;
        #25 rstn = 1;
        // 第一次测试:a=6(0110), b=1(0001)
        #20 a = 4'b0110; b = 4'b0001;
        #10 start = 1;
        #20 start = 0;
        wait(done); // 等待计算完成
        // 第二次测试:a=6(0110), b=2(0010)
        #20 a = 4'b0110; b = 4'b0010;
        #10 start = 1;
        #20 start = 0;
        wait(done);
        // 第三次测试:a=6(0110), b=1(0001)
        #20 a = 4'b0110; b = 4'b0001;
        #10 start = 1;
        #20 start = 0;
        wait(done);
        
        #20 $finish;
    end

endmodule

修正后的完整模块代码

`timescale 1ns / 1ps

module multi_8bit(
    input clk,
    input rstn,
    input start,
    input [3:0] a,
    input [3:0] b,
    output reg [7:0] result,
    output reg done
    );
   
    localparam IDLE = 3'b000,
                START = 3'b001,
                LSB = 3'b010,
                ADD = 3'b011,
                SHIFT = 3'b100,
                DONE = 3'b101;
   
    reg [2:0] state, next_state;
    reg [7:0] r_multiplicant;
    reg [7:0] r_product;
    reg [3:0] r_multiplier;
    reg [2:0] r_count;
   
    always @(posedge clk, negedge rstn)
    begin
        if(!rstn)
        begin
            state <= IDLE;
        end
        else
        begin
            state <= next_state;
        end
    end
   
    always@(*)
    begin
        case(state)
            IDLE:
            begin
                if(start)
                    next_state = START;
                else
                    next_state = IDLE;
            end
           
            START:
            begin
                if(r_count != 0)
                    next_state = LSB;
                else
                    next_state = DONE;
            end
           
            LSB:
            begin
                if(r_multiplier[0])
                    next_state = ADD;
                else
                    next_state = SHIFT;
            end
           
            ADD:
            begin
                next_state = SHIFT;
            end
           
            SHIFT:
            begin
                next_state = START;
            end
           
            DONE:
            begin
                next_state = IDLE;
            end
        endcase
    end
   
    always@(posedge clk, negedge rstn)
    begin
        if(!rstn)
        begin
            r_multiplicant <= 0;
            r_multiplier <= 0;
            r_product <= 0;
            r_count <= 4;
            result <= 0;
            done <= 0;
        end
        else
        begin
            case(state)
                IDLE:
                begin
                    done <= 1'b0;
                end
                    
                START:
                begin
                    if(state == IDLE) begin
                        r_multiplicant <= {4'b0, a};
                        r_multiplier <= b;
                        r_product <= 8'b0;
                        r_count <= 4;
                    end
                end
                    
                LSB:
                begin
                    // 无操作,仅判断LSB
                end
                    
                ADD:
                begin
                    r_product <= r_product + r_multiplicant;
                end
                    
                SHIFT:
                begin
                    r_multiplicant <= r_multiplicant << 1;
                    r_multiplier <= r_multiplier >> 1;
                    r_count <= r_count - 1;
                end
                    
                DONE:
                begin
                    result <= r_product;
                    done <= 1'b1;
                end
            endcase
        end
    end
endmodule

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:45:05