的第二个技巧是长。 它允许来自输出的信号频率非常灵活。
本文引用地址:我们将通过一个示例了解它是如何工作的。 让我们从这个简单的代码开始。
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 步长获得原始正弦频率的任意倍数。 我们当然可以在相位累加器上增加四个以上的位。 典型的实现使用非常长的位相位累加器,以在可用的输出频率中具有极高的精度和分辨率。
例如,使用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)的输出频率。 只需修改相位累加器增量即可。
上一篇:
下一篇: