优秀的VHDL代码,在完成功能的前提下,应该具备如下特点:
① 简短的代码量
② 通俗的可读性
③ 更少的资源消耗
④ 更高的工作速率
⑤ 更强的可重用性
⑥ 最后强调但最重要的是鲁棒性
这些要求,有时是相互矛盾的。但是,通过合理的程序书写风格可以使这些要求分别或整体达到最优。其中更高的工作速率是指通过合理分配组合逻辑和时序逻辑,使内部逻辑时延相对于系统工作时钟留有一定余量,从而保证逻辑的可靠性。可重用性,指整个工程功能模块分配合理,在将来其他类似设计中,可以拷贝文件或稍作修改重新使用。
简短的代码量有时等效于最少的程序行数。我们在使用protel等软件画电路时,常希望有更大的计算机显示屏,以便尽可能通览全局,及时准确地把握电路功能。那么,代码量或或行数的减少,类似于屏幕的增大,便于设计者或读者总览全局,保持思路的连续性。这一特点,客观上也提高了程序的可读性。我们知道VHDL是一门语法非常严格的语言,这在很多时候增加了代码量,这也被很多硬件工程师所诟病。那么如何规避这所谓的缺点,减少代码量呢?我们从一个很小的例子说起。
例1:假设有一个3位的计数器cn :std_logic_vector(2 downto 0),在一定时钟下按照一定规则计数,需要在计数值为0和3后输出q : std_logic为高电平、其他值为低电平。那么:
if cn=0 or cn =3 then
q <= '1';
else
q <= '0';
end if;
这时,需要5行代码完成。如果强行写成1行:
if cn=0 or cn = 3 then q <= '1'; else q<= '0'; end if;
此时的可读性我们只能以呵呵来评价。这么简单的逻辑,我们期望能像C语言一样写成:
q <= cn=0 orcn = 3;
由于q定义的是std_logic型,编译不能通过。
我们定义一个标准化函数STDZ(STanDardiZation的缩写,可读作stands)
Function STDZ (b :boolean) return std_logic is
begin
if b then return '1';
else return '0';
end if;
End;
这是个不消耗任何资源的函数,那么例1可写为:
q <=STDZ(cn=0 or cn = 3);
至此,程序编程了1行代码。
尽管在VHDL中定义了很多数据类型,但在实际编程中使用的不外乎有integer、std_logic和std_logic_vector三种,以及隐含使用的boolean类型。我个人觉得std_logic_vector类型名字有些过长,所以:subtype std_vector is std_logic_vector; 现在我们新建一个ucx_200pkg.vhd文件,初始内容如下图。为了使读者完全理解此用户自定义包,在后续内容中逐渐增加自定义包的内容。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
计数器在时序逻辑中应用极为普遍,用于计数、定时、分频和时序控制。对计数器的常用操作有装载、复位、置位、增1和减1。通常,装载、复位和置位的操作优先级高于增1和减1。装载操作与置位复位操作优先级关系随具体设计而定。增减操作中,有时减计数的优先级更高。
一、Procedure LoadValue()
例2:同样假设一个计数器cnt,受到rst, set, inc, dec, ld五个boolean类型信号控制,rst为同步复位(reset),set为同步置位,inc为增1使能(increase),dec为减1使能(decrease),ld为装载条件(load)。那么:
if rst then
cnt< = (others => '0');
elsif inc then
cnt< = cnt + 1;
elsif dec then
cnt< = cnt - 1;
end if;
其功能显而易见,不作赘述。硬件语言区别于C语言的一个显著特点是其赋值分为信号赋值和变量赋值。根据信号赋值的特点,上述简短代码等效代码如下:
if dec then
cnt< = cnt - 1;
end if;
if inc then
cnt< = cnt + 1;
end if;
if rst then
cnt< = (others => '0');
end if;
同一个进程内对同一个信号赋值,后面的赋值条件优先级高于前面的赋值条件。上述三次赋值,形式相同。形式为
if load_condition then
q< = d;
end if;
的赋值语句极为常用,所以定义:
Procedure LoadValue(signal q : out std_logic; d : in std_logic; load : in boolean) is
begin
if load then
q <= d;
end if;
End;
为了使LoadValue子进程更具一般性,重载如下:
Procedure LoadValue(signal q : out std_logic; d : in std_logic; load : in std_logic) is
begin
LoadValue(q, d, load = '1');
End;
同理,继续重载LoadValue为:
Procedure LoadValue(signal q : out std_vector; d : in std_vector; load : in boolean);
Procedure LoadValue(signal q : out std_vector; d : in std_vector; load : in std_logic);
一周热门 更多>