代码之家  ›  专栏  ›  技术社区  ›  nichollsg

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

  •  0
  • nichollsg  · 技术社区  · 7 年前

    我试图通过传入参数,即频率和所需的反弹时间来消除按钮/开关反弹,从而使我的去抖动代码更加模块化。我就是这样做的:

    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等方法已被证明会在我的设计中产生问题。

    2 回复  |  直到 7 年前
        1
  •  0
  •   Anders    7 年前

    Vivado 2016.3(我现有的最旧版本)似乎运行良好。我认为问题是2014.7版太旧了,无法支持这一点。你没有显示“包含”的内容,但我假设它是 AR# 44586 . 如果是这样的话,它应该接受并返回整数,它将为您截断实浮点值。浮点算法很适合在Verilog/SystemVerilog测试台和参数中使用。

    我如何绕过这个问题,以便确定计数器 基于从代码传入的参数的大小和最大计数值 在继承权的这个模块之上?

    • 更新到最新版本。2017.1或2017.3对我有好处。我在2016.3测试了以下内容,它也运行良好。

    • 尝试使用SystemVerilog(.sv),它本机支持$clog2()系统函数,但不支持“include”。不知道什么时候。sv开始工作,但可能需要2015年以上。

    • 在clog2中验证您的clog2版本。v标题与以下内容匹配

    注意:您发布的代码中还有一个相当严重的bug。 当您想要获取保存常量表达式“x”所需的MSB时,模式应为 $clog2((x)+1)-1 . 您只添加了0.5而不是1。当浮点表达式“x”的结果介于2^n和(2^n+0.5)之间时,这会导致没有足够的位。例如,您所拥有的错误计算常量为 17'h0 而不是 18'h4\U 0000 对于频率为87381333的,但在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
    
        2
  •  0
  •   CapnJJ    7 年前

    类型Real不可合成。在翻译/编写HDL之前,先绘制/创建您的设计,您就会意识到这一点。扪心自问:“一个真正的人在盖茨身上合成了什么?”

    对于那些确实“支持”Real类型的工具(例如Synplify),这只是供应商的解释,因此不可能“支持”,因为它未定义为任何HDL标准的一部分。这意味着:如果你有一个模拟器,它以一种方式解释类型Real,而你的合成器(可能)以另一种方式解释它,你将得到sim/syn不匹配。你可能会侥幸逃脱,这取决于你试图完成什么,但这仍然会被认为是糟糕的设计实践。

    如上所述,用于建模和在测试台中使用的行为代码是一个不同的故事,因为它不是合成的。