我在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 回答
第一个错误是:
不要那样做 . 做这个:
另一个库已经将std_logic视为已签名或未签名 . 你不应该那样想 . 然后从signed转换为std_logic_vector到unsigned . 例如 . :
但是,在你的情况下,输入已经是std_logic,所以只需转换为unsigned . 它应该工作,除非您的输入表示是非标准的 . (即有偏差) . 如果它有偏移量,请执行以下操作:
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: 我自己可能会使用强制转换为整数 .
你的i_data的范围是13 downto 0.正如Brian所说,转换可以通过添加8192来完成 .
8192是“1_0000_0000_0000”,作为表示具有与i_data匹配的长度的二进制的bit_string .
这意味着通过添加转换你只是翻转MSB,结果是最长操作数的长度 . 因为你也在s_data赋值中截断你只需要8个触发器 .
对于:
我们可以将s_data指定为:
o_data赋值变为:
不考虑进位,加法简化为单个XOR门以翻转符号,将二进制补码转换为二进制幅度表达式 .
J.H.不需要f_data和t_data . 除非需要两个额外的管道阶段,否则Bonarius表示 .
您还可以询问,仅引入一个门延迟时是否需要注册 .
如果登记册被删除:
你还可以注意到,在任何时候都没有使用'bit'i_data(5 downto 0) .
并且因为在一个输入上具有常数“1”的XOR是反转的:
该操作可以是合乎逻辑的 .
请注意,不需要算术包,也不需要类型转换(在VHDL中转换是不准确的,只允许在密切相关的类型之间进行类型转换,请参阅IEEE Std 1076-2008 9.3.6类型转换) .
如果消除了明显不必要的流水线寄存器,您还可以期望合成将优化将8192添加到基本相同的结果 . 在对原始模型进行修改以添加8192时,这也意味着某些流水线寄存器“位”会被优化掉 .
您的设计模型也不使用i_load .