全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx

上传人:b****4 文档编号:6929675 上传时间:2023-05-10 格式:DOCX 页数:16 大小:318.72KB
下载 相关 举报
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第1页
第1页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第2页
第2页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第3页
第3页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第4页
第4页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第5页
第5页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第6页
第6页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第7页
第7页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第8页
第8页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第9页
第9页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第10页
第10页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第11页
第11页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第12页
第12页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第13页
第13页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第14页
第14页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第15页
第15页 / 共16页
全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx

《全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx》由会员分享,可在线阅读,更多相关《全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx(16页珍藏版)》请在冰点文库上搜索。

全国大学生电子设计竞赛训练教程55 常见错误及其原因分析.docx

全国大学生电子设计竞赛训练教程55常见错误及其原因分析

5.5常见错误及其原因分析

初学VHDL,往往会碰到不少问题和错误。

例如:

综合时出现警告和错误、编译无法通过等问题,使得设计无法实现;或者程序,综合等均通过,但不能得到正确的仿真结果,即所设计的硬件与原意要求不符等等。

通过资料的收集和归纳,总结出以下一些注意事项,常见问题及错误,并提出改正方案,以供参考。

5.5.1避免语法错误

VHDL规定了一些固定的描述格式,用于描述各种不同的功能,在Xilinx或Max+plusⅡ环境下,关键字会以蓝色显示,端口宽度会以紫色显示,以示区别,黑色字则是可由用户自定义的名称、数值等。

下面几个简单的例子作说明:

1.端口的定义

端口的定义为:

port(端口名,端口名:

端口类型(空格)端口宽度);

entitysztopis

Port(clk:

instd_logic;

ring,sz:

outstd_logic;――定义多个相同类型的端口,用逗号格开

hour:

instd_logic_vector(3downto0);――4位数据

sec:

outstd_logic_vector(6downto0)――7位数据

);

endsztop;

2.信号和变量的定义

信号定义:

SIGNAL信号名:

数据类型;

signala:

std_logic;

signalb:

std_logic_vector(2downto0);

变量定义:

VARIABLE变量名:

数据类型;

variablec0,c1:

integer;

variabled:

integerrange0to256;

variablecnt:

std_logic_vector(3downto0);

3.CASE语句

casesegis

when"0000"=>q<="0000001";

when"0001"=>q<="1001111";

when"1001"=>q<="0000100";

whenothers=>q<="1111111";

endcase;

初学者要紧记这些语法结构,特别注意标点符号的用法,从而避免编程时可能出现的大量小错误。

5.5.2信号与变量

信号与变量都可以用于描述器件内部结构,两者的区别如表5.5.1所示。

表5.5.1信号与变量的区别

信号

变量

基本用法

电路中的信号连线

进程中局部数据存储单元

适用范围

在整个结构体内的任何地方都能使用

只能在所定义的进程中使用

定义位置

进程外部

进程内部

赋值符号

<=

:

=

多次赋值

在进程的最后才对信号赋值

立即赋值

初学编程时经常出现的错误是信号或变量的定义位置混淆,如果在进程外部定义变量,或在进程内部定义信号,综合时就会出现Unexpectedsymbolread的错误。

对信号赋值的符号是“<=”,对变量的赋值符号是“:

=”,如例5.5.1所示。

编程时应正确使用。

【例5.5.1】

entitymulticlockis

Port(clk:

instd_logic;

ps:

outstd_logic);

endmulticlock;

architectureBehavioralofmulticlockis

signalps0:

std_logic;--定义信号

begin

process(clk)

variableclk1:

integerrange0to32;--定义变量

begin

ifclk'eventandclk='1'then

clk1:

=clk1+1;--变量赋值

ifclk1=16then

ps0<='1';--信号赋值

elsifclk1=32then

ps0<='0';

clk1:

=0;

endif;

endif;

ps<=ps0;

endprocess;

下面举例说明信号与变量用法的区别:

【例5.5.2】

entitydffis

Port(clk,d:

instd_logic;

q:

outstd_logic);

enddff;

architectureBehavioralofdffis

signala,b:

std_logic;

begin

process(clk)

begin

ifclk'eventandclk='1'then

a<=d;b<=a;q<=b;

endif;

endprocess;

endBehavioral

【例5.5.3】

entitydff1is

Port(clk,d:

instd_logic;

q:

outstd_logic);

enddff1;

architectureBehavioralofdff1is

begin

process(clk)

variablea,b:

std_logic;

begin

ifclk'eventandclk='1'then

a:

=d;b:

=a;q<=b;

endif;

endprocess;

endBehavioral

例5.5.2中的三个赋值语句是并行执行的,在同一时刻中,d的值并不能立即传送到q,实际电路中,a的赋值是上一时钟周期的d,b的值是上一时钟周期的a,q的值是上一时钟周期的b,如图5.5.1所示的仿真图,q比d延时了两个时钟周期。

图5.5.1例5.5.2程序仿真图

例5.5.3由于使用了变量,它的值是立即变化的,三条赋值语句顺序执行,完成了数据的传递,得到的仿真结果如图5.5.2所示。

图5.5.2例5.3程序仿真图

5.5.3IF—ELSE语句

if—else构成的条件语句必须有严格的描述,首先要做到逻辑清晰,层次合理分明,特别注意条件的完整性,也就是说,要为所有可能发生的条件给出对应的处理方式。

例5.5.4给出两种描述一个比较器的程序:

【例5.5.4】

程序1:

entitycomp_1is

程序2:

entitycomp_2is

Port(a,b:

instd_logic;

q:

outstd_logic);

endcomp_1;

architectureBehavioralofcomp_1is

begin

process(a,b)

begin

ifa>bthenq<='1';

elsifa

--遗漏条件“a=b”对应的操作

endif;

endprocess;

endBehavioral;

Port(a,b:

instd_logic;

q:

outstd_logic);

endcomp_2;

architectureBehavioralofcomp_2is

begin

process(a,b)

begin

ifa>bthenq<='1';

elseq<='0';

endif;

endprocess;

endBehavioral;

易见,程序1忽略了当“a=b”的情况,应为else语句囊括了与if语句所描述的情形相反的全部可能。

程序2则描述了所有的情况。

从两个程序的仿真结果图5.5.3和图5.5.4也可看出,图中,当a=b时,q有两种可能取值,而图中,q只有一种取值0。

这两个程序虽然很简单,错误也很明显,但类似的逻辑上的错误往往很容易犯,因此必须特别注意。

图5.5.3例5.5程序1仿真图

图5.5.4例5.5程序2仿真图

IF-ELSE语句的嵌套也是必须十分注意的,如果嵌套的层次没有分清,逻辑混乱,就得不到预期的功能,下面看例5.5.5例和5.5.6两个程序的对比:

例5.5.5取自于一个4位数码管动态显示的驱动器,该进程完成的是一个多位的计数器功能,从最低位起开始计数,满三进一(为方便观察仿真结果,实际应用多为十进制或六进制),计数的同时输出显示。

注意该IF-ElSE的嵌套最里一层位数最高,最低位在嵌套的最外层,循环次数最多。

【例5.5.5】

entitydt1is

Port(clk:

instd_logic;

reset:

instd_logic;

cnta0,cntb0,cntc0,cntd0:

outstd_logic_vector(3downto0));

enddt1;

architectureBehavioralofdt1is

begin

counter10:

process(reset,clk)

variablecnta,cntb,cntc,cntd:

std_logic_vector(3downto0);

begin

ifreset='0'then

cnta:

="0000";cntb:

="0000";cntc:

="0000";cntd:

="0000";

elsifrising_edge(clk)then

ifcnta="0011"thencnta:

="0000";cnta0<=cnta;--最低位

ifcntb="0011"thencntb:

="0000";cntb0<=cntb;

ifcntc="0011"thencntc:

="0000";cntc0<=cntc;

ifcntd="0011"thencntd:

="0000";cntd0<=cntd;--最高位

elsecntd:

=cntd+1;cntd0<=cntd;

endif;

elsecntc:

=cntc+1;cntc0<=cntc;

endif;

elsecntb:

=cntb+1;cntb0<=cntb;

endif;

elsecnta:

=cnta+1;cnta0<=cnta;

endif;

endif;

endprocess;

endBehavioral;

图5.5.5例5.5.5程序仿真图

但是,如果将程序中的IF-ELSE结构改成例5.5.6所示:

【例5.5.6】

entitydt2is

Port(clk:

instd_logic;

reset:

instd_logic;

cnta0,cntb0,cntc0,cntd0:

outstd_logic_vector(3downto0));

enddt2;

architectureBehavioralofdt2is

begin

counter10:

process(reset,clk)

variablecnta,cntb,cntc,cntd:

std_logic_vector(3downto0);

begin

ifreset='0'then

cnta:

="0000";cntb:

="0000";cntc:

="0000";cntd:

="0000";

elsifrising_edge(clk)then

ifcnta="0011"thencnta:

="0000";cnta0<=cnta;

elsecnta:

=cnta+1;cnta0<=cnta;endif;

ifcntb="0011"thencntb:

="0000";cntb0<=cntb;

elsecntb:

=cntb+1;cntb0<=cntb;endif;

ifcntc="0011"thencntc:

="0000";cntc0<=cntc;

elsecntc:

=cntc+1;cntc0<=cntc;endif;

ifcntd="0011"thencntd:

="0000";cntd0<=cntd;

elsecntd:

=cntd+1;cntd0<=cntd;endif;

endif;

endprocess;

endBehavioral;

图5.5.6例5.6.6程序仿真图

得到图5.5.6所示的仿真结果。

可见,结果不正确,因为IF语句在进程中结构是并行执行而不是顺序执行的。

5.5.4CASE语句

CASE语句与IF-ELSE语句的功能类似,在一些应用中,如编码器、译码器等,使用CASE语句更加方便。

CASE语句的使用要注意其在程序中的位置以及其起作用的时刻。

例如,为了得到一个分频系数可预置的分频器,例5.5.7和例5.5.8两个程序虽然都能通过综合,但得到的波形仿真却不同,如图5.5.7和图5.5.8。

前者的CASE语句受“clk”信号控制,实现了功能,而后者受“en”控制,得不到所需功能。

可见,CASE语句的位置不同,也会影响功能的实现。

【例5.5.7】

entitypulseis

Port(clk,en:

instd_logic;

k:

instd_logic_vector(3downto0);

clock:

outstd_logic);

endpulse;

architectureBehavioralofpulseis

begin

counter:

process(clk,en,k)

variablecnt0,cnt1,count:

integer:

=0;

variableclk0:

std_logic;

begin

ifen='0'then

count:

=0;

clk0:

='0';

casekis

when"0000"=>cnt0:

=1;cnt1:

=2;

when"0001"=>cnt0:

=2;cnt1:

=3;

when"0010"=>cnt0:

=3;cnt1:

=6;

when"0011"=>cnt0:

=3;cnt1:

=4;

whenothers=>cnt0:

=0;cnt1:

=0;

endcase;

elsifclk'eventandclk='1'then

count:

=count+1;

ifcount=cnt0then

clk0:

='1';

elsifcount=cnt1then

count:

=0;

clk0:

='0';

endif;

endif;

clock<=clk0;

endprocesscounter;

endBehavioral;

【例5.5.8】

entitypulsepis

Port(clk,en:

instd_logic;

k:

instd_logic_vector(3downto0);

clock:

outstd_logic);

endpulsep;

architectureBehavioralofpulsepis

begin

counter:

process(clk,en,k)

variablecnt0,cnt1,count:

integer:

=0;

variableclk0:

std_logic;

begin

ifen='0'then

count:

=0;

clk0:

='0';

elsifclk'eventandclk='1'then

count:

=count+1;

casekis

when"0000"=>cnt0:

=1;cnt1:

=2;

when"0001"=>cnt0:

=2;cnt1:

=3;

when"0010"=>cnt0:

=3;cnt1:

=6;

when"0011"=>cnt0:

=3;cnt1:

=4;

whenothers=>cnt0:

=0;cnt1:

=0;

endcase;

ifcount=cnt0then

clk0:

='1';

elsifcount=cnt1then

count:

=0;

clk0:

='0';

endif;

endif;

clock<=clk0;

endprocesscounter;

endBehavioral;

图5.5.7例5.5.7仿真图

图5.5.8例5.5.8仿真图

5.5.5多时钟源的解决方案

有时,在同一个实体中往往使用多个进程,而每个进程使用不同的时钟源驱动时,就会发生错误。

例如,由分频器产生多个不同频率的时钟脉冲去控制不同的部件时,如果每个进程都采用“ifclk’eventandclk=’1’then”这样的格式来描述时钟上升沿,综合将无法进行。

此时,可以用rising_edge来描述分频后得到的时钟的上升沿,就不会出错。

libraryIEEE;

useIEEE.STD_LOGIC_1164.ALL;

useIEEE.STD_LOGIC_ARITH.ALL;

useIEEE.STD_LOGIC_UNSIGNED.ALL;

entitymulticlockis

Port(clk:

instd_logic;

d0,d1:

instd_logic;

q0,q1:

outstd_logic);

endmulticlock;

architectureBehavioralofmulticlockis

signalclka,clke:

std_logic;

begin

main:

process(clk)

variablecount0,count1:

integer;

variableclk0,clk1:

std_logic;

begin

ifclk'eventandclk='1'then

count0:

=count0+1;count1:

=count1+1;

ifcount1=16then

clk1:

='1';

elsifcount1=32then

count1:

=0;

clk1:

='0';

endif;

ifcount0=8then

clk0:

='1';

elsifcount0=16then

count0:

=0;

clk0:

='0';

endif;

endif;

clka<=clk0;clke<=clk1;

endprocessmain;

second:

process(clka)

begin

ifclka'eventandclka='1'then

q0<=d0;

endif;

endprocesssecond;

third:

process(clke)

begin

ifclke'eventandclke='1'then

q1<=d1;

endif;

endprocess;

endBehavioral;

5.5.6仿真无波形

综合成功后进行波形仿真时常常会看不到波形,一般有两种可能:

第一种是仿真周期太长而无法看到,一般见于分频器或计数器中。

例如:

对一个32MHz的晶振进行分频,要求得到1Hz的信号。

这时要等32兆个CLK波形才能看到输出有跳变,在仿真图上当然是无法看到的,如果将分频系数减小,例如8分频,就可以看到仿真波形了。

一般分频系数大于几百时就会出现这种现象。

第二种是出现不定态(UNKNOWN),设计分频器时有这种情况,一般是由于没有对变量或信号进行初始化引起的,例如STD_LOGIC有七种逻辑状态,如果不指定其初始值是“0”还是“1”,系统就无法确定。

如例5.5.9及其仿真结果(图5.5.9)所示。

【例5.5.9】

entitypulseis

Port(clk:

instd_logic;

c:

outstd_logic);

endpulse;

architectureBehavioralofpulseis

begin

process(clk)

variabledd:

integer;

begin

ifclk'eventandclk='1'then

dd:

=dd+1;

ifdd=4thenc<='0';

elsifdd=8thenc<='1';dd:

=0;

endif;

endif;

endprocess;

图5.5.9例5.5.9仿真图(无输出波形)

为解决该问题,可以在定义变量或信号时指定其初始状态。

将例中的“variabledd:

integer;”改为“variabledd:

integer:

=0;”,就能得到如图5.5.10所示的波形了。

图5.5.10例5.9改正后的仿真图(正确的波形)

另一种办法是增加一个清零或置位信号,通过一个清零或置位信号对信号或变量进行初始化,如例5.5.10所示。

得到的结果如图5.5.10所示。

【例5.5.10】

entitypppis

Port(clk,en:

instd_logic;

c:

outstd_logic);

endppp;

architectureBehavioralofpppis

begin

process(clk,en)

variabledd:

integer;

begin

ifen='0'thendd:

=0;--增加了清零信号

elsifclk'eventandclk='1'thendd:

=dd+1;

ifdd=4thenc<='0';

elsifdd=8thenc<='1';dd:

=0;

endif;

endif;

endprocess;

图5.5.11例5.50程序仿真图

5.5.7执行时端口丢失

当综合与仿真完成后,就要进行引脚锁定(EditImplementationConstraite),执行引脚锁定时,有时会发现Port表找不到某些定义过的端口。

例如下面一段程序:

【例5.5.11】

entityloseportis

Port(clk,en:

instd_logic;

c:

outstd_logic);

endloseport;

architectureBehavioralofloseportis

begin

process(clk,en)

variabledd:

integerrange0to256;--变量范围

begin

ifen='0'then

dd:

=0;

elsifclk'eventandclk='1'then

dd:

=dd+1;

ifdd=612then--分频系数

c<='0';

elsifdd=1024then

c<='1';

dd:

=0;

endif;

endif;

endprocess;

endBehavioral;

综合后出现这样的警告:

WARNING:

Xst:

646-Signal

isassignedbutneverused.

Foun

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 初中教育 > 数学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2