采用时钟频率为2MHz,不同的时钟频率需要修改相应的参数。在此只给出本时钟下的程序,其他时钟下请自行修正。
module Cymometer(clk, reset, signal, FreqNs, FreqNx, Freq);
parameter clk_freq = 2_000_000;/*clk为2MHz*/
input clk;
input reset;
input signal;
output reg[20:0] FreqNs;
output reg[31:0]FreqNx, Freq;
//============================================================
wire start;/*此信号为高电平时计数器开始计数,高电平时长1s*/
reg [20:0]CNT0;
/*产生一个门控信号,高电平有效,为了得到更快的响应速度,
此处门控信号的占空比很大,相应低电平时间很短,因此可以
使频率计大部分时间处于工作状态,可以有效提高响应速度*/
always@(posedge clk)
begin
if(reset)
CNT0 <= 0;
else
CNT0 <= CNT0 + 1;
end
assign start = ( CNT0 < (clk_freq * 3 / 4) );
//============================================================
reg CTRL;/*CTRL信号为待测信号和门控信号产生的计数器启动信号*/
always@(posedge signal)
begin
if(reset)
CTRL <= 0;
else
CTRL <= start;
end
//============================================================
//用两个计数器分别对标准信号clk和待测信号signal计数
reg [20:0]CNTs;
reg [31:0]CNTx;
/*CTRL高电平期间计数标准信号*/
always@(posedge clk)
begin
if(reset)
CNTs <= 0;
else if(CTRL)
CNTs <= CNTs + 1;
else
CNTs <= 0;
end
/*CTRL高电平期间计数待测信号*/
always@(posedge signal)
begin
if(reset)
CNTx <= 0;
else if(CTRL)
CNTx <= CNTx + 1;
else
CNTx <= 0;
end
/*CTRL下降沿输出*/
always@(negedge CTRL)
begin
if(reset)
begin
FreqNs <= 0;
FreqNx <= 0;
Freq <= 0;
end
else
begin
FreqNs <= CNTs;
FreqNx <= CNTx;
Freq <= clk_freq / CNTs * CNTx;
end
end
//============================================================
endmodule
下面是为上面的模块编写的测试平台,在Modelsim下仿真通过,因为数据量较大,建议不要使用Altera及ISE仿真。
`timescale 1ns / 1ps
module tb;
// Inputs
reg clk;
reg reset;
reg signal;
// Outputs
wire [20:0] FreqNs;
wire [31:0] FreqNx;
wire [31:0] Freq;
// Instantiate the Unit Under Test (UUT)
Cymometer uut (
.clk(clk),
.reset(reset),
.signal(signal),
.FreqNs(FreqNs),
.FreqNx(FreqNx),
.Freq(Freq)
);
always #250 clk = ~clk;
always #500 signal = ~signal;
initial begin
// Initialize Inputs
clk = 0;
reset = 1;
signal = 0;
// Wait 100 ns for global reset to finish
#1000;
reset = 0;
// Add stimulus here
#2_000_000_000 $stop;
end
endmodule
参考原理M/T测频法。
文章评论(0条评论)
登录后参与讨论