2017-08-08 96 views
1

我希望有更多VHDL经验的人可以启发我!总而言之,我有一个LCD实体和一个主实体来实例化它。液晶显示屏采用一个84字符的字符串(“msg”),这个字符串在我使用变量或信号索引时似乎会造成很大的问题。我不知道这是什么原因,但是,由于字符串显示HEX值,并且每个时钟周期,我读取一个16位值...我需要更新每个nybble的字符串的4个字符16位值。这不需要在一个时钟周期内完成,因为在大量循环之后读取新值......但是,尝试增加一个“t”变量,并且只将字符串值更改为“t”无论出于何种原因,时间都没有区别。VHDL - 字符串索引 - RAM使用率和总逻辑元素每增加100%以上

的错误是:“错误(170048):被选择设备有型M4K的26 RAM位置(S)”不过,目前的设计需要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汇总表包含57行的 “LCD:显示屏| altsyncram:复用器#### _ 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%!

如果有人有任何想法,我会非常感激!如果有人需要,我会发布下面的完整代码......但要警告,这有点麻烦,我觉得问题可能很简单。提前谢谢了!

Main.vhd LCD.vhd

+0

您正在阅读多次(嵌套for循环2)从同一ROM中同一时钟周期(从了getByte函数推断出),从而合成必须复制ROM来产生足够的读端口,因此它产生了很多M4K的块。您需要序列化,也就是说在多个时钟周期内进行翻译操作,因此只需要一个或2个(双端口ROM)接口。 – Paebbels

+1

@Paebbels听起来像一个答案。 – plugwash

+2

您的pastebin链接将在29天内过期,您的问题不提供[最小,完整和可验证示例](https://stackoverflow.com/help/mcve),也不提供pastebin代码。生成一个最小示例的过程可以引导对正在发生的事情以及可以证明其他问题的模拟进行洞察。什么是LCD显示,波特率?没有MCVe或信息,治愈不能进行,例如,双缓冲区msg,一个缓冲区连接到UART,另一个缓冲区使用多个时钟中的单个ROM进行组合。 – user1155120

回答

2

这里有几个问题。

第一个是HDL综合工具做了很多优化。这基本上意味着,如果您没有将输入和输出部分正确连接到某个可能(但不确定)被优化程序清除的事物。

第二是你必须非常小心循环和功能。基本上循环将被展开并且函数将被内联,所以一小段代码可能会产生大量的逻辑。

第三个是,在某些cicumstances数组将被转换为内存元素。

正如在注释中指出的,这个循环是大量内存使用的根本原因。

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份的公羊。阅读旋风2数据表每个副本都需要2 M4K块

那么,为什么当你使用数字而不是变量a,b,c和d不会出现这种情况?

如果编译器能弄清楚的东西是一个常数可以在编译时计算它。这将限制对“像素”的调用次数,这些像素必须被实际转换为内存块,而不是只将结果硬编码。尽管如此,我很惊讶它下降到零。

我注意到你的代码实际上除了时钟和实际上并没有被用于任何东西的“rx”输入之外没有任何输入,所以合成器很可能会被搞清楚在构建时有很多东西。通常消除一个代码可以允许消除另一个位,直到你什么也没有剩下。