VHDL将std_logic_vector中的数据签名为无符号数据

时间:2017-02-18 23:15:14

标签: casting vhdl twos-complement

我在FPGA板上有一个ADC(LTC1407A-1),它使用2个赞美符号数据填充14位寄存器。我想将此数据转换为无符号:

  • 来源数据范围:-8192 to 8191
  • 目标数据范围:0 to 16383

然而,无论我尝试什么,我似乎都无法获得理想的结果。我目前的VHDL寄存器模块工作代码部分如下:

library IEEE;
use ieee.std_logic_arith.all;
use ieee.std_logic_1164.all;

entity reg10 is
    Port ( clk : in  STD_LOGIC;                         --50MHz clock
           reset : in  STD_LOGIC;                       --asynchronous reset
           i_load : in  STD_LOGIC;                      --load signal
           i_data : in  STD_LOGIC_VECTOR (13 downto 0); --data signal
           o_data : out  STD_LOGIC_VECTOR (15 downto 0) --output data
    );
end reg10;

architecture Behavioral of reg10 is
    signal s_data : STD_LOGIC_VECTOR(9 downto 0);
    signal f_data : STD_LOGIC_VECTOR(13 downto 0);
    signal t_sign : signed (13 downto 0);
begin
    process(clk, reset)
    begin
        if reset = '1' then
            s_data <= "0000000000";
        elsif clk'event and clk = '1' then
            t_sign <= SIGNED(i_data);
            f_data <= STD_LOGIC_VECTOR(t_sign);
            s_data <= "00" & f_data(13 downto 6);
        end if;
    end process;
    o_data <= "000010" & s_data(9 downto 0);
end Behavioral;

我已经做了大量的搜索并找到了很多可以进行转换的例子,但是,我不明白正确的方法。我尝试将i_data指定为signed,在内部转换变量,以及许多其他推荐的解决方案,但都无济于事。

signal t_sign : signed (13 downto 0);
f_data <= conv_std_logic_vector(i_data, 14);

代码缓冲一个不断变化的输入向量,并将数据格式化为一个输出向量,供VGA控制器显示。

帮助表示感谢。感谢。

2 个答案:

答案 0 :(得分:1)

你的i_data的范围是13 downto 0.正如Brian所说,转换可以通过添加8192来完成。

8192是“1_0000_0000_0000”,作为表示二进制的bit_string,其长度与i_data相匹配。

这意味着通过添加转换,您只需要翻转MSB,结果是最长操作数的长度。因为你也在s_data赋值中截断你只需要8个触发器。

有关:

signal s_data:  std_logic_vector (7 downto 0);

我们可以将s_data指定为:

s_data <= (i_data(13) xor '1') & i_data(12 downto 6);

o_data赋值变为:

o_data <= "00001000" & s_data;

不考虑进位,加法简化为单个XOR门,将符号转换为二进制补码为二进制幅度表达式。

J.H.不需要f_data和t_data。除非需要两个额外的管道阶段,否则Bonarius表示。

当你只引入一个门延迟时,你也可以询问是否需要注册。

如果寄存器被删除:

o_data <= "00001000" & (i_data(13) xor '1') & i_data(12 downto 6);

你还可以注意到,在任何时候都没有使用'bit'i_data(5 downto 0)。

并且因为在一个输入上具有常数“1”的XOR是反转的:

o_data <= "00001000" & not i_data(13) & i_data(12 downto 6);

该操作可能不符合逻辑。

请注意,不需要算术包,也不需要类型转换(在VHDL中转换是不准确的,只允许在密切相关的类型之间进行类型转换,请参阅IEEE Std 1076-2008 9.3.6类型转换)。

如果消除了明显不必要的流水线寄存器,您还可以期望合成将优化将8192添加到基本相同的结果。在对原始模型进行修改以添加8192时,这也意味着某些流水线寄存器“位”会被优化掉。

您的设计模型也不使用i_load。

答案 1 :(得分:0)

第一个错误是:

use ieee.std_logic_arith.all;
不要这样做。这样做:

use ieee.numeric_std.all;

另一个库已将std_logic视为已签名或未签名。你不应该那样想。 然后从signed转换为std_logic_vector到unsigned。 e.g:

[signal] foo <= unsigned(std_logic_vector(signed(bar)));

但是,在你的情况下,输入已经是std_logic,所以只需转换为unsigned。它应该工作,除非您的输入表示是非标准的。 (即有偏差)。如果它有偏移量,请执行以下操作:

[signal] foo <= unsigned(std_logic_vector(signed(bar)+offset));

<强> N.B。 <= [signal]分配在下一个delta(https://en.wikipedia.org/wiki/Delta_delay)处分配。因此,在一个delta内评估的进程(即没有等待语句)中,直到进程结束后才会应用它们。因此,在您的示例中,即使f_data中的数据分配了t_sign t_sign之后的行,t_sign也不会更改流程结束,因此其更改不会直接影响f_data。相反,该流程将在下一个clk触发,clk'event and clk = '1'将为f_data分配新的已处理值t_sign。实际上,每个<=都会在您的示例中插入一个寄存器。

修改 我自己可能会使用强制转换为整数。

foo <= to_unsigned(to_integer(bar)+offset, foo'length);