赞
踩
目录
第二个案例来了!做一个函数信号发生器,实现产生四种波形(正弦波、方波、三角波、反三角),输出频率可变以及幅值可变。
在数字电路中实现函数信号发生器,直接数字式频率合成(DDS)是最常见的方法。DDS的主要模型如下:
由相位累加器、ROM查找表和数模转换器组成,核心为相位累加器和ROM查找表。
对于一段正弦信号来说,其幅度值是非线性的,但是其相位的值却是线性增加的。因此DDS的核心便是通过固定步长产生均匀相位,然后将相位作为地址码去查找该相位的幅度值,从而得到波形。
- module DDS(data,clk,reset);
- output [7:0] data;//幅值数据
- input clk;
- input reset;
- input switch_wave_type;//波形类别
- wire clk_300M;//300M时钟
- reg [23:0] step_length = 24'h00FFFF;//固定的步长
- wire[31:0] addr_Phase;//相位
- wire[8:0] addr;//地址码
-
- Pll(.refclk(clk),.rst(reset),.outclk_0(clk_300M));
- Phase_accumulator(addr_Phase,step_length,clk_300M);
- Rom(.address(addr),.clock(clk_300M),.q(data));
- assign addr={switch_wave_type,addr_Phase[31:24]};//低位相位和高位波形拼接成ROM地址码
- endmodule
- module Phase_accumulator(addr_Phase,step_length,clk);
- output reg[31:0] addr_Phase;
- input[23:0] step_length;
- input clk;
- //循环产生相位
- always@(posedge clk)
- begin
- if(addr_Phase>=32'hff000000)
- addr_Phase<=32'h0;
- else
- addr_Phase<=addr_Phase+step_length;
- end
- endmodule

PLL和ROM都是调用Altera的IP核,有效地减小了工程量,使用PLL,将50M的时钟倍频到300M,从而提高输出波形频率的上限。使用ROM提前存储波形幅值数据。对于PLLIP核的调用在之前有所提及,而ROM IP核的调用则需要提前写好.mif文件,用来初始化ROM。
因此需要注重的是相位累加器的编写。
相位累加器等同于一个计数器,在本次案例中我设置了32bits的计数存储单元Cnt。由于我一个波形采样了256个点,因此地址码需要八位,所以我令高八位作为地址码,低二十四位便是步长的变化范围。相位累加器通过累加步长,使得高八位均匀进位,从而得到均匀的地址码。再通过地址码寻址,输出波形幅值数据,最后经DAC转换得到模拟电压。
特别的是,我在主模块最后有一句assign语句,此语句是八位地址码和波形类型相拼接。原理是我在ROM中连续存储多个波形的幅值,每个波形都是256个点,因此我可以用更高位来区分我在ROM中查询的是哪种波形。
assign addr={switch_wave_type,addr_Phase[31:24]};
在本次案例中,上述代码仅实现了输出波形。为了方便调节步长大小,我选择LCD1602作为显示器,使用状态机编写了LCD1602的驱动模块。此内容今后会单独写成文章。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。