频率计完整程序(含 ucf 文件)
/////////////////////////////////////////////////////////////
//文件名:Fre_check_3_1
//端口表:输入:clk_50M(48MHz 时钟信号)
// rst_n(复位信号,低电平有效)
// wave_in(输入方波信号)
// 输出:led_sel(数码管位选信号)
// seg_sel(数码管段选信号)
// full(超量程)
// power(电源)
// gate(门信号)
// led_gate(当前单位)
// seg_on_n(数码管使能,低电平有效)
//实现功能:测量频率在 1Hz 到 10MHz 标准方波,精度 1Hz,自动调整量
// 程,超过量程报 LED 显示门信号,电源开关信号
//编程思路:1、频率计原理:测试 1 秒内待测信号上升沿的个数即频率
// 2、使用 counter_wv[23:0]做 6 个十进制计数器,
// 因此最大量程为 100MHz
// 3、复位:每次更换档位时自动复位
// 4、档位调整:通过对门信号(gate)手动调整,总共有 1S/
// 0.1S/0.01S 三个档位,对应量程为 1MHz/10MHz/100MHz
// 5、在测得的频率大于所在档对应的最大量程时,超量程指
// 示灯亮,可以通过换档解除报警,但是最高量程为 100MHz
//修改记录:历时两天,现为最终版本
//程序员:simple
//完成时间:2012 年 2 月 24 日
//版权声明:UESTC-2012
////////////////////////////////////////////////////////////
module Fre_chk (clk_50M,rst_n,wave_in,led_sel,seg_sel,full,gate,power,seg_on_n,led_gate);
input clk_50M;
input wave_in;
input rst_n;
output [7:0]led_sel;
output [2:0]seg_sel;
output [2:0]led_gate;
output full;
output gate;
output power;
output seg_on_n;
reg [31:0] count;
reg [9:0] gate_sel_reg;
reg [2:0] led_gate;
reg [23:0] count_wv;
reg [24:0] data;
reg full_reg;
reg [7:0]led_reg;
reg gate;
reg [1:0]count_gate;
reg flag;
reg [3:0] led_sel_reg;
reg seg_on_n;
wire wave_in;
wire rst_n;
assign power = 1'b0;
//////////////////////////////////////////////////////////////
always @ (posedge clk_50M or negedge rst_n)//门信号产生
begin
if (!rst_n)
begin
count <= 32'b0;
gate <= 1'b0;
end
else if (count == 48_000_0 * gate_sel_reg)//门周期控制
begin
count <= 32'b0;
gate <= ~gate;
end
else
count <= count + 32'b1;
end
///////////////////////////////////////////////////////////
always @ (count_gate)//门信号选择
begin
case (count_gate)
end
//////////////////////////////////////////////////////////////
always @ (negedge rst_n)//复位按钮复用,选择对应门信号
begin
1:begin led_gate = 3'b110;gate_sel_reg = 100;end//0.01s
2:begin led_gate = 3'b101;gate_sel_reg = 10;end//0.1s
3:begin led_gate = 3'b011;gate_sel_reg = 1;end//1s
default:begin led_gate = 3'b110;gate_sel_reg = 100;end
endcase
if (count_gate == 3)
count_gate = 1;
else
count_gate = count_gate + 1'b1;
end
//////////////////////////////////////////////////////////////
always @ (posedge wave_in or negedge rst_n)//频率计数部分
begin
if (!rst_n)//复位初始化
begin
data = 24'b0;
count_wv = 28'b0;
full_reg = 1'b1;
end
else
if (gate)
begin
flag = 1'b1;//锁存标记
count_wv[3:0] = count_wv[3:0] + 4'h1;
if (count_wv[3:0] > 4'h9)
begin
count_wv[3:0] = 4'h0;//进位加 1
count_wv[7:4] = count_wv[7:4] + 4'h1;
if (count_wv[7:4] > 4'h9)
begin
count_wv[7:4] = 4'h0;//进位加 1
count_wv[11:8] = count_wv[11:8] + 4'h1;
if (count_wv[11:8] > 4'h9)
begin
count_wv[11:8] = 4'h0;//进位加 1
count_wv[15:12] = count_wv[15:12] + 4'h1;
if (count_wv[15:12] > 4'h9)
begin
count_wv[15:12] = 4'h0;//进位加 1
count_wv[19:16] = count_wv[19:16] + 4'h1;
if (count_wv[19:16] > 4'h9)
begin
count_wv[19:16] = 4'h0;//进位加 1
count_wv[23:20] = count_wv[23:20] + 4'h1;
if (count_wv[23:20] > 4'h9)
begin
count_wv[23:20] = 4'b0;
full_reg = 1'b0;//超量程报警
end
end
end
end
end
end
end
else if (flag)
begin
flag = 1'b0;
data[24:0] = {full_reg,count_wv[23:0]}; //数据锁存
count_wv = 24'b0; //计数清零
full_reg = 1'b1;//超量程复位
end
end
assign full = data[24];
////////////////////////////////////////////////////////////////////////////
always @ (count[12:10] or data)
begin
case (count[12:10])
3'b000:begin seg_on_n = 1'b0;led_sel_reg = data[3:0];end
3'b001:begin seg_on_n = 1'b0;led_sel_reg = data[7:4];end
3'b010:begin seg_on_n = 1'b0;led_sel_reg = data[11:8];end
3'b011:begin seg_on_n = 1'b0;led_sel_reg = data[15:12];end
3'b100:begin seg_on_n = 1'b0;led_sel_reg = data[19:16];end
3'b101:begin seg_on_n = 1'b0;led_sel_reg = data[23:20];end
default:begin seg_on_n = 1'b1;led_sel_reg = 4'ha;end
endcase
end
assign seg_sel = count[12:10];
////////////////////////////////////////////////
always @ (posedge clk_50M)
begin
if (data[23:14] != 12'b0)
begin
led_reg[7] = 1'b0;
end
else if (count_gate == 2)
begin
if (count[12:10] == 3'b010)
if (count_gate == 1)
begin
if (count[12:10] == 3'b011)
else
led_reg[7] = 1'b1;
else
led_reg[7] = 1'b1;
end
end
else
led_reg[7] = 1'b1;
end
else if (count_gate == 3)
begin
if (count[12:10] == 3'b001)
led_reg[7] = 1'b0;
led_reg[7] = 1'b0;
else led_reg[7] =1'b1;
end
///////////////////////////////////////////////////////////////////////////
always @ (led_sel_reg)
begin
case (led_sel_reg)
4'h0 : led_reg[6:0] = 7'h40; // "0"
4'h1 : led_reg[6:0] = 7'h79; // "1"
4'h2 : led_reg[6:0] = 7'h24; // "2"
4'h3 : led_reg[6:0] = 7'h30; // "3"
4'h4 : led_reg[6:0] = 7'h19; // "4"
4'h5 : led_reg[6:0] = 7'h12; // "5"
4'h6 : led_reg[6:0] = 7'h02; // "6"
4'h7 : led_reg[6:0] = 7'h78; // "7"
4'h8 : led_reg[6:0] = 7'h00; // "8"
4'h9 : led_reg[6:0] = 7'h10; // "9"
default : led_reg[6:0] = 7'h7f;
endcase
end
assign led_sel = led_reg;
endmodule
注:器件:Xilinx Spartan 3A XS3C200
引脚配置文件:
#Created by Constraints Editor (xc3s200a-ft256-5) - 2012/02/25
NET "clk_50M" LOC = T8;
NET "full" LOC = B10;
NET "gate" LOC = A10;
NET "led_sel[0]" LOC = B14;
NET "led_sel[1]" LOC = A13;
NET "led_sel[2]" LOC = C13;
NET "led_sel[3]" LOC = C12;
NET "led_sel[4]" LOC = A12;
NET "led_sel[5]" LOC = B12;
NET "led_sel[6]" LOC = A11;
NET "led_sel[7]" LOC = C11;
NET "power" LOC = C10;
NET "seg_on_n" LOC = D7;
NET "seg_sel[0]" LOC = F8;
NET "seg_sel[1]" LOC = D8;
NET "seg_sel[2]" LOC = E7;
NET "wave_in" LOC = K16;
NET "rst_n" LOC = G6;
NET "led_gate[0]" LOC = A9;
NET "led_gate[1]" LOC = C9;
NET "led_gate[2]" LOC = C8;
# PlanAhead Generated physical constraints