玩转VHDL-001编程规范

2020-02-02 11:53发布


优秀的VHDL代码,在完成功能的前提下,应该具备如下特点:
  简短的代码量
  通俗的可读性
  更少的资源消耗
  更高的工作速率
  更强的可重用性
  最后强调但最重要的是鲁棒性
这些要求,有时是相互矛盾的。但是,通过合理的程序书写风格可以使这些要求分别或整体达到最优。其中更高的工作速率是指通过合理分配组合逻辑和时序逻辑,使内部逻辑时延相对于系统工作时钟留有一定余量,从而保证逻辑的可靠性。可重用性,指整个工程功能模块分配合理,在将来其他类似设计中,可以拷贝文件或稍作修改重新使用。
简短的代码量有时等效于最少的程序行数。我们在使用protel等软件画电路时,常希望有更大的计算机显示屏,以便尽可能通览全局,及时准确地把握电路功能。那么,代码量或或行数的减少,类似于屏幕的增大,便于设计者或读者总览全局,保持思路的连续性。这一特点,客观上也提高了程序的可读性。我们知道VHDL是一门语法非常严格的语言,这在很多时候增加了代码量,这也被很多硬件工程师所诟病。那么如何规避这所谓的缺点,减少代码量呢?我们从一个很小的例子说起。
1:假设有一个3位的计数器cn :std_logic_vector(2 downto 0),在一定时钟下按照一定规则计数,需要在计数值为03后输出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中定义了很多数据类型,但在实际编程中使用的不外乎有integerstd_logicstd_logic_vector三种,以及隐含使用的boolean类型。我个人觉得std_logic_vector类型名字有些过长,所以:subtype std_vector is std_logic_vector;  现在我们新建一个ucx_200pkg.vhd文件,初始内容如下图。为了使读者完全理解此用户自定义包,在后续内容中逐渐增加自定义包的内容。






友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
ucx
1楼-- · 2020-02-02 14:01
QQ图片.png
ucx
2楼-- · 2020-02-02 14:23
002计数器
计数器在时序逻辑中应用极为普遍,用于计数、定时、分频和时序控制。对计数器的常用操作有装载、复位、置位、增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);




ucx
3楼-- · 2020-02-02 19:13
 精彩回答 2  元偷偷看……

一周热门 更多>