河南工程学院
《EDA》课程设计
系 别 电气信息工程系 专 业 电子科学与技术 班 级 0941班 组 员
--
--
基于Verilog HDL数字频率计设计与实现
摘 要: 在电子技术中,频率是最基本的参数之一,并且与许多电参量的测
量方案、测量结果都有十分密切的关系,因此频率的测量就显得更为重要。测量频率的方法有多种,其中电子计数器测量频率具有精度高、使用方便、测量迅速,以及便于实现测量过程自动化等优点,是频率测量的重要手段之一。电子计数器测频有两种方式:一是直接测频法,即在一定闸门时间内测量被测信号的脉冲个数;二是间接测频法,如周期测频法。直接测频法适用于高频信号的频率测量,间接测频法适用于低频信号的频率测量。本文阐述了用Verilog HDL语言设计了一个简单的数字频率计的过程
关键词:周期;EDA;Verilog HDL;数字频率计;波形仿真
目录
--
--
1 引 言ﻩ错误!未定义书签。
1.1 数字频率计概述 .............................. 错误!未定义书签。 1.2 频率测量的思想和方法ﻩ错误!未定义书签。 2 Verilog HDL简介ﻩ错误!未定义书签。
2.1 Verilog HDL的简介 ...................... 错误!未定义书签。
2.2方案比较…………………………………………………………………10
3 数字频率计设计原理以及实现ﻩ错误!未定义书签。
4 总结 ............................................. 错误!未定义书签。 参考文献ﻩ错误!未定义书签。
1 引 言
在电子测量领域中,频率测量的精确度是最高的,可达10—10E-13数量级。因此,
在生产过程中许多物理量,例如温度、压力、流量、液位、PH值、振动、位移、速度、加速度,乃至各种气体的百分比成分等均用传感器转换成信号频率,然后用数字频率计来测量,以提高精确度。
国际上数字频率计的分类很多。按功能分类,测量某种单一功能的计数器。如频率计数器,只能专门用来测量高频和微波频率;时间计数器,是以测量时间为基础的计数器,其测时分辨力和准确度很高,可达ns数量级;特种计数器,它具有特种功能,如可逆计数器、予置计数器、差值计数器、倒数计数器等,用于工业和白控技术等方面。数字频率计按频段分类 (1)低速计数器:最高计数频率<10MHz; (2)中速计数器:最高计数频率10—100MHz; (3)高速计数器:最高计数频率>100MHz; (4)微波频率计数器:测频范围1—80GHz或更高。
单片机自问世以来,性能不断提高和完善,其资源又能满足很多应用场合的需要,加之
--
--
单片机具有集成度高、功能强、速度快、体积小、功耗低、使用方便、价格低廉等特点,因此,在工业控制、智能仪器仪表、数据采集和处理、通信系统、高级计算器、家用电器等领域的应用日益广泛,并且正在逐步取代现有的多片微机应用系统。单片机的潜力越来越被人们所重视。特别是当前用CMOS工艺制成的各种单片机,由于功耗低,使用的温度范围大,抗干扰能力强、能满足一些特殊要求的应用场合,更加扩大了单片机的应用范围,也进一步促使单片机性能的发展。
1.1 数字频率计概述
频率计的基本原理是用一个频率稳定度高的频率源作为基准时钟,对比测量其他信号的频率。通常情况下计算每秒内待测信号的脉冲个数,此时我们称闸门时间为1秒。闸门时间也可以大于或小于一秒。闸门时间越长,得到的频率值就越准确,但闸门时间越长则没测一次频率的间隔就越长。闸门时间越短,测的频率值刷新就越快,但测得的频率精度就受影响。本文数字频率计是用数字显示被测信号频率的仪器,被测信号可以是正弦波,方波或其它周期性变化的信号。如配以适当的传感器,可以对多种物理量进行测试,比如机械振动的频率,转速,声音的频率以及产品的计件等等。因此,数字频率计是一种应用很广泛的仪器ﻪ电子系统非常广泛的应用领域内,到处可见到处理离散信息的数字电路。
数字电路制造工业的进步,使得系统设计人员能在更小的空间内实现更多的功能,从而提高系统可靠性和速度。ﻪ集成电路的类型很多,从大的方面可以分为模拟电路和数字集成电路2大类。数字集成电路广泛用于计算机、控制与测量系统,以及其它电子设备中。一般说来,数字系统中运行的电信号,其大小往往并不改变,但在实践分布上却有着严格的要求,这是数字电路的一个特点。数字集成电路作为电子技术最重要的基础产品之一,已广泛地深入到各个应用领域ﻪ。
1.2 频率测量的思想和方法 1.频率测量的基本思想
测量被测信号在单位时间内的脉冲个数,其数字表达式 f = N / t
--
--
其中:
F为被测信号的频率 N为脉冲的个数
T为被测信号产生N个脉冲所需的时间 频率测量方法
直接测量法:直接测量被测信号的频率,通过计数法来对被测信号在一定时间内的脉冲个数进行计数。直接厕灵法的结构框图如图1.2.1所示。
图1.2.1 直接测量法的结构框图 误差来源
① 技术过程中最大存在着±1个字的量化误差
② 对时间t的准确把握,主要包括准时钟的时间准确性、整形电路、分频电路以及技术时间控制闸门的开关速度等因素。 直接法测量的最大相对误差可以表达为
( df/f )max=±( |1/N| + |G| )=±( |1/ft| + |G| ) 其中:
N为脉冲的个数,G为标准时钟的频率稳定性,f为被测信号频率,t为被测信号产生N个脉冲所需的时间。 功能及技术指标
● 频率测量范围: 10Hz ~ 100MHz ● 测量分辨率: 1Hz ● 测量通道灵敏度: 50mVpp ● 通道输入阻抗:不小于100kΩ ● 测量误差:±1
被测信号 放大整形 计 数 测量结果 标准时钟 分 频 --
--
● 测量结果显示:6位数码管显示
其中,被测信号可以有三种,分别是方波、三角波和正弦波;测量结果显示采用六个数码管来显示;量程为:0~999999Hz、
2 Verilog HDL简介
2.1 Verilog HDL的简介
Verilog HDL是一种硬件描述语言(hardware description language),
为了制作数位电路(数字电路)而用来描述ASICs和FPGAs的设计之用。Verilog 的设计者想要以 C 程序语言(en:C programming language)为基础设计一种语言,可以使工程师比较熟悉跟容易接受。事实上,它产生与 C 程序语言类似的不严谨性质,并且大概与Pascal很相像。
这种语言跟传统的程序设计语言不同,在于它的程序叙述并非严格地线性(循序)执行。Verilog 模式包含不同模组(modules)的阶层关系。模组(modules)是输出(inputs)和输入(outputs)所定义出来的一个集合。在每个模组中,有一串的电线(wires)、暂存器(registers)和子模组(submodules)的定义。并且在每个模组里面,语言叙述大部分都被群组成为各种的执行区块(blocks),用来定义该模组所产生的行为描述。在每个区块(blocks)内,使用 begin 和 end 的关键字来区隔开来,其中的叙述是循序被执行。但是同一个设计,不同的区块间的执行是平行的。
这个语言的叙述之子集合是可合成(synthesizable)。如果在一个电路设计的模组中仅包含可合成的叙述,那麽这个电路设计就可以被适当的软件,转换合成为电脑芯片的电路layout。
--
--
2.2方案比较
在设计过程中,小组的组员由于设计思路不同选择了两种不同的设计方案,现将两种设计方案呈述如下:
①四位数码管显示设计方案 ②六位数码管显示可调量程设计方案
经过比对两种方案各有优劣,第一种方案由于简单,可操作性强;第二种方案量程大,实际意义比较大,所以经过商量,我们组决定两种设计方案都做下来。
3 数字频率计设计方案及实现
方案一
要测量待测信号的频率,需要一个基准信号对其计数。我选择了系统自带的2MHz的时钟信号,通过分频器产生0.5Hz的基准信号,然后利用此信号高电平或低电平时对输入信号的上升沿计数,结果即1s内待测信号的上升沿数,即频率。
ﻩ 关于量程的显示,首先用1s的基准信号对待测信号计数,得到的计数值需要进行判断。判断过程如下:0<cnt<10000,量程10kHz,led1灭,en=0 ﻩ 10000 通过en可以从三个分频器产生的1s,0.1s,0.01s三个中选择一个合适的时钟,通过计 数模块得到计数值送到显示模块,最后的测量值为数码管显示值乘以量程代表值。 -- -- 系统流程图如下: 分频1s 计数 判断 量程显示 分频0.1s 选择时钟 计数 待测信号 系统采用自底向上的设计方法,最底层采用VerilogHDL硬件描述语言实现,尔后生成模块,连接,调试。 显示 分频0.01s 三. 方案实现 由流程图可以看到共分成8个模块。 clock1~3:三个分频器,分别产生1s,0.1s,0.01s的时钟信号,以clock1为例,clk_in为系统时钟,clk为分频产生信号。源代码如下: module clock1(clk_in,clk); in p u t c lk_ i n; output clk; reg clk; reg [25:0] cnt; always @(posedge clk_in) if(cnt<24999999) cnt=cnt+1; // (50mhz/1hz=50000000,cnt<[50000000/2-1=24999999]) else begin cnt=0; clk =! clk; -- -- end endmodule ﻩ2)count1:计数模块,用1s时钟对待测信号计数,unknown为待测信号,cnt为计数值。源代码如下: module count1 (clk,unknown,cnt); ﻩinput clk,unknown; ﻩoutput [24:0]cnt; ﻩreg [24:0]temp; reg [24:0]cnt; always @(posedge unknown) ﻩbegin ﻩ ﻩ ﻩ ﻩﻩ ﻩif (clk) ﻩbegin temp<=temp+2b’10; end ﻩelse ﻩ ﻩ ﻩﻩ ﻩ begin if(temp>0) ﻩ ﻩ begin cnt<=temp; ﻩend ﻩtemp<=0; ﻩﻩﻩend -- -- ﻩend endmodule 3)judge:判断模块,对计数值进行判断,led1~3代表量程10kHz,100kHz,1MHz,en用来选择基准信号。源代码如下: module judge (cnt,led1,led2,led3,en); input [24:0]cnt; output led1,led2,led3; output [1:0]en; reg [1:0]en; reg led1,led2,led3; always @(1) begin if (cnt<10000) begin ﻩled1<=1; ﻩled2<=0; led3<=0; en<=2'b00; ﻩend else if(cnt<100000&&cnt>10000) ﻩbegin ﻩled1<=0; led2<=1; -- -- ﻩled3<=0; ﻩen<=2'b01; ﻩend else ﻩbegin led1<=0; led2<=0; ﻩled3<=1; en<=2'b10; end else begin led1<=0; led2<=0; led3<=0; end end endmodule 4) select:通过en选择基准信号,clk1~3为分频产生的时钟信号,通过en选出一个合适的clk对待测信号计数。源代码如下: module select (clk1,clk2,clk3,en,clk); input clk1,clk2,clk3; input [1:0]en; -- -- output clk; reg clk; always @(1) if(en==0) ﻩ begin clk<=clk1; ﻩend else begin ﻩﻩif(en==1) ﻩ begin ﻩﻩclk<=clk2; end else ﻩﻩbegin ﻩﻩ ﻩ ﻩﻩ ﻩ endmodule ﻩ if(en==2) begin ﻩﻩclk<=clk3; end end end -- -- 5)count2:计数,clr为清零信号,输入1清零,cout1~4为四个寄存器,分别存储计数值的四位数。源代码如下: module count2 (clk,unknown,cout1,cout2,cout3,cout4,clr); input clk,unknown,clr; output [3:0]cout1,cout2,cout3,cout4; reg [3:0]num1,num2,num3,num4; reg [3:0]cout1,cout2,cout3,cout4; always @(posedge unknown) if(!clr) begin ﻩ if(clk) begin if(num1>=9) ﻩﻩbegin ﻩﻩnum1<=0; ﻩ if(num2>=9) ﻩbegin num2<=0; if(num3>=9) begin ﻩﻩnum3<=0; ﻩ if(num4>=9) begin -- -- ﻩ ﻩ num4<=0; end ﻩelse ﻩﻩnum4<=num4+1; end ﻩelse num3<=num3+1; end else ﻩﻩnum2<=num2+1; ﻩ end else num1<=num1+1; ﻩend ﻩelse ﻩbegin if(num1||num2||num3||num4) ﻩﻩ ﻩ ﻩﻩﻩbegin ﻩbegin ﻩﻩﻩcout1<=num1; ﻩcout2<=num2; ﻩﻩﻩﻩcout3<=num3; ﻩﻩ cout4<=num4; -- -- ﻩﻩ ﻩend ﻩ num1<=0; ﻩﻩﻩ num2<=0; ﻩ ﻩ num3<=0; ﻩﻩﻩnum4<=0; ﻩﻩﻩend ﻩ else cout1<=0; ﻩﻩﻩcout2<=0; ﻩ cout3<=0; cout4<=0; ﻩ endﻩ end else ﻩ begin ﻩ cout1<=0; cout2<=0; cout3<=0; ﻩﻩ cout4<=0; ﻩ end endmodule 6):data_mux数值选择模块 module data_mux(disp_select,A0,A1,A2,A3,Q); -- -- output [3:0] Q; input [1:0]disp_select; input [3:0] A0,A1,A2,A3; reg [3:0] Q; always @(disp_select,A3,A2,A1,A0,Q) begin case() ﻩ 2'b11: Q <= A3; 2'b10: Q <= A2; 2'b01: Q <= A1; ﻩ 2'b00: Q <= A0; default: Q <= 4'b0; endcase end endmodule 7):dispselect位选模块 module dispselect(clk,disp_select,Q); output [3:0] Q; output [1:0] disp_select; input clk; reg [3:0] Q; reg [1:0] disp_select; always @(posedge clk) -- -- begin ﻩif(disp_select < 2'b11) disp_select <= disp_select + 2'b1; ﻩelse disp_select <= 2'b0; case(disp_select) 2'b11: Q <= 4'b0111; ﻩ 2'b10: Q <= 4'b1011; ﻩ 2'b01: Q <= 4'b1101; 2'b00: Q <= 4'b1110; ﻩ default: Q <= 4'b1111; ﻩendcase end endmodule 8):dispdecoder显示模块,每位输出转换为七段数码管显示。源代码如下: module dispdecoder(disp_select,data_out,clk,data_in); output [6:0] data_out; input [1:0] disp_select; input clk; input [3:0] data_in; reg [6:0] data_out; always @(clk,disp_select,data_in,data_out) begin -- -- if(clk) case(data_in) 0 : data_out <= 7'b1000000; //0 1 : data_out <= 7'b1111001; //1 ﻩﻩ2 : data_out <= 7'b0100100; //2 ﻩ 3 : data_out <= 7'b0110000; //3 ﻩ ﻩ 4 : data_out <= 7'b0011001; //4 5 : data_out <= 7'b0100100; //5 6 : data_out <= 7'b1011111; //6 7 : data_out <= 7'b0001111; //7 ﻩ8 : data_out <= 7'b1111111; //8 9 : data_out <= 7'b1101111; //9 default : data_out <= 7'b1000000; ﻩendcase end endmodule 各模块编译无误后连线组成完整系统。 顶层电路图如下: -- -- 四.方案测试 ﻩ顶层图形文件建立后,对系统进行仿真,由于仿真时对输入输出信号的频率有要求,所以先对每个模块进行仿真。 clock1模块,仿真波形如下: 由于仿真对分频有要求,因此这里只进行了低分频,仅证明程序可进行分频,此波形为10分频,输入周期为20ns,输出200ns,结果正确。 2)judge模块,取cnt[19]=0,即cnt=524288Hz∈(100k,1M),仿真波形如下: -- -- 可见led3为1,符合判断结果。 3)select模块,取 en=01,即选择 clk2,仿真波形如下: 由图可见,输出clk频率即为clk2频率,但是有一定延时。 4)data_mux模块,disp_select输入为11,Q取值为A3,波形正确 5)dispselect位选模块,根据输入波形扫描位码, -- -- 6)count1模块,在一个完整波形clk内对unknown计数,clk周期为2us,unknown周期为20ns,计数转换为十进制后为100,结果正确。 五、系统框图 -- -- 方案二 数字频率计允许测量信号的类型有三种:方波、三角波和正弦波,并且信号的测量通道灵敏度为 50mVpp,为此,需要将被测信号放大整形成标准的TTL电平的方波型号,便于CPLD/FPGA对信号脉冲的计数。在按键的设计中,需要考虑实际按键的消抖问题。标准时钟为频率计测量提供精度相对比较高的时基信号,其时间的稳定性与精度将会直接影响到频率计测量的准确性。频率计将测量的结果通过6位数码管(LED)来显示。数字频率计中的CPLD/FPGA是频率计的核心,主要实现在一定时间内,对被测信号的脉冲个数进行计算,并且转化为相应的频率值显示在六个数码管上。首先将系统分成七个模块来分别设计仿真。分别有以下七个模块:经过上述模块化划分后的结构框如图4.1所示 -- -- 图4.1 模块化划分后的结构 ● 计数模块counter:对包含被测信号频率信息的脉冲进行计数 ● 门控模块gate_control:根据量程,控制技术模块计数。 ● 分频模块fdiv:将标准时钟分频,得到计数以及动态显示所需的时钟。 ● 寄存器模块flip_latch:对计数模块的计数值进行寄存。 ● 多路选择模块data_mux:根据动态选择信号,选择相应的需要显示的计数值 ● 动态为选择模块dispselevt:输出动态显示中的位选信号 ● BCD译码模块dispdenoder:将BCD码译成数码管的显示数据 计数模块counter 该模块主要完成对被测信号经过放大整形后输入到可编程逻辑器件的F_IN信号是现在一定的时间下的计数,采用六个异步BCD码十进制计数器来实现 0~999999范围的计数。 计数模块的结构框图如图4.2.1所示。 -- -- 图4.2.1 计数模块的结构框图 根据模块实现的功能设计Verilog HDL源代码如下: module counter(EN,CLR,F_IN,F_OUT,Q0,Q1,Q2,Q3,Q4,Q5); output [3:0] Q5,Q4,Q3,Q2,Q1,Q0; output F_OUT; input EN; input CLR; input F_IN; reg [3:0] Q5,Q4,Q3,Q2,Q1,Q0; reg F_OUT; reg F_out0,F_out1,F_out2,F_out3,F_out4; always @(posedge F_IN) begin if((EN == 1'b1)&&(CLR == 1'b0)&&(Q0 != 4'b1001)) begin Q0 <= Q0 + 4'b0001; F_OUT <= 1'b0; end else begin ﻩQ0 <= 4'b0000; ﻩif((EN == 1'b1)&&(CLR == 1'b0)&&(Q1 != 4'b1001)) begin ﻩ Q1 <= Q1 + 4'b0001; F_OUT <= 1'b0; end ﻩelse ﻩbegin -- -- ﻩ Q1 <= 4'b0000; if((EN == 1'b1)&&(CLR == ﻩ 01; ﻩ F_OUT <= 1'b0; Q4 <= Q4 + 4'b00 1'b0)&&(Q2 != 4'b1001)) begin ﻩﻩ end ﻩ else ﻩ Q2 <= Q2 + 4'b0001; F_OUT <= 1'b0; ﻩﻩ begin ﻩ Q4 <= 4'b0000; if((EN == 1'b1)&& ﻩ end else ﻩ begin ﻩ Q2 <= 4'b0000; (CLR == 1'b0)&&(Q5 != 4'b1001)) 01; ﻩ F_OUT <= 1'b0; end ﻩ begin ﻩ Q5 <= Q5 + 4'b00 if((EN == 1'b1)&&(CLR = = 1'b0)&&(Q3 != 4'b1001)) begin ﻩﻩ Q3 <= Q3 + 4'b0001; F_OUT <= 1'b0; ﻩﻩend ﻩﻩelse begin ﻩ else ﻩﻩ begin ﻩ Q5 <= 4'b0000; F_OUT <= 1'b1; ﻩ Q3 <= 4'b0000; if((EN == 1'b1)&& end end end end (CLR == 1'b0)&&(Q4 != 4'b1001)) ﻩ begin -- -- end end 该模块定义输入端口如下: ● EN:异步BCD码十进制计数器的全局使能信号 ● CLR:异步BCD码十进制计数器复位信号 ● F_IN:被测信号经过放大与整形处理后的信号 该模块定义输出端口如下: ● F_OUT:超出技术范围0~999999的输出信号,用来指示提醒用户选择更大的量程。 ● Q0:计数器的最低位输出 ● Q1:计数器的第5位输出 ● Q2:计数器的第4位输出 ● Q3:计数器的第3位输出 ● Q4:计数器的第2位输出 ● Q5:计数器的第1位输出 end endmodule 在Altera公司的软件工具QuartusII中编译和波形仿真得到波形如图4.2.2所示。 图4.2.2 计数模块counter的仿真波形 门控模块gate_control 门控模块实现检测外界量程的选择,并且根据量程输出控制6位BCD码十进制计算器的计数时钟,以及在测量完一次信号频率后,计数器计数值清零。计数器的清零要与后级 -- -- 寄存器的锁存时刻做很好的时序配合。应该实在计数器测量完一次信号频率后,首先将数据锁存到寄存器,然后再将计数器值清零,这样可以惊醒下一次测量。 门控模块的结构框图如图4.3.1所示 图4.3.1 门控模块结构框图 根据模块实现的功能设计Verilog HDL源代码如下: module gate_control( ﻩSW0,SW1,SW2, ﻩﻩﻩﻩ f1hz,f10hz,f100hz, ﻩ ﻩﻩ ); output Latch_EN; output Counter_Clr; output Counter_EN; output dp_s1hz,dp_s10hz,dp_s100hz; input SW0,SW1,SW2; input f1hz,f10hz,f100hz; reg dp_s1hz,dp_s10hz,dp_s100hz; reg fref; reg wire_1; reg wire_2; //初始化输入以及中间量 initial begin fref <= 1'b0; wire_1 <= 1'b0; wire_2 <= 1'b0; end //根据不同的外界量程选择,选择相应的计数基时钟 always @(SW0 or SW1 or SW2 or f ﻩﻩ ﻩ ﻩLatch_EN, ﻩCounter_Clr, ﻩ Counter_EN, dp_s1hz,dp_s10hz,dp_s100hz -- -- 1hz or f10hz or f100hz) begin if(SW2 == 1'b1) begin fref <= f100hz; {dp_s1hz,dp_s10hz,dp_s100hz} <= 3'b001; end else if(SW1 == 1'b1) begin fref <= f10hz; {dp_s1hz,dp_s10hz,dp_s100hz} <= 3'b010; end else if(SW0 == 1'b1) begin fref <= f1hz; {dp_s1hz,dp_s10hz,dp_s100hz} <= 3'b100; end 该模块定义输入端如下: ● SW0、SW1、SW2:量程选择开关 ● flhz:1Hz的标准时钟输入 ● fl0hz:10Hz的标准时钟输入 ● fl00hz:100Hz的标准时钟输入 该模块定义输入端口如下: ● Latch_EN:用来是能寄存器所存数据 ● Counter_Clr:用于计数器的清零 end //根据不同的计数基时钟,提供输出相应的计数器计数值的清除脉冲与锁存器锁存脉冲 always @(posedge fref) begin wire_1 <= ! wire_1; end always @(negedge fref) begin wire_2 <= wire_1; end assign Counter_EN = wire_1; assign Latch_EN = (! Counter_EN) & wire_2; assign Counter_Clr = (! Counter_EN) & (! Latch_EN) | (! wire_2); endmodule -- -- ● Counter_EN:用于使能计数器开始计数 ● dp_s1hz:选择999999Hz量程时,用于控制显示中的小数点位置 ● dp_s10hz:选择9999.99Hz量程时,用于控制显示中的小数点位置 ● dp_s100hz:选择99.9999Hz量程时,用于控制显示中的小数点位置 在Altera公司的软件工具QuartusII中编译和波形仿真得到波形如图4.3.2所示。 图4.3.2 门控模块的仿真波形 分频模块fdiv 分频模块在系统全局时钟的驱动下,经过分频得到系统中所需要的多种频率成分的时钟信号。实际的分频模块总共有四个分频时钟,在程序上只需要改变其参数要求即可,所以在这里只介绍50MHZ到1MHZ的分频,其余的不在介绍。 分频模块的结构框图如图4.4.1所示。 图4.4.1 分频模块结构框图 根据模块实现的功能设计Verilog HDL源代码如下: -- -- module div1(clk_50M,clk1,reset);// 端口的定义 input clk_50M,reset;// 总的时钟是50M output clk1;//分频后输出的时钟 1KHZ reg clk1; reg [31:0] count;//32位的计数器 always@ (posedge clk_50M or negedge reset)//异步复位 begin if(!reset) begin clk1<='d0; count=32'd0; end else if(count==32'd50_000)// 判断计时器记到了50_000吗 begin count<=32'd0;//计到50_000计数器清零 clk1<=~clk1;//输出的时钟取反 end//end begin else count<=count+1'd1;// 没计到50_000计数器加一 end//end always endmodule // 结束分频模块 该模块定义输入端口如下: ● Clk:全局系统时钟信号 该模块定义输出端口如下: ● clk1为分频信号 ● reset为复位按键 在Altera公司的软件工具QuartusII中编译和波形仿真得到波形如图4.4.2所示。 -- -- 图4.4.2 分频模块的仿真波形 寄存器模块flip_latch 寄存器模块实现每一个测量频率时,计数器计算值的暂时存储。 寄存器模块的结构框图如图4.5.1所示。 图4.5.1 寄存器模块 根据模块实现的功能设计Verilog HDL源代码如下: module flip_latch(clk,A0,A1,A2,A3,A4,A5,Q0,Q1,Q2,Q3,Q4,Q5output [3:0] Q0,Q1,Q2,Q3,Q4,Q5; input clk; input [3:0] A0,A1,A2,A3,A4,A5; reg [3:0] Q0,Q1,Q2,Q3,Q4,Q5; always @(posedge clk) begin ﻩQ2 <= A2; ﻩQ0 <= A0; Q3 <= A3; ﻩQ1 <= A1; Q4 <= A4; -- ); -- ﻩQ5 <= A5; endmodule 该模块定义输入端口如下: ● clk:所存数据信号输入,当clk的上升沿到来时,寄存器将输入端信号锁存进寄存器,并且改变输出。 ● A0,A1,A2,A3,A4,A5:寄存器的数据输入端 该模块定义输出端口如下: ● Q0,Q1,Q2,Q3,Q4,Q5:寄存器的数据输出端。 在Altera公司的软件工具QuartusII中编译和波形仿真得到波形如图4.5.2所示。 end 图4.5.2 寄存器模块的仿真波形 多路选择模块data_mux 多路选择模块实现测量频率值的分时显示,即动态显示。经过多路选择器模块来分时地传输数据。 多路选择模块的结构如图4.6.1所示。 -- -- 图4.6.1 多路选择模块结构框图 根据模块实现的功能设计Verilog HDL源代码如下: module data_mux(disp_select,A0,A1,A2,A3,A4,A5,Q); output [3:0] Q; input [2:0]disp_select; input [3:0] A0,A1,A2,A3,A4,A5; reg [3:0] Q; always @(disp_select,A5,A4,A3,A2,A1,A0,Q) begin case(disp_select) 3'b000: Q <= A5; ﻩ 3'b001: Q <= A4; ﻩ 3'b010: Q <= A3; 3'b011: Q <= A2; ﻩ 3'b100: Q <= A1; ﻩ 3'b101: Q <= A0; ﻩ default: Q <= 4'b0; endcase end endmodule 该模块定义输入端口如下: ● disp_select:选择信号输入 ● A0,A1,A2,A3,A4,A5:多路选择模块的数据输入端口 该模块定义输出端口如下: ● 多路选择模块的数据输出端口。 在Altera公司的软件工具QuartusII中编译和波形仿真得到波形如图4.6.2所示。 -- -- 图4.6.2 多路选择模块的仿真波形 动态位选模块dispselect 动态位选模块用来驱动数码动态地显示频率测量数据,分时地选择各个数码管进行显示 动态位选的结构框图4.7.1所示。 图4.7.1 动态位选模块的结构框图 根据模块实现的功能设计Verilog HDL源代码如下: module dispselect(clk,disp_select,Q); output [5:0] Q; output [2:0] disp_select; input clk; reg [5:0] Q; reg [2:0] disp_select; always @(posedge clk) begin ﻩif(disp_select < 3'b101) disp_select <= dis p_select + 3'b1; else ﻩdisp_select <= 3'b0; ﻩcase(disp_select) ﻩ 3'b000: Q <= 6'b100000; ﻩ 3'b001: Q <= 6'b010000; 3'b010: Q <= 6'b001000; ﻩ 3'b011: Q <= 6'b000100; ﻩ 3'b100: Q <= 6'b000010; -- -- ﻩ 3'b101: Q <= 6'b000001; default: Q <= 6'b00 endcase end endmodule 0000; 该模块定义输入端口如下: ● clk:动态位选的时钟信号输入,一般取1KHz左右的标准时钟。 该模块定义输出端口如下: ● disp_select:动态位选中间量输出,用于与系统中其他模块之间的同步。 ● Q:动态位选信号输出,可以直接接到数码管的公共端。 在Altera公司的软件工具QuartusII中编译和波形仿真得到波形如图4.7.2所示。 图4.7.2 动态位选模块的仿真波形 BCD译码模块dispdecoder BCD译码模块主要实现BCD码到7段数码管显示码字段的转换,同时,考虑到频率测量中的一些“零”的处理,比如选择量程1~999999Hz,但被测信号频率为100Hz,这样在显示的时候就需要将6为数码管的前三位屏蔽。 BCD译码模块的结构框图如图4.7.1所示。 -- -- 图4.8.1 BCD译码模块的结构框图 根据模块实现的功能设计Verilog HDL源代码如下: module dispdecoder( ﻩﻩ ﻩdata_in, ut) begin if(hide == 1'b0) begin , case(data_in) ﻩﻩﻩﻩﻩdisp_select, ﻩdp_s1hz,dp_s10hz,d p_s100hz, ﻩﻩ ﻩﻩQ5,Q4 4'b0000 : data_out <= 7'b1111110; //0 ﻩ4'b0001 : data_out <= 7 Q3,Q2,Q1,Q0,counter_out, ﻩ ﻩﻩ ﻩﻩ data_out, ﻩﻩdp); 'b0110000; //1 ﻩ 4'b0010 : data_out <= output [6:0] data_out; output dp; input [3:0] data_in; input [2:0] disp_select; input dp_s1hz,dp_s10hz,dp_s100hz; input [3:0] Q5,Q4,Q3,Q2,Q1,Q0; input counter_out; reg dp; reg [6:0] data_out; reg hide; initial begin dp <= 1'b0; hide <= 1'b0; end //译码显示数据 always @(data_in,hide,data_o 7'b1101101; //2 ﻩﻩ4'b0011 : data_out <= 7'b1111001; //3 4'b0100 : data_out <= 7'b0110011; //4 4'b0101 : data_out <= 7'b1011011; //5 ﻩ4'b0110 : data_out <= 7' b1011111; //6 ﻩﻩ4'b0111 : data_out <= 7'b1110000; //7 ﻩ 4'b1000 : data_out <= 7'b1111111; //8 4'b1001 : data_out <= 7'b1110011; //9 ﻩ default : data_out <= 7' b0000000; endcase -- -- end end //小数点位置与零数字的处理 always @(disp_select,dp_s1h 'b0) && ﻩ ﻩﻩ (Q4 == 4'b0) &&ﻩ ﻩﻩﻩ(dp_s100hz != 1'b1)) hide <= 1'b1; z,dp_s10hz,dp_s100hz, else Q5,Q4,Q3,Q2,Q1,counter_out,dp,hide) begin if (((disp_select == 3'b001) && (dp_s100hz == 1'b1))|| ﻩ ((disp_select == 3'b011) && (dp_s10hz == 1'b1))|| ((disp_select == 3'b101) && (dp_s1hz == 1'b1))) dp <= 1'b1; else dp <= 1'b0; case(disp_select) 3'b000: begin if((counter_out == 1'b0) && (Q5 == 4'b0)) hide <= 1'b1; else hide <= 1'b0; end 3'b001: begin if((counter_out == 1'b0) && (Q5 == 4 0; end 3'b011: begin if((counter_out == 1'b0) && (Q5 == 4'b 0 ) & hide <= 1'b0; end 3'b010: begin if((counter_out == 1'b0) && (Q5 == 4'b0) && ((Q3 Q 4== 4 == ' 4b 'b0) 0) && && (dp_s100hz != 1'b1)) hide <= 1'b1; else hide <= 1'b & (Q4 == (Q3 (Q2 = 4'b0) && == 4'b0) && = 4 'b 0 ) && (dp_s100hz != (dp_s10hz != 1'b1)) 1'b1)&& -- -- hide <= 1'b1; else hide <= 1'b0; end 3'b100: begin if((counter_out == 1'b0) && (Q5 == 4'b0) & 0; (Q1 == 4'b0) && (dp_s100hz != 1'b1)&& (dp_s10hz != 1'b1)) hide <= 1'b1; else hide <= 1'b0; end default: hide <= 1'b & endcas e (Q4 == 4'b0) && end (Q3 == 4'b0) && endmo dule (Q2 == 4'b0) && 该模块定义输入端口如下: ● data_in:BCD码字输入信号 ● disp_select:来自动态显示位模块,实现两者之间的同步 ● dp_s1hz,dp_s10hz,dp_s100hz:输入小数点位置控制信号来自门控模块 ● Q5,Q4,Q3,Q2,Q1,Q0:计数器的计数值输入,用来控制“零”显示控制 ● counter_out:计数器计数溢出信号,用来提示用户更换更大量程 该模块定义输出端口如下: ● data_out:经过译码后的7段数码管显示数据输出,可以直接连接到数码管的数据端口 ● dp:小数点控制信号 在Altera公司的软件工具QuartusII中编译和波形仿真得到波形如图4.8.2所示。 -- -- 图4.8.2 BCD译码模块的仿真波形 顶层电路top 在设计完各个模块后,需要将各个模块有机地组合成一个整体,最后来实现系统的功能。在数字频率计中,同时采用了电路原理图示的设计以及Verilog HDL语言来编写的顶层电路,其中顶层如图4.9.1所示。 图4.9.1 顶层电路top 4 总结 -- -- 为期两周的实训结束了,很辛苦,但是收获很大。刚开始拿到实训题目的时候,说实话连从哪里入手也不知道,只是从网上搜集了相关的资料。资料很全面,但是,资料在手也不知道怎么利用,真的是两眼一抹黑。脑子里根本没有一个完整的流程,心中也没什么底气甚至担心,自己根本不能完成实训。还好,在同学及老师的帮助下完成了实训,达到了锻炼自己的目的。 在实训的第一天,并没有什么好的想法,只是又重新熟悉了一下,Quartus II等开发工具的使用方法,其实平常上机课的时候都有练习,但是每次都是照着课本,一步一步照着做,根本没有有意识的去记忆软件的使用方法,而且自己掌握的也仅仅是程序的编译,连生成电路器件都不会。第一天就在学习和练习中过去了,终于在结束的时候,基本掌握了Quartus II的各项基本功能。算是为实训,打了一个基础。 第二天,开始设计方案了。要完成一个题目,一步步怎么来,都是有章程的。其实设计一个方案并没有想象中那么困难。Verilog,其实是一门硬件描述语言,通俗的讲就是通过语言描述一件器件的功能,生成一个虚拟器件,然后将各个虚拟器件连接起来,就组成了一个完整的系统。这个系统就是一个完整的方案设计了。其实,这和数字电路设计其实是很类似的,不同的是数字电路设计中的芯片是别人设计好的,而Verilog中的“芯片”是自己设计的。相比较而言,Verilog更灵活。在设计过程中,我第一次体会到了,当一个设计者的乐趣。 在和队友的相互探讨学习中,三天的时间就过去了,我们采用自底向上的设计方法,先设计好了各个模块的程序,然后再将各个模块通过顶层电路连接起来。在星期四的时候我们总算将整个系统完成了。 在星期五的那天,我们进行引脚锁定,这时意外出现了,我们做的的是数字频率计,需要用到数码管显示,我们做的是四位显示,设计时我们设计的是静态显示,而实验箱中只有两位的静态显示数码管,还有就是八位动态显示数码管。这时我们有两种选择,一是更改程序设计动态显示,而是通过液晶来显示,通过对比我们决定用动态显示。数码管的动态显示在学习单片机的时候,学习过也并不困难。但是难的是怎样只更改显示部分,而不对其它模块产生影响。通过参考其它实验例程的显示部分,我们终于找到了方法。在星期五当天一套新的方案,我们就从新做出来了。 在第二周的星期一我们在实验箱上进行了仿真,令我们期待已久的结果并没有出来,设计的三个功能,仅有一个实现了。通过查找原因,原来我们设计的计数器出了问题,计数器是整个实验最关键的部分,无论是分频还是计数,都靠它。计数器出了问题频率计是不可能成功的。通过,对计数器的的波形仿真,我们发现了问题,原来我们设定的是仅在输入波形是高电平的时候计数,而在低电平的时候不计数,因此当然计数不准确了。最后我们做了更改,采用输入计数,输出进位的方式进行计数,这样通过串联的方式,那么计数就准确多了。在我们再次将做好的程序下载到实验箱上进行仿真的时候,我们终于成功了。那一刻我们终于尝到了成功的喜悦。 我们体会到了,付出之后收获成功那一刻的喜悦,虽然人辛苦,但是我们认为都很值得,收获也很大。在此感谢在实训期间帮助我们的同学以及指导我们的老师,在你们的帮助下我们才能顺利的完成实训,容我说一声谢谢。 姓名: 学号:2 -- -- 参考文献 [1]陈敬远.数字频率计的VHDL设计[J].浙江传媒学院学报; 2002,01: 36-38. [2]何均 ,杨明.适合于单片机实现的极值搜索算法[J].单片机与嵌入式系统应用,2004,24. [3]杜玉远.基于top-down方法的数字频率计的设计与实现[J].电子世界, 2004,5: 30-32. [4]钱进.基于AT89C2051的高度精度数字频率计的设计[J].机电产品开发与创新,2007,20(1):86-87. [5]冯雷星,杨伟,芦燕龙.基于单片机高性价比频率计的设计与实现[B].微计算机信息,2007,20. [6]赫建国,刘立新,党剑华.基于单片机的频率计设计[J].西安邮电学院学报,2003,03:34-37+75. [7]张毅刚.单片机原理及应用.高等教育出版社[M],2003.12(1). -- 因篇幅问题不能全部显示,请点此查看更多更全内容