DDS直接数字合成3 - 相位累加器

嵌入式系统 时间:2024-01-16来源:EEPW编译

DDS的第二个技巧是长相位累加器。 它允许来自DDS输出的信号频率非常灵活。

我们将通过一个示例了解它是如何工作的。 让我们从这个简单的代码开始。

reg [10:0] cnt;   // 11bit counter
always @(posedge clk) cnt <= cnt + 11'h1;

sine_lookup my_sine(.clk(clk), .addr(cnt), .value(sine_lookup_output));

计数器实际上是一个“相位累加器”。 那是因为它每次递增,它都会将正弦波移动 360°/2048=0.175°

因此,让我们将计数器重命名为更好的名称。

reg [10:0] phase_acc;   // 11bit
always @(posedge clk) phase_acc <= phase_acc + 11'h1;

sine_lookup my_sine(.clk(clk), .addr(phase_acc), .value(sine_lookup_output));

现在,如果我们想将正弦输出的频率提高一倍,我们将相位累加器增加 2 而不是 1。

always @(posedge clk) phase_acc <= phase_acc + 11'h2;

但是,如果我们想将频率减半呢?我们运气不好,因为我们不能将相位累加器增加 0.5(Verilog 仅支持整数)。 我们需要的是相位累加器的更高分辨率。

让我们看看如何通过向相位累加器添加更多位来完成它,但现在以提供与 11 位相位累加器相同的输出的方式完成。

reg [14:0] phase_acc;   // 4 more bits, for a total of 15 bits
always @(posedge clk) phase_acc <= phase_acc + 15'd16;   // increment by 16 instead of 1

sine_lookup my_sine(.clk(clk), .addr(phase_acc[14:4]), .value(sine_lookup_output));   // shifted lookup address

由于我们将计数器递增 16 并在查找地址中使用 phase_acc[14:4],因此我们没有更改输出。 但是多四个位为我们提供了一个具有更好分辨率的相位累加器。 现在,我们当然可以将输出频率减半(通过将相位累加器增加 8 而不是 16)。

将相位累加器分辨率提高 16 后,我们可以以 1/16 步长获得原始正弦频率的任意倍数。 我们当然可以在相位累加器上增加四个以上的位。 典型的DDS实现使用非常长的位相位累加器,以在可用的输出频率中具有极高的精度和分辨率。

例如,使用32位相位累加器和100MHz时钟,输出的频率分辨率为0.023Hz!
这是一个 32 位相位累加器,用于从 440MHz 时钟生成 100Hz 信号。

reg [31:0] phase_acc;   // 32bit phase accumulator
always @(posedge clk) phase_acc <= phase_acc + 18898;   // 440Hz output when clocked at 100MHz

sine_lookup my_sine(.clk(clk), .addr(phase_acc[31:21]), .value(sine_lookup_output));

虽然 440Hz 相当慢,但使用上述代码可以实现高达 50MHz(或接近 <>MHz)的输出频率。 只需修改相位累加器增量即可。

上一篇:DDS直接数字合成2 - 任意信号

下一篇:DDS直接数字合成4 - 插值

关键词: FPGA DDS 相位累加器

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章


用户评论

请文明上网,做现代文明人
验证码:
查看电脑版