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

4位寄存器实现中输出始终为0的问题求助

4位寄存器实现中输出始终为0的问题求助

嘿,我来帮你拆解下这个问题!你现在碰到的是寄存器输出一直锁死在0的情况,咱们先把你的代码摆出来,一步步排查问题根源:

你的寄存器模块代码

module register(input [7:0] inp, input load,clk,clr, output reg [7:0] out);

always@(posedge clk or posedge clr) begin
    if(clr)
        out <= 8'b00000000;
    else if(load)
        out<= inp;
end

endmodule

你的测试模块代码

module register_tb;

reg [7:0] inp;
reg load,clk,clr;
wire [7:0] out;
integer count1,count2;

register store(inp,load,clk,clr,out);

initial begin
    clk = 1'b0;
    repeat(2**10) #10 clk = {$random};
end

initial begin
    for(count1 = 0;count1<2**8;count1 = count1 + 1) begin
        for(count2 = 0;count2<4;count2 = count2 + 1) begin
            {clr,load} = count2;
            {inp} = count1;
            #10;
        end
    end
end

endmodule

先提个小细节:你说要做4位寄存器,但代码里全是8位位宽([7:0]),这个后面可以改,但先解决输出为0的核心问题:

问题1:随机时钟导致采样完全不同步

你测试模块里的时钟是用$random生成的,这会让时钟的上升沿完全随机,和你每10ns就更新一次的输入激励(clr/load/inp)完全对不上。比如当你把load置1想加载新值时,大概率碰不到时钟上升沿,寄存器根本不会触发加载操作,自然就一直保持初始的0值(或者被clr置0后再也不变)。

问题2:频繁触发clr清零操作

看你的测试循环,count2从0到3时,{clr,load}的取值是:

  • count2=0: clr=0,load=0
  • count2=1: clr=0,load=1
  • count2=2: clr=1,load=0
  • count2=3: clr=1,load=1

每次循环都会轮到count2=2或3,这时候clr是高电平,posedge clr会直接触发寄存器的always块,强制把out置0。就算偶尔碰到时钟上升沿加载了值,下一次循环的clr操作又会把它打回0,所以你看到的输出就一直是0。

问题3:代码规范小瑕疵(非核心但影响可读性)

你的always块里,当clr=0且load=0时没有给out赋值,虽然Verilog会默认保持寄存器值,但加上else out <= out;会让代码逻辑更清晰,也避免综合工具产生不必要的锁存器警告。

解决步骤

  1. 把时钟改成固定周期的方波,这样才能和你的激励同步,比如:
initial begin
    clk = 1'b0;
    forever #10 clk = ~clk; // 20ns周期的时钟,每10ns翻转一次
end

这样时钟上升沿会刚好和你的激励更新时间点对齐,保证load信号能被正确采样。

  1. 重构测试激励,避免频繁清零:不要在每次循环都触发clr,比如先把clr置0,专门测试load的加载和保持功能,最后再测试clr的清零效果。

  2. 把8位位宽改成4位:把所有[7:0]改成[3:0],2**8改成2**4,贴合你做4位寄存器的需求。

  3. 加个打印语句辅助调试:在测试模块里加$monitor,能实时看到每个时刻的信号值,方便你跟踪问题:

initial begin
    $monitor("Time: %0t | clr: %b | load: %b | inp: %h | out: %h", $time, clr, load, inp, out);
end

修正后的示例代码

4位寄存器模块

module register(input [3:0] inp, input load,clk,clr, output reg [3:0] out);

always@(posedge clk or posedge clr) begin
    if(clr)
        out <= 4'b0000;
    else if(load)
        out <= inp;
    else
        out <= out; // 显式保持值,逻辑更清晰
end

endmodule

测试模块

module register_tb;

reg [3:0] inp;
reg load,clk,clr;
wire [3:0] out;
integer count1;

register store(inp,load,clk,clr,out);

// 固定周期时钟
initial begin
    clk = 1'b0;
    forever #10 clk = ~clk;
end

// 实时打印信号值
initial begin
    $monitor("Time: %0t | clr: %b | load: %b | inp: %h | out: %h", $time, clr, load, inp, out);
end

initial begin
    // 初始化所有信号
    clr = 1'b0;
    load = 1'b0;
    inp = 4'b0000;
    #10;

    // 先测试clr清零功能
    clr = 1'b1;
    #20;
    clr = 1'b0;
    #10;

    // 测试load加载和保持功能
    for(count1 = 0;count1<2**4;count1 = count1 + 1) begin
        inp = count1;
        // 先测试load=0,保持当前值
        load = 1'b0;
        #20;
        // 测试load=1,加载新值
        load = 1'b1;
        #20;
    end

    // 最后再测试一次清零
    clr = 1'b1;
    #20;
    $finish;
end

endmodule

这样修改后,你应该能看到寄存器正常完成加载、保持和清零的操作,不会再一直输出0了。

备注:内容来源于stack exchange,提问作者Ervin Ranjan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 09:10:28