[FPGA]数字等精度频率计设计II

[FPGA]数字等精度频率计设计II[门控信号长度自适应(对上一个的优化)]

理论分析

改进目标

提高低频时的测量速度。

改进方案

上一篇文章的第二种方案。

约定一个门控信号长度上限,比如1s。

在输出门控信号时进行clk计时,如果超过1s,则在下一个待测信号上升沿提前结束门控信号。

得到门控信号后对待测信号和clk同时计数,计数结果送入计算模块计算。

程序设计

模块设计

如果把计数和计算模块放在一起的话,则这个模块代码会比较多,略显臃肿。

如果分开,只需要写一个计数模块如何实例化两次即可,但是需要考虑模块间的时序问题。

各有利弊,不过都是小问题。此处选择的是分开的设计。

请添加图片描述

右侧设置的所有端口均为采集信号时方便。

代码实现

Gate模块

本设计改进主要在Gate模块门控信号的生成上。

在门控信号生成的同时使用GATE_CLK_CNT计时,当计时时间超过额定时间时在下一个待测信号上升沿结束门控信号。此处使用的结束方法是改变门控信号计数器,调整计数器值到quantity + 2’b10,则在下一个待测信号上升沿处计数值为0,再下一个待测信号上升沿处门控信号结束。

GATE_CLK_CNT计时并不是严格记录门控信号的长度,而是从门控信号下降沿检测信号NEG_GATE结束后开始计时,即计的是两个NEG_GATE信号之间的时间,大概是整个门控信号生成周期减去一个待测信号周期。这样同时也可以起到对门控信号长度进行监测和截断的作用。

注意写代码的时候一个reg只在一个always中更改,即第一个只计GATE_CLK_CNT,第二个计时并根据GATE_CLK_CNT对GATE_CNT和NEG_GATE进行更新,第三个always生成门控信号。这样更加清晰明确。

Gate
module Gate( CLK , SIGNAL , RST , GATE , NEG_GATE );
input	CLK;
input	SIGNAL;
input	RST;
output	GATE;
output	NEG_GATE;		// the negedge of gate


parameter	quantity = 16'b0001_0011_1000_1000;						// 5000
//parameter	time_length = 28'b0001_0111_1101_0111_1000_0011_1110;	// 0.5 seconds -1 , 24_999_999 clks

reg		GATE;
reg		NEG_GATE;//_fx;
reg		[16-1:0]	GATE_CNT;

reg		[28-1:0]	GATE_CLK_CNT;		// make sure that Gate wont last longer than 1s

//GATE_CLK_CNT//
always @ ( posedge CLK or negedge RST ) begin
	if (!RST)
		GATE_CLK_CNT <= 28'b0;
	else if ( NEG_GATE )
		GATE_CLK_CNT <= 28'b0;
	else
		GATE_CLK_CNT <= GATE_CLK_CNT + 1'b1;
end

//GATE_CNT & NEG_GATE//
always @ ( posedge SIGNAL or negedge RST ) begin
	if (!RST) begin
		GATE_CNT <= 16'b0;
		NEG_GATE <= 1'b0;
	end
	else if (GATE_CNT == 16'b0) begin
		GATE_CNT <= GATE_CNT + 1'b1;
		NEG_GATE <= 1'b1;
	end
	else if (GATE_CNT == quantity + 2'b10) begin
		GATE_CNT <= 16'b0;
		NEG_GATE <= 1'b0;
	end
//	else if(GATE_CLK_CNT >= time_length) begin								// fku parameter
	else if(GATE_CLK_CNT >= 28'b0001_0111_1101_0111_1000_0011_1110) begin
		if (GATE_CNT >= 1'b1) begin
			GATE_CNT <= quantity + 2'b10;
			NEG_GATE <= 1'b0;
		end
	end
	else begin
		GATE_CNT <= GATE_CNT + 1'b1;
		NEG_GATE <= 1'b0;
	end
end

//GATE//
always @ ( posedge SIGNAL or negedge RST ) begin
	if (!RST)
		GATE <= 1'b0;
	else if (GATE_CNT <= 2'b10)					// for the gap of adjacent gates
		GATE <= 1'b0;
	else if (GATE_CNT <= quantity + 2'b10)
		GATE <= 1'b1;
	else
		GATE <= 1'b0;
end

endmodule 

这个模块第三个always的第三个else if处有一句注释。其实一个设计我在三天前就已经完成了,这个优化我在两天前也就已经做完了设计和代码编写,但在测试的时候这句else if一直不起作用。我两天内换了几种逻辑设计,将GATE_CLK_CNT的判断放在GATE处或是更改time_length的值,但都没用。直到我在测试时为了方便修改,将time_length换成了具体的数值,他就可以了!parameter的这个time_length真tm是惊天大内鬼。我换了几个参数值,只要将具体数值放进if里来就可以正常工作,放time_length这个名字就完犊子了,我改了两天就揪出这么个内鬼,也没搞明白为什么。在网上查资料也没有找到任何关于parameter对参数设置的要求,如有高见还望不吝赐教。

Counter模块

Counter模块在上一次写好了,不需要怎么修改。

Counter
module Counter( SIGNAL , RST , GATE , NEG_GATE , CNT_READY , SIGNAL_CNT );
input	SIGNAL;
input	RST;
input	GATE;
input	NEG_GATE;
output	CNT_READY;
output	[32-1:0]	SIGNAL_CNT;

reg		CNT_READY;
reg		[32-1:0]	SIGNAL_CNT;
reg 	[32-1:0]	SIGNAL_CNT_temp;

always @ ( posedge SIGNAL or negedge RST ) begin
	if (!RST) begin
		SIGNAL_CNT_temp <= 32'b0;
		SIGNAL_CNT <= 32'b0;
		CNT_READY <= 1'b0;
	end
	else if (GATE) begin							// when gate , count
		SIGNAL_CNT_temp <= SIGNAL_CNT_temp + 1'b1;
		CNT_READY <= 1'b0;
	end
	else if (NEG_GATE) begin						// when gate end , count end
		if (SIGNAL_CNT_temp)
			SIGNAL_CNT <= SIGNAL_CNT_temp;			// until next count end , the ans will stay on bus for read
		SIGNAL_CNT_temp  <= 32'b0;
		CNT_READY <= 1'b1;
	end
end

endmodule 
Calculation模块
Calculation
module Calculation( EN1 , EN2 , RST , CNT_fx , CNT_f0 , ANS );
input	EN1;
input	EN2;
input	RST;
input	[32-1:0]	CNT_fx;
input	[32-1:0]	CNT_f0;
output	[40-1:0]	ANS;

localparam			CLK_fs = 26'b0010_1111_1010_1111_0000_1000_0000;
reg		[40-1:0]	ANS;

always @ ( posedge EN1 or posedge EN2 or negedge RST ) begin
	if (!RST)
		ANS <= 32'b0;
	else if (EN1)
		if (EN2) begin
			ANS <=  CLK_fs * CNT_fx / CNT_f0 ;
		end
end

endmodule 

对于Counter模块和Calculation模块之间的时序问题要注意。

因为两个Counter模块是对不同的信号进行计数,待测信号周期较长而基准时钟周期较短,所以基准时钟先输出计数结果,待测信号后输出计数结果。要等到两个计数结果都输出,Calculation再去接收计数值并计算结果。同时也就需要Counter模块对输出结果进行保持。有两种保持方法。第一种简单,SIGNAL_CNT_temp非零时赋值给SIGNAL_CNT。如果不使用这个非零赋值,观察Counter模块的输出时序可知,基准时钟的计数模块需要一个长度为基准时钟周期的NEG_GATE信号。这个信号的生成我最少需要写两个always,所以采用了第一种方法。感兴趣可以自己尝试。

测试验证

请添加图片描述
请添加图片描述
请添加图片描述

请添加图片描述

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

测量精度基本没有问题。并且可以观察到,低频时的门控信号对应的待测信号周期数也自适应地减少,从而降低了低频时的测量时间。

低频测量时间如下(手计):

频率/Hz测量时间/s
18
26.5
33.3
42.8
5~102.3~2.0

频率再高则基本在2s以内,100Hz以上基本在1s以内。可以测量速度说有了大的提升。

继续改进

问题

较低频的测量速度虽然得到了很大改善,但仍然不是很理想。

改进

  • 试一试上一篇文章的第一个改进方案。
  • 调整GATE的输出时序:

目前的输出时序为:

请添加图片描述

(没错我找不到合适的软件所以这个时序图就是用excel画的XD)

其中前面的空档是为了信号稳定和门控信号之间的区分间隔,而且把间隔都放在前面比较容易写逻辑。XD

可以去掉最前面的档并把门控信号之间的区分间隔放在后面。

改进后的输出时序:

请添加图片描述

但去掉最前面的空档似乎牺牲了最开始一个周期的测量精度。在假设需要3次刷新可以得到精确的数值的,换得的仅仅是1至5Hz时速度快些,超过5Hz时仅仅将信号之间的空格放在后面就可以满足要求了,而且也无法将1至4Hz时的测量时间压缩到1s内,所以好像不太划算。

本设计并没有这么改。因为我按这个时序推了下,1Hz应该需要5s左右时间。但实际上我将时序改成这样后去测试,1Hz的测量时间长达27s,而且在1kHz至50kHz的范围内测量速度也明显降低了。现在还没找到原因,大概我时序写错了。找到原因再改。而且就算能达到理论的5s,5s也是远远不够的,所以下次试一试第一种方案。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于FPGA的等精度频率计是一种高精度的频率测量设备。FPGA是可编程逻辑器件,具有高速并行处理能力和灵活性,可以快速实现频率计算和数字信号处理。 首先,设计基于FPGA的等精度频率计需要选择合适的FPGA芯片。通常选择带有高速时钟与计数器模块的FPGA芯片,以确保频率计的高精度和稳定性。 其次,设计需要包括输入模块和计数模块。输入模块用于接收待测频率信号,可以通过外部引入时钟或者通过输入捕获模块获取输入信号的频率。计数模块用于实现频率计算和测量,可以使用计数器模块进行周期性计数,并通过先进的算法将计数结果转化为频率值。 另外,为了提高频率计精度,可以采取一些技术手段。例如,可以使用PLL(锁相环)技术来生成高稳定度的时钟信号,以提高测量精度。还可以使用差分输入和输出电路来抑制干扰信号,保证测量结果的准确性。 此外,为了方便使用和显示结果,可以设计用户界面模块和显示模块。用户界面模块可以提供操作界面,让用户输入参数、控制测量过程等。显示模块可以用于显示测量结果,可以使用数码管或者液晶显示屏等。 最后,还需要进行系统的验证和测试工作。通过各种测试用例和实际应用场景的验证,可以确保基于FPGA的等精度频率计的性能和稳定性。 总结来说,基于FPGA的等精度频率计设计涉及芯片选择、输入模块、计数模块、PLL 技术、差分电路设计、用户界面设计和系统验证等多个方面,通过合理的设计和实现,可以实现高精度的频率测量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值