为了给FFT产生输入信号,写了一个信号发生器,用于产生特定频率的方波、三角波、正弦波与余弦波。时钟固定为10M,输出假定为一个12位的DA,三角波、正弦与余弦使用dds生成。
源文件如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer: longrejoy
//
// Create Date: 2017/04/24 01:12:29
// Design Name:
// Module Name: signal_gen
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module signal_gen(
input clk, //clock,fixed to 10MHz pls
input [23:0] freq, //[23:0] target frquence in Hz between 1 and 5M for square,1 ang 2.5M for triangle,312.5KHz for sin and cos
output signal_square, //signal of square
output [11:0] signal_dds, //signal of triangle ,sin or cos
input [1:0] sel, //[1:0] wave form, 00->sin, 01->cos, 10->triangle, 11->square
input rstn //reset, low level reset the module
);
reg signal_square_reg;
reg [23:0] f_count; //counter for clk
reg [23:0] count_over;
reg [11:0] signal_dds_reg;
reg [11:0] dds_triangle [3:0];
reg [11:0] dds_sin_cos [31:0];
reg [4:0] i;
assign signal_square = signal_square_reg;
assign signal_dds = signal_dds_reg;
always @ (posedge clk or negedge rstn)
begin
if (!rstn)
begin
signal_square_reg <= 1'b0;
signal_dds_reg <= 12'b0;
f_count <= 24'b0;
if (sel == 2'b01)
i <= 5'd24;
else
i <= 5'b0;
case (sel)
2'b00,2'b01://sin and cos
begin
dds_sin_cos [0 ] <= 12'h7FF;
dds_sin_cos [1 ] <= 12'h98E;
dds_sin_cos [2 ] <= 12'hB0E;
dds_sin_cos [3 ] <= 12'hC70;
dds_sin_cos [4 ] <= 12'hDA7;
dds_sin_cos [5 ] <= 12'hEA5;
dds_sin_cos [6 ] <= 12'hF63;
dds_sin_cos [7 ] <= 12'hFD7;
dds_sin_cos [8 ] <= 12'hFFF;
dds_sin_cos [9 ] <= 12'hFD7;
dds_sin_cos [10] <= 12'hF63;
dds_sin_cos [11] <= 12'hEA5;
dds_sin_cos [12] <= 12'hDA7;
dds_sin_cos [13] <= 12'hC70;
dds_sin_cos [14] <= 12'hB0E;
dds_sin_cos [15] <= 12'h98E;
dds_sin_cos [16] <= 12'h7FF;
dds_sin_cos [17] <= 12'h66F;
dds_sin_cos [18] <= 12'h4EF;
dds_sin_cos [19] <= 12'h38D;
dds_sin_cos [20] <= 12'h256;
dds_sin_cos [21] <= 12'h158;
dds_sin_cos [22] <= 12'h9A ;
dds_sin_cos [23] <= 12'h26 ;
dds_sin_cos [24] <= 12'h0 ;
dds_sin_cos [25] <= 12'h26 ;
dds_sin_cos [26] <= 12'h9A ;
dds_sin_cos [27] <= 12'h158;
dds_sin_cos [28] <= 12'h256;
dds_sin_cos [29] <= 12'h38D;
dds_sin_cos [30] <= 12'h4EF;
dds_sin_cos [31] <= 12'h66F;
count_over <= 24'd312500 / freq - 1'b1;
end
2'b10://triangle
begin
dds_triangle[0] <= 12'h7FF;
dds_triangle[1] <= 12'hFFE;
dds_triangle[2] <= 12'h7FF;
dds_triangle[3] <= 12'h0;
count_over <= 24'd2500000 / freq - 1'b1;
end
2'b11://square
count_over <= 24'd5000000 / freq - 1'b1;
default:count_over <= 24'd5000000 / freq - 1'b1;
endcase
end
else
begin
case (sel)
2'b00://sin
begin
f_count <= f_count + 1'b1;
if (f_count == count_over)
begin
if (i == 5'd31)
i <= 5'd0;
else
i <= i + 1'b1;
signal_dds_reg <= dds_sin_cos[i];
f_count <= 24'b0;
end
end
2'b01://cos
begin
f_count <= f_count + 1'b1;
if (f_count == count_over)
begin
if (i == 5'd31)
i <= 5'd0;
else
i <= i + 1'b1;
signal_dds_reg <= dds_sin_cos[i];
f_count <= 24'b0;
end
end
2'b10://triangle
begin
f_count <= f_count + 1'b1;
if (f_count == count_over)
begin
if (i == 5'd3)
i <= 5'd0;
else
i <= i + 1'b1;
signal_dds_reg <= dds_triangle[i];
f_count <= 24'b0;
end
end
2'b11://square
begin
f_count <= f_count + 1'b1;
if (f_count == count_over)
begin
signal_square_reg <= ~signal_square_reg;
f_count <= 24'd0;
end
end
default:
begin
signal_square_reg <= 1'bz;
end
endcase
end
end
endmodule
testbench如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer: longrejoy
//
// Create Date: 2017/04/24 01:34:33
// Design Name:
// Module Name: testbench
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module testbench();
reg clk;
reg [23:0] freq;
wire square;
wire [11:0] triangle;
wire [11:0] cos;
wire [11:0] sin;
//reg [1:0] sel;
reg rstn;
initial
begin
clk = 1'b0;
rstn = 1'b1;
freq = 24'd1000;
# 100 rstn = 1'b0;
# 10 rstn = 1'b1;
end
always #50 clk = ~clk;
signal_gen square_inst(
.clk(clk), //clock,fixed to 10MHz pls
.freq(freq), //[23:0] target frquence in Hz between 1 and 5M for square,1 ang 2.5M for triangle,312.5KHz for sin and cos
.signal_square(square), //signal of square
.signal_dds(), //signal of triangle ,sin or cos
.sel(2'b11), //[1:0] wave form, 00->sin, 01->cos, 10->triangle, 11->square
.rstn(rstn) //reset, low level reset the module
);
signal_gen triangle_inst(
.clk(clk), //clock,fixed to 10MHz pls
.freq(freq), //[23:0] target frquence in Hz between 1 and 5M for square,1 ang 2.5M for triangle,312.5KHz for sin and cos
.signal_square(), //signal of square
.signal_dds(triangle), //signal of triangle ,sin or cos
.sel(2'b10), //[1:0] wave form, 00->sin, 01->cos, 10->triangle, 11->square
.rstn(rstn) //reset, low level reset the module
);
signal_gen cos_inst(
.clk(clk), //clock,fixed to 10MHz pls
.freq(freq), //[23:0] target frquence in Hz between 1 and 5M for square,1 ang 2.5M for triangle,312.5KHz for sin and cos
.signal_square(), //signal of square
.signal_dds(cos), //signal of triangle ,sin or cos
.sel(2'b01), //[1:0] wave form, 00->sin, 01->cos, 10->triangle, 11->square
.rstn(rstn) //reset, low level reset the module
);
signal_gen sin_inst(
.clk(clk), //clock,fixed to 10MHz pls
.freq(freq), //[23:0] target frquence in Hz between 1 and 5M for square,1 ang 2.5M for triangle,312.5KHz for sin and cos
.signal_square(), //signal of square
.signal_dds(sin), //signal of triangle ,sin or cos
.sel(2'b00), //[1:0] wave form, 00->sin, 01->cos, 10->triangle, 11->square
.rstn(rstn) //reset, low level reset the module
);
endmodule
仿真结果如下:
注意:
if (i == 5'd31)
i <= 5'd0;
else
i <= i + 1'b1;
这边一定要这么写,不能写成
i <= i + 1'b1;
if (i == 5'd32)
i <= 5'd0;