Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/cplusplus11/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用;功能“;在VHDL中,从同一计算返回多个变量?_Vhdl_Fpga - Fatal编程技术网

如何使用;功能“;在VHDL中,从同一计算返回多个变量?

如何使用;功能“;在VHDL中,从同一计算返回多个变量?,vhdl,fpga,Vhdl,Fpga,我试图在函数中实现一个解码代码以返回多个变量,因为我必须解码两个定点变量,并且由于fpga中的逻辑不足而导致错误。所以我需要像在c语言中一样执行解码代码-->使用两个变量调用函数两次,并以单个数字返回。这可以执行吗?如果可能的话,怎么做?还是有其他方法可以做到这一点 我正在为两个固定点数执行以下代码两次 对于整数部分和小数部分,解码效果很好。 解码后,我将它们转换成std_逻辑_向量并发送到我的lcd。这就是我解码值的原因。代码大约有1000行。 所以我不能把它放在这里 在当前代码中,我执行了两

我试图在函数中实现一个解码代码以返回多个变量,因为我必须解码两个定点变量,并且由于fpga中的逻辑不足而导致错误。所以我需要像在c语言中一样执行解码代码-->使用两个变量调用函数两次,并以单个数字返回。这可以执行吗?如果可能的话,怎么做?还是有其他方法可以做到这一点

我正在为两个固定点数执行以下代码两次 对于整数部分和小数部分,解码效果很好。 解码后,我将它们转换成std_逻辑_向量并发送到我的lcd。这就是我解码值的原因。代码大约有1000行。 所以我不能把它放在这里

在当前代码中,我执行了两次相同的解码,因此它产生了fpga不支持的大逻辑。他们各自工作。所以我需要把它放到一个函数中,然后调用函数两次


正如链接代码所示,我得到6个整数部分变量和6个小数部分变量。我需要把这段代码放在一个函数中,它返回12个变量

在参考问题中,雷诺·帕卡莱(Renaud Pacalet)在其回答中评论说,在实际转换过程中,没有特别的理由使用有符号的定点数字,也没有整数

有一种算法()使用移位和4位条件加法,可以在循环语句中实现。这里的一个是20位整数部分算法的扩展

还有一种方法可以实现分数部分的等效:

[多位数二进制到十进制转换器(也有小数!)(“多位数二进制到十进制转换器(也有小数!)”)

有关算法工作原理的说明,请访问本网站:

但我更进一步,并想出了如何应用相同的原理将二进制分数转换为十进制分数。例如,0.11(bin)可以转换为0.75(dec)。通过使用转换表执行反向功能(-3,如果8或更多)并反向移动

Hans_Lemurson最后编辑日期:2012年6月9日

虽然没有在Minecraft游戏中实现,但分数涉猎在每次比较和减法中都涉及一个逻辑单元,就像双重涉猎在加法中一样

位是串行移位的,double-dabble是一个乘法器,france-dabble是一个除法器。双数据块的add3逻辑单元的最大数量为20位x7 BCD数字(28位)或140个逻辑单元。由于未达到阈值(>4)或保证具有所有“0”输入,因此减少了无法更改结果的单元数。最终形成57个逻辑单元(每个单元有4个4x1 LUT)

分数涉猎使用更多的单元格,因为从左移会立即抛出sub3操作的阈值。从18位x 6 BCD数字或108个sub3单元进行合成映射后的缩减 仅丢失6个,给出102个逻辑单元。add3和sub3之间的差异是模四加与减,阈值(>4)与(>7)

通过使BCD值成为一个时钟寄存器并一次迭代20或18个操作时钟,可以进一步减少逻辑单元的数量(对于分数可涉猎的单元,可以进一步减少)。状态机需要与输入和输出握手,并迭代表示二进制输入值长度的时钟数

绝对值转换小于40个逻辑单元

这里的想法是,一次使用顺序操作位表示性能和大小之间的权衡(注意,您还没有使用固定除法和模缩减指定当前实现的大小)

下面的代码将这两个浅尝辄止的函数实现为不同的函数,它们可以根据更大或更小的固定值和BCD位数进行缩放,并且可能前面有Brian Drummond提到的多路复用器,尽管根据它们的大小,这似乎不太可能。(多路复用器有多大?)

“较慢”性能的含义是,更新输入值(此处显示为
cp
)的速度不会快于绝对值转换的下降时间,该下降时间和两个小数据中最长的时间(较大的一个)连接在一起

此代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.fixed_pkg.all;                    -- included in -2008

entity iopertyki is
end entity;

architecture fum of iopertyki is
    function doubledabble_20bit (inp:  std_logic_vector(19 downto 0)) 
            return unsigned is
        variable bin:   std_logic_vector(inp'range);
        variable bcd:   unsigned(27 downto 0);
    begin
        bin := inp;
        bcd := (others => '0');
        for i in 0 to 19 loop
            if bcd(3 downto 0) > 4 then
                bcd(3 downto 0) := bcd(3 downto 0) + 3;
            end if;
            if bcd(7 downto 4) > 4 then
                bcd(7 downto 4) := bcd(7 downto 4) + 3;
                end if;
            if bcd(11 downto 8) > 4 then
                bcd(11 downto 8) := bcd(11 downto 8) + 3;
            end if;
            if bcd(15 downto 12) > 4 then
                bcd(15 downto 12) := bcd(15 downto 12) + 3;
            end if;
            if bcd(19 downto 16) > 4 then
                bcd(19 downto 16) := bcd(19 downto 16) + 3;
            end if;
            if bcd(23 downto 20) > 4 then
                bcd(23 downto 20) := bcd(23 downto 20) + 3;
            end if;
            bcd := bcd(26 downto 0) & bin(19);
            bin := bin(18 downto 0) & '0';
        end loop;
        return bcd;
    end function;

    function fracdabble_19bit (inp:  std_logic_vector(18 downto 0)) 
            return unsigned is
        variable bin:   std_logic_vector(inp'range);
        variable bcd:   unsigned(23 downto 0);
        -- variable tbcd:  unsigned(23 downto 0); -- DEBUG
    begin
        bin := inp;
        bcd := (others => '0');                -- DEBUG
        for i in 0 to 18 loop

            bcd := bin(0) & bcd(23 downto 1);
            bin := '0' & bin(18 downto 1);
            -- tbcd := bcd;                       -- DEBUG

            if bcd(3 downto 0) > 7 then
                bcd(3 downto 0) := bcd(3 downto 0) - 3;
            end if;
            if bcd(7 downto 4) > 7 then
                bcd(7 downto 4) := bcd(7 downto 4) - 3;
                end if;
            if bcd(11 downto 8) > 7 then
                bcd(11 downto 8) := bcd(11 downto 8) - 3;
            end if;
            if bcd(15 downto 12) > 7 then
                bcd(15 downto 12) := bcd(15 downto 12) - 3;
            end if;
            if bcd(19 downto 16) > 7 then
                bcd(19 downto 16) := bcd(19 downto 16) - 3;
            end if;
            if bcd(23 downto 20) > 7 then
                bcd(23 downto 20) := bcd(23 downto 20) - 3;
            end if;
            -- report "i = " & integer'image(i) & LF & HT &  -- DEBUG
            --     "prior sub3 bcd = " & to_string (tbcd) & LF & HT & -- DEBUG
            --     "after sub3 bcd = " & to_string (bcd); -- DEBUG
        end loop;
        bcd(0) := inp(0);  -- An odd binary produces an odd decimal value
        return bcd;        -- the algorithm loses the LSB
    end function;

    signal cp: sfixed(20 downto -19) := to_sfixed(174334.738295,20,-19);
begin
BCD_CONVERT:
    process (cp)
        variable int_digits:    unsigned(27 downto 0);
        variable frac_digits:   unsigned(23 downto 0);

        alias L6:   unsigned(3 downto 0) is int_digits(27 downto 24);
        alias L5:   unsigned(3 downto 0) is int_digits(23 downto 20);
        alias L4:   unsigned(3 downto 0) is int_digits(19 downto 16);
        alias L3:   unsigned(3 downto 0) is int_digits(15 downto 12);
        alias L2:   unsigned(3 downto 0) is int_digits(11 downto 8);
        alias L1:   unsigned(3 downto 0) is int_digits(7 downto 4);
        alias L0:   unsigned(3 downto 0) is int_digits(3 downto 0);
        alias R5:   unsigned(3 downto 0) is frac_digits(23 downto 20);
        alias R4:   unsigned(3 downto 0) is frac_digits(19 downto 16);
        alias R3:   unsigned(3 downto 0) is frac_digits(15 downto 12);
        alias R2:   unsigned(3 downto 0) is frac_digits(11 downto 8);
        alias R1:   unsigned(3 downto 0) is frac_digits(7 downto 4);
        alias R0:   unsigned(3 downto 0) is frac_digits(3 downto 0);
        variable scp:           sfixed(20 downto -19);
        variable sign:          character;
    begin
        if cp < 0.0 then
            scp := "-"(0.0, cp)(20 downto -19);  -- change sign, slice length
            sign := '-';
        else
            scp := cp;
            sign := ' ';  -- no sign instead of '+'
        end if;
        report LF & HT & "             cp = " & to_string(cp) &
               LF & HT & "absolute val cp = " & to_string(scp);
        report LF & HT & "slv int = " & to_string(to_slv(scp)(38 downto 19))
               & " slv frac = " & to_string(to_slv(scp)(18 downto 0));
        -- leave off sign bit:
        int_digits := doubledabble_20bit(to_slv(scp)(38 downto 19));
        report "int_digits = " & to_string (int_digits);
        -- 55 logic cells following mspping and reduction:
        frac_digits := fracdabble_19bit(to_slv(scp)(18 downto 0)); 
        report "frac_digits = " & to_string (frac_digits);
        -- R6 = "0000"

        report "result   = " & sign &
                integer'image(to_integer(L6)) &
                integer'image(to_integer(L5)) &
                integer'image(to_integer(L4)) &
                integer'image(to_integer(L3)) &
                integer'image(to_integer(L2)) &
                integer'image(to_integer(L1)) &
                integer'image(to_integer(L0)) &
                '.' &
                integer'image(to_integer(R5)) &
                integer'image(to_integer(R4)) &
                integer'image(to_integer(R3)) &
                integer'image(to_integer(R2)) &
                integer'image(to_integer(R1)) &
                integer'image(to_integer(R0));
    end process;

MORE:
    process
    begin
        wait for 20 ns;
        cp <= "-"(cp)(20 downto -19);  -- change sign, slice length
        wait for 20 ns;
        cp <= to_sfixed(-307.83929,20,-19);
        wait;
    end process;
end architecture;
证明正确的转换

在不了解LCD显示器的情况下,尝试将BCD数字映射到LCD显示器似乎是不切实际的


这些从固定值到BCD数字的转换代表了硬件思维,而不是机器指令思维。如果不满足减少空间的需要,则使用时钟移位寄存器可以进一步减小大小,减少add3或sub3单元与小型状态机交换的要求。这是因为眼睛和LCD显示器的工作方式都具有光学持久性。你根本看不到在几毫秒内不会持续的东西。

为什么不包括一些代码来演示你的问题,这样我们就可以清楚地知道你想做什么。@trunk\u jeff我添加了一个链接,其中包含我正在跟踪的部分代码,将有符号值转换为有符号大小,以节省时间签名整数和分数部分可以看作是两个独立的二进制值。用于创建二进制编码的十进制(BCD)数字。为显示中的每个数字使用BCD数字预挂起符号,并在正确的位置显示小数点。据我回忆,你从未演示过显示方法,也没有描述过转换率或用途。“所以我需要像在c语言中一样执行解码…”你怎么会认为这是
ghdl -a --std=08 iopertyki.vhdl
ghdl -e --std=08 iopertyki
ghdl -r --std=08 iopertyki
iopertyki.vhdl:112:9:@0ms:(report note):
               cp = 000101010100011111110.1011110100000000111
  absolute val cp = 000101010100011111110.1011110100000000111
iopertyki.vhdl:114:9:@0ms:(report note):
  slv int = 00101010100011111110 slv frac = 1011110100000000111
iopertyki.vhdl:118:9:@0ms:(report note): int_digits = 0000000101110100001100110100
iopertyki.vhdl:121:9:@0ms:(report note): frac_digits = 011100111000001010010101
iopertyki.vhdl:124:9:@0ms:(report note): result   =  0174334.738295
iopertyki.vhdl:112:9:@20ns:(report note):
               cp = 111010101011100000001.0100001011111111001
  absolute val cp = 000101010100011111110.1011110100000000111
iopertyki.vhdl:114:9:@20ns:(report note):
  slv int = 00101010100011111110 slv frac = 1011110100000000111
iopertyki.vhdl:118:9:@20ns:(report note): int_digits = 0000000101110100001100110100
iopertyki.vhdl:121:9:@20ns:(report note): frac_digits = 011100111000001010010101
iopertyki.vhdl:124:9:@20ns:(report note): result   = -0174334.738295
iopertyki.vhdl:112:9:@40ns:(report note):
               cp = 111111111111011001100.0010100100100100010
  absolute val cp = 000000000000100110011.1101011011011011110
iopertyki.vhdl:114:9:@40ns:(report note):
  slv int = 00000000000100110011 slv frac = 1101011011011011110
iopertyki.vhdl:118:9:@40ns:(report note): int_digits = 0000000000000000001100000111
iopertyki.vhdl:121:9:@40ns:(report note): frac_digits = 100000111001001010010000
iopertyki.vhdl:124:9:@40ns:(report note): result   = -0000307.839290