首页 文章

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

提问于
浏览
0

我在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 回答

  • 1

    第一个错误是:

    use ieee.std_logic_arith.all;
    

    不要那样做 . 做这个:

    use ieee.numeric_std.all;
    

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

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

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

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

    N.B. <= [signal] assignments are assigned at the next delta (https://en.wikipedia.org/wiki/Delta_delay). So in a process that is evaluated within one delta (i.e. without wait statements), they are not applied until after the process ends. So in you example, even though f_data is assigned by the data in t_sign the line after t_sign is assigned, t_sign will not change until the end of the process, so its change will not directly effect f_data. Instead the process will trigger on the next clk and clk'event and clk = '1' will assign f_data the new processed value t_sign. In effect each <= will insert a register in your example.

    edit: 我自己可能会使用强制转换为整数 .

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

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

    8192是“1_0000_0000_0000”,作为表示具有与i_data匹配的长度的二进制的bit_string .

    这意味着通过添加转换你只是翻转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 .

相关问题