VHDL语言中的截断时间 [英] truncating time in VHDL

查看:13
本文介绍了VHDL语言中的截断时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不理解为什么我在以下代码中得到错误&011111111111&qot;.我所要做的就是将VHDL时间截断到最接近的1/100毫秒.

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
use std.textio.all;

entity tb is

end entity;

architecture beh of tb is
begin

    process
        variable l  :line;
        variable t1 :time := 85.84999999999999 ms;
        variable i1 :integer := integer((t1 * 100) / 1 ms);
        variable r1 :real := real(i1) / 100;
        variable t2 :time := r1 * 1 ms;
    begin
        write(l, string'("t1 = "));
        write(l, t1, justified => right, field => 20, unit => ms);                  
        writeline(output, l);

        write(l => l, value => string'("i1 = "));
        write(l => l, value => i1);     
        writeline(output, l);

        write(l => l, value => string'("r1 = "));
        write(l => l, value => r1);     
        writeline(output, l);

        write(l, string'("t2 = "));
        write(l, t2, justified => right, field => 20, unit => ms);                  
        writeline(output, l);
                
        wait;
    end process;

end architecture;
## run all
t1 = 85.84999999999999 ms
i1 = 8585
r1 = 8.585000e+01
t2 = 85.84999999999999 ms
## quit

推荐答案

物理文本由抽象文本和至少带有一个分隔符的单元组成。抽象文字,这里是十进制文字,可以是通用整数类型,也可以是通用实数类型,具体取决于(小数)点的存在。对于将在精化过程中出现的Time类型变量的初始值表达式。

请注意,在评估时,T1 85.84999999999999毫秒四舍五入为85.84ms。如果您将分数部分右端的两个9修剪掉,将表达时间限制在飞秒精度内,则这里不会进行舍入。

通用实数的IEEE64位浮点值的尾数(所有当前实现都支持)也是精度的限制因素。中的通用整数(无点)类型的64位值更准确。该标准措辞谨慎,以使此行为可接受。

如何才能保持所有可能的精度?以文本方式执行截断。

在该答案中,提供了能够指定该点之后的位数的修改的写入过程。它使用现有的写入过程并调用一个调整函数(在-2008中引入)来提供完整的功能。

它与额外参数位数设置为0的现有写入过程兼容。在它自己的库中,当两个声明都通过USE子句直接可见时,它不共享现有写入过程的名称,以避免与不同数量参数的默认值的歧义。

use std.textio.all;

package write_time_pkg is
    -- write TIME value to a line at an arbitrary precision
    procedure write_precision ( 
        l:          inout line;
        value:      in    time;
        justified:  in    side := right;
        field:      in    width := 0;
        unit:       in    time := ns;
        digits:     in    natural := 0  -- digits to right of decimal point
    );
end package;

package body write_time_pkg is
    function zeros (num: natural) return string is
        variable rets:  string (1 to num) := (others => '0');
    begin
        return rets;
    end function;
    
    function spaces (num: natural) return string is
        variable rets: string (1 to num) := (others => ' ');
    begin
        return rets;
    end function;
    
    function justify (
        value:      string;
        justified:  side := right;
        field:      width := 0
    ) return string is
      constant len : width :=  value'length;
    begin
      if field <= len then
        return value;
      else
        case justified is
          when right =>
            return spaces (field - len) & value;
          when left =>
            return value & spaces (field - len);
        end case;
      end if;
    end function justify;
    
    procedure write_precision (
            l:          inout line;
            value:      in    time;
            justified:  in    side := right; 
            field:      in    width := 0;
            unit:       in    time := ns; 
            digits:     in    natural := 0 -- to right of decimal point
    ) is
        variable editbuf:   line;
        variable point:     natural;
        variable separator: natural;
    begin
        if digits = 0 then -- No decimal place precision specified
            write (l, value, justified, field, unit); -- package std.textio
            return;
        else
            write (editbuf, VALUE, unit => unit); -- defaults, field = 0
        end if;
        
        for i in 1 to editbuf.all'length loop -- find point and units
            if editbuf.all(i) = '.' then
                point := i;
            elsif editbuf.all(i) = ' ' then
                separator := i;  -- unit immediately following space
                exit;            -- in string representation
            end if;
        end loop;
        
        if point = 0 then  -- No fraction part present
            write (l,
                justify (editbuf.all(1 to separator - 1) & 
                    '.' & zeros(digits) & -- added fraction part
                    editbuf.all(separator to editbuf.all'length), -- unit
                    justified, field
                )
            );
        elsif separator - 1 - point < digits then -- Not enough fraction part
            write (l,
                justify (editbuf.all (1 to separator - 1) &
                    zeros (digits - (separator - 1 - point)) &  -- fill
                    editbuf.all(separator to editbuf.all'length), -- unit
                    justified, field
                )
            );
        else  -- Truncate including to same length
            write (l,
                justify (editbuf.all (1 to point + digits) &
                    editbuf.all(separator to editbuf.all'length), -- unit
                    justified, field
                )
            );
        end if;
        deallocate (editbuf);
    end procedure write_precision;
end package body;

其功能可以演示:

use std.TEXTIO.all;
use work.write_time_pkg.all; 

entity truncate is
end entity;

architecture foo of truncate is
    constant t1:    time := 85.849_999_999_999 ms; -- WAS 85.849_999_999_999_99
                         -- ms  us  ns  ps  fs            ms  us  ns  ps  fs ?
    -- trimmed fraction of fs so evaluation of physical literal doesn't round up
    constant t2:    time := 1 ms;
    constant t3:    time := 85.849_999_999_999_99 ms;  -- fractions of femtosec
begin
    process
        variable buf:       line;
    begin
        write_precision (buf, t1, unit => ms, digits => 2);
        report LF & HT & "t1 = " & time'image(t1);
        report LF & HT & "t1 ms, truncated to 1/100 ms = " & string'(buf.all);
        deallocate (buf);
        write_precision (buf, t2, unit => ms, digits => 2);
        report LF & HT & "t2 = " & time'image(t2);
        report LF & HT & "t2 ms, truncated to 1/100 ms = " & string'(buf.all); 
        deallocate (buf);
        write_precision (buf, t3, unit => ms, digits => 4);
        report LF & HT & "t3 = " & time'image(t3);
        report LF & HT & "t3 ms, truncated to 1/10000 ms = " & string'(buf.all); 
        deallocate (buf);
        write_precision (buf, t1, justified => right, field => 24, 
                         unit => ms, digits => 2);
        report LF & HT & "t1 = " & time'image(t1);
        report LF & HT & "t1 ms, to 1/100 ms, justified - " & string'(buf.all); 
        deallocate (buf);
        write_precision (buf, t1, justified => right, field => 20, 
                         unit => ms, digits => 0);
        report LF & HT & "t1 = " & time'image(t1);
        report LF & HT & "t1 ms, std.textio.write justified - " & string'(buf.all); 
        deallocate (buf);
        wait;
    end process; 
end architecture;

这将产生:

/usr/local/bin/ghdl -r  truncate
truncate.vhdl:18:9:@0ms:(report note):
    t1 = 85849999999999 fs
truncate.vhdl:19:9:@0ms:(report note):
    t1 ms, truncated to 1/100 ms = 85.84 ms
truncate.vhdl:22:9:@0ms:(report note):
    t2 = 1000000000000 fs
truncate.vhdl:23:9:@0ms:(report note):
    t2 ms, truncated to 1/100 ms = 1.00 ms
truncate.vhdl:26:9:@0ms:(report note):
    t3 = 85850000000000 fs
truncate.vhdl:27:9:@0ms:(report note):
    t3 ms, truncated to 1/10000 ms = 85.8500 ms
truncate.vhdl:31:9:@0ms:(report note):
    t1 = 85849999999999 fs
truncate.vhdl:32:9:@0ms:(report note):
    t1 ms, to 1/100 ms, justified -                 85.84 ms
truncate.vhdl:36:9:@0ms:(report note):
    t1 = 85849999999999 fs
truncate.vhdl:37:9:@0ms:(report note):
    t1 ms, std.textio.write justified -   85.849999999999 ms
%:

在以下三种情况之一中,所有添加的算法都是字符数组字符串索引操作。

这篇关于VHDL语言中的截断时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆