VHDL - 字符串索引 - RAM 使用量和逻辑元素总数均增加了 100% 以上
VHDL - String indexing - RAM usage and total logic elements increase by over 100% each
希望有更多VHDL经验的人能赐教!总而言之,我有一个 LCD 实体和一个实例化它的 Main 实体。 LCD 采用 84 个字符宽的字符串 ("msg"),一旦我使用变量或信号对其进行索引,这似乎给我带来了巨大的问题。但是,我不知道这是什么原因,因为字符串显示的是 HEX 值,并且每个时钟周期,我读取一个 16 位值...我需要为每个 nybble 更新字符串的 4 个字符16 位值。这不需要在一个时钟周期内完成,因为在大量周期后会读取一个新值......但是,尝试增加一个 "t" 变量,并且只改变字符串值一个 [=一次 34=] 无论出于何种原因都没有区别。
错误是:"Error (170048): Selected device has 26 RAM location(s) of type M4K"不过目前的设计需要26个以上才能成功拟合
这里是有问题的编译报告:
Flow Status Flow Failed - Tue Aug 08 18:49:21 2017
Quartus II 64-Bit Version 13.0.1 Build 232 06/12/2013 SP 1 SJ Web Edition
Revision Name Revision1
Top-level Entity Name Main
Family Cyclone II
Device EP2C5T144C6
Timing Models Final
Total logic elements 6,626 / 4,608 ( 144 % )
Total combinational functions 6,190 / 4,608 ( 134 % )
Dedicated logic registers 1,632 / 4,608 ( 35 % )
Total registers 1632
Total pins 50 / 89 ( 56 % )
Total virtual pins 0
Total memory bits 124,032 / 119,808 ( 104 % )
Embedded Multiplier 9-bit elements 0 / 26 ( 0 % )
Total PLLs 1 / 2 ( 50 % )
RAM 摘要 table 包含 57 行,共 "LCD:display|altsyncram:Mux####_rtl_0|altsyncram_####:auto_generated|ALTSYNCRAM"
这是 LCD 实体:
entity LCD is
generic(
delay_time : integer := 50000;
half_period : integer := 7
);
port(
clk : in std_logic;
SCE : out std_logic := '1';
DC : out std_logic := '1';
RES : out std_logic := '0';
SCLK : out std_logic := '1';
SDIN : out std_logic := '0';
op : in std_logic_vector(2 downto 0);
msg : in string(1 to 84);
jx : in integer range 0 to 255 := 0;
jy : in integer range 0 to 255 := 0;
cx : in integer range 0 to 255 := 0;
cy : in integer range 0 to 255 := 0
);
end entity;
以下代码是导致问题的原因,其中 a、b、c 和 d 是每次读取后递增 4 的变量:
msg(a) <= getHex(data(3 downto 0));
msg(b) <= getHex(data(7 downto 4));
msg(c) <= getHex(data(11 downto 8));
msg(d) <= getHex(data(15 downto 12));
删除其中一些行会导致内存和逻辑元素的使用率都下降,但它们看起来仍然高得离谱,我不明白原因。
将 a、b、c 和 d 替换为整数,如 1、2、3 和 4 会使问题完全消失,逻辑元素为 22%,RAM 使用率为 0%!
如果有人有任何想法,我将不胜感激!我将 post 下面的完整代码以防万一有人需要它...但请注意,它有点混乱,我觉得问题可能很简单。非常感谢!
这里有一些问题。
首先是 HDL 综合工具进行了大量优化。这基本上意味着如果你没有正确连接输入和输出部分 to/from 一些东西很可能(但不确定)被优化器消除。
第二个是你必须非常小心循环和函数。基本上循环将被展开,函数将被内联,所以少量的代码可以产生大量的逻辑。
三是在某些情况下数组会被翻译成内存元素
正如评论中所指出的,这个循环是大量内存使用的根本原因。
for j in 0 to 83 loop
for i in 0 to 5 loop
pixels((j*6) + i) <= getByte(msg(j+1), i);
end loop;
end loop;
这可能会占用大量内存资源。每次调用 "getByte" 都需要 "ram"(的一部分)上的读取端口,但 blockrams 只有两个读取端口。所以 "ram" 被复制以满足更多读取端口的需要。内循环正在读取同一位置的不同部分,因此外循环的每次迭代基本上都需要 ram 上的独立读取端口。所以这大约是 40 个 ram 副本。阅读 Cyclone 2 数据表每个副本将需要 2 个 m4k 块
那么,当您使用数字而不是变量 a、b、c 和 d 时,为什么不会发生这种情况?
如果编译器可以计算出某个东西是常量,它可以在编译时计算它。这将限制对 "pixels" 的调用次数,这些调用必须实际转换为内存块,而不仅仅是将结果硬编码。我仍然很惊讶它下降到零。
我注意到你的代码实际上除了时钟和 "rx" 输入之外没有任何输入,实际上似乎没有被用于任何东西,所以合成器很可能可能在构建时弄清楚很多东西。通常消除一位代码可以让另一位代码被消除,直到你一无所有。
希望有更多VHDL经验的人能赐教!总而言之,我有一个 LCD 实体和一个实例化它的 Main 实体。 LCD 采用 84 个字符宽的字符串 ("msg"),一旦我使用变量或信号对其进行索引,这似乎给我带来了巨大的问题。但是,我不知道这是什么原因,因为字符串显示的是 HEX 值,并且每个时钟周期,我读取一个 16 位值...我需要为每个 nybble 更新字符串的 4 个字符16 位值。这不需要在一个时钟周期内完成,因为在大量周期后会读取一个新值......但是,尝试增加一个 "t" 变量,并且只改变字符串值一个 [=一次 34=] 无论出于何种原因都没有区别。
错误是:"Error (170048): Selected device has 26 RAM location(s) of type M4K"不过目前的设计需要26个以上才能成功拟合
这里是有问题的编译报告:
Flow Status Flow Failed - Tue Aug 08 18:49:21 2017
Quartus II 64-Bit Version 13.0.1 Build 232 06/12/2013 SP 1 SJ Web Edition
Revision Name Revision1
Top-level Entity Name Main
Family Cyclone II
Device EP2C5T144C6
Timing Models Final
Total logic elements 6,626 / 4,608 ( 144 % )
Total combinational functions 6,190 / 4,608 ( 134 % )
Dedicated logic registers 1,632 / 4,608 ( 35 % )
Total registers 1632
Total pins 50 / 89 ( 56 % )
Total virtual pins 0
Total memory bits 124,032 / 119,808 ( 104 % )
Embedded Multiplier 9-bit elements 0 / 26 ( 0 % )
Total PLLs 1 / 2 ( 50 % )
RAM 摘要 table 包含 57 行,共 "LCD:display|altsyncram:Mux####_rtl_0|altsyncram_####:auto_generated|ALTSYNCRAM"
这是 LCD 实体:
entity LCD is
generic(
delay_time : integer := 50000;
half_period : integer := 7
);
port(
clk : in std_logic;
SCE : out std_logic := '1';
DC : out std_logic := '1';
RES : out std_logic := '0';
SCLK : out std_logic := '1';
SDIN : out std_logic := '0';
op : in std_logic_vector(2 downto 0);
msg : in string(1 to 84);
jx : in integer range 0 to 255 := 0;
jy : in integer range 0 to 255 := 0;
cx : in integer range 0 to 255 := 0;
cy : in integer range 0 to 255 := 0
);
end entity;
以下代码是导致问题的原因,其中 a、b、c 和 d 是每次读取后递增 4 的变量:
msg(a) <= getHex(data(3 downto 0));
msg(b) <= getHex(data(7 downto 4));
msg(c) <= getHex(data(11 downto 8));
msg(d) <= getHex(data(15 downto 12));
删除其中一些行会导致内存和逻辑元素的使用率都下降,但它们看起来仍然高得离谱,我不明白原因。 将 a、b、c 和 d 替换为整数,如 1、2、3 和 4 会使问题完全消失,逻辑元素为 22%,RAM 使用率为 0%!
如果有人有任何想法,我将不胜感激!我将 post 下面的完整代码以防万一有人需要它...但请注意,它有点混乱,我觉得问题可能很简单。非常感谢!
这里有一些问题。
首先是 HDL 综合工具进行了大量优化。这基本上意味着如果你没有正确连接输入和输出部分 to/from 一些东西很可能(但不确定)被优化器消除。
第二个是你必须非常小心循环和函数。基本上循环将被展开,函数将被内联,所以少量的代码可以产生大量的逻辑。
三是在某些情况下数组会被翻译成内存元素
正如评论中所指出的,这个循环是大量内存使用的根本原因。
for j in 0 to 83 loop
for i in 0 to 5 loop
pixels((j*6) + i) <= getByte(msg(j+1), i);
end loop;
end loop;
这可能会占用大量内存资源。每次调用 "getByte" 都需要 "ram"(的一部分)上的读取端口,但 blockrams 只有两个读取端口。所以 "ram" 被复制以满足更多读取端口的需要。内循环正在读取同一位置的不同部分,因此外循环的每次迭代基本上都需要 ram 上的独立读取端口。所以这大约是 40 个 ram 副本。阅读 Cyclone 2 数据表每个副本将需要 2 个 m4k 块
那么,当您使用数字而不是变量 a、b、c 和 d 时,为什么不会发生这种情况?
如果编译器可以计算出某个东西是常量,它可以在编译时计算它。这将限制对 "pixels" 的调用次数,这些调用必须实际转换为内存块,而不仅仅是将结果硬编码。我仍然很惊讶它下降到零。
我注意到你的代码实际上除了时钟和 "rx" 输入之外没有任何输入,实际上似乎没有被用于任何东西,所以合成器很可能可能在构建时弄清楚很多东西。通常消除一位代码可以让另一位代码被消除,直到你一无所有。