VHDL - 同时添加大型二维阵列。这是什么语法

VHDL - Simultaneous addition of large 2D array. What is the syntax for this

我在我的设计中已经到了需要大量增加并行化的位置,但我们在 FPGA 中有很多资源可以使用。

为此,我将类型定义为

type LargeByteArray is array(0 to 10000) of std_logic_vector(7 downto 0);

我有两个,我想 "byte-wise" 在尽可能少的操作中进行平均,并向右移动以除以二。因此,例如,avg(0) 应该是一个 8 位标准逻辑向量,即 a_in(0) + b_in(0) / 2。avg(1) 应该是 a_in(1 ) + b_in(1) / 2 等等。暂时假设我们不关心两个 8 位数字加到一个 9 位数字上。我希望能够并行执行全部 10000 个操作。

我想我需要使用一个中间步骤才能像这样使用信号"inter"进行位移。

entity Large_adder is
Port ( a_in : LargeByteArray;
       b_in : LargeByteArray;
       avg_out : LargeByteArray);

architecture arch of Large_adder is
    SIGNAL inter : LargeByteArray;
begin

我当前的代码看起来有点像这样;

inter(0) <= std_logic_vector((unsigned(a_in(0)) + unsigned(b_in(0))));
inter(1) <= std_logic_vector((unsigned(a_in(1)) + unsigned(b_in(1))));

10000 行之后...

inter(10000) <= std_logic_vector((unsigned(a_in(10000)) + unsigned(b(10000))));

还有一个类似的故事,用于最终用位移位分配输出

avg_out(0) <= '0' & inter(0)(7 downto 1);
avg_out(1) <= '0' & inter(1)(7 downto 1);

一直下降到 10000。

肯定有更 space 有效的方法来指定它。

我试过了

inter <= std_logic_vector((unsigned(a_in) + unsigned(b)));

但我收到有关找到“0”匹配 <= 运算符定义的错误。

现在显然这个数字可以从 10000 减少,以防这个问题在我想要实现的目标中看起来很愚蠢,但总的来说,你如何优雅地编写这些类型的操作而不用一行来表示我的每个元素类型?

如果非要我猜的话,我会说我们可以向“<=”运算符描述在遇到 LargeByteArray 类型时该怎么做。但我不知道该怎么做或在哪里定义这种行为。

谢谢

你有两个选择。进程内的 for 循环:

  process (a_in, b_in)
  begin
    for I in 0 to 10000 loop
      inter(I) <= std_logic_vector((unsigned(a_in(I)) + unsigned(b_in(I))));
    end loop;
  end process;

  process (inter)
  begin
    for I in 0 to 10000 loop
      c_out(I) <= '0' & inter(I)(7 downto 1);
    end loop;
  end process;

或进程外的生成循环:

G1: for I in 0 to 10000 generate
  inter(I) <= std_logic_vector((unsigned(a_in(I)) + unsigned(b_in(I))));
end generate;

G2: for I in 0 to 10000 generate
  c_out(I) <= '0' & inter(I)(7 downto 1);
end generate;

https://www.edaplayground.com/x/3hJV

模拟器执行for循环(进程内)顺序内的行,因为模拟器总是顺序执行进程内的行(但同时将其他进程和并发分配)。模拟器同时执行 generate loop 内的行,因为 generate loop 是一种用于生成多个并发事物的语言结构。由于电路的拓扑结构(一切都是并行的),这两种方法在仿真和综合中的行为相同。

使用常规流程:

process(a_in, b_in)
  variable tmp: unsigned(8 downto 0);
begin
  for i in a_in'range loop
    tmp := unsigned('0' & a_in(i)) +  unsigned('0' & b_in(i));
    avg_out(i) <= std_logic_vector(tmp(8 downto 1));
  end loop;
end process;

它看起来是顺序的,但实际上不是,因为 VHDL 语义太长,无法在此处解释。你的合成器会做你想要的。

另外,两个 8 位无符号数的和是一个 9 位无符号数(变量 tmp 声明为 unsigned(8 downto 0) 的原因)。除以二只是向右移动一个位置(如果最低有效位在最右边,通常是这种情况)。因此,如果您想要一个 8 位结果,只需将您的操作数向左扩展一位,添加它们并删除结果的 LSB,如上述过程中所建议的那样。相反,如果您在没有扩展名的情况下添加它们,您将遇到溢出问题和严重的错误。