Array 通过 for 循环的 VHDL 平均值
VHDL average of Array through for loop
我在 VHDL 中有一个 X 整数值数组,声明为进程内的变量。
我想计算 for 循环中所有值的平均值。
如果我手动写出 3 个值,一切正常(在硬件上测试):
entity MyEntity is
Port(
Enable : IN STD_LOGIC ;
CLK : IN STD_LOGIC;
SpeedOut : OUT INTEGER
);
end MyEntity;
Average : process
type SampleArray is Array (2 downto 0) of INTEGER;
variable SpeedSamples : SampleArray;
begin
wait until rising_edge(CLK);
if ENABLE = '1' then
SpeedOut <= ( SpeedSamples(0)+ SpeedSamples(1)+SpeedSamples(2) ) / 3;
end if;
end process Average;
如果我使用 for 循环来做同样的事情,SpeedOut 是常量 0:
entity MyEntity is
Port(
Enable : IN STD_LOGIC ;
CLK : IN STD_LOGIC;
SpeedOut : Out INTEGER
);
end MyEntity;
Average : process
type SampleArray is Array (2 downto 0) of INTEGER;
variable SpeedSamples : SampleArray;
variable tempVar : Integer;
begin
wait until rising_edge(CLK);
if ENABLE = '1' then
for i in 0 to 2 loop
tempVar := tempVar + SpeedSamples(i);
end loop;
SpeedOut <= tempVar / 3;
end if;
end process Average;
我知道如果数组更大,这将需要大量资源,但我认为我的代码存在根本性错误。
是否有经过验证的 VHDL 移动平均线计算方法?
像这样在每个时钟周期累加大量样本效率不高;具有 n 输入的加法器将消耗大量逻辑资源,因为 n 开始增加。
我的建议是为样本实施一个内存缓冲区,它在滚动平均值中的位置将与您想要的样本一样多。这将在每个时钟周期写入一个新样本;您还将在以下时钟边沿将相同的样本添加到总数中。
使用双口内存,可以同时从同一位置读出内存中的'oldest'样本(前提是内存处于先读后写模式)。从你的总数中减去这个,然后进行除法。我希望到目前为止最有效的除数是 2 的幂,这样你的除法就不会消耗任何逻辑资源。其他类型的分频器使用的逻辑比较多。
因此设计将归结为一个内存缓冲区、一个 3 输入加法器、一个用作样本缓冲区指针的计数器和一个线移位除法器。如果性能是一个问题,您可以流水线化 add/subtract 阶段,这样您就只需要 2 个输入加法器。
至于关于使用循环创建多输入加法器的实际编码问题,除了评论中提出的建议之外,我想说这真的取决于您的综合工具是否能够识别这是一个多输入加法器。您是否在综合报告中查看了与该代码段相关的任何消息?
我在 VHDL 中有一个 X 整数值数组,声明为进程内的变量。 我想计算 for 循环中所有值的平均值。 如果我手动写出 3 个值,一切正常(在硬件上测试):
entity MyEntity is
Port(
Enable : IN STD_LOGIC ;
CLK : IN STD_LOGIC;
SpeedOut : OUT INTEGER
);
end MyEntity;
Average : process
type SampleArray is Array (2 downto 0) of INTEGER;
variable SpeedSamples : SampleArray;
begin
wait until rising_edge(CLK);
if ENABLE = '1' then
SpeedOut <= ( SpeedSamples(0)+ SpeedSamples(1)+SpeedSamples(2) ) / 3;
end if;
end process Average;
如果我使用 for 循环来做同样的事情,SpeedOut 是常量 0:
entity MyEntity is
Port(
Enable : IN STD_LOGIC ;
CLK : IN STD_LOGIC;
SpeedOut : Out INTEGER
);
end MyEntity;
Average : process
type SampleArray is Array (2 downto 0) of INTEGER;
variable SpeedSamples : SampleArray;
variable tempVar : Integer;
begin
wait until rising_edge(CLK);
if ENABLE = '1' then
for i in 0 to 2 loop
tempVar := tempVar + SpeedSamples(i);
end loop;
SpeedOut <= tempVar / 3;
end if;
end process Average;
我知道如果数组更大,这将需要大量资源,但我认为我的代码存在根本性错误。
是否有经过验证的 VHDL 移动平均线计算方法?
像这样在每个时钟周期累加大量样本效率不高;具有 n 输入的加法器将消耗大量逻辑资源,因为 n 开始增加。
我的建议是为样本实施一个内存缓冲区,它在滚动平均值中的位置将与您想要的样本一样多。这将在每个时钟周期写入一个新样本;您还将在以下时钟边沿将相同的样本添加到总数中。
使用双口内存,可以同时从同一位置读出内存中的'oldest'样本(前提是内存处于先读后写模式)。从你的总数中减去这个,然后进行除法。我希望到目前为止最有效的除数是 2 的幂,这样你的除法就不会消耗任何逻辑资源。其他类型的分频器使用的逻辑比较多。
因此设计将归结为一个内存缓冲区、一个 3 输入加法器、一个用作样本缓冲区指针的计数器和一个线移位除法器。如果性能是一个问题,您可以流水线化 add/subtract 阶段,这样您就只需要 2 个输入加法器。
至于关于使用循环创建多输入加法器的实际编码问题,除了评论中提出的建议之外,我想说这真的取决于您的综合工具是否能够识别这是一个多输入加法器。您是否在综合报告中查看了与该代码段相关的任何消息?