当前位置:   article > 正文

quartus II 与AD9767(双路14位输出)的fpga主要代码,测试代码,matlab调幅度代码以及遇到的问题。_ad9765输出频率

ad9765输出频率

1.需求:利用FPGA与DDS技术的结合输出14位的双路波形,因为位数高能提高输出的精度。

首先,注意精度和速度的问题:DDS引用IP核的mif文件中,文本输出的波形纵坐标是由输出位数决定的(0~2^14),横坐标是采样点个数width(也叫深度)。因此AD驱动时钟只能决定输出频率越高(输出频率f=clk/width),不能说明速度越快,因此尽量满足采样时钟的情况下,提高采样精度是必须的。

一句话总结:FPGA的时钟是50M,AD驱动时钟要比这个高,才能获得相应高输出频率,而mif纵坐标与输出位数有关,输出位数越高,输出精度越高。

问题:mif文件在rom核里面必须是手动输入(否则rom的q无法输出数据);mif文件必须核工程文件在同一个目录下(否则rom无法识别mif文件)。

2.以quartus为平台的fpga代码(之前代码是没根据AD9767时序,硬件输出有问题,现在更改了):

  1. module DACout(
  2. input clk , //时钟
  3. input rst, //复位信号,低电平有效
  4. output da_clk1 , //DA(AD9767)驱动时钟
  5. output [13:0] da_data1, //输出给 DA 的数据
  6. output da_wrt1,
  7. output da_clk2 , //DA(AD9767)驱动时钟
  8. output [13:0] da_data2, //输出给 DA 的数据
  9. output da_wrt2
  10. );
  11. reg [8:0] rd_addr1; //rom的地址位数,也是采样点深度
  12. wire [13:0] rd_data1;//rom的q,输出给da的数据
  13. reg [8:0] rd_addr2;//rom的地址位数,也是采样点深度
  14. wire [13:0] rd_data2;//rom的q,输出给da的数据
  15. //*****************************************************
  16. //** main code
  17. //*****************************************************
  18. //数据 rd_data 是在 clk 的上升沿更新的,所以 DA 芯片在 clk 的下降沿锁存数据是稳定的时刻
  19. //而 DA 实际上在 da_clk 的上升沿锁存数据,所以时钟取反,这样 clk 的下降沿相当于da_clk 的上升沿
  20. assign da_clk1 = clk;
  21. assign da_wrt1 = clk;
  22. assign da_clk2 = clk;
  23. assign da_wrt2 = clk;
  24. assign da_data1 = rd_data1+rd_data2; //将读到的 ROM 数据赋值给 DA 数据端口,14位正弦和锯齿的叠加波
  25. assign da_data2 = rd_data2; // 幅度是10%锯齿波的32.55k正弦波
  26. //例化rom
  27. rom1 u_rom1(
  28. .address (rd_addr1),
  29. .clock (clk),
  30. .q (rd_data1)
  31. );
  32. rom2 u_rom2 (
  33. .address (rd_addr2),
  34. .clock (clk),
  35. .q (rd_data2)
  36. );
  37. //parameter
  38. //频率调节控制
  39. parameter FREQ_ADJ1 =8'd9765; //频率调节,FREQ_ADJ 的越大,最终输出的频率越低,范围 0~512
  40. //reg define
  41. reg [7:0] freq_cnt1 ; //频率调节计数器
  42. //频率调节计数器
  43. always @(posedge clk or negedge rst) begin
  44. if(rst == 1'b0)
  45. freq_cnt1 <= 8'd0;
  46. else if(freq_cnt1 == FREQ_ADJ1)
  47. freq_cnt1 <= 8'd0;
  48. else
  49. freq_cnt1 <= freq_cnt1 + 8'd1;
  50. end
  51. //读 ROM 地址
  52. always @(posedge clk or negedge rst) begin
  53. if(rst == 1'b0)
  54. rd_addr1 <= 8'd0;
  55. else begin
  56. if(freq_cnt1 == FREQ_ADJ1) begin
  57. rd_addr1 <= rd_addr1 + 8'd1;
  58. end
  59. end
  60. end
  61. //parameter
  62. //频率调节控制
  63. parameter FREQ_ADJ2 =8'd0; //频率调节,FREQ_ADJ 的越大,最终输出的频率越低,范围 0~1024
  64. //reg define
  65. reg [7:0] freq_cnt2 ; //频率调节计数器
  66. always @(posedge clk or negedge rst) begin
  67. if(rst == 1'b0)
  68. freq_cnt2 <= 8'd0;
  69. else if(freq_cnt2 == FREQ_ADJ2)
  70. freq_cnt2 <= 8'd0;
  71. else
  72. freq_cnt2 <= freq_cnt2 + 10'd1;
  73. end
  74. //读 ROM 地址
  75. always @(posedge clk or negedge rst) begin
  76. if(rst == 1'b0)
  77. rd_addr2 <= 8'd0;
  78. else begin
  79. if(freq_cnt2 == FREQ_ADJ2) begin
  80. rd_addr2 <= rd_addr2 + 8'd1;
  81. end
  82. end
  83. end
  84. endmodule

3.测试代码:

  1. `timescale 1 ns/ 1 ns
  2. module DACout_vlg_tst();
  3. // constants
  4. // general purpose registers
  5. //reg eachvec;
  6. // test vector input registers
  7. reg clk;
  8. reg rst;
  9. // wires
  10. wire da_clk1;
  11. wire da_clk2;
  12. wire [13:0] da_data1;
  13. wire [13:0] da_data2;
  14. // assign statements (if any)
  15. DACout i1 (
  16. // port map - connection between master ports and signals/registers
  17. .clk(clk),
  18. .da_clk1(da_clk1),
  19. .da_clk2(da_clk2),
  20. .da_data1(da_data1),
  21. .da_data2(da_data2),
  22. .rst(rst)
  23. );
  24. initial
  25. begin
  26. // code that executes only once
  27. // insert code here --> begin
  28. clk =0;
  29. rst =0;
  30. #20 rst =1;
  31. // --> end
  32. $display("Running testbench");
  33. end
  34. always
  35. // optional sensitivity list
  36. // @(event1 or event2 or .... eventn)
  37. begin
  38. // code executes for every event on sensitivity list
  39. // insert code here --> begin
  40. # 10 clk =~clk;
  41. //@eachvec;
  42. // --> end
  43. end
  44. endmodule

4.matlab对正弦波的编程:

  1. clc;
  2. clear;
  3. depth =512; %存储器的深度
  4. widths = 14; %数据宽度为10
  5. % L = 0:2047; %把一个周期的正弦信号分为2048
  6. % s =sin(2*pi *L/2048); %计算0 ~2*pi之间的sin值
  7. qqq = fopen('sine.mif','wt'); %使用fopen函数生成sine.mif
  8. fprintf(qqq, 'depth = %d;\n',depth); %使用fprintf打印depth = 2048;
  9. fprintf(qqq, 'width = %d;\n',widths); %使用fprintf打印width = 10;
  10. fprintf(qqq, 'address_radix = UNS;\n'); %使用fprintf打印address_radix = UNS; 表示无符号显示数据
  11. fprintf(qqq,'data_radix = UNS;\n'); %使用fprintf打印data_radix = UNS; 表示无符号显示数据
  12. fprintf(qqq,'content begin\n'); %使用fprintf打印content begin
  13. for(x = 1 : depth) %产生正弦数据
  14. fprintf(qqq,'%d:%d;\n',x-1,round(819.2*sin(2*pi*(x-1)/512)+819.2));
  15. fplot(@(x)round(819.2.*sin(2.*pi.*(x)./512)+819.2),[0,511]);
  16. end
  17. fprintf(qqq, 'end;'); %使用fprintf打印end;
  18. fclose(qqq);

5.功能仿真效果图(实际硬件输出噪声有点大,初步认为杜邦线连接原因,也可能示波器不行):

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

闽ICP备14008679号