1,原理
主要是通过两个计数器,在系统时钟下对高低电平保持时间计数,来实现计算输入信号的频率和占空比,
2,Verilog代码
//频率计
module freq_cnt(
input clk,
input rst_n,
input signal_in, //输入信号
output [25:0] freq, //信号频率
output [25:0] duty_cycle //信号的占空比
);
reg state; //输出信号的状态
parameter high_state = 1'b0,
low_state = 1'b1;
reg [25:0] low_cnt; //计算低电平维持的周期数
reg [25:0] high_cnt; //计算低电平维持的周期数
reg [25:0] low_time;
reg [25:0] high_time;
assign freq = 1_000_000 / (low_time * 20 + high_time * 20); //信号频率
assign duty_cycle = (high_time * 100) / (high_time + low_time); //信号的占空比
always @(posedge clk,negedge rst_n)begin
if(!rst_n)begin
low_cnt <= 26'd0;
low_time <= 26'd0;
high_cnt <= 26'd0;
high_time <= 26'd0;
state <= high_state;
end
else begin
case(state)
high_state: //在高电平状态下,如果输入为低电平,则转换到低电平状态;
begin //并将high_cnt计数器里的值寄存到high_time中;
if(!signal_in) begin
state <= low_state;
high_cnt <= 26'd0;
high_time <= high_cnt;
end
else
begin
state <= high_state;
high_cnt <= high_cnt + 1'b1;
end
end
low_state:
begin //在低电平状态下,如果输入为高电平,则转换到高电平状态;
if(signal_in) begin //并将low_cnt计数器里的值寄存到low_time中;
state <= high_state;
low_cnt <= 26'd0;
low_time <= low_cnt;
end
else
begin
state <= low_state;
low_cnt <= low_cnt + 1'b1;
end
end
default:state <= high_state;
endcase
end
end
endmodule
3,仿真文件
`timescale 1 ns/ 1 ns
module freq_cnt_tb();
// test vector input registers
reg clk;
reg rst_n;
reg signal_in;
// wires
wire [25:0] duty_cycle;
wire [25:0] freq;
// assign statements (if any)
freq_cnt i1 (
// port map - connection between master ports and signals/registers
.clk(clk),
.duty_cycle(duty_cycle),
.freq(freq),
.rst_n(rst_n),
.signal_in(signal_in)
);
always #10 clk = ~clk;
initial
begin
clk = 1'b0;
rst_n = 1'b0;
#200 rst_n = 1'b1;
end
initial begin
signal_in = 1'b1;
forever begin//产生占空比为80%,频率为100KHz的方波
# 8000
signal_in = 1'b0;
# 2000
signal_in = 1'b1;
end
end
endmodule
4,总结与反思
没什么可说的,一句话,我自己真的太菜了。