频率计(电子竞赛2015年题目)

题目:

1、频率和周期测量:正弦波,1Hz~~10MHz,50mV~1V幅度,相对误差绝对值小于等于10^-4

2、时间间隔测量:方波,100Hz~~1MHz,50mV~1V幅度,时间间隔范围是0.1us~100ms,相对误差绝对值小于等于10^-2

3、增加脉冲信号占空比测量:矩形波,1Hz~5MHz,50mV~1V幅度,占空比范围10%~90%,相对误差绝对值小于等于10^-2

本组信号发生器可以达到的范围

最大频率5MHz,占空比50%

4MHz,占空比40~60%

其他频率20~80%

 我的完成程度:

频率测量达到精度

占空比有0.1%的误差

间隔时间测量因为从题目无法理解实际时间间隔多少,完成了输出异或后信号的占空比输出,没有继续调试

一、总体思路

gate表示门限使能,在门限内进行测量

 1、测频率——等精度测量法

对待测信号fx计数5000个周期,在此期间gate为高,基准信号f=50MHz,比待测信号都快,对应也产生一个门限使能gate_f0(与gate同电平但对应的时钟上升沿不同),在gate_f0高电平计数基准信号,得到的数值通过计数就是频率。

2、占空比

同样在gate为高,在待测信号高电平时计数,与测频率时的数字做比得到占空比

问题在于fpga没有小数,我输出的比值是小数点后移一位的,单片机显示再做除10

另一种方法:

倍频50MHz时钟,对待测时钟测两个周期高电平时候的计数

原因:测5000个周期会有5000次跳变,容易产生误差,测两个周期可能少些误差

 3、时间间隔

输入两路信号clk1,clk2,二分频后异或,产生clk3,测占空比

目前代码输出的结果是clk3的占空比,没有转换成时间

二、代码

1、测频率

输入:CLK,基准时钟;

clk_in:待测时钟;

clr:清零;

输出:

gate_f0:基准时钟的gate;

gate_f0_down:基准时钟的gate下降沿标志

fx:待测信号的频率;

cnt_CLK:基准时钟的计数值;

module freq_cnt(
	input CLK,
	input clk_in,
	input clr,
	output reg gate_f0,
	output wire gate_f0_down,
	output wire [wid32-1:0] fx,
	output reg [wid32-1:0] cnt_CLK);
	//output reg [N-1:0] N3
parameter CNTVAL_x=5000;
parameter wid16=16;
parameter wid32=32;
parameter wid64=64;

reg [64-1:0]cnt_fx;
reg gate,gate_fx_d0,gate_fx_d1;   wire gate_fx_down;  
reg gate_temp;
reg gate_f0_d0,gate_f0_d1;  //wire gate_f0_down;
reg [wid16-1:0]cnt;
reg [wid32-1:0] cnt_f0;
counter of clock for test 
always @(posedge clk_in or negedge clr) begin
	if(!clr)
		cnt<=0;
    else if(cnt >= CNTVAL_x + 5'd20)
        cnt <= 0;
    else
        cnt <= cnt + 1'b1;
end
///clock's gate for test	  
always @(posedge clk_in or negedge clr) begin
	if(!clr)
		gate<=0;
	else if(cnt<=4'd10)
		gate<=0;
	else if(cnt<=CNTVAL_x+4'd10)
		gate<=1;
	else if(cnt<CNTVAL_x+5'd20)
		gate<=0;
	else
		gate<=0;
	
	if(!clr)begin
		gate_fx_d1<=0;
		gate_fx_d0<=0;
		end
	else begin
		gate_fx_d0<=gate;
		gate_fx_d1<=gate_fx_d0;
		end
	
end
assign gate_fx_down = gate_fx_d1 & (~gate_fx_d0);
//50Mclock's gate
always @(posedge CLK or negedge clr) begin
	if(!clr)begin
		gate_temp<=0;
		gate_f0<=0;
		end
	else begin
		gate_temp<=gate;
		gate_f0<=gate_temp;
		end
		
	if(!clr)begin
		gate_f0_d1<=0;
		gate_f0_d0<=0;
		end
	else begin
		gate_f0_d0<=gate_f0;
		gate_f0_d1<=gate_f0_d0;
		end
end

assign gate_f0_down = gate_f0_d1 & (~gate_f0_d0);
assign fx=cnt_fx;
always @ (posedge CLK or negedge clr) begin
	if(!clr)begin
		cnt_CLK<=0;
		cnt_f0<=0;
		cnt_fx<=0;
	end
	else if(gate_f0_down) begin
		cnt_f0<=0;
		cnt_CLK<=cnt_f0;
		cnt_fx<=(CNTVAL_x*50000000)/cnt_f0;
		end
	else if(gate_f0)
		cnt_f0<=cnt_f0+1'b1;
end

endmodule 

第一个always:对待测时钟计数5000,因为延时问题,多出20便于产生gate;

第二个always:产生待测时钟的gate和下降沿标志gate_down,因为延时,gate在非清零,10~5000+10内是高电平;

第三个always:产生基准时钟的gate和gate_down,注意:两个always使用的时钟沿不同

第四个always:对基准时钟计数,并且计算频率。注意:因为5000*50M数字过大,中间使用了一个64bit的cnt_fx,时序电路赋值给32bit的fx

2、占空比

输入:gate、gate_down来控制占空比数字的计算和输出;

cnt_CLK:5000待测信号对应的基准时钟周期数;

输出

pwm:10倍占空比

module pwm_in(
	input CLK	,
	input clk_in,
	input clr, 
	input gate,
	input gate_down,
	input [31:0]cnt_CLK,
	output reg [wid32-1:0]pwm);

parameter wid32=32;
reg [wid32-1:0]cnt_clk_in;
reg [wid32-1:0]cnt_clk_in_high;
reg [63:0]pwm_temp;

always @(posedge CLK or negedge clr) begin
	if(!clr)begin
		cnt_clk_in<=0;
		cnt_clk_in_high<=0;
		pwm<=0;
		end
	else if(gate_down) begin
		cnt_clk_in_high<=cnt_clk_in;
		cnt_clk_in<=0;
		pwm_temp<=((cnt_clk_in_high*10000)/cnt_CLK)/10;
		pwm<=pwm_temp[15:0];
		end
	else if(gate & clk_in)
		cnt_clk_in <=cnt_clk_in+1'b1;
end

endmodule

always中要使用基准时钟,所以使用的gate是来自基准时钟产生的,对应的时钟沿不同、高电平时间长度不同

3、时间间隔

输出pwm_clk3:异或之后clk3的占空比

module interval_2(
	input CLK,
	input clk1,
	input clk2,
	input clr,
	input gate,
	input gate_down,
	input [31:0]cnt_CLK,
	output wire [31:0] pwm_clk3);

wire   r_clk1,r_clk2;
wire clk3;

freq_div_2 freq1(
	.clk	(clk1),
    .rst_n	(clr),
    .clk_div(r_clk1));
freq_div_2 freq2(
	.clk	(clk2),
    .rst_n	(clr),
    .clk_div(r_clk2));
assign clk3 = (r_clk1) ^ (r_clk2);
//assign clk3 =clk1 ^clk2;

pwm_in pwm_in(
	.CLK	(CLK),
	.clk_in	(clk3),
	.cnt_CLK	(cnt_CLK),
	.clr	(clr), 
	.gate	(gate),
	.gate_down(gate_down),
	.pwm	(pwm));
assign pwm_clk3=pwm*2;
endmodule

先分别对clk1和clk2二分频,异或产生clk3,使用占空比测量模块,输出clk3的占空比,时间间隔对应的数字需要×2

三、signaltap波形

暂时用这个完成5kHz以上的测频率,5kHz以下使用另外的方法测,以免需要太大的时间

 

--------------------------------------分割线--------------------------------------

博客是写低频之前写的,后面写完低频,可以完成1Hz的检测,但是时间要略慢一些。

对低频信号的测量

思路:之前的测量无法测低频信号的原因是对低频信号计数5000个时间过长,计数后对基准时钟的计数值过大,使用64位二进制数有些浪费。通过同样的测量方法,对低频信号测8个周期对应的基准时钟计数值计算得到频率。

重新写了一个模块,使用了两个子模块,先算8个周期,测的频率高于5000就使用5000个周期得出的数据,低于5000,就直接输出这个频率

freq_cnt freq_cnt_H(
	.CLK		(CLK),
	.clk_in		(clk_in),
	.clr		(clr),
	.gate_f0	(gate_H),
	.gate_f0_down(gate_down_H),
	.fx	(fx_H),
	.cnt_CLK	(cnt_CLK_H));
	
defparam freq_cnt_L.CNTVAL_x=8;	
freq_cnt freq_cnt_L(
	.CLK		(CLK),
	.clk_in		(clk_in),
	.clr		(clr),
	.gate_f0	(gate_L),
	.gate_f0_down(gate_down_L),
	.fx	(fx_L),
	.cnt_CLK	(cnt_CLK_L));	

always @(posedge CLK or negedge clr)begin
	if(!clr)
		fx<=0;
	else if(fx_L>5000)begin
		fx<=fx_H;
		gate<=gate_H;
		gate_down<=gate_down_H;
		cnt_CLK<=cnt_CLK_H;
		end
	else begin
		fx<=fx_L;
		gate<=gate_L;
		gate_down<=gate_down_L;
		cnt_CLK<=cnt_CLK_L;
		end
end
endmodule	

以下测了1Hz,12Hz,123Hz,1234Hz 

两路波形是从信号发生器同相位输出,且因为周期比较长,略有时间差在周期内的占比也很低。

--------------------------------------分割线--------------------------------------

加了spi模块后完成了与单片机的通信

一、顶层设计

图一主要是频率计的部分

 图二是spi通信部分的连接

 RTL视图

 二、spi通信总结

单片机输入有四个:sclk,cs,sdin,sdout

sdin是单片机串行输入,spi_bus_32b_A15RD1WR0模块移位成32位并行输出,低16位是数据,高16位是地址,在单片机读时,地址指向不同的功能,例如WE[7]是select_in_to_out模块的选择使能,单片机输入高16位0x00,0x07表示单片机要读取数据;
select_in_to_out模块的输入有待测信号频率的高16,低16,占空比的高16位,低16位,两路间隔时间的占空比高16位,低16位,,单片机输入的低16位进行选择,例如:0x00,0x00表示频率的高16位从FPGA输出到单片机。

FPGA输出是串行从sdout输出。

 

 

 

 

  • 6
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值