【问题标题】:For-loop in VerilogVerilog中的for循环
【发布时间】:2013-10-16 02:30:13
【问题描述】:

我是 Verilog 的新手,所以我在使用 if 时遇到了一些问题

基本上我有一个 5 位数字,并且想要拆分它,以便我可以有一个 2 位十进制数。为此,我有这段代码

reg [4:0] position, aux;
reg [3:0] display1, display2;
reg [2:0] secondDigit;

always @(negedge iKEY[1] or negedge iKEY[2]) begin
    aux = position;

    for(secondDigit = 2'b0; aux >= 5'b01010; secondDigit = secondDigit + 2'b01)
        aux = aux - 5'b01010;

    assign display1 = aux[3:0];
    assign display2 = {2'b0, secondDigit};

end

问题是我收到了这条消息

loop with non-constant loop condition must terminate within 250 iterations


我也尝试用 for 循环代替这个 while,但总是遇到同样的错误

aux = position;
secondDigit = 2'b0;
while(aux > 5'b01010) begin
    aux = aux - 5'b01010;
    secondDigit = secondDigit + 2'b01;
end

有人可以帮助我吗? 谢谢

【问题讨论】:

    标签: verilog


    【解决方案1】:

    如果你把你的逻辑分成两个 always 块会更容易。一种用于组合逻辑,一种用于同步逻辑。在组合逻辑中应该如下所示。请注意,for 循环可以分解为三个连续的 if 语句。

    integer index;
    always @* begin // combination logic
      aux = position;
      secondDigit = 2'b00;
      for(index = 0; index < 3; index = index + 1) begin
        if(firstDigit >= 5'b0_1010) begin
          aux = aux- 5'b0_1010;
          secondDigit = secondDigit + 1'b1;
        end
      end
    end
    

    正如 Morgan 所说,您不应该使用 @(negedge iKEY[1] or negedge iKEY[2]),因为它会产生奇怪的合成结果。看起来你打算翻牌。我会推荐以下内容:

    wire enable = !(iKEY[1] && iKEY[2]); // clocking signal
    always @(posedge enable) begin // use enable as a clock
      display1 <= aux[3:0];
      display2 <= {2'b00,secondDigit[1:0]};
    end
    

    使用准系统测试平台的工作代码:http://www.edaplayground.com/s/6/245

    【讨论】:

    • 我需要知道 iKEY[1] 或 iKEY[2] 中的哪一个已经改变了它的状态(它们是板上的按钮),所以我认为我需要在 always阻止
    • @J0rge 您可以在块内使用iKEYenable 只允许合成器将其用作时钟参考。我假设您没有实际运行的时钟,并且您希望输出来自触发器。否则你应该设计一个闩锁。合成器在看到多个边沿敏感信号时将不知道该怎么做,除非清楚哪个是同步的,哪些是异步的。
    • 谢谢,我以更简单的方式解决了我最大的问题(分隔数字),但是您的建议帮助我了解了更多的硬件逻辑
    【解决方案2】:

    我只在 RTL 中使用可以静态展开的 for 循环,这里可能就是这种情况,但我没有看到。

    当条件基于aux 时,您正在使用循环递增secondDigit。对我来说,这表明循环的次数是可变的。

    aux = aux - 5'b01010; 行将被执行 n 次,这意味着并行的减法器数量可变。

    尽管查看您的状况aux &gt;= 5'b01010,这是否意味着最多只能循环一次? if 语句在这里不是更简单吗?

    看起来你正在做同样的事情:

    if ( aux >= 5'b01010 ) begin
      secondDigit = 2'b01 ;
      aux         = aux - 5'b01010;
    end
    

    注意:不要在 always 块中使用 assign 它只是:

    always @(negedge iKEY[1] or negedge iKEY[2]) begin
      display1 = aux[3:0];
      display2 = {2'b0, secondDigit};
    end
    

    你想用always@(negedge iKEY[1] or negedge iKEY[2])暗示什么硬件?

    【讨论】:

    • 逻辑没问题——OP使用重复减法来进行二进制到BCD的转换(即aux/10aux%10)。我认为/希望他不是想合成它……
    • 是的,我正在做连续减法以便从二进制转换为 BCD,所以在某些情况下,我需要模式而不是一步。我正在使用 Altera DE2-70 作为硬件
    • 好的,您需要考虑硬件,而不是软件 - 请参阅 Morgan 的初学者答案。
    • 在您的第二个总是阻塞(同步的)中,您正在使用阻塞分配。使用&lt;= 而不是= 来并行分配它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 2018-03-16
    相关资源
    最近更新 更多