一、调用步骤
1、打开Quartus
右上角搜索ROM,如图所示
2、点击后会弹出如图所示
其中文件路径需要选择你自己的
3、点击OK弹出如图所示
图中红色改为12与1024
4、然后一直点NEXT,直到下图
这里要选择后缀为 .mif的文件
5、用C语言生成 .mif文件
c
// 生成1024点正弦波表(C程序)
#include <stdio.h>
#include <math.h>
#define PI 3.14159265358979323846
#define DEPTH 1024 // ROM深度
#define WIDTH 12 // 数据宽度(12位)
int main() {
FILE *fp = fopen("sine_rom.mif", "w");
if (!fp) return -1;
fprintf(fp, "WIDTH=%d;\nDEPTH=%d;\nADDRESS_RADIX=HEX;\nDATA_RADIX=HEX;\nCONTENT BEGIN\n", WIDTH, DEPTH);
for (int i = 0; i < DEPTH; i++) {
float phase = (float)i / DEPTH * 2 * PI;
short value = (short)(sin(phase) * (pow(2, WIDTH-1) - 1));
fprintf(fp, "%03x : %03x;\n", i, value & 0xFFF);
}
fprintf(fp, "END;\n");
fclose(fp);
return 0;
}
然后运行.c文件,会在文件所在目录下生成一个.mif文件,然后你就在第4步中选择它就行。
然后一直next,直到finish
二 、核心模块
1、相位累加器
bash
module phase_accumulator (
input wire clk, // 50MHz系统时钟
input wire [23:0] K, // 频率控制字(24位)
output reg [23:0] phase // 相位累加值
);
always @(posedge clk) begin
phase <= phase + K; // 相位累加
end
endmodule
2、波形选择器
bash
module waveform_selector (
input wire [23:0] phase, // 相位地址(24位)
input wire sel, // 波形选择(0:正弦,1:方波)
output reg [11:0] data_out
);
reg [11:0] sine_data; // 正弦波数据
reg [11:0] square_data; // 方波数据
// 正弦ROM
reg [11:0] sine_rom [0:1023];
initial begin
$readmemh("sine_rom.mif", sine_rom);
end
assign sine_data = sine_rom[phase[22:12]]; // 取中间12位地址
// 方波ROM
reg [11:0] square_rom [0:1023];
initial begin
$readmemh("square_rom.mif", square_rom);
end
assign square_data = square_rom[phase[22:12]];
always @(*) begin
if (sel) data_out = square_data;
else data_out = sine_data;
end
endmodule
3、时钟分频器
bash
module clock_divider (
input wire clk_in, // 50MHz输入时钟
output reg clk_out // 分频后的时钟(10MHz)
);
reg [1:0] cnt;
always @(posedge clk_in) begin
cnt <= cnt + 1;
if (cnt == 2'b11) // 分频系数为4(50MHz → 12.5MHz),或调整为5(10MHz)
clk_out <= ~clk_out;
end
endmodule
4、顶层模块
bash
module dds_top (
input wire clk_50m, // 系统时钟(50MHz)
input wire [23:0] K, // 频率控制字(来自拨码开关)
input wire sel, // 波形选择(按钮控制)
output reg [11:0] dac_data // DAC数据输出
);
wire [23:0] phase; // 相位累加值
wire clk_out; // 分频后的时钟
// 相位累加器
phase_accumulator phase_acc (
.clk(clk_50m),
.K(K),
.phase(phase)
);
// 波形选择器
waveform_selector wave_sel (
.phase(phase),
.sel(sel),
.data_out(dac_data)
);
// 时钟分频(可选,用于DAC时钟)
clock_divider clk_div (
.clk_in(clk_50m),
.clk_out(clk_out) // 连接到DAC时钟输入
);
endmodule
5、波形图
参考博客https://blog.csdn.net/weixin_50722839/article/details/109960391