波形发生器

来源:互联网 发布:国内外手游推荐知乎 编辑:程序博客网 时间:2024/05/01 20:13

为了给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;

0 0
原创粉丝点击