重置If-Else语句会产生不正确的结果

时间:2014-03-11 21:36:37

标签: if-statement verilog

我一直在尝试调试此代码,但我找不到错误。但是,它没有产生我期望的结果。这是代码:

module countAdd( btn, reset, thousands, hundreds, tens, ones, led);

  //Port Assignments
  input [2:0] btn;
  input reset;

  output [0:7] thousands, hundreds, tens, ones;
  output reg led;

  //Internal Port Assignments
  reg [15:0] sum;
  wire [15:0] sumBCD;
  reg [15:0] inc;

  //Add some stuff
  always @(btn or reset)
    begin

        //Determine which button is active
        case(btn)
            3'b110: inc <= 1;
            3'b101: inc <= 10;
            3'b011: inc <= 100;
            default: inc <= 0;
        endcase

        //Add
        sum <= sum + inc;

        //Should we reset?
        if(reset)
            begin
                sum <= 0;
                led <= 1;
            end
        else
            begin
                led <= 0;
            end

    end

  //translate sum to sumBCD
  binToBCD translate (sum, sumBCD[15:12], sumBCD[11:8], sumBCD[7:4], sumBCD[3:0]);

  //display results on SS display
  ssFromBCD seg0 (sumBCD[3:0], ones);
  ssFromBCD seg1 (sumBCD[7:4], tens);
  ssFromBCD seg2 (sumBCD[11:8], hundreds);
  ssFromBCD seg3 (sumBCD[15:12], thousands);
endmodule


module binToBCD(sum, thousands, hundreds, tens, ones);
  //Port Assignments
  input [15:0] sum;
  output reg [3:0] thousands;
  output reg [3:0] hundreds;
  output reg [3:0] tens;
  output reg [3:0] ones;

  //Begin conversion
  integer i;
  always @(sum)
    begin
        //set 1000's, 100's, 10's, and 1's to 0
        thousands = 4'd0;
        hundreds = 4'd0;
        tens = 4'd0;
        ones = 4'd0;

        for(i = 15; i >= 0; i=i-1)
            begin
                //Add 3 to columns >= 5
                if(thousands >= 5)
                    thousands = thousands + 3;
                if(hundreds >= 5)
                    hundreds = hundreds + 3;
                if(tens >= 5)
                    tens = tens + 3;
                if(ones >= 5)
                    ones = ones + 3;

                //Shift left ones
                thousands = thousands << 1;
                thousands[0] = hundreds[3];
                hundreds = hundreds << 1;
                hundreds[0] = tens[3];
                tens = tens << 1;
                tens[0] = ones[3];
                ones = ones << 1;
                ones[0] = sum[i];   
            end

    end 
endmodule

module ssFromBCD(in, ssOut);
  //Port Assignments
  input [3:0] in;
  output reg [0:7] ssOut;

  always @(in)
    begin
        case(in)
            4'b0000: ssOut = 8'b00000011;
            4'b0001: ssOut = 8'b10011111;
            4'b0010: ssOut = 8'b00100101;
            4'b0011: ssOut = 8'b00001101;
            4'b0100: ssOut = 8'b10011001;
            4'b0101: ssOut = 8'b01001001;
            4'b0110: ssOut = 8'b01000001;
            4'b0111: ssOut = 8'b00011111;
            4'b1000: ssOut = 8'b00000001;
            4'b1001: ssOut = 8'b00011001;
            default: ssOut = 8'b11111111;
        endcase
    end
endmodule

此代码没有测试平台;它反而加载到DE0板上。我的想法是,当我按下按钮1时,总和应该增加1.按钮2将其递增10,按钮3将其递增100.然而,封装if-else的{​​{1}}模块似乎造成了一些严重的问题。

例如,当我激活开关控制复位时,总和按预期变为0。但是,当我尝试使用三个按钮中的任何一个增加总和时,会添加一个随机数 - 而不是1,10或100.

我还尝试在reset语句之前移动if-else语句。出现了另一个问题。即使未激活开关,总和也会设置为0,就好像忽略了复位条件一样。但是,如果我激活开关,则LED会亮起。如果我将其关闭,则LED将停用。但是,无论开关的状态如何,总和将始终设置为0。但是,在这种情况下,如果我按住一个按钮,我会看到总和中添加了1,10或100。一旦我释放它,总和就会重置为0.

显然,我认为我的if-else声明有问题。我不确定为什么它没有像我预期的那样工作。基本上,逻辑如下:

  1. 确定按下哪个按钮,相应地指定增量
  2. 将增量值添加到sum
  3. 总和应该重置吗?如果是,请将sum设置为0.
  4. 请注意,最后两个模块很简单。 case将二进制字符串bintoBCD转换为其BCD等效值。然后sum只是一个七段显示编码器。

3 个答案:

答案 0 :(得分:3)

这取决于你想要的以下几行:

always @(btn or reset)

组合逻辑还是顺序(触发器)?

如果支持SystemVerilog,

组合使用always @*always_comb。自动灵敏度列表表现为组合硬件确实减少了模拟不匹配。

同时使用=阻止组合分配。

顺序使用always @(posedge clk or negedge rst)之类的内容并使用<=这将允许模拟与硬件匹配。


您发现它们可能来自sum <= sum + inc;,然后是可选的重置语句。 <=的使用在这里是不正确的,因为它是具有手动灵敏度列表的组合块。 <=作业的安排可能会让一些事情失去作用。

目前正在考虑您可能期望的硬件:

always @* begin
  sum = sum + 1;
end

反对你得到的:

always @(posedge clk or negedge rst_n) begin
  if (~rst) begin
    sum <= 'b0;
  end
  else begin
    sum <= sum + 1;
  end
end

我认为如果你为你的设计添加一个时钟并暗示一个计数器的触发器(总和),你将朝着正确的方向迈出一大步。

答案 1 :(得分:3)

  

此代码没有测试平台

首先:创建一个测试平台!它并不困难(你甚至可以做online),对于逻辑错误,在模拟中调试比迭代更快真正的硬件。

其次:您的代码中没有时钟。这是最高级别的吗? FPGA在异步设计方面并不擅长,特别是在您尝试存储状态时(在本例中为sum)。目前尚不清楚Quartus会推断出什么 - 它可能已将您的一个输入连接到时钟网络。您应该在RTL查看器中检查合成设计并查看综合日志。

  

但是,当我尝试使用三个按钮中的任何一个增加总和时,会添加一个随机数

您是否正在对开关输入进行去抖动?如果您不是,那么按下每个按钮很可能会获得随机数量的切换。

请注意,此处的敏感度列表不正确 - 它也应包含sum

always @(btn or reset)
讽刺的是(鉴于我的开场评论)这不会影响合成,但会改变模拟中的行为。您最好使用always_comb(或always @(*),如果您遇到Verilog)。

答案 2 :(得分:1)

正在显示一个随机数,因为sumbtn正在改变状态时不断增加。明确的开始和停止点必须明确。

尝试使用时钟对btn进行采样。在组合块中分配inc。如果past_btn等于btn,则将inc指定为零。应在时钟模块中分配sum

alwasy @* begin
 if (past_btn == btn) inc = 'b0;
 else begin
   // case(btn) ...
 end
end

always @(posedge clk) begin
  past_btn <= btn;
  if (!reset)  sum <= 'b0;
  else         sum <= sum + inc;
end

如果您仍然获得随机数字,那么按钮可能不会被谴责。在这种情况下,为按钮采样添加另一个阶段,并仅使用采样值。

alwasy @* begin
 if (past_btn == sync_btn) inc = 'b0;
 else begin
   // case(sync_btn) ...
 end
end

always @(posedge clk) begin
  sync_btn <= btn;
  past_btn <= sync_btn;
  if (!reset)  sum <= 'b0;
  else         sum <= sum + inc;
end

始终制作测试台并在模拟中运行。逻辑错误和实现问题很难从FPGA调试。

相关问题