首页 文章

SystemVerilog的问题是否具有非阻塞分配的循环?

提问于
浏览
2

当我在基于SystemVerilog的FPGA设计工作时,我遇到了一种情况,我必须在时钟边缘计算4个元素的数组之和 . 我能够使用带有非阻塞赋值语句的for循环来做到这一点 .

该设计在Quartus 15.0上成功合成,但当我尝试在Modelsim Altera上使用相同的RTL运行模拟时,结果出乎意料 . 我已经编写了一个示例代码来说明相同的内容 .

module schedule;

logic [7:0] abc [0:3];
logic [7:0] sum=0;
logic clk=0;

always begin 
   #5.0ns clk <= ~clk; 
end

initial begin
    abc = '{1,3,5,6};
end

initial @(posedge clk) begin
    for(int i = 0; i <= 3;i++ ) begin
        sum <= sum + abc[i];
    end
end

initial 
$monitor("Sum is %d",sum);

endmodule

This image shows the simulation results.

在此示例代码中, sum 是使用非阻塞分配计算的 . 它的目的是在clk的第一个构造上具有(1 3 5 6)= 15的值;我在原始硬件中观察到过 . 但是在模拟中,结果是clk(即 abc[3] )的结果是6 . 由于systemverilog模拟器为非阻塞语句安排了分配,我相信会创建4个sum实例 .

sum <= sum + abc[0];
sum <= sum + abc[1];
sum <= sum + abc[2];
sum <= sum + abc[3];

由于所有预定的分配同时发生,可能是最后一个实例更新的总和,我们有一个sum <= 0的值 . 如果我错了,请纠正我 .

现在我的问题是如何使模拟器按顺序安排这些分配,以便即使在模拟中我也能获得15的值?由于阻塞分配不是综合中的一个选项,我无法找到任何方法来保持RTL的一致性 . 谢谢 .

3 回答

  • 0

    您的分析似乎正确 . 您是否尝试过以下方法?

    logic [7:0] temp;
    always@(*) begin
        temp = 0;
        for (int i = 0; i < 4; i = i + 1) 
            temp = temp + abc[i];
    end
    
    always @(posedge clk)
        sum <= temp;
    

    这样, sum 只在时钟边沿上更新,但我们仍然可以在组合块中展开 for 循环(因此添加仍应按预期工作) .

  • 3

    SystemVerilog具有内置和数组减少运算符,无需for循环

    sum <= abc.sum() with (8'(item));
    

    需要转换为8位,因为默认情况下,结果的类型与数组元素类型相同 .

  • 2

    我想,你可以在另一个总阻塞中使用阻塞分配(这不是时钟边缘敏感,组合阻塞),它可以提供给 posedge clksum

    reg [7:0] temp_sum;
    
    always @ (*)
    begin
      temp_sum = abc[0];
      temp_sum = temp_sum + abc[1];
      temp_sum = temp_sum + abc[2];
      temp_sum = temp_sum + abc[3];
    end
    
    always @ (posedge clk)
      sum <= temp_sum;
    

    我想,这可能会奏效 .

相关问题