如何在VHDL中将8位转换为16位?

17

我有一个来自ADC转换器的输入信号,它是8位的 (std_logic_vector(7 downto 0))。 我需要将它们转换为16位信号(std_logic_vector(15 downto 0)),以用于16位信号处理到16位系统。

5个回答

33

如果将这个8位值解释为带符号的(2的补码),那么通用的和标准的VHDL转换方法是使用IEEE numeric_std库:

library ieee;
use ieee.numeric_std.all;

architecture sim of tb is
    signal slv_8  : std_logic_vector( 8 - 1 downto 0);
    signal slv_16 : std_logic_vector(16 - 1 downto 0);
begin
    slv_16 <= std_logic_vector(resize(signed(slv_8), slv_16'length));
end architecture;

首先,将std_logic_vector转换为有符号值,然后应用resize操作,该操作将对有符号值进行符号扩展,最后再将结果转换回std_logic_vector。
虽然转换过程比较冗长,但它的优点是通用的,即使以后更改目标长度也可以使用。
属性'length'只是返回slv_16 std_logic_vector的长度,因此为16。
如果要使用无符号表示而不是有符号表示,可以使用"unsigned"而不是"signed",因此可以使用以下代码:
    slv_16 <= std_logic_vector(resize(unsigned(slv_8), slv_16'length));

我试图将变量从16位调整为8位,代码如下: resized_var1 := std_logic_vector(resize(unsigned(Kp)*unsigned(integration1)),8); 但是我遇到了错误:“类型转换(到std_logic_vector)不能有聚合操作数。” 为什么会出现这种情况? - Mojo Jojo
因为 ,8 应该在 resize() 的括号内而不是 std_logic_vector()。 - Charles Steinkuehler
我认为需要注意的是,调整大小不会改变数字值。当调整到更大的向量时,在左侧添加零。 - Damo
2
@Damo:你的评论只有在改变无符号类型的长度时才是正确的。如果使用 resize 来缩短无符号或有符号类型,则会截断 MSB,从而可能改变值,并且如果使用 resize 来扩展有符号值,则使用符号(MSB)进行填充,而不是 0。 - Morten Zilmer

7
architecture RTL of test is
    signal s8: std_logic_vector(7 downto 0);
    signal s16: std_logic_vector(15 downto 0);
begin
    s16 <= X"00" & s8;
end;

1
第5行中的“X”是什么意思? - Panpetch Pinrao
3
"x"代表"十六进制"。因此,x"00"基本上是"00000000"的二进制。 - Passepartout
1
如果我想将“11111111”转换为“1111111111111111” - Panpetch Pinrao
1
等一下,所以你想一直在数值前面添加1吗,还是只有当该数值为“负数”时才添加?如果是前者,你应该执行s16 <= x"ff" & s8s16 <= (7 downto 0 => '1') & s8。如果是后者,你应该提取s8的第7位,并将第二个语句中的“1”替换为该位。 - Zhehao Mao
这实际上是一个错误的答案,对于负信号,您将在此扩展之后得到错误的信号。 - Jason Liu
@Passepartout,这个关于x"00的答案真的很有用。我在网上找了很久。 - Yannis Dran

4
这样做可以在不编辑0的宽度的情况下处理转换,无论std_logic_vector是否发生变化:
architecture RTL of test is
    signal s8: std_logic_vector(7 downto 0);
    signal s16: std_logic_vector(15 downto 0) := (others => '0');
begin
    s16(s8'range) <= s8;
end;

4

借助新发布的VHDL-2019标准,您可以进行以下操作:

larger_vec <= extend(shorter_vec);

其中extend是以下函数的定义

function extend(vec : std_logic_vector) return target_vec of std_logic_vector is
  variable result : std_logic_vector(target_vec'length - 1 downto 0) := (others => '0');
begin
  assert vec'length <= target_vec'length report "Cannot extend to shorter vector";
  result(vec'length - 1 downto 0) := vec;
  return result;
end function;

工具支持仍然有些有限,但至少有一个模拟器支持此功能(Riviera-PRO)。


3

为了完整起见,还有一种偶尔有用的方式:

--  Clear all the slv_16 bits first and then copy in the bits you need.  
process (slv_8)
begin
    slv_16 <= (others => '0');
    slv_16(7 downto 0) <= slv_8;
end process;

据我所知,我从未尝试过针对向量进行此操作,但在更加复杂的情况下,我确实需要这样做:将仅几个相关信号复制到更大、更复杂的记录中。


2
符号扩展是通过第一个赋值完成的,如 slv_16 <= (others => slv_8(7)); - Morten Zilmer
1
这在功能上是正确的,但我认为如果你想要符号扩展,你应该使用适当的数字类型(即signed),然后使用resize函数 - 就像你在答案中提出的一样 :) - Martin Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接