打印
[VHDL]

玩转VHDL006-写编译器能懂的语句

[复制链接]
832|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ucx|  楼主 | 2017-10-4 18:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我们在写程序的时候,有没有考虑过编译器其实并不足够智能?那么程序语句能给编译器指明最简捷的道路尤为重要。下面以Quartus II v13.1为平台,举两个小例子说明。
1:设计一个32位计数器,在计数器为全1时输出一个脉冲,输出不用组合逻辑实现。那么,这么个简单的功能,可以用4中写法列举如下:
clock                   : instd_logic;
q                          :out std_logic;
signal cn            :std_vector(0 to 31);
Process(clock) begin
         if rising_edge(clock)then
                   cn <= cn+ 1;
         1       q <= STDZ(signed(cn)=-2);
         2       q <= STDZ(signed(cn)=3-5);
         3       q <= STDZ(signed(cn)+5 = 3);
         4       q <= STDZ(cn = 2**cn'length-2);
         end if;
End process;
最后综合的结果是,前两种消耗资源相同,速率也较高,第3种资源消耗大速率也低,第4种没有实现我们想要的功能,完全被综合掉了。当信号cn的比特长度小于32时,第4种写法与前2种是完全相同的,2**32超出了VHDL所能表示的整数范围被解释为0,用定义为std_vector型的cn与一个负数比较则永远不相等,所以被综合掉了。第3种写法不同于其他写法的原因是综合器(或者说编译器,就那么回事)并没有智能到会在等式两边移项的程度,况且在有些时候移项也是不合理的,在此,我们称之为移项问题。但综合器知道合并常数,即第1和第2写法完全相同。本例中只涉及一个变量cn,如果有两个或多个变量,那么移项问题依然存在。
1告诉我们,注意不同类型数据的取值范围,移项问题完全由程序员自己决定。
2:有一个8位计数器cnt,在不同数值下输出一个3位状态q,功能描述如下
q                : outstd_vector(0 to 2);
signal cnt : std_vector(0 to7);
Process(clock) begin
         if rising_edge(clock)then
                   cnt <=cnt+1;
                   if cnt = 0then
                            q<= "000";
                   elsif cnt =1 then
                            q<= "001";
                   elsif  cnt <= 8 then
                            q<= "010";
                   elsif cnt =10 then
                            q<= "011";
                   elsif cnt =20 then
                            q<= "100";
                   elsif cnt>= 23 and cnt <= 32 then
                            q<= "101";
                   else
                            q<= "110";
                   end if;
         end if;
End process;
在功能保持不变的情况下,也可以写成:
Process(clock) begin
         if rising_edge(clock)then
                   cnt <=cnt+1;
                   caseSTDV_INT(cnt) is
                   when 0                        => q <="000";
                   when 1                        => q <="001";
                   when 2 to 8              =>q <= "010";
                   when 10                     => q <="011";
                   when 20                     => q <="100";
                   when 23   to 32         =>q <= "101";
                   when others              => q <= "110";
                   end case;
         end if;
End process;
或者写成
with STDV_INT(cnt) select iq
<=     "000"        when 0,
         "001"        when 1,
         "010"        when 2 to 8,
         "011"        when 10,
         "100"        when 20,
         "101"        when 23 to 32,
         "110"        when others;
Process(clock) begin
         if rising_edge(clock)then
                   cnt <=cnt+1;
                   q <= iq;
         end if;
End process;
综合后,后两种写法结果相同,但与第一种写法不同。例2告诉我们,代码的表述方式能用开关选择的逻辑就不用优先编码的逻辑。
一句话:编译器很听话,但不会懂你。

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

ucx

29

主题

89

帖子

5

粉丝