<?xml version="1.0" encoding="gbk"?> <rss version="2.0"><channel> <title>定阅帖子更新</title> <link>http://www.broadkey.com.cn/XML.ASP</link><description>TEAM Board - 意得法电子</description> <copyright>TEAM 2.0.5 Release</copyright><generator>TEAM Board by TEAM5.Cn Studio</generator> <ttl>30</ttl><item><link>http://www.broadkey.com.cn/Thread.asp?tid=108 </link><title>VHDL中Loop动态条件的可综合转化</title><author>admin</author><pubDate>2009-11-28 11:51:21</pubDate><description><![CDATA[引言<br />
<br />
VHDL是一种硬件描述语言，于1983年被IEEE制定为国际标准IEEE1076。近年来国内引进和出版了不少教<br />
<br />
材，使其在国内得到迅速推广。由于VHDL最初目的是为了实现硬件的建模而被提出的，所以其措施能力<br />
<br />
超越了数字逻辑集成电路的范围。而现有的EDA工具基本上只能支持VHDL的子集，特别是针对FPGA/CPLD<br />
<br />
器件进行的不同的综合工具，其综合子集并非统一，不少初学者很难掌握。即使是部分有经验的设计者<br />
<br />
，对于通常高级语言中都会涉及的循环语句，在VHDL中往往也不能运用自如，甚至无法表达此类逻辑，<br />
<br />
从而限制了VHDL的应用水平。例如，VHDL的并行堆排序描述就是一个比较典型的例子。该实例十分类似<br />
<br />
通常数据结构的描述，推广前景诱人；但只能通过仿真，却不能在目前任何一个EDA工具进行综合，导致<br />
<br />
无实用价值。<br />
<br />
本文从高级语言涉及最多的Loop语句出发，讨论如何在VHDL中解决这类问题。<br />
<br />
1&nbsp;无法综合的Loop动态条件<br />
<br />
VHDL中Loop表达式有三种体现形式：While&hellip;&hellip;Loop、For&hellip;&hellip;Loop和单独的Loop语句。它还支持Next、<br />
<br />
Exit和标号，因此，循环语句的表达能力大于常规的C或PASCAL语言。程序1是利用For语句和While语句<br />
<br />
描述插入算法的部分代码。<br />
<br />
程序1&nbsp;不可综合的VHDL循环语句<br />
<br />
&hellip;&hellip;<br />
<br />
for&nbsp;I&nbsp;in&nbsp;2&nbsp;to&nbsp;Length&nbsp;loop&nbsp;---Length为一个变量<br />
<br />
Temp:=MyList(I)；<br />
<br />
J：=I；<br />
<br />
While(j&gt;1)and&nbsp;MyList(j-1)&lt;Temp&nbsp;loop<br />
<br />
MyList(j):=MyList(j-1);<br />
<br />
j:=j-1;<br />
<br />
End&nbsp;loop;<br />
<br />
MyList(j):=Temp；<br />
<br />
End&nbsp;loop;<br />
<br />
&hellip;&hellip;<br />
<br />
对于第一个For语句，EDA工具Synplify综合时将会给出无边界的范围错误提示。<br />
<br />
@E：<em>&quot;</em>H：.vhd<em>&quot;</em>|for&nbsp;loops&nbsp;with&nbsp;unbound&nbsp;ranges&nbsp;should&nbsp;contain&nbsp;w&nbsp;wait&nbsp;statement<br />
<br />
即使部分优秀的综合工具，例如ORCAD&nbsp;Express、Mentor&nbsp;Grpahs&nbsp;QuickHDL等能够综合第一个For语句，<br />
<br />
也无法支持第二个While条例表达式。ORCAD&nbsp;Express将给出表达式不可静态计算的错误提示。<br />
<br />
..vhd(45):Error,expression&nbsp;does&nbsp;not&nbsp;evaluate&nbsp;to&nbsp;a&nbsp;constant.<br />
<br />
由于程序1在C程序员看来是没有问题的，因此，初学者往往不能解决好此类问题，从而使学习陷入困境<br />
<br />
，无法充分利用VHDL来表述逻辑。<br />
<br />
2&nbsp;直接代换法<br />
<br />
对于第一类无边界的范围错误问题，可以用循环的综合机制转化为相应的语句。例如下面代码：<br />
<br />
for&nbsp;I&nbsp;in&nbsp;0&nbsp;to&nbsp;1&nbsp;loop<br />
<br />
Out_Bus(i)&lt;=In_Bus(i)；<br />
<br />
End&nbsp;loop；<br />
<br />
其对应综合后的电路见图1。<br />
<br />
相应的，也可以用下列语句直接代入代换：<br />
<br />
Out_Bus(0)&lt;=In_Bus(0);<br />
<br />
Out_Bus(1)&lt;=In_Bus(1)；<br />
<br />
程序1可以采用下列VHDL代码表示：<br />
<br />
K:=2；<br />
<br />
Temp:=MyList(2);<br />
<br />
If(MyList(1)&lt;Temp&nbsp;then<br />
<br />
MyList(2):=MyList(1);<br />
<br />
J:=1;<br />
<br />
End&nbsp;if;<br />
<br />
MyList(J):=Temp;<br />
<br />
J:=3;<br />
<br />
Temp:=MyList(3);<br />
<br />
If(MyList(2)&lt;Temp&nbsp;then<br />
<br />
MyList(3):=MyList(2);<br />
<br />
J:=2;<br />
<br />
End&nbsp;if;<br />
<br />
If(MyList(1)&lt;Temp&nbsp;then<br />
<br />
MyList(2):=MyList(1);<br />
<br />
J:=1;<br />
<br />
End&nbsp;if;<br />
<br />
MyList(J):=Temp;<br />
<br />
&hellip;&hellip;<br />
<br />
然而，这种使用方法要求设计者清楚循环条件一定会执行的次数，否则将无法实施。当循环次数比较大<br />
<br />
时，代码编写工作量将十分庞大，因此可以采用第二种方法&mdash;&mdash;边界扩充法。<br />
3&nbsp;边界扩充法<br />
<br />
边界扩充法是指在边界未定时，可以将边界定为最大可能的范围，即用静态表达来替代。例如程序1的代<br />
<br />
码可以改写为：<br />
<br />
constant&nbsp;MAX:integer=100;&nbsp;--MAX必须大于MyLen所有可能的取值<br />
<br />
&hellip;&hellip;<br />
<br />
Out_loop:for&nbsp;I&nbsp;in&nbsp;2&nbsp;to&nbsp;MAX&nbsp;loop<br />
<br />
Exit&nbsp;out_loop&nbsp;when&nbsp;I&gt;MyLen;&nbsp;--MyLen为变量<br />
<br />
Temp:=MyList(I);<br />
<br />
countj:=I;<br />
<br />
inter_loop:for&nbsp;j&nbsp;in&nbsp;I&nbsp;downto&nbsp;2&nbsp;loop<br />
<br />
countj:=j;<br />
<br />
exit&nbsp;inter_loop&nbsp;when&nbsp;MyList(j-1)&lt;Temp;&nbsp;--退出循环<br />
<br />
MyList(j):=MyList(j-1);<br />
<br />
End&nbsp;loop;<br />
<br />
MyList(countj):=Temp;<br />
<br />
End&nbsp;loop;<br />
<br />
尽管这种方法可以处理未知边界和未定表达式的情况，但十分消耗空间，特别是当MyLen相对MAX比较小<br />
<br />
的时候，代价非常大。此时，可以利用时间换空间的方法进行转换。<br />
<br />
图1&nbsp;For语句的综合示例<br />
<br />
4&nbsp;计数器法<br />
<br />
计数器法是指引入时钟和计数器，用计数器对边界条件进行控制，也可以将动态表达式直接代入转化相<br />
<br />
应的静态表达式。例如，上述代码的For条件可以用下列代码替换：<br />
<br />
if(Reset=<em>'</em>1<em>'</em>)then<br />
<br />
I:=2;<br />
<br />
Elsif&nbsp;clk=<em>'</em>1<em>'</em>and&nbsp;clk<em>'</em>event&nbsp;then<br />
<br />
Temp:=MyList(I);<br />
<br />
J:=2;<br />
<br />
While(j&gt;1)and&nbsp;MyList(j-1)&lt;Temp&nbsp;loop<br />
<br />
MyList(j):=MyList(j-1);<br />
<br />
j:=j-1;<br />
<br />
End&nbsp;loop;<br />
<br />
MyList(j):=Temp;<br />
<br />
I:=(I+1);<br />
<br />
If(I=MyLen+1)then&nbsp;I:=2;end&nbsp;if;<br />
<br />
End&nbsp;if;<br />
<br />
相比原来的代码，引入了1个时钟和1个复位。但综合开销最大的循环语句却被取代了，因此，综合产生<br />
<br />
门的数目将大幅度下降，但处理时间将相应延长到原来循环条件范围。<br />
<br />
本刊网络补充版（<img border="0" align="absMiddle" src="http://www.embedworld.com/skin/skin_3/small/url.gif" alt="" /><a href="http://www.dpj.com.cn/" target="_blank">http://www.dpj.com.cn</a>）中发表了四个源代码，分别为不可综合例子、直接代换法、<br />
<br />
边界扩充法和计算器法，内部都有相应注释。其中计数器法改进为双计数器方法。<br />
结语<br />
<br />
以上三种方法各有优缺点，不可一概而论，可以根据实际情况处理。直接代换法一般用于循环次数少的<br />
<br />
情况；边界扩充法一般用于循环次数接近最大边界时；计数器方法一般用于芯片内部时钟相对信号时钟<br />
<br />
快许多的情况。<br />
<br />
本文章来自中国IT实验室<img border="0" align="absMiddle" src="http://www.embedworld.com/skin/skin_3/small/url.gif" alt="" /><a href="http://embed.chinaitlab.com/" target="_blank">http://embed.chinaitlab.com/</a><br />]]></description></item></channel></rss>