当前位置:   article > 正文

Verilog 代码编写 DDS信号发生器(幅频相可调正弦波、方波、三角波、锯齿波)纯VIVADO编写仿真_verilog dds

verilog dds

       DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有相对带宽大,频率转换时间短、分辨率高和相位连续性好等优点。较容易实现频率、相位以及幅度的数控调制,广泛应用于通信领域。

        DDS的基本结构框图如下所示:

     

       由图可以看出,DDS 主要由相位累加器、相位调制器、波形数据表以及D/A 转换器构成。本次实验仅在VIVADO平台上完成DDS的仿真,故设计流程不需要D/A转换器,在PC端完成仿真设计即可。若需要结合FPGA开发板使用,则需要再外接一个D/A转换模块,将产生的数字信号转换为模拟信号即可。

       其中相位累加器由 N 位加法器与 N 位寄存器构成。每个时钟周期的时钟上升沿,加法器就将频率控制字与累加寄存器输出的相位数据相加,相加的结果又反馈至累加寄存器的数据输入端,以使加法器在下一个时钟脉冲的作用下继续与频率控制字相加。这样,相位累加器在时钟作用下,不断对频率控制字进行线性相位累加。即在每一个时钟脉冲输入时,相位累加器便把频率控制字累加一次。相位累加器输出的数据就是合成信号的相位。相位累加器输出的数据,作为波形存储器的相位采样地址,这样就可以把存储在波形存储器里的波形采样值经查表找出,完成相位到幅度的转换。波形存储器的输出数据送到 D/A 转换器,由 D/A 转换器将数字信号转换成模拟信号输出。

        DDS 信号流程示意图如下: 

       这里相位累加器位数为 N 位(N 的取值范围实际应用中一般为 24~32),相当于把正弦信号在相位上的精度定义为 N 位,所以其分辨率为1⁄2^N。 若 DDS 的时钟频率为Fclk,频率控制字 fword 为 1,则输出频率为Fout = Fclk/2^N ,这个频率相当于“基频”。若 fword 为 B,则输出频率为Fout = B × Fclk /2^N 。

       因此理论上由以上三个参数就可以得出任意的Fout输出频率。且可得出频率分辨率由时钟频率和累加器的位数决定的结论。当参考时钟频率越高,累加器位数越高,输出频率分辨率就越高。

       从上式分析可得,当系统输入时钟频率Fclk不变时,输出信号频率由频率控制字 B 所决定。其中 B 为频率字且只能取整数。为了合理控制 ROM 的容量,此处选取 ROM 查询的地址时,可以采用截断式,即只取 32 位累加器的高 M 位。这里相位寄存器输出的位数一般取 10~16 位。

       故按照一定的时钟,产生顺序的相位值,将该值作为ROM查找表的地址,即可顺序读出存储的正弦波表数据,作为数据输出,同样的,为了产生其他不同类型的波形,只需要改变波表数据即可。

       为了实现频率的改变,只需要加入一个频率控制字,按照一定的规则取地址即可(比如三点取一点、五点取一点),这样依然能输出完整的波形,只不过取的点数变了,导致频率改变。

      为了实现相位的改变,只需要加入一个相位控制字,根据该值选择起始的地址点即可,实现波形的移动,相位的改变。

      为了实现幅值的改变,只需要加入一个幅度控制字,按照一定比例将该值与产生数据相乘,即可改变输出数据的大小,实现幅度的改变。

      在此设计了四种波形的幅频相可调的波形发生器,可以产生一定频率范围内的波形数据。根据不同的输入产生不同的输出波形。

     基于FPGA编写的DDS信号波形发生器,通过波表查找的方式生成正弦波。设置系统的时钟为50MHz,输出数据位宽为10位,从0-1023。可以输入波形控制字、频率控制字、相位控制字及幅度控制字来控制所生成波形的形式。该DDS模块可以产生正弦波、方波、三角波与锯齿波,频率范围为1KHz-5MHz,相位0-360°,幅度为0-1023的波形数据。其中设定D/A模块为10位的D/A转换器,产生的波形幅值为0-5V,因此根据不同的输出数据将转换为0-5V的电压值输出。

 

      其中各端口定义如下:

clk:系统时钟输入

rst:复位信号

wave[3:0]:波形选择输入,00 正弦波,01 方波,10 三角波,11 锯齿波

Fword[9:0]:频率控制字,选择输出频率

Pword[9:0]:相位控制字,选择输出相位

Aword[9:0]:幅度控制字,选择输出幅度

clkout:输出同步时钟,此处与输入时钟一致

dataout[9:0]:波形数据输出

     代码如下:

  1. //DDS数字信号发生器
  2. //波形控制字:
  3. //wave: 00:正弦波 01:方波 10:三角波 11: 锯齿波
  4. //频率控制字:
  5. //fout=fclk*Fword/2^(N) N:相位累加器的位数 ,Fword:频率控制字,当Fword=2^(32(位宽)-N)时 达到基频
  6. //设置基频为50KHz,对于正弦波、三角波、锯齿波、方波的Fword为4194304,Fword变大,频率变大,Fword变小,频率变小
  7. //此时 fout=fclk/2^(N)
  8. //频率分辨率=fclk/2^32(位宽)=0.01164Hz
  9. //想获得任意频率,Fword=f/0.01164,一般大于0,小于fclk/2
  10. //fout=fclk*Fword/2^(32)选用不同的Fword,得到不同的fout
  11. //相位控制字:
  12. //Pword:从0-1024,对应0-2pi
  13. //幅度控制字:
  14. //Aword:从0-1024,设定对于模拟输出0-5V,初始为1023,对应5V
  15. module DDS(
  16. input clk,
  17. input rst,
  18. input [1:0]wave,
  19. input [31:0]Fword,
  20. input [9:0]Pword,
  21. input [9:0]Aword,
  22. output clkout,
  23. output [9:0]dataout
  24. );
  25. //波形数据:
  26. reg [9:0] wavedata;
  27. //波形信号:
  28. wire [9:0] sindata;
  29. wire [9:0] squdata;
  30. wire [9:0] tridata;
  31. wire [9:0] sawdata;
  32. assign clkout = clk;
  33. //正弦波形产生:
  34. //相位寄存器:
  35. reg [31:0]frechange;
  36. always @(posedge clk or negedge rst) begin
  37. if(!rst)
  38. frechange <= 32'd0;
  39. else
  40. frechange <= frechange + Fword;
  41. end
  42. //相位累加器:
  43. reg [9:0]romaddr;
  44. always @(posedge clk or negedge rst) begin
  45. if(!rst)
  46. romaddr <= 10'd0;
  47. else
  48. romaddr <= frechange[31:22] + Pword;
  49. end
  50. //正弦波表:
  51. rom_sin romsin (
  52. .clka(clk), // input wire clka
  53. .addra(romaddr), // input wire [9 : 0] addra
  54. .douta(sindata) // output wire [9 : 0] douta
  55. );
  56. //其他波形产生器:
  57. reg [31:0] phaseacc;
  58. always @(posedge clk or negedge rst) begin
  59. if(!rst)
  60. phaseacc <= 32'b0;
  61. else
  62. phaseacc <= phaseacc+Fword;
  63. end
  64. wire [31:0] phase=phaseacc+Pword;
  65. //方波:
  66. assign squdata = phase[31] ? 10'd1023:10'd0;
  67. //三角波:
  68. assign tridata = phase[31]? (~phase[30:21]): phase[30:21];
  69. //锯齿波:
  70. assign sawdata = phase[31:22];
  71. //波形选择:
  72. always @(*) begin
  73. case(wave)
  74. 2'b00: wavedata<= sindata;
  75. 2'b01: wavedata<= squdata;
  76. 2'b10: wavedata<= tridata;
  77. 2'b11: wavedata<= sawdata;
  78. default: wavedata<= sindata;
  79. endcase
  80. end
  81. //调幅:
  82. wire [9:0] data;
  83. assign data = wavedata;
  84. reg [19:0] AMdata;
  85. always@(posedge clk)
  86. if(!rst)
  87. AMdata<=1'd0;
  88. else
  89. AMdata<=data*Aword;
  90. assign dataout = AMdata[19:10];
  91. endmodule

       正弦波波表数据 存储在ROM里,这里调用了VIVADO的IP核,波表数据的coe文件可以利用MATLAB或者相关的软件生成,这里不再赘述,需要可以在附件中下载。

仿真部分:

       利用设计的DDS模块,可以在VIVADO平台上仿真得到波形,此处编写testbench以后,仿真显示了多种波形和调幅、频、相后的结果。

       例化四个DDS模块,生成1.56MHz,幅值为1024单位的四种不同类型的波形信号,仿真结果如下所示:

       图中产生了四种不同类型的波形,按照不同的波形控制字得到不同的输出,波形的频率为1.56MHz,此处只测量了正弦波的频率,其他波形的频率也一样。由图中数据可知T=649us,故f约等于1.56MHz。

      例化四个DDS模块,生成1.56MHz,幅值为1024单位的四个不同相位的正弦波,分别为0°,90°,180°,270°,实现调相功能,仿真结果如下所示:

 

       以绿色波形为0°基准,四个波形各相差90°,完成功能实现。

      例化四个DDS模块,生成1.56MHz,相位为0°,幅值大小不同的四个正弦波,分别为1024、512、256、128(如DA部分生成电压为0-5V,则分别对应电压幅值为5V、2.5V、1.25V、0.625V),仿真结果如下所示:

        由各波形的输出峰值大小可以看出,四个波形的数字输出各有不同,经过D/A以后输出的模拟波形幅值就是不一样的,实现了调幅功能。

       例化四个DDS模块,生成相位为0°,幅值为1024单位,频率大小不同的四个正弦波,分别为1.56MHz、780KHz、390KHz、195KHz,仿真结果如下所示:

        由波形图可知,按照设定的数值,实现了不同频率波形的产生,此处为2分频的结果,频率测量只测量了1.56MHz的波形,由数据可知T=640us,故频率f约为1.56MHz,其余波形就不再显示。 

        仿真部分代码(多波形发生可自行例化):

  1. `timescale 1ns / 1ps
  2. module DDS_tb();
  3. reg clk;
  4. reg rst;
  5. reg [1:0]wave1;
  6. reg [31:0]Fword1;
  7. reg [9:0]Pword1;
  8. reg [9:0]Aword1;
  9. wire clkout1;
  10. wire [9:0]dataout1;
  11. reg [1:0]wave2;
  12. reg [31:0]Fword2;
  13. reg [9:0]Pword2;
  14. reg [9:0]Aword2;
  15. wire clkout2;
  16. wire [9:0]dataout2;
  17. reg [1:0]wave3;
  18. reg [31:0]Fword3;
  19. reg [9:0]Pword3;
  20. reg [9:0]Aword3;
  21. wire clkout3;
  22. wire [9:0]dataout3;
  23. reg [1:0]wave4;
  24. reg [31:0]Fword4;
  25. reg [9:0]Pword4;
  26. reg [9:0]Aword4;
  27. wire clkout4;
  28. wire [9:0]dataout4;
  29. parameter frequence = 50000000;//50MHz 系统
  30. always # 10 clk=~clk;
  31. DDS dds1(
  32. .clk(clk),
  33. .rst(rst),
  34. .wave(wave1),
  35. .Fword(Fword1),
  36. .Pword(Pword1),
  37. .Aword(Aword1),
  38. .clkout(clkout1),
  39. .dataout(dataout1)
  40. );
  41. DDS dds2(
  42. .clk(clk),
  43. .rst(rst),
  44. .wave(wave2),
  45. .Fword(Fword2),
  46. .Pword(Pword2),
  47. .Aword(Aword2),
  48. .clkout(clkout2),
  49. .dataout(dataout2)
  50. );
  51. DDS dds3(
  52. .clk(clk),
  53. .rst(rst),
  54. .wave(wave3),
  55. .Fword(Fword3),
  56. .Pword(Pword3),
  57. .Aword(Aword3),
  58. .clkout(clkout3),
  59. .dataout(dataout3)
  60. );
  61. DDS dds4(
  62. .clk(clk),
  63. .rst(rst),
  64. .wave(wave4),
  65. .Fword(Fword4),
  66. .Pword(Pword4),
  67. .Aword(Aword4),
  68. .clkout(clkout4),
  69. .dataout(dataout4)
  70. );
  71. initial begin
  72. rst<= 1'b0;
  73. clk<=1'b0;
  74. //一路信号:
  75. Fword1 <= 32'd1;
  76. Pword1 <= 10'd0;
  77. Aword1 <= 10'd1023;
  78. wave1 <= 2'b00;
  79. //二路信号:
  80. Fword2 <= 32'd1;
  81. Pword2 <= 10'd0;
  82. Aword2 <= 10'd1023;
  83. wave2 <= 2'b00;
  84. //三路信号:
  85. Fword3 <= 32'd1;
  86. Pword3 <= 10'd0;
  87. Aword3 <= 10'd1023;
  88. wave3 <= 2'b00;
  89. //四路信号:
  90. Fword4 <= 32'd1;
  91. Pword4 <= 10'd0;
  92. Aword4 <= 10'd1023;
  93. wave4 <= 2'b00;
  94. #500
  95. rst <= 1'b1;
  96. #500
  97. //基频 50KHz,Fword=4194304:
  98. // 1.56MHz: Fword <= 32'd134217728;
  99. Fword1 <= 32'd134217728;
  100. Fword2 <= 32'd134217728;
  101. Fword3 <= 32'd134217728;
  102. Fword4 <= 32'd134217728;
  103. wave2<=2'b01;
  104. wave3<=2'b10;
  105. wave4<=2'b11;
  106. #10000000000
  107. $stop;
  108. end
  109. endmodule

      波表数据地址:https://download.csdn.net/download/qq_46132759/77509190

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/724159
推荐阅读
相关标签
  

闽ICP备14008679号