DDS模块产生可调正弦波
时间:10-02
整理:3721RD
点击:
做一个dds模块,产生可调正弦波,遇到了一点问题,已经解决,但想不明白为什么原来的方法不行。之前想的是在状态机切换的组合逻辑中直接更新相位累加器的值,但在功能仿真时发现,会造成时钟停止,但当我把相位累加器更新过程放在时序逻辑中就解决问题了。不知为什么?求懂得人指点一下!代码如下:
(1) 出问题的代码:
- `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // Company:
- // Engineer:
- //
- // Create Date: 20:39:32 05/01/2016
- // Design Name:
- // Module Name: dds_sin
- // Project Name:
- // Target Devices:
- // Tool versions:
- // Description:
- //
- // Dependencies:
- //
- // Revision:
- // Revision 0.1
- // Additional Comments:
- //
- //////////////////////////////////////////////////////////////////////////////////
- module dds_sin
- (input clk_dds,rst_n,out_en,
- input [31:0] freq_sin,phase_sin_init,
- input [15:0] amp_sin,
- output [31:0] sin_out);
-
- wire [31:0] phase_acc;
- reg [31:0] phase_acc_temp;
- wire [13:0] sin_addr;
- wire [15:0] sin_wave;
- reg main_state,next_state;
-
- localparam [24:0] PHASE_ACC_MAX = 25'd20000000;
- localparam IDLE = 1'b0;
- localparam R0 = 1'b1;
-
- assign sin_addr = phase_acc[24:11];
- assign phase_acc = (phase_acc_temp < PHASE_ACC_MAX) ? phase_acc_temp: phase_acc_temp - PHASE_ACC_MAX;
-
- always @ (posedge clk_dds or negedge rst_n)
- begin
- if (!rst_n ) main_state <= IDLE;
- else main_state <= next_state;
- end
-
-
- always @*
- begin
- case(main_state)
- IDLE: begin
- if (out_en == 1'b1 ) begin
- phase_acc_temp = phase_sin_init; //Load initial phase
- next_state = R0;
- end
- else next_state = IDLE;
- end
- R0: begin
- phase_acc_temp = phase_acc + freq_sin;
- if (out_en == 1'b0)
- begin
- next_state = IDLE;
- phase_acc_temp = phase_sin_init;
- end
- else
- next_state = R0;
- end
- default: next_state = IDLE;
- endcase
- end
- /*
- always@(posedge clk_dds or negedge rst_n) begin
- if(!rst_n) phase_acc_temp <= phase_sin_init; // Load initial phase
- else if(main_state == IDLE) phase_acc_temp <= phase_sin_init;
- else if(main_state == R0) phase_acc_temp <= phase_acc + freq_sin;
- else phase_acc_temp <= phase_acc;
- end
- */
- mult_32_signed amp_mult_sin (
- .clk(clk_dds), // input wire CLK
- .a(sin_wave), // input wire [15 : 0] A
- .b(amp_sin), // input wire [15 : 0] B
- .p(sin_out) // output wire [31 : 0] P
- );
-
- blk_sin_9765 u_sin (
- .clka(clk_dds), // input wire clka
- .addra(sin_addr), // input wire [13 : 0] addra
- .douta(sin_wave) // output wire [15 : 0] douta
- );
- endmodule
(2)修改代码之后:代码如下
- `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // Company:
- // Engineer:
- //
- // Create Date: 20:39:32 05/01/2016
- // Design Name:
- // Module Name: dds_sin
- // Project Name:
- // Target Devices:
- // Tool versions:
- // Description:
- //
- // Dependencies:
- //
- // Revision:
- // Revision 0.1
- // Additional Comments:
- //
- //////////////////////////////////////////////////////////////////////////////////
- module dds_sin
- (input clk_dds,rst_n,out_en,
- input [31:0] freq_sin,phase_sin_init,
- input [15:0] amp_sin,
- output [31:0] sin_out);
-
- wire [31:0] phase_acc;
- reg [31:0] phase_acc_temp;
- wire [13:0] sin_addr;
- wire [15:0] sin_wave;
- reg main_state,next_state;
-
- localparam [24:0] PHASE_ACC_MAX = 25'd20000000;
- localparam IDLE = 1'b0;
- localparam R0 = 1'b1;
-
- assign sin_addr = phase_acc[24:11];
- assign phase_acc = (phase_acc_temp < PHASE_ACC_MAX) ? phase_acc_temp: phase_acc_temp - PHASE_ACC_MAX;
-
- always @ (posedge clk_dds or negedge rst_n)
- begin
- if (!rst_n ) main_state <= IDLE;
- else main_state <= next_state;
- end
-
-
- always @*
- begin
- case(main_state)
- IDLE: begin
- if (out_en == 1'b1 ) begin
- // phase_acc_temp = phase_sin_init; //Load initial phase
- next_state = R0;
- end
- else next_state = IDLE;
- end
- R0: begin
- // phase_acc_temp = phase_acc + freq_sin;
- if (out_en == 1'b0)
- begin
- next_state = IDLE;
- // phase_acc_temp = phase_sin_init;
- end
- else
- next_state = R0;
- end
- default: next_state = IDLE;
- endcase
- end
- always@(posedge clk_dds or negedge rst_n) begin
- if(!rst_n) phase_acc_temp <= phase_sin_init; // Load initial phase
- else if(main_state == IDLE) phase_acc_temp <= phase_sin_init;
- else if(main_state == R0) phase_acc_temp <= phase_acc + freq_sin;
- else phase_acc_temp <= phase_acc;
- end
-
- mult_32_signed amp_mult_sin (
- .clk(clk_dds), // input wire CLK
- .a(sin_wave), // input wire [15 : 0] A
- .b(amp_sin), // input wire [15 : 0] B
- .p(sin_out) // output wire [31 : 0] P
- );
-
- blk_sin_9765 u_sin (
- .clka(clk_dds), // input wire clka
- .addra(sin_addr), // input wire [13 : 0] addra
- .douta(sin_wave) // output wire [15 : 0] douta
- );
- endmodule
(3) Testbench代码如下:
- `timescale 1ns / 1ps
- ////////////////////////////////////////////////////////////////////////////////
- // Company:
- // Engineer:
- //
- // Create Date: 10:25:17 05/02/2016
- // Design Name: dds_sin
- // Module Name: F:/Xilinx/zedboard/ise14.7/dds_sin_0502/dds_sin_tb.v
- // Project Name: dds_sin_0502
- // Target Device:
- // Tool versions:
- // Description:
- //
- // Verilog Test Fixture created by ISE for module: dds_sin
- //
- // Dependencies:
- //
- // Revision:
- // Revision 0.01 - File Created
- // Additional Comments:
- //
- ////////////////////////////////////////////////////////////////////////////////
- module dds_sin_tb;
- // Inputs
- reg clk_dds;
- reg rst_n;
- reg out_en;
- reg [31:0] freq_sin;
- reg [31:0] phase_sin_init;
- reg [15:0] amp_sin;
- // Outputs
- wire [31:0] sin_out;
- // Instantiate the Unit Under Test (UUT)
- dds_sin uut (
- .clk_dds(clk_dds),
- .rst_n(rst_n),
- .out_en(out_en),
- .freq_sin(freq_sin),
- .phase_sin_init(phase_sin_init),
- .amp_sin(amp_sin),
- .sin_out(sin_out)
- );
- initial begin
- clk_dds = 0;
- rst_n = 0;
- out_en = 1;
- freq_sin = 32'd4000; //10KHz
- phase_sin_init = 32'd0;
- amp_sin = 16'd1000;
-
- #100;
- rst_n = 1;
- end
-
- always begin
- #5;
- clk_dds <= 1;
- #5;
- clk_dds <= 0;
- end
-
- endmodule
你检查一下复位对不对,高电平复位的话,rst高了就该停止吧
是低电平复位的
小编你好,你有没有QQ啊?有些技术问题想向你讨教一下