将C宏转换为VHDL

时间:2014-02-24 04:13:06

标签: c vhdl

我对VHDL很新,并试图将两个给定的C宏转换为我的FPGA上的单个指令。宏是:

#define m_in_bits(buf, num) (buf) >> (24 - (num)) // buf is uint32_t
#define m_ext_bits(buf, i) ((buf) < (1<<((i)-1)) ? (buf) + (((-1)<<(i)) + 1) : (buf))

使用宏的C代码是:

m_ext_bits(m_in_bits(buffer, size), size);

我在让m_ext_bits正确编译方面遇到问题。这是我的VHDL:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity myEntity is
port(
  signal buffer: in std_logic_vector(31 downto 0);
  signal result: out std_logic_vector(31 downto 0)
);
end entity myEntity;

architecture myArch of myEntity  is
  signal size : signed (3 downto 0);
begin

size <= signed(buffer(27 downto 24));

result(15 downto 0) <= std_logic_vector(signed(buffer(23 downto 0)) srl (24 - to_integer(size))
                     + signed((-1 sll to_integer(size)) + 1)); -- the offending line

end architecture myArch ;

result(15 downto 0) <=开头的长行实际上编译时没有错误(实现m_in_bits宏)。但是,当我添加以下行时,从+开始,会发生错误。我尝试使用std_logic_vectorsigned类型,并且错误会发生变化。

  

表达的类型不明确 - &#34; SIGNED&#34;或者&#34; UNSIGNED&#34;是两个可能的比赛...
  无法确定运营商的定义&#34;&#34; sll&#34;&#34; - 找到0个可能的定义......
  非法签字表达......

我认为这是一个正确的铸造和使用正确类型来完成所需操作的问题。

1 个答案:

答案 0 :(得分:2)

首先,buffer是一个保留的VHDL字,所以要改变它;使用下面的argbuf

表达式-1 sll to_integer(size)未在VHDL中定义,因为 整数值-1是一个只有没有位表示的数字表达式 由VHDL指定,因此无法进行转换。这些操作都不像 整数上的按位和/或等。可以将以24位signed类型的-1表示创建为:

to_signed(-1, 24)

分配存在长度问题,因为16位信号(result(15 downto 0))被分配了24位值(基于右侧argbuf(23 downto 0))。

然后在解决上述问题时编译srl

代码为:

result(15 downto 0) <= std_logic_vector(resize((signed(argbuf(23 downto 0)) srl (24 - to_integer(size)))
                                               + signed((to_signed(-1, 24) sll to_integer(size)) + 1), 16));

然而,VHDL移位运算符,例如srl,可能会产生意想不到的结果 在本页"Arithmetic and logical shifts and rotates are done with functions in VHDL, not operators"中描述, 所以你可以考虑使用numeric_std中定义的shift函数, 例如shift_right,作为一般编码风格。功能代码如下:

result(15 downto 0) <= std_logic_vector(resize(shift_right(signed(argbuf(23 downto 0)), 24 - to_integer(size))
                                               + signed(shift_left(to_signed(-1, 24), to_integer(size)) + 1), 16));