频率计数器设计要求
设计一个4位频率计,主要设计模块为测频控制器、计数器、锁存器、译码器,使计数结果稳定地显示在4个7段LED数码管上。
【 1. 源代码 】
顶层文件
- CLKK作为控制模块的参考信号,控制模块根据CLKK决定计数器使能信号EN,计数器复位信号rst,锁存允许信号laod,
- 被测信号signal作为计数器的计数计数频率。计数器模块的输出作为锁存信号的输入。
- 当锁存信号有效时,锁存器将当前计数值输入到数码管模块进行显示。
1. 控制器模块
- 在参考时钟CLKK的有效上升沿时,对临时变量JICUN取反。则在CLKK的两个相邻周期内,临时变量JICUN是一高一低两种状态,用于区分计数模式和准备模式。
- 当CLKK或JICUN变化时,若CLKK为0且JICUN为0,将复位信号RST_CNT赋值为1进行复位,否则赋值为0不复位。此步属于准备模式,即在下次测频前在CLKK的半个周期内将计数值清空。
- 当JICUN发生变化时,令LOAD=JICUN的取反。此步属于准备模式,当LOAD=1出现上升沿,将值加载到锁存器中。
- CNT_EN=JICUN,即两者同时变化,即当JICUN=1时,CNT_EN=1进行计时,否则不计时。
//CLKK参考信号,LOAD锁存允许,RST_CNT清零,CNT_EN计数允许
module control(CLKK,CNT_EN,RST_CNT,LOAD);
input wire CLKK;
output wire CNT_EN,LOAD;
output reg RST_CNT;
reg JICUN;
always @(posedge CLKK)
JICUN<=~JICUN;
always @(CLKK or JICUN)
begin
if(CLKK==1'b0 & JICUN==1'b0) RST_CNT<=1'b1;
else RST_CNT<=1'b0;
end
assign LOAD=~JICUN;
assign CNT_EN=JICUN;
endmodule
2. 计数器模块
- 计数器模块端口:
时钟输入:clk 上升沿有效
同步复位信号:rst 高电平有效
使能信号:cnts 高电平有效
计数结果:Q1、Q2、Q3、Q4。 - 当clk上升沿有效时。
若clk=1,则对输出Q1、Q2、Q3、Q4清零;
否则若使能信号cnts为1有效时,开始计数。若最低位Q1计数到9,则令Q1清零,Q2+1,若Q2计数到9时,则对Q2清零,Q3+1,若Q3计数到9时,则对Q3清零,Q4+1,若Q4计数到9时,则对Q4清零。此步是进位操作。
若在上升沿来时,Q1≠9,则令Q1加1操作。
module Counter(clk,en,rst,Q1,Q2,Q3,Q4);
input wire clk,rst,en;
output reg [3:0] Q1,Q2,Q3,Q4;
always @(posedge clk)
if(rst)
begin
Q1<=4'b0000;
Q2<=4'b0000;
Q3<=4'b0000;
Q4<=4'b0000;
end
else if(en) //4个if完成4位计数器的进位
begin
if(Q1==4'b1001)
begin
Q1<=4'b0000;
Q2<=Q2+4'b1;
if(Q2==4'b1001)
begin
Q2<=4'b0000;
Q3<=Q3+4'b1;
if(Q3==4'b1001)
begin
Q3<=4'b0000;
Q4<=Q4+4'b1;
if(Q4==4'b1001) Q4<=4'b0000;
end
end
end
else
Q1<=Q1+4'b1;
end
endmodule
3. 锁存器模块
- 锁存器模块端口:
锁存允许信号:kaiguan上升沿有效
输入值:data1,data2,data3,data4
输出值:result1,result2,result3,result4 - 当锁存允许信号kaiguan上升沿有效时,将输入值赋值给输出值。
module Lock(in1,in2,in3,in4,out1,out2,out3,out4,en);
input wire [3:0] in1,in2,in3,in4;
output reg [3:0] out1,out2,out3,out4;
input en;
always @(posedge en)
if(en)
begin
out1<=in1;
out2<=in2;
out3<=in3;
out4<=in4;
end
endmodule
4. 数码管模块
- 数码管端口:
输入值:4位的code
输出值:8位的Y - 根据输入值code,将code对应到8位数码管的段码表上,令8位的输出值为预显示数字的段码,即可显示相应的数字。
module shuma(in,out);
input wire [3:0] in;
output reg [7:0] out;
always@(*)
begin
if(in==4'b0000) //0 0x3f
out<=8'b011_1111;
else if(in==4'b0001) //1 0x06
out<=8'b000_0110;
else if(in==4'b0010) //2 0x5b
out<=8'b101_1011;
else if(in==4'b0011) //3 0x4f
out<=8'b100_1111;
else if(in==4'b0100) //4 0x66
out<=8'b110_0110;
else if(in==4'b0101) //5 0x6d
out<=8'b110_1101;
else if(in==4'b0110) //6 0x7d
out<=8'b111_1101;
else if(in==4'b0111) //7 0x07
out<=8'b000_0111;
else if(in==4'b1000) //8 0x7f
out<=8'b111_1111;
else if(in==4'b1001) //9 0x6f
out<=8'b110_1111;
else if(in==4'b1010) //A 0x77
out<=8'b111_0111;
else if(in==4'b1011) //B 0x7c
out<=8'b111_1100;
else if(in==4'b1100) //C 0x39
out<=8'b011_1001;
else if(in==4'b1101) //D 0x5e
out<=8'b101_1110;
else if(in==4'b1110) //E 0x79
out<=8'b111_1001;
else if(in==4'b1111) //F 0x71
out<=8'b111_0001;
else
out<=8'b00;
end
endmodule
// code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
【 2. 仿真图 】
- 如图所示,在参考时钟CLKK的两个相邻周期内,分为计数模式和准备模式。
- 计数模式下,计数使能端EN=1有效并进行计数,计数清零端rst=0无效,锁存允许信号load=0无效,
- 准备模式下。计数使能信号EN=0无效暂停计数。锁存允许信号load在刚进入准备模式时,跳变成上升沿有效并进行锁存。同时在准备模式的最后半个周期内清零信号rst=1有效对计数器清零,并准备进入下个计数模式。
- 总的来说,本次频率计数计还有缺陷。本次设计中,参考信号CLKK作为计数器的参考,参考是指在CLKK的一个周期内对被测信号signal的计数,若CLKK的周期小于被测信号的周期,则不能进行相关测频功能。因此CLKK的频率的选择应该足够小。同时,被测信号频率的显示只是基于1HZ的CLKK信号(即在1s内测signal信号上升沿的次数,也就是signal的频率),若CLKK频率更改则需要进行重新设计显示代码。