Vivado能否处理用户定义的物理类型?[英] Can Vivado handle user defined physical types?

本文是小编为大家收集整理的关于Vivado能否处理用户定义的物理类型?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我为Xilinx XST,ISIM,Altera Quartus II,Mentor Graphics QuestAsim和GHDL编写了一些跨平台VHDL库.现在,我想将我的ISE 14.7项目移植到Vivado 2014.4,但一个图书馆似乎有致命的问题.

我的库physical定义了几种新用户定义的物理类型,例如:FREQUENCY和BAUD;转换功能和报告功能.

一个主要用例是计算给定延迟和系统频率的延迟或反周期.因此,例如,125 ns的延迟需要在100 MHz处12或13个延迟循环(这取决于.5的圆形模式).

我从Vivado合成器那里获得了几个Infos和警告(有些是断言语句的结果,请参见下面的最小示例):

[Synth 8-638] synthesizing module 'Top_PhysicalTest' ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":410]
[Synth 8-63] RTL assertion: "to_time: f= 2147483647.1000 THz  return 2147483647.1000 sec" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":277]
[Synth 8-63] RTL assertion: "res_real: 0.000000" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":321]
[Synth 8-63] RTL assertion: "TimingToCycles: 
  Timing: 2147483647.1000 sec
  Clock_Period: 2147483647.1000 sec
  RoundingStyle: TO_NEAREST
  res_real = 2147483647.1000
  => 0" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":323]
[Synth 8-26] 'image of non-integer, non-enum type not implemented ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":422]
[Synth 8-63] RTL assertion: "CLOCK_FREQ: <complex-type>" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":422]
[Synth 8-63] RTL assertion: "CLOCK_FREQ: 2147483647.1000 THz" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":423]
[Synth 8-26] 'image of non-integer, non-enum type not implemented ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":424]
[Synth 8-63] RTL assertion: "DELAY: <complex-type>" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":424]
[Synth 8-63] RTL assertion: "DELAY: 2147483647.1000 sec" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":425]
[Synth 8-63] RTL assertion: "CYCLES: 0" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":426]
[Synth 8-256] done synthesizing module 'Top_PhysicalTest' (1#1) ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":410]
[Synth 8-3330] design Top_PhysicalTest has an empty top module
[Synth 8-3331] design Top_PhysicalTest has unconnected port Clock
[Synth 8-3330] design Top_PhysicalTest has an empty top module
[Synth 8-3331] design Top_PhysicalTest has unconnected port Clock
[Project 1-571] Translating synthesized netlist

我的场景有点复杂,因此最小的示例看起来并不像应该看起来那么最小.我没有嵌入所有功能以防止复制/替换错误,也没有删除调试和断言/报告例程.

概述:

  1. 软件包utils:常见类型,枚举和功能
  2. 软件包字符串:字符串操纵和转换功能
  3. 软件包物理:新类型及其功能
  4. 实体:实现简单延迟元素/shift-register
  5. 的单个顶级实体

最小示例:

-- EMACS settings: -*-  tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- 
-- ============================================================================
-- Package:                 Common functions and types
--
-- Authors:                 Thomas B. Preusser
--                          Martin Zabel
--                          Patrick Lehmann
--
-- License:
-- ============================================================================
-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
--                                       Chair for VLSI-Design, Diagnostics and Architecture
-- 
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
-- 
--      http://www.apache.org/licenses/LICENSE-2.0
-- 
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- ============================================================================

library IEEE;
use     IEEE.STD_LOGIC_1164.all;
use     IEEE.NUMERIC_STD.all;

package utils is
    -- rounding style
    type T_ROUNDING_STYLE   is (ROUND_TO_NEAREST, ROUND_TO_ZERO, ROUND_TO_INF, ROUND_UP, ROUND_DOWN);

    function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING;
    function imin(arg1 : integer; arg2 : integer) return integer;
    function imax(arg1 : integer; arg2 : integer) return integer;
    function log2ceil(arg : positive) return natural;
    function log2ceilnz(arg : positive) return positive;
end package utils;

package body utils is
    function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is
    begin
        if cond then
            return value1;
        else
            return value2;
        end if;
    end function;

    function imin(arg1 : integer; arg2 : integer) return integer is
    begin
        if arg1 < arg2 then return arg1; end if;
        return arg2;
    end function;

    function imax(arg1 : integer; arg2 : integer) return integer is
    begin
        if arg1 > arg2 then return arg1; end if;
        return arg2;
    end function;

    function log2ceil(arg : positive) return natural is
        variable tmp : positive     := 1;
        variable log : natural      := 0;
    begin
        if arg = 1 then return 0; end if;
        while arg > tmp loop
            tmp := tmp * 2;
            log := log + 1;
        end loop;
        return log;
    end function;

    function log2ceilnz(arg : positive) return positive is
    begin
        return imax(1, log2ceil(arg));
    end function;
end utils;

-- ============================================================================
-- Package:                 String related functions and types
--
-- Authors:                 Thomas B. Preusser
--                          Martin Zabel
--                          Patrick Lehmann
--
-- =============================================================================
library IEEE;
use     IEEE.STD_LOGIC_1164.all;
use     IEEE.NUMERIC_STD.all;
use     IEEE.MATH_REAL.all;

use     work.utils.all;

package strings is
    function raw_format_nat_dec(value : NATURAL)                return STRING;
    function str_format(value : REAL; precision : NATURAL := 3) return STRING;
    FUNCTION resize(str : STRING; size : POSITIVE; FillChar : CHARACTER := NUL) RETURN STRING;
    function str_length(str : STRING)                           return NATURAL;
    function str_trim(str : STRING)                             return STRING;
    function str_substr(str : STRING; start : INTEGER := 0; length : INTEGER := 0) return STRING;
end package strings;

package body strings is
    -- raw_format_* functions
    function raw_format_nat_dec(value : NATURAL) return STRING is
    begin
        return INTEGER'image(value);
    end function;

    -- str_format_* functions
    function str_format(value : REAL; precision : NATURAL := 3) return STRING is
        constant s      : REAL          := sign(value);
        constant int    : INTEGER       := integer((value * s) - 0.5);                                                                      -- force ROUND_DOWN
        constant frac   : INTEGER       := integer((((value * s) - real(int)) * 10.0**precision) - 0.5);    -- force ROUND_DOWN
        constant res    : STRING        := raw_format_nat_dec(int) & "." & raw_format_nat_dec(frac);
    begin
--      assert (not MY_VERBOSE)
--          report "str_format:" & CR &
--                       "  value:" & REAL'image(value) & CR &
--                       "  int = " & INTEGER'image(int) & CR &
--                       "  frac = " & INTEGER'image(frac)
--          severity note;
        return ite((s   < 0.0), "-" & res, res);
    end function;

    -- resize
    FUNCTION resize(str : STRING; size : POSITIVE; FillChar : CHARACTER := NUL) RETURN STRING IS
        CONSTANT MaxLength  : NATURAL               := imin(size, str'length);
        VARIABLE Result     : STRING(1 TO size)     := (OTHERS => FillChar);
    BEGIN
        if (MaxLength > 0) then
            Result(1 TO MaxLength) := str(str'low TO str'low + MaxLength - 1);
        end if;
        RETURN Result;
    END FUNCTION;

    -- String functions
    FUNCTION str_length(str : STRING) RETURN NATURAL IS
        VARIABLE l  : NATURAL       := 0;
    BEGIN
        FOR I IN str'range LOOP
            IF (str(I) = NUL) THEN
                RETURN l;
            ELSE
                l := l + 1;
            END IF;
        END LOOP;
        RETURN str'length;
    END FUNCTION;

    function str_trim(str : STRING) return STRING is
        constant len    : NATURAL   := str_length(str);
    begin
        if (len = 0) then
            return "";
        else
            return resize(str, len);
        end if;
    end function;

    function str_substr(str : STRING; start : INTEGER := 0; length : INTEGER := 0) return STRING is
        variable StartOfString      : positive;
        variable EndOfString        : positive;
    begin
        if (start < 0) then         -- start is negative -> start substring at right string boundary
            StartOfString       := str'high + start + 1;
        elsif (start = 0) then  -- start is zero -> start substring at left string boundary
            StartOfString       := str'low;
        else                                        -- start is positive -> start substring at left string boundary + offset
            StartOfString       := start;
        end if;

        if (length < 0) then        -- length is negative -> end substring at length'th character before right string boundary
            EndOfString         := str'high + length;
        elsif (length = 0) then -- length is zero -> end substring at right string boundary
            EndOfString         := str'high;
        else                                        -- length is positive -> end substring at StartOfString + length
            EndOfString         := StartOfString + length - 1;
        end if;

        if (StartOfString < str'low) then   report "StartOfString is out of str's range. (str=" & str & ")" severity error;     end if;
        if (EndOfString < str'high) then    report "EndOfString is out of str's range. (str=" & str & ")" severity error;           end if;

        return str(StartOfString to EndOfString);
    end function;
end strings;


-- ============================================================================
-- Package:                 This VHDL package declares new physical types and their
--                                  conversion functions.
--
-- Authors:                 Patrick Lehmann
-- 
-- ============================================================================
library IEEE;
use     IEEE.MATH_REAL.all;

use     work.utils.all;
use     work.strings.all;

package physical is
    type FREQ is range 0 to INTEGER'high units
        Hz;
        kHz = 1000 Hz;
        MHz = 1000 kHz;
        GHz = 1000 MHz;
        THz = 1000 GHz;
    end units;

    constant C_PHYSICAL_REPORT_TIMING_DEVIATION     : BOOLEAN       := TRUE;
    function to_time(f : FREQ)  return TIME;
    function to_real(t : TIME;          scale : TIME)       return REAL;
    function to_real(f : FREQ;          scale : FREQ)       return REAL;
    function TimingToCycles(Timing : TIME; Clock_Period : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL;
    function TimingToCycles(Timing : TIME; Clock_Frequency  : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL;
    function to_string(t : TIME; precision : NATURAL := 3)  return STRING;
    function to_string(f : FREQ; precision : NATURAL := 3)  return STRING;
end physical;


package body physical is
    -- iSim 14.7 does not support fs in simulation by default (fs values are converted to 0 ps)
    --  activate fs support by overriding the time precision
    --  fuse[.exe] [...] -timeprecision_vhdl 1fs [...]
    function MinimalTimeResolutionInSimulation return TIME is
    begin
        if      (1 fs > 0 sec) then return 1 fs;
        elsif   (1 ps > 0 sec) then return 1 ps;
        elsif   (1 ns > 0 sec) then return 1 ns;
        elsif   (1 us > 0 sec) then return 1 us;
        elsif   (1 ms > 0 sec) then return 1 ms;
        else                                            return 1 sec;
        end if;
    end function;

    -- real division for physical types
    function div(a : TIME; b : TIME) return REAL is
        constant MTRIS  : TIME      := MinimalTimeResolutionInSimulation;
    begin
        if  (a < 1 us) then
            return real(a / MTRIS) / real(b / MTRIS);
        elsif (a < 1 ms) then
            return real(a / (1000 * MTRIS)) / real(b / MTRIS) * 1000.0;
        elsif (a < 1 sec) then
            return real(a / (1000000 * MTRIS)) / real(b / MTRIS) * 1000000.0;
        else
            return real(a / (1000000000 * MTRIS)) / real(b / MTRIS) * 1000000000.0;
        end if;
    end function;

    function div(a : FREQ; b : FREQ) return REAL is
    begin
        return real(a / 1 Hz) / real(b / 1 Hz);
    end function;


    -- conversion functions
    function to_time(f : FREQ) return TIME is
        variable res : TIME;
    begin
        if    (f < 1.0 kHz) then res := div(1.0  Hz, f) * 1.0 sec;
        elsif (f < 1.0 MHz) then res := div(1.0 kHz, f) * 1.0 ms;
        elsif (f < 1.0 GHz) then res := div(1.0 MHz, f) * 1.0 us;
        elsif (f < 1.0 THz) then res := div(1.0 GHz, f) * 1.0 ns;
        else                     res := div(1.0 THz, f) * 1.0 ps;
        end if;

        assert FALSE report "to_time: f= " & to_string(f) & "  return " & to_string(res) severity note;
        return res;
    end function;

    -- convert physical types (TIME, FREQ) to standard type (REAL)
    function to_real(t : TIME; scale : TIME) return REAL is
    begin
        if      (scale = 1.0    fs) then    return div(t, 1.0    fs);
        elsif   (scale = 1.0    ps) then    return div(t, 1.0    ps);
        elsif   (scale = 1.0    ns) then    return div(t, 1.0    ns);
        elsif   (scale = 1.0    us) then    return div(t, 1.0    us);
        elsif   (scale = 1.0    ms) then    return div(t, 1.0    ms);
        elsif   (scale = 1.0 sec) then  return div(t, 1.0 sec);
        else    report "to_real: scale must have a value of '1.0 <unit>'" severity failure;
        end if;
    end;

    function to_real(f : FREQ; scale : FREQ) return REAL is
    begin
        if      (scale = 1.0    Hz) then    return div(f, 1.0    Hz);
        elsif   (scale = 1.0 kHz) then  return div(f, 1.0 kHz);
        elsif   (scale = 1.0 MHz) then  return div(f, 1.0 MHz);
        elsif   (scale = 1.0 GHz) then  return div(f, 1.0 GHz);
        elsif   (scale = 1.0 THz) then  return div(f, 1.0 THz);
        else    report "to_real: scale must have a value of '1.0 <unit>'" severity failure;
        end if;
    end;

    -- calculate needed counter cycles to achieve a given 1. timing/delay and 2. frequency/period
    -- ===========================================================================
    --  @param Timing           A given timing or delay, which should be achived
    --  @param Clock_Period     The period of the circuits clock
    --  @RoundingStyle          Default = round to nearest; other choises: ROUND_UP, ROUND_DOWN
    function TimingToCycles(Timing : TIME; Clock_Period : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL is
        variable res_real   : REAL;
        variable res_nat    : NATURAL;
    begin
        res_real := div(Timing, Clock_Period);  
        case RoundingStyle is
            when ROUND_TO_NEAREST =>    res_nat := natural(round(res_real));
            when ROUND_UP =>            res_nat := natural(res_real + 0.5);
            when ROUND_DOWN =>          res_nat := natural(res_real);
            when others =>  report "RoundingStyle '" & T_ROUNDING_STYLE'image(RoundingStyle) & "' not supported." severity failure;
        end case;
        report "res_real: " & REAL'image(res_real) severity note;

        assert FALSE
            report "TimingToCycles: " &     CR &
                         "  Timing: " &             to_string(Timing) & CR &
                         "  Clock_Period: " &       to_string(Clock_Period) & CR &
                         "  RoundingStyle: " &  str_substr(T_ROUNDING_STYLE'image(RoundingStyle), 7) & CR &
                         "  res_real = " &          str_format(res_real, 3) & CR &
                         "  => " &                  INTEGER'image(res_nat)
            severity note;

        return res_nat;
    end;

    function TimingToCycles(Timing : TIME; Clock_Frequency  : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL is
    begin
        return TimingToCycles(Timing, to_time(Clock_Frequency), RoundingStyle);
    end function;

    -- convert and format physical types to STRING
    function to_string(t : TIME; precision : NATURAL := 3) return STRING is
        variable unit       : STRING(1 to 3)    := (others => NUL);
        variable value  : REAL;
    begin
        if (t < 1.0 ps) then
            unit(1 to 2)    := "fs";
            value           := to_real(t, 1.0 fs);
        elsif (t < 1.0 ns) then
            unit(1 to 2)    := "ps";
            value           := to_real(t, 1.0 ps);
        elsif (t < 1.0 us) then
            unit(1 to 2)    := "ns";
            value           := to_real(t, 1.0 ns);
        elsif (t < 1.0 ms) then
            unit(1 to 2)    := "us";
            value           := to_real(t, 1.0 us);
        elsif (t < 1.0 sec) then
            unit(1 to 2)    := "ms";
            value           := to_real(t, 1.0 ms);
        else
            unit            := "sec";
            value           := to_real(t, 1.0 sec);
        end if;

        return str_format(value, precision) & " " & str_trim(unit);
    end function;

    function to_string(f : FREQ; precision : NATURAL := 3) return STRING is
        variable unit       : STRING(1 to 3)    := (others => NUL);
        variable value  : REAL;
    begin
        if (f < 1.0 kHz) then
            unit(1 to 2)    := "Hz";
            value           := to_real(f, 1.0 Hz);
        elsif (f < 1.0 MHz) then
            unit            := "kHz";
            value           := to_real(f, 1.0 kHz);
        elsif (f < 1.0 GHz) then
            unit            := "MHz";
            value           := to_real(f, 1.0 MHz);
        elsif (f < 1.0 THz) then
            unit            := "GHz";
            value           := to_real(f, 1.0 GHz);
        else
            unit            := "THz";
            value           := to_real(f, 1.0 THz);
        end if;

        return str_format(value, precision) & " " & str_trim(unit);
    end function;
end package body;


library IEEE;
use     IEEE.STD_LOGIC_1164.ALL;
use     IEEE.NUMERIC_STD.ALL;

use     work.utils.all;
use     work.strings.all;
use     work.physical.all;

entity Top_PhysicalTest is
    Port (
        Clock   : in    STD_LOGIC;
        Input   : in    STD_LOGIC;
        Output  : out   STD_LOGIC
    );
end;

architecture rtl of Top_PhysicalTest is
    -- configuration
    constant CLOCK_FREQ                 : FREQ          := 100 MHz;
    constant SHIFTER_DELAY              : TIME          := 125 ns;
    -- calculations
    constant SHIFTER_DELAY_CYCLES       : NATURAL       := TimingToCycles(SHIFTER_DELAY, CLOCK_FREQ);
    constant SHIFTER_BITS               : NATURAL       := SHIFTER_DELAY_CYCLES + 2; -- to prevent an underrun, while Vivado has a bug

    signal Shifter_nxt                  : STD_LOGIC_VECTOR(SHIFTER_BITS - 1 downto 0);
    signal Shifter_d                    : STD_LOGIC_VECTOR(SHIFTER_BITS - 2 downto 0)   := (others => '0');

begin
    assert false report "CLOCK_FREQ: " & FREQ'image(CLOCK_FREQ)                             severity note;
    assert false report "CLOCK_FREQ: " & to_string(CLOCK_FREQ)                            severity note;
    assert false report "DELAY: "      & TIME'image(SHIFTER_DELAY)                      severity note;
    assert false report "DELAY: "      & to_string(SHIFTER_DELAY)                       severity note;
    assert false report "CYCLES: "     & INTEGER'image(SHIFTER_DELAY_CYCLES)  severity note;

    Shifter_nxt <= Shifter_d & Input;
    Shifter_d   <= Shifter_nxt(Shifter_d'range) when rising_edge(Clock);
    Output      <= Shifter_nxt(SHIFTER_DELAY_CYCLES);
end;

udpt :: =用户定义的物理类型

我的观察:

  • 综合均未发生任何错误,但导致虚假计算
  • '图像未实现 - >一个应该如何调试?
  • 似乎拥有整数的价值

问题:

  • 如何为Vivado进行修复?
  • 任何人都可以确认这种行为吗?
  • 哪个VHDL标准(87,93,...)引入了物理类型?

注意:将我的问题从CR转移到So.

编辑1:

我将错误删除到:

  • 物理类型中的十进制文字是错误处理的 - >结果在每种情况下为0
  • 属性'image(..)在物理类型上不再实现
  • 具有物理类型的操作,包括.比较导致错误的值
  • 物理类型的价值范围不是单调

这些问题在 xilinx论坛.

推荐答案

THz的类型时间最小范围不超出范围(请参见IEEE STD 1076-2008,16.3包装标准,"类型Integer ins range instructation_defined;",5.2.3 Integer类型...可以限制除Universal_Integer类型以外的整数类型的范围约束的边界.但是,实现应允许声明任何整数类型的范围完全包含在–2147483647和+2147483647和+2147483647中.

从顶部计数,线:POS 272:65,298:55,384:51.

我对您的结果并不感到惊讶.

  • 如何为Vivado进行修复?

预分型.使用两个整数,一个用于某些整数单元的一部分.或者使用一个位数组类型,将问题转移到字符串转换之一.

似乎不太可能让xilinx支持64位整数范围,如类型声明中:

type FREQ is range 0 to INTEGER'high units
    Hz;
    kHz = 1000 Hz;
    MHz = 1000 kHz;
    GHz = 1000 MHz;
    THz = 1000 GHz;
end units;
  • 任何人都可以确认这种行为吗?

算术可以解决,没有维瓦尔多.它说32位整数得到了支持.

  • 哪个VHDL标准(87,93,...)引入了物理类型?

正如Bill Lynch注意到的物理类型,在IEEE STD 1076-1987,3.1.3物理类型,第3-5页.

.

这证明了使用VHDL分析仪/模拟器在合成之前验证设计规范的优点:

ghdl -a top_physicaltest.vhdl
top_physicaltest.vhdl:272:65:静态常数违反界限
top_physicaltest.vhdl:298:55:静态常数违反界限
top_physicaltest.vhdl:384:51:静态常数违反界限


使用GHDL-0.31 i增加了FREQ的高界:

    type FREQ is range 0 to 2**61 units

这起作用是因为GHDL的通用整数为64位,并且物理类型可以具有通用整数范围.

(GHDL中有一个错误,应该与整数相当于2 ** 63 -1,Tristan的修复程序我认为GHDL -0.33.我很高兴知道2 ** 61是一个安全的绑定).

分析.您可能会注意到,实际范围限制了您表演的任何缩放的准确性.没有检查,我无法告诉您GHDL是否具有64位universal real可以匹配它的64位通用整数.

因此,然后分析,详细和运行top_physicaltest(测试台).

ghdl -r top_physicaltest
./top_physicaltest:error:bund of byshy.vhdl:117
GHDL:汇编错误

    -- raw_format_* functions
    function raw_format_nat_dec(value : NATURAL) return STRING is
    begin
        return INTEGER'image(value);
    end function;

    -- str_format_* functions
    function str_format(value : REAL; precision : NATURAL := 3) return STRING is
        constant s      : REAL          := sign(value);
        constant int    : INTEGER       := integer((value * s) - 0.5);                                                                      -- force ROUND_DOWN
        constant frac   : INTEGER       := integer((((value * s) - real(int)) * 10.0**precision) - 0.5);    -- force ROUND_DOWN
        constant res    : STRING        := raw_format_nat_dec(int) & "." & raw_format_nat_dec(frac); -- LINE 117
    begin
--      assert (not MY_VERBOSE)
--          report "str_format:" & CR &
--                       "  value:" & REAL'image(value) & CR &
--                       "  int = " & INTEGER'image(int) & CR &
--                       "  frac = " & INTEGER'image(frac)
--          severity note;
        return ite((s   < 0.0), "-" & res, res);
    end function;

其中117行是包装字符串包装主体中常数res的声明.

和std.standard:

subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;

类型整数在GHDL中为32位精度(并且在合成工具中普遍使用).

看起来像'IMAGE错误,我可能会或可能没有通知tristan(是的! rel =" nofollow">#31类型转换子类型约束检查未执行,它也已修复为0.33(gee,我想跳过0.32)).

所以我尝试了NVC,它也有64位通用整数,并且我以前提交了一些错误的说法:

nvc -a物理.vhdl
NVC -E top_physicaltest
**致命:表达不能折叠为整数常数
文件物理.vhdl,第412行

和第412行在top_physicaltest中:

    constant CLOCK_FREQ                 : FREQ          := 100 MHz;
    constant SHIFTER_DELAY              : TIME          := 125 ns;
    -- calculations
    constant SHIFTER_DELAY_CYCLES       : NATURAL       := TimingToCycles(SHIFTER_DELAY, CLOCK_FREQ);
    constant SHIFTER_BITS               : NATURAL       := SHIFTER_DELAY_CYCLES + 2; -- to prevent an underrun, while Vivado has a bug

    constant SHIFTER_BITS               : NATURAL       := SHIFTER_DELAY_CYCLES + 2; -- to prevent an underrun, while Vivado has a bug

    signal Shifter_nxt                  : STD_LOGIC_VECTOR(SHIFTER_BITS - 1 downto 0);

信号shifter_nxt的声明

(看起来像其他类型的错误).

其他推荐答案

我看起来像Xilinx Vivado 2019.2要修复物理类型,尤其是时间.

摘自Vivado 2019.2发行说明:
在此处输入图像描述

本文地址:https://www.itbaoku.cn/post/2091021.html

问题描述

I wrote some cross platform VHDL libraries for Xilinx XST, iSim, Altera Quartus II, Mentor Graphics QuestaSim and GHDL. Now I wanted to port my ISE 14.7 project, which uses these libraries to Vivado 2014.4, but one library seems to have fatal problems.

My library physical defines several new user defined physical types like: FREQUENCY and BAUD; conversion functions and report functions.

One main use case is the calculation of delay or counter cycles for a given delay and system frequency. So for example a delay of 125 ns requires 12 or 13 delay cycles at 100 MHz (it depends on the rounding mode at .5).

I get several infos and warnings from Vivado Synth (some are results of an assert statement, see minimal example below):

[Synth 8-638] synthesizing module 'Top_PhysicalTest' ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":410]
[Synth 8-63] RTL assertion: "to_time: f= 2147483647.1000 THz  return 2147483647.1000 sec" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":277]
[Synth 8-63] RTL assertion: "res_real: 0.000000" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":321]
[Synth 8-63] RTL assertion: "TimingToCycles: 
  Timing: 2147483647.1000 sec
  Clock_Period: 2147483647.1000 sec
  RoundingStyle: TO_NEAREST
  res_real = 2147483647.1000
  => 0" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":323]
[Synth 8-26] 'image of non-integer, non-enum type not implemented ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":422]
[Synth 8-63] RTL assertion: "CLOCK_FREQ: <complex-type>" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":422]
[Synth 8-63] RTL assertion: "CLOCK_FREQ: 2147483647.1000 THz" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":423]
[Synth 8-26] 'image of non-integer, non-enum type not implemented ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":424]
[Synth 8-63] RTL assertion: "DELAY: <complex-type>" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":424]
[Synth 8-63] RTL assertion: "DELAY: 2147483647.1000 sec" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":425]
[Synth 8-63] RTL assertion: "CYCLES: 0" ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":426]
[Synth 8-256] done synthesizing module 'Top_PhysicalTest' (1#1) ["D:/Temp/PhysicalTest_Vivado2014.4/vhdl/Top_PhysicalTest.vhd":410]
[Synth 8-3330] design Top_PhysicalTest has an empty top module
[Synth 8-3331] design Top_PhysicalTest has unconnected port Clock
[Synth 8-3330] design Top_PhysicalTest has an empty top module
[Synth 8-3331] design Top_PhysicalTest has unconnected port Clock
[Project 1-571] Translating synthesized netlist

My scenario is a bit complex, so the minimal example look not as minimal as it should look. I did not inline every function to prevent copy/replace errors and I did not remove the debug and assert/report routines.

Overview:

  1. Package utils: common types, enums and functions
  2. Package strings: string manipulation and conversion functions
  3. Package physical: the new type and it's functions
  4. Entity: a single top-level entity implementing a simple delay element / shift-register

Minimal example:

-- EMACS settings: -*-  tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- 
-- ============================================================================
-- Package:                 Common functions and types
--
-- Authors:                 Thomas B. Preusser
--                          Martin Zabel
--                          Patrick Lehmann
--
-- License:
-- ============================================================================
-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
--                                       Chair for VLSI-Design, Diagnostics and Architecture
-- 
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
-- 
--      http://www.apache.org/licenses/LICENSE-2.0
-- 
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- ============================================================================

library IEEE;
use     IEEE.STD_LOGIC_1164.all;
use     IEEE.NUMERIC_STD.all;

package utils is
    -- rounding style
    type T_ROUNDING_STYLE   is (ROUND_TO_NEAREST, ROUND_TO_ZERO, ROUND_TO_INF, ROUND_UP, ROUND_DOWN);

    function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING;
    function imin(arg1 : integer; arg2 : integer) return integer;
    function imax(arg1 : integer; arg2 : integer) return integer;
    function log2ceil(arg : positive) return natural;
    function log2ceilnz(arg : positive) return positive;
end package utils;

package body utils is
    function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is
    begin
        if cond then
            return value1;
        else
            return value2;
        end if;
    end function;

    function imin(arg1 : integer; arg2 : integer) return integer is
    begin
        if arg1 < arg2 then return arg1; end if;
        return arg2;
    end function;

    function imax(arg1 : integer; arg2 : integer) return integer is
    begin
        if arg1 > arg2 then return arg1; end if;
        return arg2;
    end function;

    function log2ceil(arg : positive) return natural is
        variable tmp : positive     := 1;
        variable log : natural      := 0;
    begin
        if arg = 1 then return 0; end if;
        while arg > tmp loop
            tmp := tmp * 2;
            log := log + 1;
        end loop;
        return log;
    end function;

    function log2ceilnz(arg : positive) return positive is
    begin
        return imax(1, log2ceil(arg));
    end function;
end utils;

-- ============================================================================
-- Package:                 String related functions and types
--
-- Authors:                 Thomas B. Preusser
--                          Martin Zabel
--                          Patrick Lehmann
--
-- =============================================================================
library IEEE;
use     IEEE.STD_LOGIC_1164.all;
use     IEEE.NUMERIC_STD.all;
use     IEEE.MATH_REAL.all;

use     work.utils.all;

package strings is
    function raw_format_nat_dec(value : NATURAL)                return STRING;
    function str_format(value : REAL; precision : NATURAL := 3) return STRING;
    FUNCTION resize(str : STRING; size : POSITIVE; FillChar : CHARACTER := NUL) RETURN STRING;
    function str_length(str : STRING)                           return NATURAL;
    function str_trim(str : STRING)                             return STRING;
    function str_substr(str : STRING; start : INTEGER := 0; length : INTEGER := 0) return STRING;
end package strings;

package body strings is
    -- raw_format_* functions
    function raw_format_nat_dec(value : NATURAL) return STRING is
    begin
        return INTEGER'image(value);
    end function;

    -- str_format_* functions
    function str_format(value : REAL; precision : NATURAL := 3) return STRING is
        constant s      : REAL          := sign(value);
        constant int    : INTEGER       := integer((value * s) - 0.5);                                                                      -- force ROUND_DOWN
        constant frac   : INTEGER       := integer((((value * s) - real(int)) * 10.0**precision) - 0.5);    -- force ROUND_DOWN
        constant res    : STRING        := raw_format_nat_dec(int) & "." & raw_format_nat_dec(frac);
    begin
--      assert (not MY_VERBOSE)
--          report "str_format:" & CR &
--                       "  value:" & REAL'image(value) & CR &
--                       "  int = " & INTEGER'image(int) & CR &
--                       "  frac = " & INTEGER'image(frac)
--          severity note;
        return ite((s   < 0.0), "-" & res, res);
    end function;

    -- resize
    FUNCTION resize(str : STRING; size : POSITIVE; FillChar : CHARACTER := NUL) RETURN STRING IS
        CONSTANT MaxLength  : NATURAL               := imin(size, str'length);
        VARIABLE Result     : STRING(1 TO size)     := (OTHERS => FillChar);
    BEGIN
        if (MaxLength > 0) then
            Result(1 TO MaxLength) := str(str'low TO str'low + MaxLength - 1);
        end if;
        RETURN Result;
    END FUNCTION;

    -- String functions
    FUNCTION str_length(str : STRING) RETURN NATURAL IS
        VARIABLE l  : NATURAL       := 0;
    BEGIN
        FOR I IN str'range LOOP
            IF (str(I) = NUL) THEN
                RETURN l;
            ELSE
                l := l + 1;
            END IF;
        END LOOP;
        RETURN str'length;
    END FUNCTION;

    function str_trim(str : STRING) return STRING is
        constant len    : NATURAL   := str_length(str);
    begin
        if (len = 0) then
            return "";
        else
            return resize(str, len);
        end if;
    end function;

    function str_substr(str : STRING; start : INTEGER := 0; length : INTEGER := 0) return STRING is
        variable StartOfString      : positive;
        variable EndOfString        : positive;
    begin
        if (start < 0) then         -- start is negative -> start substring at right string boundary
            StartOfString       := str'high + start + 1;
        elsif (start = 0) then  -- start is zero -> start substring at left string boundary
            StartOfString       := str'low;
        else                                        -- start is positive -> start substring at left string boundary + offset
            StartOfString       := start;
        end if;

        if (length < 0) then        -- length is negative -> end substring at length'th character before right string boundary
            EndOfString         := str'high + length;
        elsif (length = 0) then -- length is zero -> end substring at right string boundary
            EndOfString         := str'high;
        else                                        -- length is positive -> end substring at StartOfString + length
            EndOfString         := StartOfString + length - 1;
        end if;

        if (StartOfString < str'low) then   report "StartOfString is out of str's range. (str=" & str & ")" severity error;     end if;
        if (EndOfString < str'high) then    report "EndOfString is out of str's range. (str=" & str & ")" severity error;           end if;

        return str(StartOfString to EndOfString);
    end function;
end strings;


-- ============================================================================
-- Package:                 This VHDL package declares new physical types and their
--                                  conversion functions.
--
-- Authors:                 Patrick Lehmann
-- 
-- ============================================================================
library IEEE;
use     IEEE.MATH_REAL.all;

use     work.utils.all;
use     work.strings.all;

package physical is
    type FREQ is range 0 to INTEGER'high units
        Hz;
        kHz = 1000 Hz;
        MHz = 1000 kHz;
        GHz = 1000 MHz;
        THz = 1000 GHz;
    end units;

    constant C_PHYSICAL_REPORT_TIMING_DEVIATION     : BOOLEAN       := TRUE;
    function to_time(f : FREQ)  return TIME;
    function to_real(t : TIME;          scale : TIME)       return REAL;
    function to_real(f : FREQ;          scale : FREQ)       return REAL;
    function TimingToCycles(Timing : TIME; Clock_Period : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL;
    function TimingToCycles(Timing : TIME; Clock_Frequency  : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL;
    function to_string(t : TIME; precision : NATURAL := 3)  return STRING;
    function to_string(f : FREQ; precision : NATURAL := 3)  return STRING;
end physical;


package body physical is
    -- iSim 14.7 does not support fs in simulation by default (fs values are converted to 0 ps)
    --  activate fs support by overriding the time precision
    --  fuse[.exe] [...] -timeprecision_vhdl 1fs [...]
    function MinimalTimeResolutionInSimulation return TIME is
    begin
        if      (1 fs > 0 sec) then return 1 fs;
        elsif   (1 ps > 0 sec) then return 1 ps;
        elsif   (1 ns > 0 sec) then return 1 ns;
        elsif   (1 us > 0 sec) then return 1 us;
        elsif   (1 ms > 0 sec) then return 1 ms;
        else                                            return 1 sec;
        end if;
    end function;

    -- real division for physical types
    function div(a : TIME; b : TIME) return REAL is
        constant MTRIS  : TIME      := MinimalTimeResolutionInSimulation;
    begin
        if  (a < 1 us) then
            return real(a / MTRIS) / real(b / MTRIS);
        elsif (a < 1 ms) then
            return real(a / (1000 * MTRIS)) / real(b / MTRIS) * 1000.0;
        elsif (a < 1 sec) then
            return real(a / (1000000 * MTRIS)) / real(b / MTRIS) * 1000000.0;
        else
            return real(a / (1000000000 * MTRIS)) / real(b / MTRIS) * 1000000000.0;
        end if;
    end function;

    function div(a : FREQ; b : FREQ) return REAL is
    begin
        return real(a / 1 Hz) / real(b / 1 Hz);
    end function;


    -- conversion functions
    function to_time(f : FREQ) return TIME is
        variable res : TIME;
    begin
        if    (f < 1.0 kHz) then res := div(1.0  Hz, f) * 1.0 sec;
        elsif (f < 1.0 MHz) then res := div(1.0 kHz, f) * 1.0 ms;
        elsif (f < 1.0 GHz) then res := div(1.0 MHz, f) * 1.0 us;
        elsif (f < 1.0 THz) then res := div(1.0 GHz, f) * 1.0 ns;
        else                     res := div(1.0 THz, f) * 1.0 ps;
        end if;

        assert FALSE report "to_time: f= " & to_string(f) & "  return " & to_string(res) severity note;
        return res;
    end function;

    -- convert physical types (TIME, FREQ) to standard type (REAL)
    function to_real(t : TIME; scale : TIME) return REAL is
    begin
        if      (scale = 1.0    fs) then    return div(t, 1.0    fs);
        elsif   (scale = 1.0    ps) then    return div(t, 1.0    ps);
        elsif   (scale = 1.0    ns) then    return div(t, 1.0    ns);
        elsif   (scale = 1.0    us) then    return div(t, 1.0    us);
        elsif   (scale = 1.0    ms) then    return div(t, 1.0    ms);
        elsif   (scale = 1.0 sec) then  return div(t, 1.0 sec);
        else    report "to_real: scale must have a value of '1.0 <unit>'" severity failure;
        end if;
    end;

    function to_real(f : FREQ; scale : FREQ) return REAL is
    begin
        if      (scale = 1.0    Hz) then    return div(f, 1.0    Hz);
        elsif   (scale = 1.0 kHz) then  return div(f, 1.0 kHz);
        elsif   (scale = 1.0 MHz) then  return div(f, 1.0 MHz);
        elsif   (scale = 1.0 GHz) then  return div(f, 1.0 GHz);
        elsif   (scale = 1.0 THz) then  return div(f, 1.0 THz);
        else    report "to_real: scale must have a value of '1.0 <unit>'" severity failure;
        end if;
    end;

    -- calculate needed counter cycles to achieve a given 1. timing/delay and 2. frequency/period
    -- ===========================================================================
    --  @param Timing           A given timing or delay, which should be achived
    --  @param Clock_Period     The period of the circuits clock
    --  @RoundingStyle          Default = round to nearest; other choises: ROUND_UP, ROUND_DOWN
    function TimingToCycles(Timing : TIME; Clock_Period : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL is
        variable res_real   : REAL;
        variable res_nat    : NATURAL;
    begin
        res_real := div(Timing, Clock_Period);  
        case RoundingStyle is
            when ROUND_TO_NEAREST =>    res_nat := natural(round(res_real));
            when ROUND_UP =>            res_nat := natural(res_real + 0.5);
            when ROUND_DOWN =>          res_nat := natural(res_real);
            when others =>  report "RoundingStyle '" & T_ROUNDING_STYLE'image(RoundingStyle) & "' not supported." severity failure;
        end case;
        report "res_real: " & REAL'image(res_real) severity note;

        assert FALSE
            report "TimingToCycles: " &     CR &
                         "  Timing: " &             to_string(Timing) & CR &
                         "  Clock_Period: " &       to_string(Clock_Period) & CR &
                         "  RoundingStyle: " &  str_substr(T_ROUNDING_STYLE'image(RoundingStyle), 7) & CR &
                         "  res_real = " &          str_format(res_real, 3) & CR &
                         "  => " &                  INTEGER'image(res_nat)
            severity note;

        return res_nat;
    end;

    function TimingToCycles(Timing : TIME; Clock_Frequency  : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return NATURAL is
    begin
        return TimingToCycles(Timing, to_time(Clock_Frequency), RoundingStyle);
    end function;

    -- convert and format physical types to STRING
    function to_string(t : TIME; precision : NATURAL := 3) return STRING is
        variable unit       : STRING(1 to 3)    := (others => NUL);
        variable value  : REAL;
    begin
        if (t < 1.0 ps) then
            unit(1 to 2)    := "fs";
            value           := to_real(t, 1.0 fs);
        elsif (t < 1.0 ns) then
            unit(1 to 2)    := "ps";
            value           := to_real(t, 1.0 ps);
        elsif (t < 1.0 us) then
            unit(1 to 2)    := "ns";
            value           := to_real(t, 1.0 ns);
        elsif (t < 1.0 ms) then
            unit(1 to 2)    := "us";
            value           := to_real(t, 1.0 us);
        elsif (t < 1.0 sec) then
            unit(1 to 2)    := "ms";
            value           := to_real(t, 1.0 ms);
        else
            unit            := "sec";
            value           := to_real(t, 1.0 sec);
        end if;

        return str_format(value, precision) & " " & str_trim(unit);
    end function;

    function to_string(f : FREQ; precision : NATURAL := 3) return STRING is
        variable unit       : STRING(1 to 3)    := (others => NUL);
        variable value  : REAL;
    begin
        if (f < 1.0 kHz) then
            unit(1 to 2)    := "Hz";
            value           := to_real(f, 1.0 Hz);
        elsif (f < 1.0 MHz) then
            unit            := "kHz";
            value           := to_real(f, 1.0 kHz);
        elsif (f < 1.0 GHz) then
            unit            := "MHz";
            value           := to_real(f, 1.0 MHz);
        elsif (f < 1.0 THz) then
            unit            := "GHz";
            value           := to_real(f, 1.0 GHz);
        else
            unit            := "THz";
            value           := to_real(f, 1.0 THz);
        end if;

        return str_format(value, precision) & " " & str_trim(unit);
    end function;
end package body;


library IEEE;
use     IEEE.STD_LOGIC_1164.ALL;
use     IEEE.NUMERIC_STD.ALL;

use     work.utils.all;
use     work.strings.all;
use     work.physical.all;

entity Top_PhysicalTest is
    Port (
        Clock   : in    STD_LOGIC;
        Input   : in    STD_LOGIC;
        Output  : out   STD_LOGIC
    );
end;

architecture rtl of Top_PhysicalTest is
    -- configuration
    constant CLOCK_FREQ                 : FREQ          := 100 MHz;
    constant SHIFTER_DELAY              : TIME          := 125 ns;
    -- calculations
    constant SHIFTER_DELAY_CYCLES       : NATURAL       := TimingToCycles(SHIFTER_DELAY, CLOCK_FREQ);
    constant SHIFTER_BITS               : NATURAL       := SHIFTER_DELAY_CYCLES + 2; -- to prevent an underrun, while Vivado has a bug

    signal Shifter_nxt                  : STD_LOGIC_VECTOR(SHIFTER_BITS - 1 downto 0);
    signal Shifter_d                    : STD_LOGIC_VECTOR(SHIFTER_BITS - 2 downto 0)   := (others => '0');

begin
    assert false report "CLOCK_FREQ: " & FREQ'image(CLOCK_FREQ)                             severity note;
    assert false report "CLOCK_FREQ: " & to_string(CLOCK_FREQ)                            severity note;
    assert false report "DELAY: "      & TIME'image(SHIFTER_DELAY)                      severity note;
    assert false report "DELAY: "      & to_string(SHIFTER_DELAY)                       severity note;
    assert false report "CYCLES: "     & INTEGER'image(SHIFTER_DELAY_CYCLES)  severity note;

    Shifter_nxt <= Shifter_d & Input;
    Shifter_d   <= Shifter_nxt(Shifter_d'range) when rising_edge(Clock);
    Output      <= Shifter_nxt(SHIFTER_DELAY_CYCLES);
end;

UDPT ::= user defined physical type

My observations:

  • synthesis runs through without any error but causes false calculations
  • 'image is not implemented -> How should one debug this?
  • seems to hold a value of INTEGER'high

Questions:

  • How can I fix this for Vivado?
  • Can anyone confirm this behavior?
  • Which VHDL standard (87, 93, ...) introduced physical types?

Notice: Move my question from CR to SO by hand.

Edit 1:

I stripped the errors down to:

  • decimal literals in physical types are false handled -> result is 0 in every case
  • attribute 'image(..) on physical types is not implemented any more
  • operations with physical types, incl. comparisons results in false values
  • value ranges of physical types are not monotone

The issues are reported in the Xilinx forum.

推荐答案

THz is out of range for the minimum range of type Time (see IEEE Std 1076-2008, 16.3 Package standard, "type INTEGER is range implementation_defined;", 5.2.3 Integer types "...An implementation may restrict the bounds of the range constraint of integer types other than type universal_integer. However, an implementation shall allow the declaration of any integer type whose range is wholly contained within the bounds –2147483647 and +2147483647 inclusive.", type FREQ).

Counting from the top, line:pos 272:65, 298:55, 384:51.

I'm not surprised at your results.

  • How can I fix this for Vivado?

Prescalers. Use two integers, one for a fraction part of some integer unit. Alternatively use a bit array type, which shifts the problem to one of string conversion.

It seems unlikely you'll get Xilinx to support 64 bit integers for ranges as in the type declaration:

type FREQ is range 0 to INTEGER'high units
    Hz;
    kHz = 1000 Hz;
    MHz = 1000 kHz;
    GHz = 1000 MHz;
    THz = 1000 GHz;
end units;
  • Can anyone confirm this behavior?

The arithmetic works out, no Vivaldo. It says 32 bit integers are supported.

  • Which VHDL standard (87, 93, ...) introduced physical types?

As Bill Lynch notes physical types are found in IEEE Std 1076-1987, 3.1.3 Physical types, Page 3-5.

This demonstrates the advantages of using a VHDL analyzer/simulator to validate a design specification before synthesis:

ghdl -a top_physicaltest.vhdl
top_physicaltest.vhdl:272:65: static constant violates bounds
top_physicaltest.vhdl:298:55: static constant violates bounds
top_physicaltest.vhdl:384:51: static constant violates bounds


Using ghdl-0.31 I increased the HIGH bound of FREQ:

    type FREQ is range 0 to 2**61 units

This works because ghdl's universal integer is 64 bit and physical types can have a universal integer range.

(There's a bug in ghdl, should work with the integer equivalent of 2**63 -1, Tristan's fixed it I think for ghdl-0.33. I happended to know 2**61 is a safe bound).

That analyzes. You could note that the Real Range limits the accuracy of any scaling your perform. Without checking I couldn't tell you if ghdl has a 64 bit universal Real to match it's 64 bit universal integer.

So then analyze, elaborate and run Top_PhysicalTest (the test bench).

ghdl -r top_physicaltest
./top_physicaltest:error: bound check failure at physical.vhdl:117
ghdl: compilation error

    -- raw_format_* functions
    function raw_format_nat_dec(value : NATURAL) return STRING is
    begin
        return INTEGER'image(value);
    end function;

    -- str_format_* functions
    function str_format(value : REAL; precision : NATURAL := 3) return STRING is
        constant s      : REAL          := sign(value);
        constant int    : INTEGER       := integer((value * s) - 0.5);                                                                      -- force ROUND_DOWN
        constant frac   : INTEGER       := integer((((value * s) - real(int)) * 10.0**precision) - 0.5);    -- force ROUND_DOWN
        constant res    : STRING        := raw_format_nat_dec(int) & "." & raw_format_nat_dec(frac); -- LINE 117
    begin
--      assert (not MY_VERBOSE)
--          report "str_format:" & CR &
--                       "  value:" & REAL'image(value) & CR &
--                       "  int = " & INTEGER'image(int) & CR &
--                       "  frac = " & INTEGER'image(frac)
--          severity note;
        return ite((s   < 0.0), "-" & res, res);
    end function;

Where Line 117 is the declaration for constant res in the package body for package strings.

And from std.standard:

subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;

Type integer is 32 bit precision in ghdl (and universally in synthesis tools).

And that looks like a 'IMAGE error I may or may not have notified Tristan of (Yup!, see #31 Type conversion subtype constraint check not performed, it's fixed for 0.33, too (gee I'm going to skip 0.32 I think)).

So I tried with nvc, which also has 64 bit universal integers, and I had previously submitted some errors to do with expressions for:

nvc -a physical.vhdl
nvc -e Top_PhysicalTest
** Fatal: expression cannot be folded to an integer constant
File physical.vhdl, Line 412

And Line 412 is in Top_PhysicalTest:

    constant CLOCK_FREQ                 : FREQ          := 100 MHz;
    constant SHIFTER_DELAY              : TIME          := 125 ns;
    -- calculations
    constant SHIFTER_DELAY_CYCLES       : NATURAL       := TimingToCycles(SHIFTER_DELAY, CLOCK_FREQ);
    constant SHIFTER_BITS               : NATURAL       := SHIFTER_DELAY_CYCLES + 2; -- to prevent an underrun, while Vivado has a bug

    constant SHIFTER_BITS               : NATURAL       := SHIFTER_DELAY_CYCLES + 2; -- to prevent an underrun, while Vivado has a bug

    signal Shifter_nxt                  : STD_LOGIC_VECTOR(SHIFTER_BITS - 1 downto 0);

The declaration for signal Shifter_nxt.

(And which looks like a different type of error).

其他推荐答案

I seems like Xilinx Vivado 2019.2 is going to fix physical types and especially TIME.

From Vivado 2019.2 release notes:
enter image description here