寒假在家练项目3_杜彩卉
本项目是基于FPGAXo21200HC的训练板,制作了一个可以用作可调电压源、频率计、电压表、示波器和任意波形发生器的口袋仪器
标签
嵌入式系统
FPGA
zdw
更新2021-03-07
1059

项目需求:

  • 可调电压源:能够产生直流电压,且电压值可以数控,变化范围从-3V到+3V,由于是原型设计,负载能力支持到20mA即可;
  • 信号发生器:基于DDS的任意波形产生,能够生成频谱分量高达100KHz的任意波形,尤其是3种常用的波形:正弦波、方波、三角波,除了波形可以选择外,频率设置的精度达到1Hz,幅度调节范围为最高5Vpp,且都可数字控制;
  • 电压表/示波器:能够测量直流电压、采集0-10KHz的交流信号,并将采集到的波形进行频谱分析;
  • 频率计的功能:能够测量外部信号的频率

 

项目系统设计及核心代码:

基于需求,本项目通过利用PWM和低通滤波器产生任意幅度的信号,进而实现信号发生器和可调电压源;通过利用PWM和低通滤波器产生任意幅度的信号,再通过比较器将参考信号和外部输入信号进行比较,进而实现电压表和示波器。此外,本项目通过UART和上位机进行通信,并在上位机设计相应的界面来实现人机交互。

项目管脚分配如下图所示,其中,为了节约资源和便于与示波器相连,任意信号发生器模块和直流电压模块均采用23号管脚。

FvybDiBn9kha0n2gzngljkTUPNFE

项目整体的RTL示意图如下图所示:

Fu9uOJ8FrvR44XayDIf4Jr0K1Fh5

项目总体资源占用情况(不包括fft)如下图所示:

FnG7ySeonwnTOL7uFb_rWCgS719c

任意信号发生器模块和直流电压模块均通过改变PWM的占空比并将输出信号通过低通滤波器来输出任意幅值的电压或波形。核心代码如下,其中clk_240为利用PLL输出的高频时钟信号,用于控制任意信号发生器中PWM的输出,以保证PWM信号的输出频率远高于相应电路图中二阶RC低通滤波器的截止频率:

reg signed[5:0]sin1[0:7];
reg signed[5:0]square[0:1];
reg signed[5:0]triangle[0:7];
reg [4:0]count_num;
reg signed [15:0] wave1;
always @(posedge clk_signal or negedge flag) begin
	if(!flag) begin
		 sin1[0] = 0;sin1[1] = 5; sin1[2] = 7;sin1[3] = 5;sin1[4] = 0;sin1[5] = -5; sin1[6] = -7;sin1[7] = -5;
		square[0] = 7;square[1]=-7;
        triangle[0] =  -7;  triangle[1] = -3;triangle[2] = 0;triangle[3] = 3;triangle[4] = 7;triangle[5] = 3;triangle[6] = 0;triangle[7] = -3;
		count_num <= 0;
		duty = 0;
	end
	else begin
        case(type) 
            2'b00: begin 
				if(count_num==7) count_num <= 0;
				if(amplitude==32) wave1[15:5] = sin1[count_num];
				if(amplitude<32&&amplitude>=16) wave1[15:4] = sin1[count_num];
				if(amplitude<16&&amplitude>=8) wave1[15:3] = sin1[count_num];
				if(amplitude==0) wave1 = 0;
				
			end
            2'b01: begin 
				if(count_num==1) count_num <= 0;
				if(amplitude==32) wave1[15:5] = square[count_num];
				if(amplitude<32&&amplitude>=16) wave1[15:4] = square[count_num];
				if(amplitude<16&&amplitude>=8) wave1[15:3] = square[count_num];
				if(amplitude==0) wave1 = 0;
			end
            2'b10: begin 
				if(count_num==7) count_num <= 0;
				if(amplitude==32) wave1[15:5] = triangle[count_num];
				if(amplitude<32&&amplitude>=16) wave1[15:4] = triangle[count_num];
				if(amplitude<16&&amplitude>=8) wave1[15:3] = triangle[count_num];
				if(amplitude==0) wave1 = 0;
			end
        endcase
		count_num <= count_num+1;
		wave1 = wave1+offset+448;
		duty <=wave1[15:4];
    end
end

reg [5:0] count_pwm;
always @(posedge clk_240) begin
	if(!flag) begin
		count_pwm<=0;
		dds<=0;
	end
	else begin
		count_pwm<=count_pwm+1;
		if(count_pwm<=duty) dds<=0;
		else dds<=1;	
	end
end

reg [23:0] count;
always @(posedge clk_in) begin
    if(!flag) begin
        clk_signal<=0;
        count<=0;
    end
    else begin
        count<=count+1;
		if(count==freq) begin
			count<=0;
			clk_signal<=1;
		end
		else clk_signal<=0;
    end
end

电压表和示波器模块也通过PWM和低通滤波器输出任意幅度的信号,并将输出值输入比较器作为参考信号。通过比较器,将参考信号和外部输入信号进行比较,并通过比较器的输出判断参考信号和外部输入信号的大小关系,进而实现任意电压值的测量和电压波形的显示。核心代码如下:

reg [5:0] duty;
always @(posedge clk_measure or negedge flag ) begin
    if(!flag) begin
		duty<=1;
		data1=0;
    end
    else begin
		if(current_state == 0) begin 
			data1 = duty;
			duty<=duty-1;
		end 
		else begin duty<=duty+1;end
    end
end

reg [5:0] count_pwm;
always@(posedge clk_240) begin
    if(!flag) begin
        pwm1<=1;
        count_pwm<=0;
    end
    else begin
        count_pwm<=count_pwm+1;
        if(count_pwm <= duty) pwm1 <= 1;
        else pwm1 <= 0;
    end
end

和上述两个模块相似,频率计模块主要利用的也是PWM,通过PWM和低通滤波器产生指定幅度的信号,再通过比较器的输出判断输入信号与该参考信号的大小关系。由于外部输入信号为正弦波、方波或三角波,在信号的一个周期内,比较器的输出相应的会发生一次切换。因此,可通过判断一定时间内,比较器输出的切换次数即可得到输出信号的频率。具体核心代码如下:

reg compare_out_r;
always @ (posedge clk_in) begin
	if(!flag) compare_out_r <= 1'b0;
	else compare_out_r <= compare_out;
end
wire	neg_compare_out_en = compare_out_r & (~compare_out);
 

reg [7:0] freq_count;
reg [29:0] count_clk;
reg count_clk1;
always @(posedge clk_in or negedge flag) begin
    if(!flag) begin
        freq_count<=0;
		count_clk<=0;
		count_clk1<=0;
		tx_data<=0;
    end
    else begin
		count_clk<=count_clk+1;
		if(count_clk==30'd119_999) begin
			count_clk1<=1;
			count_clk<=0;
		end
		if(neg_compare_out_en) begin
			freq_count<=freq_count+1;
		end
		if(count_clk1&&freq_count!=0) begin
			tx_data<=freq_count;
			count_clk1<=0;
			freq_count<=0;
		end
	end
end

UART通信模块用于实现人机交互,代码参考电子森林网站上的例程,网址:

https://www.eetree.cn/wiki/uart%E4%B8%B2%E5%8F%A3%E6%A8%A1%E5%9D%97

项目的功能:

实现了直流电压、任意波形发生器、电压表、示波器和频率计,但未能够实现信号的频谱分析。

遇到的问题:

  • 由于假期内仅有一个比较器,设备有限,无法确保任意波形发生器中输出波形,误以为比较器产生了损坏,且无法得到符合要求的波形图

解决方案:在回校后,通过示波器查看实际发出信号的波形后,提高PWM信号的频率。并利用Lattice Diamond 中针对PLL的IP核实现时钟的倍频,进一步提升PWM信号的频率。

  • 由于对Lattice Diamond 中针对FFT的IP核的了解有限,未能实现针对信号波形的FFT

解决方案:未解决

  • 由于FPGA的资源有限,无法成功实现乘法器或除法器

解决方案:通过移位实现乘法或除法,从而大幅度降低FPGA的运算量

 

附件下载
final_impl1.jed
团队介绍
北京理工大学信息与电子学院
团队成员
杜彩卉
来自北京理工大学信息与电子学院的大四学生
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号