DDS模块产生可调正弦波

2019-07-15 22:48发布

本帖最后由 yangzhiyuan0928 于 2016-5-2 20:34 编辑

    做一个dds模块,产生可调正弦波,遇到了一点问题,已经解决,但想不明白为什么原来的方法不行。之前想的是在状态机切换的组合逻辑中直接更新相位累加器的值,但在功能仿真时发现,会造成时钟停止,但当我把相位累加器更新过程放在时序逻辑中就解决问题了。不知为什么?求懂得人指点一下!!!代码如下:
   (1) 出问题的代码:
  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date:    20:39:32 05/01/2016
  7. // Design Name:
  8. // Module Name:    dds_sin
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.1
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21.   module dds_sin
  22.         (input        clk_dds,rst_n,out_en,
  23.          input  [31:0] freq_sin,phase_sin_init,
  24.              input  [15:0] amp_sin,
  25.              output  [31:0] sin_out);

  26.           wire   [31:0] phase_acc;
  27.           reg     [31:0] phase_acc_temp;
  28.           wire   [13:0] sin_addr;
  29.           wire   [15:0] sin_wave;
  30.           reg               main_state,next_state;
  31.         
  32.           localparam  [24:0]      PHASE_ACC_MAX = 25'd20000000;  
  33.           localparam                 IDLE = 1'b0;
  34.           localparam                 R0  = 1'b1;
  35.            
  36.          assign  sin_addr  = phase_acc[24:11];        
  37.          assign  phase_acc = (phase_acc_temp < PHASE_ACC_MAX) ? phase_acc_temp: phase_acc_temp - PHASE_ACC_MAX;
  38.          
  39.           always @ (posedge clk_dds or negedge rst_n)
  40.             begin
  41.               if (!rst_n )  main_state <= IDLE;
  42.               else main_state <= next_state;
  43.             end              
  44.          
  45.             
  46.          always @*
  47.               begin
  48.                 case(main_state)  
  49.                     IDLE:  begin
  50.                                if (out_en == 1'b1 ) begin
  51.                                   phase_acc_temp = phase_sin_init;   //Load initial phase
  52.                                   next_state = R0;        
  53.                                end
  54.                                else  next_state = IDLE;        
  55.                                end                                                      
  56.                     R0:  begin
  57.                                                                          phase_acc_temp = phase_acc + freq_sin;               
  58.                          if (out_en == 1'b0)
  59.                              begin
  60.                              next_state = IDLE;
  61.                              phase_acc_temp = phase_sin_init;
  62.                              end                                                      
  63.                 else
  64.                      next_state = R0;
  65.                         end
  66.                                            default: next_state = IDLE;
  67.                 endcase
  68.             end
  69. /*
  70.                         always@(posedge clk_dds or negedge rst_n) begin
  71.                                 if(!rst_n) phase_acc_temp <= phase_sin_init;  // Load initial phase
  72.                                 else if(main_state == IDLE) phase_acc_temp <= phase_sin_init;
  73.                                 else if(main_state == R0) phase_acc_temp <= phase_acc + freq_sin;
  74.                                 else phase_acc_temp <= phase_acc;
  75.                         end
  76. */            
  77.     mult_32_signed   amp_mult_sin (
  78.               .clk(clk_dds),  // input wire CLK
  79.               .a(sin_wave),      // input wire [15 : 0] A
  80.               .b(amp_sin),      // input wire [15 : 0] B
  81.               .p(sin_out)      // output wire [31 : 0] P
  82.             );
  83.          
  84.     blk_sin_9765    u_sin (
  85.                                         .clka(clk_dds),    // input wire clka
  86.                                         .addra(sin_addr),  // input wire [13 : 0] addra
  87.                                         .douta(sin_wave)  // output wire [15 : 0] douta
  88.                                       );

  89. endmodule
复制代码 功能仿真的数据:红 {MOD}部分标注的表明,始终只能工作到这里,之后时钟停止工作。
dds1.PNG


(2)修改代码之后:代码如下
  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date:    20:39:32 05/01/2016
  7. // Design Name:
  8. // Module Name:    dds_sin
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.1
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21.   module dds_sin
  22.         (input        clk_dds,rst_n,out_en,
  23.          input  [31:0] freq_sin,phase_sin_init,
  24.              input  [15:0] amp_sin,
  25.              output  [31:0] sin_out);

  26.           wire   [31:0] phase_acc;
  27.           reg     [31:0] phase_acc_temp;
  28.           wire   [13:0] sin_addr;
  29.           wire   [15:0] sin_wave;
  30.           reg               main_state,next_state;
  31.         
  32.           localparam  [24:0]      PHASE_ACC_MAX = 25'd20000000;  
  33.           localparam                 IDLE = 1'b0;
  34.           localparam                 R0  = 1'b1;
  35.            
  36.          assign  sin_addr  = phase_acc[24:11];        
  37.          assign  phase_acc = (phase_acc_temp < PHASE_ACC_MAX) ? phase_acc_temp: phase_acc_temp - PHASE_ACC_MAX;
  38.          
  39.           always @ (posedge clk_dds or negedge rst_n)
  40.             begin
  41.               if (!rst_n )  main_state <= IDLE;
  42.               else main_state <= next_state;
  43.             end              
  44.          
  45.             
  46.          always @*
  47.               begin
  48.                 case(main_state)  
  49.                     IDLE:  begin
  50.                                if (out_en == 1'b1 ) begin
  51.                               //    phase_acc_temp = phase_sin_init;   //Load initial phase
  52.                                   next_state = R0;        
  53.                                end
  54.                                else  next_state = IDLE;        
  55.                                end                                                      
  56.                     R0:  begin
  57.                                                                 //         phase_acc_temp = phase_acc + freq_sin;               
  58.                          if (out_en == 1'b0)
  59.                              begin
  60.                              next_state = IDLE;
  61.                         //     phase_acc_temp = phase_sin_init;
  62.                              end                                                      
  63.                 else
  64.                      next_state = R0;
  65.                         end
  66.                                            default: next_state = IDLE;
  67.                 endcase
  68.             end

  69.                         always@(posedge clk_dds or negedge rst_n) begin
  70.                                 if(!rst_n) phase_acc_temp <= phase_sin_init;  // Load initial phase
  71.                                 else if(main_state == IDLE) phase_acc_temp <= phase_sin_init;
  72.                                 else if(main_state == R0) phase_acc_temp <= phase_acc + freq_sin;
  73.                                 else phase_acc_temp <= phase_acc;
  74.                         end
  75.            
  76.     mult_32_signed   amp_mult_sin (
  77.               .clk(clk_dds),  // input wire CLK
  78.               .a(sin_wave),      // input wire [15 : 0] A
  79.               .b(amp_sin),      // input wire [15 : 0] B
  80.               .p(sin_out)      // output wire [31 : 0] P
  81.             );
  82.          
  83.     blk_sin_9765    u_sin (
  84.                                         .clka(clk_dds),    // input wire clka
  85.                                         .addra(sin_addr),  // input wire [13 : 0] addra
  86.                                         .douta(sin_wave)  // output wire [15 : 0] douta
  87.                                       );

  88. endmodule
复制代码仿真得到的数据:


(3) Testbench代码如下:
  1. `timescale 1ns / 1ps

  2. ////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date:   10:25:17 05/02/2016
  7. // Design Name:   dds_sin
  8. // Module Name:   F:/Xilinx/zedboard/ise14.7/dds_sin_0502/dds_sin_tb.v
  9. // Project Name:  dds_sin_0502
  10. // Target Device:  
  11. // Tool versions:  
  12. // Description:
  13. //
  14. // Verilog Test Fixture created by ISE for module: dds_sin
  15. //
  16. // Dependencies:
  17. //
  18. // Revision:
  19. // Revision 0.01 - File Created
  20. // Additional Comments:
  21. //
  22. ////////////////////////////////////////////////////////////////////////////////

  23. module dds_sin_tb;

  24.         // Inputs
  25.         reg clk_dds;
  26.         reg rst_n;
  27.         reg out_en;
  28.         reg [31:0] freq_sin;
  29.         reg [31:0] phase_sin_init;
  30.         reg [15:0] amp_sin;

  31.         // Outputs
  32.         wire [31:0] sin_out;

  33.         // Instantiate the Unit Under Test (UUT)
  34.         dds_sin uut (
  35.                 .clk_dds(clk_dds),
  36.                 .rst_n(rst_n),
  37.                 .out_en(out_en),
  38.                 .freq_sin(freq_sin),
  39.                 .phase_sin_init(phase_sin_init),
  40.                 .amp_sin(amp_sin),
  41.                 .sin_out(sin_out)
  42.         );

  43.          initial begin
  44.         clk_dds = 0;
  45.         rst_n = 0;
  46.         out_en = 1;
  47.         freq_sin = 32'd4000;  //10KHz
  48.         phase_sin_init = 32'd0;
  49.         amp_sin = 16'd1000;
  50.         
  51.         #100;
  52.         rst_n = 1;     
  53.     end
  54.    
  55.         always begin
  56.                         #5;
  57.                         clk_dds <= 1;
  58.                         #5;
  59.                         clk_dds <= 0;        
  60.         end   
  61.       
  62. endmodule

复制代码





友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
runileking
1楼-- · 2019-07-16 04:04
你检查一下复位对不对,高电平复位的话,rst高了就该停止吧
yangzhiyuan0928
2楼-- · 2019-07-16 08:20
runileking 发表于 2016-5-3 09:13
你检查一下复位对不对,高电平复位的话,rst高了就该停止吧

是低电平复位的
张瑾洛  
3楼-- · 2019-07-16 13:04
楼主你好,你有没有QQ啊?有些技术问题想向你讨教一下

一周热门 更多>