使用实参数确定计数器大小

Using real parameter to determine counter sizes

我试图通过传入参数(频率和所需的反弹时间)来消除 button/switch 反弹,从而使我的去抖动代码更加模块化。这就是我处理它的方式:

module debounceCounter 
#(
    parameter CLOCK_FREQUENCY_Hz = 50_000_000,
    parameter BOUNCE_TIME_s     = 0.003
)
(
    input wire sysClk, reset,
    input wire i_async,
    output reg o_sync  
);
    /* include tasks/functions */
    `include "clog2.v"

    /* constants */
    parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 0.5) - 1) : 0] 
        MAX_COUNT = BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz;

使用 Xilinx ISE 14.7 的综合抛出此错误:

Xst:850 - "../../rtl/verilog/debounceCounter.v" line0: Unsupported real 
    constant

如何解决这个问题,以便我可以根据从层次结构中此模块上方的代码传入的参数来确定计数器大小和最大计数值?我的大部分代码都有变量的大小,这些变量由频率泛型决定,所以不能使用像 VHDL 这样的方法已经证明会在我的设计中产生问题。

似乎在 Vivado 2016.3(我可用的最旧版本)上运行良好。我认为问题是 2014.7 太旧了,不支持这个。您没有显示 `include 的内容,但我假设它来自 AR# 44586。如果是这样,它应该采用和 return 整数,它会为你截断真正的浮点值。浮点运算可以很好地用于 Verilog/SystemVerilog 测试台和参数。

How can I get around this issue so that I can determine the counter size and max count value based on parameters being passed in from code above this module in the heirarchy?

  • 更新到最新版本。 2017.1 或 2017.3 对我来说效果很好。我在 2016.3 上测试了以下内容,它也运行良好。

  • 尝试使用 SystemVerilog (.sv),它本身支持 $clog2() 系统函数,无需 `include。不确定 .sv 何时开始工作,但可能需要 2015+.

  • 验证 clog2.v header 中的 clog2 版本是否与以下内容匹配

注意:您发布的代码中还有另一个非常严重的错误。 当您想要获得保存常量表达式 "x" 所需的 MSB 时,模式应该是 $clog2((x)+1)-1。您只添加了 0.5 而不是 1。这会导致浮点表达式 "x" 的结果落在 2^n 和 (2^n + 0.5) 之间时没有足够的位。例如,对于频率 87381333,您错误地将常量计算为 17'h0 而不是 18'h4_0000 但它在 50Mhz 下,您的示例似乎仍然有效。墨菲定律说你会在最糟糕的时候不小心落入这个狭窄的坏范围,但绝不会在测试期间:)。

作为参考,这是我测试过的,使用`include expanded inline:

`timescale 1ns / 1ps

module debounceCounter 
#(
    //parameter CLOCK_FREQUENCY_Hz = 50_000_000,
    parameter CLOCK_FREQUENCY_Hz = 87381333, // whoops
    parameter BOUNCE_TIME_s     = 0.003
)
(
    input wire sysClk, reset,
    input wire i_async,
    output reg o_sync  
);
    /* include tasks/functions */
    //`include "clog2.v"
    function integer clog2;
        input integer value;
        begin
            value = value-1;
            for (clog2=0; value>0; clog2=clog2+1)
                value = value>>1;
        end
    endfunction

    /* constants */
    //parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 0.5) - 1) : 0] // <- BUG!!! 0.5 should 1
    parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 1) - 1) : 0]
    MAX_COUNT = BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz;

    initial
        $display("MAX_COUNT %d", MAX_COUNT);

 endmodule

Real 类型不可合成。 Draw/Create 在翻译 into/write HDL 之前你的设计,你会意识到这一点。问问自己,"What does a real synthesize to in gates?"

对于那些 "support" Type Real 的工具(例如 Synplify),它只是供应商的解释,因此不可能 "support" 因为它没有定义为任何 HDL 的一部分标准。含义:如果您有一个以一种方式解释 Real 类型的模拟器,而您的合成器(很可能)以另一种方式解释它,您将得到 sim/syn 不匹配。根据您要完成的目标,您可能会摆脱它们,但是,它仍然会被认为是糟糕的设计实践。

行为代码,用于建模和在测试平台中使用,如上所述,不同的故事,因为它没有被综合。