VHDL语言设计数字频率计.docx
- 文档编号:7179207
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:18
- 大小:335.07KB
VHDL语言设计数字频率计.docx
《VHDL语言设计数字频率计.docx》由会员分享,可在线阅读,更多相关《VHDL语言设计数字频率计.docx(18页珍藏版)》请在冰豆网上搜索。
VHDL语言设计数字频率计
公司标准化编码[QQX96QT-XQQB89Q8-NQQJ6Q8-MQM9N]
VHDL语言设计数字频率计
数字频率计的设计
一、频率计实现的功能
要设计的频率计的测量范围为1MHz。
为了提高测量的精度,量程分为三档,分别是:
10kHz、100kHz、1MHz。
并要求在测量频率大于或小于选择的量程时,频率计自动换档。
1、当读数大于999时,频率计处于超量程状态,下一次测量时,量程自动增加一档。
2、当读数小于009时,频率计处于欠量程状态,下一次测量时,量程自动减小一档。
3、当超出测量范围时,显示错误。
4、在计数时不显示数据,计数完成后只显示测量结果。
5、小数点位置要自动移位。
二、频率计各部分的分析
在这个设计中,需要用计数器来进行计数,而且计数器在各个档位要被重复使用,在测量的过程中,计数允许时钟信号还要进行调整,故将计数器设计成一个单独的模块,提供计数值的输出。
显示结果包括数值显示,档位显示及溢出标志显示。
其中数值显示要用到三个数码管,实验箱上连在一起的三个数码管中,只有两个数码管内部接有译码器,因此我们自己还要在程序中为那个没有译码器的数码管再加一段七段译码器程序来显示结果。
档位标志由三个LED灯来显示,代替数码管上的小数点的功能。
溢出标志由两个LED灯来显示,其中一个显示结果溢出,另一个显示输入信号在测量范围之内。
该频率计的顶层逻辑电路原理图如图
(1)所示:
图
(1)
三、频率计各部分的设计和实现
从上面的分析可以知道,频率计可以由三个模块来组成。
下面对各个模块的设计方法和实现方法进行详细说明。
1、时基进程的设计和实现
在实际使用时,输入的信号是随意的,没有办法预知输入的频率。
因此选取频率计的时基是非常重要的。
在设计要求中,将量程分为三档,在某一档进行测量时,需要提供该档的时基。
在10kHz档,该档最大读数为,最小读数为kHz,所以要提供的时基是频率为kHz的脉冲。
同理,在100kHz档上,要提供的时基应该是频率为kHz的脉冲。
在1MHz档上,要提供的时基是频率为1kHz的脉冲。
这三种脉冲信号从输入信号中提取,可以采用分频的方法来产生。
将输入信号先进行分频产生1kHz的脉冲信号,然后将分频后的1kHz信号通过一个10倍的分频器,产生kHz的脉冲信号,同时使用一个100倍分频器对1kHz的信号分频产生kHz的脉冲信号。
在测量频率时,采用输入信号作为时基,以输入信号为时钟,用一个计数器测量在一个时基周期里输入的信号的周期数,这样就可以得到输入信号的频率。
产生一个高电平为时基信号周期的脉冲信号作为时基,使得能够在程序中以“如果时基信号为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;
usecounteris
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;
useviewis
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;
usecymometeris
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;
usepljis
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(3downto0);
out_data:
outstd_logic_vector(0to6));
endcomponent;
signalen_s:
std_logic;--子模块之间接口信号说明
signalq3out_s:
std_logic_vector(3downto0);
begin--在结构体描述中使用元件例化语句
U0:
cymometerportmap(reset,clk,q3out_s,en_s,cntok,cntov,dot);
U1:
counterportmap(reset,testsignal,en_s,q1,q2,q3out_s);
U2:
viewportmap(q3out_s,q3);
endrtl;
四、仿真与测试
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VHDL 语言 设计 数字 频率计