std_logic_vector 中的 VHDL 签名数据到未签名数据

VHDL signed data in std_logic_vector to unsigned data

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

然而,无论我怎样尝试,我似乎都得不到想要的结果。我目前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 控制器显示。

感谢帮助。谢谢。

第一个错误是:

use ieee.std_logic_arith.all;

不要那样做。这样做:

use ieee.numeric_std.all;

另一个库已经将 std_logic 视为已签名或未签名。你不应该那样。 然后从 signed to std_logic_vector 转换为 unsigned。例如:

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

然而,在你的情况下,输入已经是 std_logic,所以只需转换为无符号。它应该可以工作,除非您的输入表示是 non-standard。 (即有一个偏移量)。如果它有偏移量,请执行以下操作:

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

N.B。 <= [信号] 分配在下一个增量 (https://en.wikipedia.org/wiki/Delta_delay) 分配。因此,在一个增量内评估的流程中(即没有等待语句),直到流程结束后才会应用它们。因此,在您的示例中,即使 f_datat_sign 中的数据赋值,但 after 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);

您的 i_data 的范围是 13 到 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 门以翻转符号,将二进制补码转换为二进制幅度表达式。

f_data 和 t_data 不需要,因为 J.H。 Bonarius 表示除非需要两个额外的流水线阶段。

你也可以问,只引入一个gate delay,到底要不要注册

如果寄存器被淘汰:

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

您还可以注意到,在任何时候都不会使用 'bits' i_data(5 到 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 时,这也意味着其中一些流水线寄存器 'bits' 被优化掉了。

您的设计模型也没有使用 i_load。