基于FPGA的高精度频率计

链接:https://pan.baidu.com/s/1AjCw2kyBkggQ5doQ2vNWkg
提取码:1234

一、 设计要求
利用FPGA设计一个信号测频器,要求:
(1)测量脉冲信号;
(2)频率测量1-10MHz以及占空比10%-99% 精确到1%;
(3)将测出频率和占空比显示在LCD1602上;

二、 设计方案
FPGA设计主要分为三个大模块来设计:1.被测信号产生模块;2.被测信号检测模块;3.数字显示模块。设计框图如图 1所示。

图 1 基于FPGA的信号测频器设计框图

  1. 被测信号产生模块
    该模块主要是用来产生被测信号,可以在模块中设置被测信号的频率和占空比。采用的方法是对系统时钟进行计数分频产生被测信号。这部分也采用了一个PLL,输出一个100MHz的时钟作为检测模块的采样时钟。该部分涉及的模块:signal_gen模块和PLL模块。

  2. 被测信号检测模块
    该模块对被测信号进行检测的方法是等精度测频法:
    (1)被测信号频率检测
    检测被测信号的频率,通过在外部使能信号有效时(即一段时间内),计数系统时钟脉冲数Ns与被测信号脉冲数Nd,若系统时钟频率为Fs,被测信号频率为Fd,则有Fs/Ns=Fd/Nd 最后有Fd=(Fs/Ns)·Nd。
    (2)被测信号占空比检测:
    检测被测信号的占空比,利用系统时钟,在外部使能信号有效时(即一段时间内),计数被测信号的正脉宽数Np和负脉宽数Nn,则占空比ducy=Np/(Np+Nn)*100%。
    该部分涉及的模块:signal_detect模块。

  3. 数字显示模块
    该模块主要分为两个部分:一个部分是把检测的频率码转换为十进制BCD码,采用这种方法虽然会提高运算时间,但却可以大大节省FPGA的资源(面积与速度的折衷);另外一个部分是驱动LCD1602进行显示。这里给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例): 1.将二进制码左移一位(或者乘2);2.找到左移后的码所对应的个,十,百位;3.判断在个位,十位和百位的码是否大于等于5;4.继续重复以上三步直到移位8次后停止;5.如果是则该段码加3。该部分涉及的模块:BCD2to10模块和lcd1602模块。

最终在FPGA的RTL视图如图 2所示:
在这里插入图片描述

//synopsys translate_off
`timescale 1 ns/ 1 ps
//synopsys translate_on
module BCD2to10(
	clk_100M,
	rst_n,
	d_clk_freq,
	qw,
	bw,
	sw,
	w,
	q,
	b,
	s,
	g);
	
	input 			clk_100M;											// 采样时钟 100MHz
	input 			rst_n;												// 复位信号
	input  [31:0] 	d_clk_freq;											// 被测信号频率
	output [3:0] 	qw;													// 转换提取千万位
	output [3:0] 	bw;													// 转换提取百万位
	output [3:0] 	sw;													// 转换提取十万位
	output [3:0] 	w;													// 转换提取万位
	output [3:0] 	q;													// 转换提取千位
	output [3:0] 	b;													// 转换提取百位
	output [3:0] 	s;													// 转换提取十位
	output [3:0] 	g;													// 转换提取个位
	
	parameter ST0 = 2'b00;
	parameter ST1 = 2'b01;
	parameter ST2 = 2'b10;
	
	//-------------------------------------------------------------------
	// 首先给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例)
	// 1.将二进制码左移一位(或者乘2)
	// 2.找到左移后的码所对应的个,十,百位。?
	// 3.判断在个位,十位和百位的码是否大于等于5
	// 4.继续重复以上三步直到移位8次后停止。
	// 5,如果是则该段码加3。
	//-----------------------------------------------------------------
	
	reg [31:0]  d_clk_shift_reg;
	reg [5:0]	shift_count;
	reg			shift_done;
	reg [31:0] 	bcd_reg;
	reg [3:0] 	qw;
	reg [3:0] 	bw;
	reg [3:0] 	sw;
	reg [3:0] 	w;
	reg [3:0] 	q;
	reg [3:0] 	b;
	reg [3:0] 	s;
	reg [3:0] 	g;
	reg [1:0]	state;
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			d_clk_shift_reg <= #1 32'b0;
		else
		begin
			if(shift_done == 1'b1)
				d_clk_shift_reg <= #1 32'b0;
			else
				d_clk_shift_reg <= #1 d_clk_freq << shift_count;	
		end
	end
		
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			shift_done <= #1 1'b0;
		else
		begin
			if(shift_count == 6'd32)
				shift_done <= #1 1'b1;
			else
				shift_done <= #1 1'b0;
		end
	end

	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
		begin
			bcd_reg <= #1 32'b0;
			shift_count <= #1 6'b0;
			state <= #1 ST0;
		end
		else
		begin
		
			if(shift_done == 1'b0)
			begin
				case(state)
				ST0:begin
						bcd_reg <= #1 {bcd_reg[31:1],d_clk_shift_reg[31]}; //移位
						state <= #1 ST1;
					end
				ST1:begin	
						if(bcd_reg[31:28] >= 4'd5)   					// qw
							bcd_reg[31:28] <=#1 bcd_reg[31:28] + 4'd3;
						else
							bcd_reg[31:28] <=#1 bcd_reg[31:28];
							
						if(bcd_reg[27:24] >= 4'd5)						// bw
							bcd_reg[27:24] <=#1 bcd_reg[27:24] + 4'd3;
						else
							bcd_reg[27:24] <=#1 bcd_reg[27:24];
						
						if(bcd_reg[23:20] >= 4'd5)						// sw
							bcd_reg[23:20] <=#1 bcd_reg[23:20] + 4'd3;
						else
							bcd_reg[23:20] <=#1 bcd_reg[23:20];
							
						if(bcd_reg[19:16] >= 4'd5)						// w
							bcd_reg[19:16] <=#1 bcd_reg[19:16] + 4'd3;
						else
							bcd_reg[19:16] <=#1 bcd_reg[19:16];	
						
						if(bcd_reg[15:12] >= 4'd5)						// q
							bcd_reg[15:12] <=#1 bcd_reg[15:12] + 4'd3;
						else
							bcd_reg[15:12] <=#1 bcd_reg[15:12];	
						
						if(bcd_reg[11:8] >= 4'd5)						// b
							bcd_reg[11:8] <=#1 bcd_reg[11:8] + 4'd3;
						else
							bcd_reg[11:8] <=#1 bcd_reg[11:8];	
							
						if(bcd_reg[7:4] >= 4'd5)						// s
							bcd_reg[7:4] <=#1 bcd_reg[7:4] + 4'd3;
						else
							bcd_reg[7:4] <=#1 bcd_reg[7:4];	

						if(bcd_reg[3:0] >= 4'd5)						// g
							bcd_reg[3:0] <=#1 bcd_reg[3:0] + 4'd3;
						else
							bcd_reg[3:0] <=#1 bcd_reg[3:0];			
						state <= #1 ST2;							
						end
				ST2:begin
						bcd_reg <= #1 bcd_reg << 1'b1; 					//移位
						shift_count <= #1 shift_count + 1'b1;
						state <= #1 ST0;
					end
				
				default:bcd_reg <= #1 bcd_reg;
				endcase
			end
				
			else
			begin
				state <= #1 ST0;
				bcd_reg <= #1 32'b0;
				shift_count <= #1 6'b0;
			end	
		end
	end
	
	reg [31:0] bcd_reg2;
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			bcd_reg2 <= #1 32'b0;
		else
		begin
			if(shift_count == 6'd32)
				bcd_reg2 <= #1 bcd_reg;
			else
				bcd_reg2 <= #1 bcd_reg2;
		end
	end
	
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			qw <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				qw <= #1 bcd_reg2[31:28];
			else
				qw <= #1 qw; 
		end
	end
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			bw <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				bw <= #1 bcd_reg2[27:24];
			else
				bw <= #1 bw; 
		end
	end
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			sw <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				sw <= #1 bcd_reg2[23:20];
			else
				sw <= #1 sw; 
		end
	end
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			w <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				w <= #1 bcd_reg2[19:16];
			else
				w <= #1 w; 
		end
	end
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			q <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				q <= #1 bcd_reg2[15:12];
			else
				q <= #1 q; 
		end
	end
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			b <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				b <= #1 bcd_reg2[11:8];
			else
				b <= #1 b; 
		end
	end
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			s <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				s <= #1 bcd_reg2[7:4];
			else
				s <= #1 s; 
		end
	end
	
	always@(posedge clk_100M or negedge rst_n)
	begin
		if(rst_n == 1'b0)
			g <= #1 4'b0;
		else
		begin
			if(shift_done == 1'b1)
				g <= #1 bcd_reg2[3:0];
			else
				g <= #1 g; 
		end
	end
	
endmodule
  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于FPGA的等精度频率计是一种高精度的频率测量设备。FPGA是可编程逻辑器件,具有高速并行处理能力和灵活性,可以快速实现频率计算和数字信号处理。 首先,设计基于FPGA的等精度频率计需要选择合适的FPGA芯片。通常选择带有高速时钟与计数器模块FPGA芯片,以确保频率计高精度和稳定性。 其次,设计需要包括输入模块和计数模块。输入模块用于接收待测频率信号,可以通过外部引入时钟或者通过输入捕获模块获取输入信号的频率。计数模块用于实现频率计算和测量,可以使用计数器模块进行周期性计数,并通过先进的算法将计数结果转化为频率值。 另外,为了提高频率计精度,可以采取一些技术手段。例如,可以使用PLL(锁相环)技术来生成高稳定度的时钟信号,以提高测量精度。还可以使用差分输入和输出电路来抑制干扰信号,保证测量结果的准确性。 此外,为了方便使用和显示结果,可以设计用户界面模块和显示模块。用户界面模块可以提供操作界面,让用户输入参数、控制测量过程等。显示模块可以用于显示测量结果,可以使用数码管或者液晶显示屏等。 最后,还需要进行系统的验证和测试工作。通过各种测试用例和实际应用场景的验证,可以确保基于FPGA的等精度频率计的性能和稳定性。 总结来说,基于FPGA的等精度频率计设计涉及芯片选择、输入模块、计数模块、PLL 技术、差分电路设计、用户界面设计和系统验证等多个方面,通过合理的设计和实现,可以实现高精度的频率测量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值