这个简单的 VHDL for 循环有什么问题?

What's wrong with this simple VHDL for loop?

出于某种原因,OutputTmp 变量在模拟中始终未初始化。我可以让它在没有 for 循环的情况下工作,但我真的想自动化它,这样我以后可以转向更大的向量。中间变量工作正常。

注意:我是一名 DBA 和 C# 程序员,对 VHDL 非常陌生,如果这是一个愚蠢的问题,我深表歉意。

architecture Arch of VectorMultiplier4 is

signal Intermediate : std_logic_vector(0 to 4);
signal OutputTmp : std_logic;

begin

process (Intermediate)
begin

  for i in 0 to 4 loop
    Intermediate(i) <= (VectorA(i) AND VectorB_Reduced(i));    
  end loop;

  --THIS IS WHAT DOES NOT WORK APPARENTLY
  OutputTmp <= '0';
  for i in 0 to 4 loop
    OutputTmp <= OutputTmp XOR Intermediate(i);
  end loop;
Output <= OutputTmp;
end process;

end architecture;

谢谢!

当您进入 VHDL 进程时,信号会保持其值直到进程完成(或到达等待时间)。因此,所有分配 OutputTmp 的行都可以替换为

OutputTmp <= OutputTmp XOR Intermediate(4);

如果进入进程时OutputTmp未知,则明确保持OutputTmp未知。

编程时,所有的语句都是一个接一个的执行。在 HDL 中,所有的语句都是同时执行的。你可以在VHDL中使用变量来实现与在C中相同的功能,但我不建议初学者愿意学习VHDL进行综合。

这与 fru1tbat 指向的答案略有不同。

信号分配的一个特征是它被安排在当前或未来的模拟时间。当任何模拟过程挂起时,实际上没有信号分配生效(并且所有涉及信号的语句都被转移到保留层次结构和过程或仅过程的块语句中)。

您不能在同一模拟周期内依赖刚刚分配(计划更新)的信号值。

新信号值在当前模拟周期中不可用。

没有波形延迟的信号分配(没有after Time)将在下一个模拟周期中可用,这将是一个增量周期。您只能'see'信号的当前值。

因为 OutputTmp 似乎被命名为中间值,您可以将其声明为过程中的变量(删除信号声明,或重命名一个或另一个)。

    process (VectorA, VectorB_Reduced)
        variable OutputTmpvar:  std_logic;
        variable Intermediate: std_logic_vector (0 to 4);
    begin

      for i in 0 to 4 loop
        Intermediate(i) := (VectorA(i) AND VectorB_Reduced(i));    
      end loop;

      -- A variable assignment takes effect immediately
      OutputTmpvar := '0';
      for i in 0 to 4 loop
        OutputTmpvar := OutputTmpv XOR Intermediate(i);
      end loop;
    Output := OutputTmpvar;
    end process;

这将产生 Intermediate 个数组元素的奇偶校验值。

请注意,出于同样的原因,Intermediate 也已成为变量,并且 VectorAVectorB_Reduced 已被放置在敏感度列表中,而不是 Intermediate

所有这些都可以进一步减少。

    process (VectorA, VectorB_Reduced)
        variable OutputTmpvar:  std_logic;
    begin

      -- A variable assignment takes effect immediately
      OutputTmpvar := '0';
      for i in 0 to 4 loop
        OutputTmpvar := OutputTmpvar XOR (VectorA(i) AND VectorB_Reduced(i));
      end loop;
    Output <= OutputTmpvar;
    end process;

正在删除 Intermediate

合成和尺寸扩展性定制

如果您需要合成循环:

    process (VectorA, VectorB_Reduced)
        variable OutputTmp: std_logic_vector (VectorA'RANGE) := (others => '0');
    begin

      for i in VectorA'RANGE loop
          if i = VectorA'LEFT then
              OutputTmp(i) := (VectorA(i) AND VectorB_Reduced(i));
          else 
              OutputTmp(i) := OutputTmp(i-1) XOR (VectorA(i) AND VectorB_Reduced(i));
          end if;
      end loop;
    Output <= OutputTmp(VectorA'RIGHT);
    end process;

假设 VectorAVectorB_reduced 具有相同的维度(边界)。

这样做是为合成结果的每个节点 'netlist' 提供一个唯一的名称,并将生成由五个与门馈送的四个异或门链。

此过程还展示了如何使用属性处理任何大小匹配边界输入数组(示例中的 VectorAVectorB_Reduced)。如果您需要处理两个输入具有不同边界但长度相同的情况,您可以创建 它们具有相同边界的可变副本,如果这是在函数中实现的,您希望在形式上做一些事情。

展平 XOR 链是在综合域中使用性能约束处理的事情。 (对于许多 FPGA 架构,由于 XOR 的交换和关联属性,XOR 将适合一个 LUT)。

(以上过程已经在VHDL模型中进行了分析、阐述和仿真)