VHDL语言设计数字频率计word文档良心出品.docx

上传人:b****2 文档编号:25735610 上传时间:2023-06-12 格式:DOCX 页数:22 大小:335.56KB
下载 相关 举报
VHDL语言设计数字频率计word文档良心出品.docx_第1页
第1页 / 共22页
VHDL语言设计数字频率计word文档良心出品.docx_第2页
第2页 / 共22页
VHDL语言设计数字频率计word文档良心出品.docx_第3页
第3页 / 共22页
VHDL语言设计数字频率计word文档良心出品.docx_第4页
第4页 / 共22页
VHDL语言设计数字频率计word文档良心出品.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

VHDL语言设计数字频率计word文档良心出品.docx

《VHDL语言设计数字频率计word文档良心出品.docx》由会员分享,可在线阅读,更多相关《VHDL语言设计数字频率计word文档良心出品.docx(22页珍藏版)》请在冰豆网上搜索。

VHDL语言设计数字频率计word文档良心出品.docx

VHDL语言设计数字频率计word文档良心出品

数字频率计的设计

一、频率计实现的功能

要设计的频率计的测量范围为1MHz。

为了提高测量的精度,量程分为三档,分别是:

10kHz、100kHz、1MHz。

并要求在测量频率大于或小于选择的量程时,频率计自动换档。

1、当读数大于999时,频率计处于超量程状态,下一次测量时,量程自动增加一档。

2、当读数小于009时,频率计处于欠量程状态,下一次测量时,量程自动减小一档。

3、当超出测量范围时,显示错误。

4、在计数时不显示数据,计数完成后只显示测量结果。

5、小数点位置要自动移位。

二、频率计各部分的分析

在这个设计中,需要用计数器来进行计数,而且计数器在各个档位要被重复使用,在测量的过程中,计数允许时钟信号还要进行调整,故将计数器设计成一个单独的模块,提供计数值的输出。

显示结果包括数值显示,档位显示及溢出标志显示。

其中数值显示要用到三个数码管,实验箱上连在一起的三个数码管中,只有两个数码管内部接有译码器,因此我们自己还要在程序中为那个没有译码器的数码管再加一段七段译码器程序来显示结果。

档位标志由三个LED灯来显示,代替数码管上的小数点的功能。

溢出标志由两个LED灯来显示,其中一个显示结果溢出,另一个显示输入信号在测量范围之内。

该频率计的顶层逻辑电路原理图如图

(1)所示:

(1)

三、频率计各部分的设计和实现

从上面的分析可以知道,频率计可以由三个模块来组成。

下面对各个模块的设计方法和实现方法进行详细说明。

1、时基进程的设计和实现

在实际使用时,输入的信号是随意的,没有办法预知输入的频率。

因此选取频率计的时基是非常重要的。

在设计要求中,将量程分为三档,在某一档进行测量时,需要提供该档的时基。

在10kHz档,该档最大读数为9.99kHz,最小读数为0.01kHz,所以要提供的时基是频率为0.01kHz的脉冲。

同理,在100kHz档上,要提供的时基应该是频率为0.1kHz的脉冲。

在1MHz档上,要提供的时基是频率为1kHz的脉冲。

这三种脉冲信号从输入信号中提取,可以采用分频的方法来产生。

将输入信号先进行分频产生1kHz的脉冲信号,然后将分频后的1kHz信号通过一个10倍的分频器,产生0.1kHz的脉冲信号,同时使用一个100倍分频器对1kHz的信号分频产生0.01kHz的脉冲信号。

在测量频率时,采用输入信号作为时基,以输入信号为时钟,用一个计数器测量在一个时基周期里输入的信号的周期数,这样就可以得到输入信号的频率。

产生一个高电平为时基信号周期的脉冲信号作为时基,使得能够在程序中以“如果时基信号为1”作为判断条件,如果满足条件则计数器开始计数。

同理,在设计中还要产生高电平为时基信号周期的1/10和1/100的脉冲信号作为时基。

这三种时基采用有限状态机来实现。

状态机采用1kHz的脉冲信号触发,由于还要产生高电平为10ms和1ms的脉冲信号,故采用100个状态的有限状态机。

要产生高电平为1ms的脉冲信号,只要在状态99的时候产生高电平,状态100的时候恢复到低电平即可。

要产生高电平为10ms的脉冲信号,只要在状态90的时候产生高电平,在状态100的时候恢复到低电平即可。

需要产生哪一个时基就根据此时频率计所在的档位作为判断条件进行控制。

在100个状态中,很多状态的功能是相同的,可以将它们合并在一起。

2、计数器的设计和实现

为了计数方便,将计数器定义成一个整型信号。

只要使用“计数器<=计数器+1;”就可以。

这个计数值要作为显示输出,就要将这个计数器用个位、十位、百位分开表示,并且要遵循加法规则。

这样可以直接通过七段译码器进行显示。

在不同的档位,小数点的位置是不同的,可以用小数点的显示所在的档位为判断条件。

由于实验箱上的数码管没有小数点的,故在实验板上用三个LED灯来代替小数点的现实。

计数器的VHDL语言描述如程序1所示。

其中,reset为异步置位端口,sig_clk为时钟输入端口,en为信号输入端口,q1为计数值的个位输出端口,q2为计数值的十位输出端口,q3为计数值的百位输出端口。

cou1为计数值的个位,cou2为计数值的十位,cou3为计数值的百位。

ctrcou为控制计数功能的进程,outctr为控制计数值输出的进程。

程序1:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_arith.all;

useieee.std_logic_unsigned.all;

entitycounteris

port(reset:

instd_logic;

sig_clk:

instd_logic;--时钟输入端口

en:

instd_logic;--信号输入端口

q1:

outstd_logic_vector(3downto0);--计数值的个位输出端口

q2:

outstd_logic_vector(3downto0);--计数值的十位输出端口

q3:

outstd_logic_vector(3downto0));--计数值的百位输出端口

end;

architecturecountofcounteris

signalcou1:

std_logic_vector(3downto0);--计数值的个位

signalcou2:

std_logic_vector(3downto0);--计数值的十位

signalcou3:

std_logic_vector(3downto0);--计数值的百位

begin

--控制计数功能的进程

ctrcou:

process(reset,sig_clk)

begin

ifreset='1'then

cou1<="0000";

cou2<="0000";

cou3<="0000";

else

ifsig_clk'eventandsig_clk='1'then

ifen='1'then

ifcou3="1010"then

cou3<="1010";

elsifcou3="1001"andcou2="1001"andcou1="1001"then

cou1<="0000";

cou2<="0000";

cou3<="1010";

elsifcou1="1001"andcou2="1001"then

cou1<="0000";

cou2<="0000";

cou3<=cou3+1;

elsifcou1="1001"then

cou1<="0000";

cou2<=cou2+1;

else

cou1<=cou1+1;

endif;

else

cou1<="0000";

cou2<="0000";

cou3<="0000";

endif;

endif;

endif;

endprocessctrcou;

--控制计数值输出的进程

outctr:

process(reset,en)

begin

ifreset='1'then

q1<="0000";

q2<="0000";

q3<="0000";

else

ifen'eventanden='0'then

q1<=cou1;

q2<=cou2;

q3<=cou3;

endif;

endif;

endprocessoutctr;

endcount;

3、七段译码器的设计和实现

七段译码器将输入的从0~9的4位二进制数,以七段译码的方式输出。

使用一个7位向量来分表表示七段译码器种的七段。

程序如程序2所示:

程序2:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_arith.all;

useieee.std_logic_unsigned.all;

entityviewis

port(in_data:

instd_logic_vector(3downto0);--输入的二进制数

out_data:

outstd_logic_vector(0to6));--输出的译码

endview;

architectureouviewofviewis

begin

process(in_data)

begin

casein_datais

when"0000"=>out_data<="1111110";--0的显示

when"0001"=>out_data<="0110000";--1的显示

when"0010"=>out_data<="1101101";--2的显示

when"0011"=>out_data<="1111001";--3的显示

when"0100"=>out_data<="0110011";--4的显示

when"0101"=>out_data<="1011011";--5的显示

when"0110"=>out_data<="1011111";--6的显示

when"0111"=>out_data<="1110000";--7的显示

when"1000"=>out_data<="1111111";--8的显示

when"1001"=>out_data<="1111011";--9的显示

whenothers=>out_data<="0110001";

endcase;

endprocess;

endouview;

其中in_data表示输入的4位二进制数的端口,out_data为七段译码输出端口。

4、有限状态机的设计和实现

有限状态机程序如程序3所示。

state是用于产生时基的状态机类型。

在其中有开始状态(start)、判断状态(judge)、计数状态1(count1)、计数状态2~89(count2to89)、计数状态90(count90)、计数状态91~98(count91to98)、计数状态99(count99)、计数状态100(count100)。

由于计数状态2~89是相同的,所以将它们合成一个,同样对计数状态91~98也进行合并。

由于时基信号都要在计数状态100时清零,所以计数状态100单独提取。

产生高电平为100ms的时基需要在计数状态1的时候将时基信号置1,从1~99计数状态只有99ms,在计数状态1之前的judge状态中,如果处于10kHz的档位,就要将时基信号置1。

产生高电平为10ms的时基,需要在计数状态90将时基信号置1。

产生高电平为1ms的时基,需要在计数状态99的时候将时基信号置1,所以计数状态1、计数状态90和计数状态99要单独提取。

程序3中,mycrm是一个state类型的信号,信号crmcou用于状态机中的计数器,其计数值从0到100,信号clk1k为产生的频率为1kHz的脉冲信号。

标志信号flag用于标志不同的档位,当flag为0时表示10kHz的测频档,当flag为1时表示100kHz的测频档,当flag为2时表示1MHz的测频档,当它为其他时表示溢出。

程序3:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_arith.all;

useieee.std_logic_unsigned.all;

entitycymometeris

port(areset:

instd_logic;

aclk:

instd_logic;

q2_in:

instd_logic_vector(3downto0);

enclk,cntok,cntov:

outstd_logic;

dot:

outstd_logic_vector(2downto0));--小数点的输出

end;

architecturecymofcymometeris

typestateis(start,judge,count1,count2to89,count90,count91to98,count99,count100);

signalmycrm:

state;

signalcrmcou:

integerrange0to100;--状态机中的计数器

signalclk1k:

std_logic;--1kHz的脉冲信号

signalcou1s:

integerrange0to999;--产生1s显示计时信号的计数器

signalclk1s:

std_logic;--产生1s显示计时信号的脉冲信号

signalflag:

std_logic_vector(1downto0);--测频档的标志

 

begin

--使用2KHz的脉冲产生频率为1KHz的脉冲进程

crclk1k:

process(areset,aclk)

begin

ifareset='1'then--计数器清零

clk1k<='0';

else

ifaclk'eventandaclk='1'then

clk1k<=notclk1k;

endif;

endif;

endprocesscrclk1k;

--产生1S的显示计时信号

cr1s:

process(areset,clk1k)

begin

ifareset='1'then

cou1s<=0;

clk1s<='0';

else

ifclk1k'eventandclk1k='1'then

ifcou1s=997then

clk1s<=notclk1s;

cou1s<=cou1s+1;

elsifcou1s=999then

clk1s<=notclk1s;

cou1s<=0;

else

cou1s<=cou1s+1;

endif;

endif;

endif;

endprocesscr1s;

--控制小数点的显示

crdot:

process(flag)

begin

caseflagis

when"00"=>dot<="100";

when"01"=>dot<="010";

when"10"=>dot<="001";

whenothers=>dot<="111";

endcase;

endprocesscrdot;

--用于产生时基的状态机

cretimer:

process(areset,clk1k)

begin

ifareset='1'then

cntov<='0';

cntok<='0';

crmcou<=0;

enclk<='0';

flag<="01";

mycrm<=start;

else

ifclk1k'eventandclk1k='1'then

casemycrmis

whenstart=>--开始状态

ifclk1s='1'then

crmcou<=0;

enclk<='0';

mycrm<=judge;

else

mycrm<=start;

ifq2_in="0000"orq2_in="1010"then

cntov<='1';

cntok<='0';

else

cntov<='0';

cntok<='1';

endif;

endif;

whenjudge=>--判断状态

ifflag="11"then--溢出档

ifq2_in="1010"then

flag<="11";

else

flag<="10";

endif;

elsifflag="00"then--10kHz测频档

ifq2_in="0000"then

flag<="00";

enclk<='1';

elsifq2_in="1010"then

flag<="01";

else

flag<=flag;

endif;

elsifflag="01"then--100kHz测频档

ifq2_in="0000"then

flag<=flag-1;

enclk<='1';

elsifq2_in="1010"then

flag<=flag+1;

else

flag<=flag;

endif;

else--1MHz测频档

ifq2_in="0000"then

flag<=flag-1;

elsifq2_in="1010"then

flag<=flag+1;

else

flag<=flag;

endif;

endif;

mycrm<=count1;--状态转移到计数状态1

whencount1=>--计数状态1

ifflag="00"then

enclk<='1';

endif;

crmcou<=1;

mycrm<=count2to89;

whencount2to89=>--计数状态2~89

ifcrmcou=88then

crmcou<=89;

mycrm<=count90;

else

crmcou<=crmcou+1;

mycrm<=count2to89;

endif;

whencount90=>--计数状态90

ifflag="01"then

enclk<='1';

endif;

crmcou<=90;

mycrm<=count91to98;

whencount91to98=>--计数状态91~98

ifcrmcou=97then

crmcou<=98;

mycrm<=count99;

else

crmcou<=crmcou+1;

mycrm<=count91to98;

endif;

whencount99=>--计数状态99

ifflag="10"orflag="11"then

enclk<='1';

endif;

crmcou<=99;

mycrm<=count100;

whencount100=>--计数状态100

crmcou<=100;

enclk<='0';

mycrm<=start;

whenothers=>null;

endcase;

endif;

endif;

endprocesscretimer;

endcym;

5、频率计的综合设计

将前面设计好的模块例化到一个程序里,组成了所要设计的频率计。

程序如程序4所示。

程序4:

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_arith.all;

useieee.std_logic_unsigned.all;

entitypljis

port(reset:

instd_logic;

clk:

instd_logic;

testsignal:

instd_logic;

q1:

outstd_logic_vector(3downto0);

q2:

outstd_logic_vector(3downto0);

q3:

outstd_logic_vector(0to6);

cntok,cntov:

outstd_logic;

dot:

outstd_logic_vector(2downto0));--小数点的输出

attributelock:

string;--引脚锁定

attributelockofreset:

signalis"34";

attributelockofclk:

signalis"20";

attributelockoftestsignal:

signalis"52";

attributelockofq1:

signalis"53,54,55,56";

attributelockofq2:

signalis"57,58,59,60";

attributelockofq3:

signalis"81,80,79,78,77,76,75";

attributelockofcntok:

signalis"17";

attributelockofcntov:

signalis"15";

attributelockofdot:

signalis"71,70,69";

end;

architecturertlofpljis

componentcymometer--对控制器进行元件说明

port(areset:

instd_logic;

aclk:

instd_logic;

q2_in:

instd_logic_vector(3downto0);

enclk,cntok,cntov:

outstd_logic;

dot:

outstd_logic_vector(2downto0));--小数点的输出

endcomponent;

componentcounter--对计数器进行元件说明

port(reset:

instd_logic;

sig_clk:

instd_logic;--外部时钟输入

en:

instd_logic;--时基信号

q1:

outstd_logic_vector(3downto0);--计数值个位

q2:

outstd_logic_vector(3downto0);--计数值十位

q3:

outstd_logic_vector(3downto0));--计数值百位

endcomponent;

componentviewis--引用七段译码器

port(in_data:

instd_logic_vector(3downt

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

当前位置:首页 > 考试认证 > 交规考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1