1. 实验目的
- 掌握直接数字频率合成(DDS)技术的基本原理和应用。
- 使用DE2-115开发板实现正弦波和方波的生成。
- 使用SignalTap II嵌入式逻辑分析仪测试输出波形的离散数据。
2. 实验原理
- DDS技术:通过相位累加器生成相位信息,结合波形存储器(ROM)输出波形数据。
- 波形存储器:使用ROM存储正弦波和方波的采样数据。
- 频率控制:通过调整相位累加器的步长实现不同频率的输出。
3. 实验步骤
- 生成波形数据:使用C语言或MATLAB生成正弦波和方波的采样数据,并保存为MIF文件。
- 调用ROM IP核:在Quartus中生成ROM IP核,并加载生成的MIF文件。
- 设计DDS模块:实现相位累加器和波形选择逻辑。
- 顶层模块设计:将DDS模块与开发板的时钟、复位、按键等信号连接。
4. 代码实现
4.1 顶层模块代码
module DE2_115_DDS_top(
input CLOCK_50,
input [3:0] KEY,
input [17:0] SW,
output [12:0] GPIO_0,
output [0:0] LEDG
);
wire CLOCK_100;
assign GPIO_0[12] = CLOCK_100;
wire RSTn = KEY[3];
wire [1:0] WaveSel = SW[17:16];
wire [12:0] K = SW[12:0];
wire [11:0] WaveValue;
assign GPIO_0[11:0] = WaveValue;
DDS_top DE2(
.CLOCK_50(CLOCK_50),
.RSTn(RSTn),
.WaveSel(WaveSel),
.K(K),
.WaveValue(WaveValue),
.LEDG(LEDG),
.CLOCK_100(CLOCK_100)
);
endmodule
4.2 DDS核心模块代码
module DDS_top(
input CLOCK_50,
input RSTn,
input [1:0] WaveSel,
input [12:0] K,
output reg [11:0] WaveValue,
output reg [0:0] LEDG,
output CLOCK_100
);
reg [31:0] PhaseAcc;
reg [10:0] ROMAddr;
reg [11:0] SineValue, SquareValue;
// 时钟分频
reg [24:0] ClockDiv;
wire Clock_100;
always @(posedge CLOCK_50 or negedge RSTn) begin
if (!RSTn) begin
ClockDiv <= 0;
end else begin
if (ClockDiv == 10000000) begin
ClockDiv <= 0;
Clock_100 <= ~Clock_100;
end else begin
ClockDiv <= ClockDiv + 1;
end
end
end
// 相位累加器
always @(posedge CLOCK_50 or negedge RSTn) begin
if (!RSTn) begin
PhaseAcc <= 0;
end else begin
PhaseAcc <= PhaseAcc + K;
end
end
// ROM地址生成
assign ROMAddr = PhaseAcc[31:21];
// 波形选择
always @(posedge CLOCK_50 or negedge RSTn) begin
if (!RSTn) begin
SineValue <= 0;
SquareValue <= 0;
WaveValue <= 0;
LEDG <= 0;
end else begin
case (WaveSel)
2'b00: begin
WaveValue <= SineValue;
LEDG <= 1'b0;
end
2'b01: begin
WaveValue <= SquareValue;
LEDG <= 1'b1;
end
default: begin
WaveValue <= 0;
LEDG <= 0;
end
endcase
end
end
// ROM模块
rom_sine rom_sine_inst(
.address(ROMAddr),
.clock(CLOCK_50),
.q(SineValue)
);
rom_square rom_square_inst(
.address(ROMAddr),
.clock(CLOCK_50),
.q(SquareValue)
);
endmodule
4.3 ROM模块代码
// 正弦波ROM
module rom_sine(
input [10:0] address,
input clock,
output reg [11:0] q
);
reg [11:0] mem [0:2047];
initial begin
$readmemb("Sine1024.mif", mem);
end
always @(posedge clock) begin
q <= mem[address];
end
endmodule
// 方波ROM
module rom_square(
input [10:0] address,
input clock,
output reg [11:0] q
);
reg [11:0] mem [0:2047];
initial begin
$readmemb("Square1024.mif", mem);
end
always @(posedge clock) begin
q <= mem[address];
end
endmodule
4.4 波形数据生成代码
// 生成正弦波MIF文件
#include <stdio.h>
#include <math.h>
#define PI 3.141592
#define DEPTH 1024
#define WIDTH 12
int main(void)
{
int n, temp;
float v;
FILE *fp;
fp = fopen("Sine1024.mif", "w+");
if (NULL == fp) {
printf("Can not creat file!\r\n");
return -1;
} else {
printf("File created successfully!\n");
fprintf(fp, "DEPTH=%d;\n", DEPTH);
fprintf(fp, "WIDTH=%d;\n", WIDTH);
fprintf(fp, "ADDRESS_RADIX=HEX;\n");
fprintf(fp, "DATA_RADIX=HEX;\n");
fprintf(fp, "CONTENT\n");
fprintf(fp, "BEGIN\n");
for (n = 0; n < DEPTH; n++) {
v = sin(2 * PI * n / DEPTH);
temp = (int)((v + 1) * 4095 / 2);
fprintf(fp, "%04x : %03x;\n", n, temp);
}
fprintf(fp, "END;\n");
fclose(fp);
}
return 0;
}
5.定制ROM IP核设置
6.查看生成RTL
7.Signal Tap采样分析
8.结果