主要关于调相方面
从图像上来理解调整相位就是原函数在X轴上进行水平移动。
在本项目中函数的波形图按照顺序存在ROM中,我们只要按照比例调整读取ROM的地址,即可调相。
前文中我们使用32位寄存器的高8位用做ROM的地址,因此只要有按键按下,我们按照相位同比例的调整读取ROM的地址即可。
ROM的深度为1024、宽度为8储存标准正弦函数,那么可知其式为:
这里x对应的是ROM地址、y对应的是ROM中数据也即幅值。范围取x从0到1023、y从0到255。
若按键一次,相位增加PI/2,则有:

其中绿色为f(x),紫色为调整相位后的g(x)。
即每次按下按键后相当于将图像向左平移256,那么也就是按下按键后,提前读取256个地址之后的数据。
module phase_ctrl( input clk, input rst_n, input f_phase, output [9:0] initiala_address);assign initiala_address = 10'd256;endmodulemodule addr_ctrl( input clk, input rst_n, input [31:0] freq_num, input [9:0] initiala_address, input f_phase, output [9:0] address);reg [31:0] cnt;always @(posedge clk,negedge rst_n)begin if(rst_n == 0) cnt <= 32'd0; else if(f_phase == 1) cnt[31:22] <= cnt[31:22] + initiala_address; else cnt <= cnt + freq_num;end assign address = cnt[31:22];endmodule重点关注在f_phase拉高前后,正弦波上3个点(address,data)的大小

(43,161) (43+256,251)=(299,251)

(754,0) (754+256)=(1010,117)

(856,18) (856+256-1024,193)=(88,193)

(43,161)(43,251) (754,0)(754,117) (856,18) (856,193)
可以看到调相模块准确的完成了每次按键按下,相移PI/2的任务。
这一部分在代码方面比较简单,实际验证还需要数模转换和示波器的配合,限于条件无法达到,因此只展仿真结果。
在程序上要注意位宽的变化,由于不断的放大,因此将输出data设计为32位。
每次按键按下。幅值放大两倍。
module amplitude_ctrl( input clk, input rst_n, input f_ampli, input [7:0] data_in, output [31:0] data);reg [23:0] ampli_num;always @(posedge clk,negedge rst_n)begin if(rst_n == 0) ampli_num <= 24'd1; else if(f_ampli == 1) ampli_num <= ampli_num * 24'd2; else ampli_num <= ampli_num;end assign data = ampli_num * data_in;endmodule
系统结构图为:


ModelSim仿真:
频率变化:


相位变化:

幅值变化:

测试代码:
`timescale 1ns/1nsmodule key_dds_tb(); reg clk; reg rst_n; reg key_freq; reg key_phase; reg key_ampli; wire [31:0] data; key_dds key_dds_inst( .clk (clk), .rst_n (rst_n), .key_freq (key_freq), .key_phase(key_phase), .key_ampli(key_ampli), .data (data));initial clk = 1;always #10 clk = !clk;initialbegin rst_n = 0; key_freq = 1; key_phase = 1; key_ampli = 1; #200 rst_n = 1; #200 key_freq = 1; #10000000 key_freq = 0; #2000 key_freq = 1; #10000000 key_freq = 0; #1000000 key_freq = 1; #10000000 key_phase = 1; #2000000 key_phase = 0; #70000 key_phase = 1; #11500 key_phase = 0; #70000 key_phase = 1; #25000 key_phase = 0; #23333 key_phase = 1; #1000000 key_ampli = 1; #10000000 key_ampli = 0; #2000 key_ampli = 1; #1000000 #10000 $stop; endendmodule作者:13tree
出处:https://www.cnblogs.com/13tree/
本文版权归作者所有,如需转载请保留此段声明。