Vivado可以处理用户定义的物理类型吗?

时间:2020-12-22 16:27:35

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.

我为Xilinx XST、iSim、Altera Quartus II、导师图形QuestaSim和GHDL编写了一些跨平台VHDL库。现在我想移植我的ISE 14.7项目,它将这些库用于Vivado 2014.4,但是一个库似乎有致命的问题。

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).

一个主要用例是给定延迟和系统频率的延迟或计数器周期的计算。例如,125 ns的延迟需要12或13个延迟周期为100 MHz(这取决于在.5的舍入模式)。

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

我从Vivado Synth那里得到了一些信息和警告(一些是assert语句的结果,见下面的最小示例):

[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. 程序包:通用类型、枚举和函数。
  3. Package strings: string manipulation and conversion functions
  4. 包字符串:字符串操作和转换函数。
  5. Package physical: the new type and it's functions
  6. 包物理:新类型和它的功能。
  7. Entity: a single top-level entity implementing a simple delay element / shift-register
  8. 实体:实现简单延迟元素/移位寄存器的单个*实体。

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

upt:=用户定义的物理类型。

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?
  • 我怎样才能为Vivado解决这个问题呢?
  • Can anyone confirm this behavior?
  • 有人能证实这一行为吗?
  • Which VHDL standard (87, 93, ...) introduced physical types?
  • 哪个VHDL标准(87,93,…)引入了物理类型?

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

注意:将我的问题从CR移到手动。

Edit 1:

I stripped the errors down to:

我把这些错误归结为:

  • decimal literals in physical types are false handled -> result is 0 in every case
  • 物理类型的十进制数字是错误处理的->的结果是0。
  • 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.

在Xilinx论坛上报道了这些问题。

1 个解决方案

#1


1  

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).

THz超出了类型时间的最小范围(参见IEEE Std 1076-2008, 16.3包标准,“类型INTEGER是range实现_defined;”,5.2.3整数类型“……”一个实现可以限制整数类型的范围约束的范围,而不是universal_integer类型。然而,一个实现应该允许任何整数类型的声明,其范围完全包含在边界-2147483647和+2147483647的范围内。”,输入频率)。

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

从上到下计数:pos 272:65, 298:55, 384:51。

I'm not surprised at your results.

我对你的结果并不感到惊讶。

  • How can I fix this for Vivado?
  • 我怎样才能为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:

您似乎不太可能得到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;
  • Can anyone confirm this behavior?
  • 有人能证实这一行为吗?

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

算术算出来了,没有Vivaldo。它表示支持32位整数。

  • Which VHDL standard (87, 93, ...) introduced physical types?
  • 哪个VHDL标准(87,93,…)引入了物理类型?

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

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

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

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

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

ghdl——top_physicaltest。硬件描述语言(vhdl)top_physicaltest。vhdl:272:65:静态常量违反了限制物理测试。vhdl:298:55:静态常量违反了限制物理测试。vhdl:384:51:静态常数违反了边界。


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

使用ghdl-0.31,我增加了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.

这是可行的,因为ghdl的通用整数是64位,而物理类型可以有一个通用的整数范围。

(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).

(在ghdl中有一个bug,应该使用相当于2**63 -1的整数,Tristan把它固定在ghdl-0.33中。我碰巧知道2**61是一个安全的界限。

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.

这一分析。您可以注意到,实际的范围限制了您执行的任何缩放的准确性。如果没有检查,我不能告诉你ghdl是否有一个64位的通用实数匹配它的64位通用整数。

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

然后分析,详细说明并运行top_物理测试(测试工作台)。

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

top_physical caltest:error:绑定检查在物理上的失败。硬件描述语言(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;

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

第117行是包体中用于包字符串的常量的声明。

And from std.standard:

从std.standard:

subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;

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

型整数在ghdl中是32位精度(在合成工具中是普遍的)。

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)).

这看起来像一个“图像错误”,我可能或者没有通知Tristan(是的!,参见#31类型转换子类型约束检查不执行,它也固定为0.33,也(我想我将跳过0.32))。

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,它也有64位通用整数,我之前已经提交了一些关于表达式的错误:

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

签证中心——物理。vhdl nvc -e Top_PhysicalTest **致命:表达式不能被折叠到一个整数常量文件物理。硬件描述语言(vhdl),第412行

And Line 412 is in Top_PhysicalTest:

第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);

The declaration for signal Shifter_nxt.

信号转换的声明。

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

(这看起来是一种不同类型的错误)。

#1


1  

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).

THz超出了类型时间的最小范围(参见IEEE Std 1076-2008, 16.3包标准,“类型INTEGER是range实现_defined;”,5.2.3整数类型“……”一个实现可以限制整数类型的范围约束的范围,而不是universal_integer类型。然而,一个实现应该允许任何整数类型的声明,其范围完全包含在边界-2147483647和+2147483647的范围内。”,输入频率)。

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

从上到下计数:pos 272:65, 298:55, 384:51。

I'm not surprised at your results.

我对你的结果并不感到惊讶。

  • How can I fix this for Vivado?
  • 我怎样才能为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:

您似乎不太可能得到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;
  • Can anyone confirm this behavior?
  • 有人能证实这一行为吗?

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

算术算出来了,没有Vivaldo。它表示支持32位整数。

  • Which VHDL standard (87, 93, ...) introduced physical types?
  • 哪个VHDL标准(87,93,…)引入了物理类型?

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

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

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

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

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

ghdl——top_physicaltest。硬件描述语言(vhdl)top_physicaltest。vhdl:272:65:静态常量违反了限制物理测试。vhdl:298:55:静态常量违反了限制物理测试。vhdl:384:51:静态常数违反了边界。


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

使用ghdl-0.31,我增加了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.

这是可行的,因为ghdl的通用整数是64位,而物理类型可以有一个通用的整数范围。

(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).

(在ghdl中有一个bug,应该使用相当于2**63 -1的整数,Tristan把它固定在ghdl-0.33中。我碰巧知道2**61是一个安全的界限。

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.

这一分析。您可以注意到,实际的范围限制了您执行的任何缩放的准确性。如果没有检查,我不能告诉你ghdl是否有一个64位的通用实数匹配它的64位通用整数。

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

然后分析,详细说明并运行top_物理测试(测试工作台)。

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

top_physical caltest:error:绑定检查在物理上的失败。硬件描述语言(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;

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

第117行是包体中用于包字符串的常量的声明。

And from std.standard:

从std.standard:

subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;

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

型整数在ghdl中是32位精度(在合成工具中是普遍的)。

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)).

这看起来像一个“图像错误”,我可能或者没有通知Tristan(是的!,参见#31类型转换子类型约束检查不执行,它也固定为0.33,也(我想我将跳过0.32))。

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,它也有64位通用整数,我之前已经提交了一些关于表达式的错误:

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

签证中心——物理。vhdl nvc -e Top_PhysicalTest **致命:表达式不能被折叠到一个整数常量文件物理。硬件描述语言(vhdl),第412行

And Line 412 is in Top_PhysicalTest:

第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);

The declaration for signal Shifter_nxt.

信号转换的声明。

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

(这看起来是一种不同类型的错误)。