/******************************************************************************************
Author: 荷包蛋
E-mail: shuangfeiyanworld@163.com
Device: EP2C8Q208C8
Tool: Quartus 8.1
Function:数字频率计(用8个数码管显示结果,单位为HZ)(理论基础:在单位时间1s内待测信号所产生的脉冲数即为待测信号的频率)
Version: 2011-9-5 v1.0
********************************************************************************************/
module frequence (
input CLK_50M, // 50MHZ基准频率
input CLK_X, // 待测信号
output reg [7 :0] WEI,DUAN // 数码管位选和段选
);
reg [31:0] cnt1,num; //cnt1用来作延时用,num用来计算1s内待测信号所发出的脉冲数
reg sec,state; //sec用来产生周期为2s,占空比为50%的单位脉冲(即一个周期内高电平和低电平持续时间均为1s)
reg [31:0] freq ; //频率输出
/**** 产生占空比为50%,周期为2s的单位脉冲sec ****/
always @ (posedge CLK_50M)
begin
if(cnt1==50_000_000) // delay 1s,cnt1=50_000_000是为了延时1s(因为基准时钟为50M),如果基准时钟为20M,则应写为cnt1==20_000_000,以此类推,总之,只要实现1s延时即可
begin
cnt1<=0;
sec<=~sec;
end
else
cnt1<=cnt1+1;
end
/**** 统计待测信号在单位时间1s内产生的脉冲数 ****/
always @ (posedge CLK_X)
begin
if(sec) // sec为高电平期间(1s),统计待测信号产生的脉冲数
begin
num<=num+1;
state<=0;
end
else // sec为低电平期间(1s),读取待测信号产生的脉冲数
case(state)
0: begin freq<=num; state<=1; end // 读取脉冲数(由于freq为reg型,在下一次sec低电平到来之前,会一直保持当前值不变)
1: num<=0; // 将num清零,为下一个sec高电平期间脉冲数的统计做准备
endcase
end
/**** 以下为频率测量结果的显示模块 ****/
reg [3 :0] wei1,wei2,wei3,wei4,wei5,wei6,wei7,wei8 ; //待测
always @ ( posedge CLK_50M ) // 得到待测信号频率输出的个位数,十位数,百位数,......(提示:N**M的意思是N的M次方)
begin
wei1 <= (freq/10**0)%10 ;
wei2 <= (freq/10**1)%10 ;
wei3 <= (freq/10**2)%10 ;
wei4 <= (freq/10**3)%10 ;
wei5 <= (freq/10**4)%10 ;
wei6 <= (freq/10**5)%10 ;
wei7 <= (freq/10**6)%10 ;
wei8 <= (freq/10**7)%10 ;
end
//display part
reg [15:0]jishu;
always@(posedge CLK_50M) // 为数码管动态扫描的时间间隔作准备
begin
if (jishu==16'hffff)
jishu<=0;
else
begin
jishu<=jishu+1;
end
end
reg [3:0]tab;
always@(posedge CLK_50M)
begin
case(jishu[15:13]) // 位值读取;每一个时间间隔读取一个位(个位、十位、百位 ...)
0:tab<=wei1[3:0];
1:tab<=wei2[3:0];
2:tab<=wei3[3:0];
3:tab<=wei4[3:0];
4:tab<=wei5[3:0];
5:tab<=wei6[3:0];
6:tab<=wei7[3:0];
7:tab<=wei8[3:0];
default:tab<=4'bz;
endcase
case(jishu[15:13]) // 位选;在对应的时间间隔上打开对应的数码管(第一个、第二个、第三个 ...)
0:WEI<=8'b1111_1110;//显示在第一个数码管上的数
1:WEI<=8'b1111_1101;//显示在第二个数码管上的数,以下同理
2:WEI<=8'b1111_1011;
3:WEI<=8'b1111_0111;
4:WEI<=8'b1110_1111;
5:WEI<=8'b1101_1111;
6:WEI<=8'b1011_1111;
7:WEI<=8'b0111_1111;
default:WEI<=4'bz;
endcase
case(tab) // 段选;当tab(即wei1/wei2 ...)为0,1,2...时,打开数码管相应的段
0:DUAN<=8'hc0;
1:DUAN<=8'hf9;
2:DUAN<=8'ha4;
3:DUAN<=8'hb0;
4:DUAN<=8'h99;
5:DUAN<=8'h92;
6:DUAN<=8'h82;
7:DUAN<=8'hf8;
8:DUAN<=8'h80;
9:DUAN<=8'h90;
default:DUAN<=8'h??;
endcase
end
endmodule
用户377235 2015-8-3 09:38