fpga ADC模块 常用小模块(测频率、测Vpp)

我的是12位adc

目录

1.vpp_calc测量峰峰值

2.freq_calc等精度数字频率计

3.脉冲生成模块


模块3是配合1,2使用的

1.vpp_calc测量峰峰值


// 峰峰值测量模块 12位adc 单位用mV

module vpp_calc(  
    input               ad_clk,     // AD时钟
    input               clk_50,
    input               rst_n,      // 复位信号
    input      [11:0]    ad_data,    // AD输入数据
    input               ad_pulse,   // 由AD波形得到的脉冲信号
    output reg [11:0]    ad_vpp,     // AD峰峰值 单位是mv
    output reg [11:0]    ad_max,     // AD最大值
    output reg [11:0]    ad_min      // AD最小值
);


reg         vpp_flag;               // 测量峰峰值标志信号
reg         vpp_flag_d;             // vpp_flag 滞后一个ad_clk周期
reg [11:0]   ad_data_max;            // AD一个周期内的 当前 最大值
reg [11:0]   ad_data_min;            // AD一个周期内的 当前 最小值

wire        vpp_flag_pos;           // vpp_flag上升沿标志信号
wire        vpp_flag_neg;           // vpp_flag下降沿标志信号



//边沿检测
//捕获信号上升沿
assign vpp_flag_pos = (~vpp_flag_d) & vpp_flag;
//下降沿
assign vpp_flag_neg = vpp_flag_d & (~vpp_flag);

//利用vpp_flag标志一个被测时钟周期 ----------------- ad_pulse是待测信号同频率的一个方波(比较后得到的)
always @(posedge ad_pulse or negedge rst_n) begin
    if(!rst_n)
        vpp_flag <= 1'b0; 
    else 
        vpp_flag <= ~vpp_flag; 
end

//将vpp_flag延时一个AD时钟周期
always @(posedge ad_clk or negedge rst_n) begin
    if(!rst_n)
        vpp_flag_d <= 1'b0; 
    else 
        vpp_flag_d <= vpp_flag; 
end

//筛选一个被测时钟周期内的最大/最小值
always @(posedge ad_clk or negedge rst_n) begin
    if(!rst_n) begin
        ad_data_max <= 11'd0; 
        ad_data_min <= 11'd0;
    end
    else if(vpp_flag_pos)begin      //测试开始时,默认比较值都为当前adc值
        ad_data_max <= ad_data; 
        ad_data_min <= ad_data;
    end
    else if(vpp_flag_d) begin   
        if(ad_data > ad_data_max)
            ad_data_max <= ad_data; //计算最大值
        if(ad_data < ad_data_min)
            ad_data_min <= ad_data; //计算最小值
    end    
end

//计算被测时钟周期内的峰峰值
always @(posedge ad_clk or negedge rst_n) begin
    if(!rst_n) begin
        ad_vpp <= 12'd0;
        ad_max <= 12'd0;
        ad_min <= 12'd0;
    end
    else if(vpp_flag_neg) begin     // 测量结束时结算
        ad_vpp <= ((ad_data_max - ad_data_min)*1000)/968;     //根据ADC来调整  vpp=1v对应968
        ad_max <= ad_data_max;
        ad_min <= ad_data_min;
    end
end








endmodule 

2.freq_calc等精度数字频率计

测正弦波频率,直接拿最高位给数字频率计,相当于trigger为0,也可以自己设置trigger的值,每次比较产生一个方波,然后给数字频率计测频率

module  freq_calc
(
    input   wire            sys_clk     ,      // 50MHz
    input   wire            sys_rst_n   ,   
    input   wire            clk_test    ,     // 待测信号
    input   wire            stand_clk   ,     // 100MHz
    output  reg     [33:0]  freq            

);

parameter   CNT_GATE_S_MAX  =   28'd74_999_999  , 
            CNT_RISE_MAX    =   28'd12_500_000  ; 
parameter   CLK_STAND_FREQ  =   28'd100_000_000 ; 

wire            clk_stand           ;
wire            gate_a_fall_s       ;
wire            gate_a_fall_t       ;

reg     [27:0]  cnt_gate_s          ; 
reg             gate_s              ; 
reg             gate_a              ; 
reg             gate_a_stand        ; 
reg             gate_a_test         ;
reg     [47:0]  cnt_clk_stand       ; 
reg     [47:0]  cnt_clk_stand_reg   ; 
reg     [47:0]  cnt_clk_test        ; 
reg     [47:0]  cnt_clk_test_reg    ; 
reg             calc_flag           ;
reg     [63:0]  freq_reg            ; 
reg             calc_flag_reg       ; 


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_gate_s  <=  28'd0;
    else    if(cnt_gate_s == CNT_GATE_S_MAX)
        cnt_gate_s  <=  28'd0;
    else
        cnt_gate_s  <=  cnt_gate_s + 1'b1;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        gate_s  <=  1'b0;
    else    if((cnt_gate_s>= CNT_RISE_MAX)
                && (cnt_gate_s <= (CNT_GATE_S_MAX - CNT_RISE_MAX)))
        gate_s  <=  1'b1;
    else
        gate_s  <=  1'b0;

always@(posedge clk_test or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        gate_a  <=  1'b0;
    else
        gate_a  <=  gate_s;

always@(posedge clk_stand or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_clk_stand   <=  48'd0;
    else    if(gate_a == 1'b0)
        cnt_clk_stand   <=  48'd0;
    else    if(gate_a == 1'b1)
        cnt_clk_stand   <=  cnt_clk_stand + 1'b1;

always@(posedge clk_test or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_clk_test    <=  48'd0;
    else    if(gate_a == 1'b0)
        cnt_clk_test    <=  48'd0;
    else    if(gate_a == 1'b1)
        cnt_clk_test    <=  cnt_clk_test + 1'b1;

always@(posedge clk_stand or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        gate_a_stand    <=  1'b0;
    else
        gate_a_stand    <=  gate_a;

assign  gate_a_fall_s = ((gate_a_stand == 1'b1) && (gate_a == 1'b0))
                        ? 1'b1 : 1'b0;

always@(posedge clk_stand or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_clk_stand_reg   <=  32'd0;
    else    if(gate_a_fall_s == 1'b1)
        cnt_clk_stand_reg   <=  cnt_clk_stand;

always@(posedge clk_test or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        gate_a_test <=  1'b0;
    else
        gate_a_test <=  gate_a;

assign  gate_a_fall_t = ((gate_a_test == 1'b1) && (gate_a == 1'b0))
                        ? 1'b1 : 1'b0;

always@(posedge clk_test or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_clk_test_reg   <=  32'd0;
    else    if(gate_a_fall_t == 1'b1)
        cnt_clk_test_reg   <=  cnt_clk_test;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        calc_flag   <=  1'b0;
    else    if(cnt_gate_s == (CNT_GATE_S_MAX - 1'b1))
        calc_flag   <=  1'b1;
    else
        calc_flag   <=  1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        freq_reg    <=  64'd0;
    else    if(calc_flag == 1'b1)
        freq_reg    <=  (CLK_STAND_FREQ * cnt_clk_test_reg / cnt_clk_stand_reg  ) + 1'd1;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        calc_flag_reg   <=  1'b0;
    else
        calc_flag_reg   <=  calc_flag;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        freq    <=  34'd0;
    else    if(calc_flag_reg == 1'b1)
        freq    <=  freq_reg;

assign clk_stand = stand_clk;

endmodule

3.脉冲生成模块




module pulse_gen(
    input            rst_n,      //系统复位,低电平有效
    
    input  [11:0]    trig_level,

    input            ad_clk,     //ADC模块驱动时钟
    input  [11:0]    ad_data,    //AD输入数据 12位

    
    output           ad_pulse    //输出的脉冲信号
);

parameter CNT_MAX = 10'd20;

//reg define
reg [12:0] cnt;

reg pulse;
reg pulse_delay;
reg pulse_delay2;
reg pulse_delay3;



assign ad_pulse = pulse & pulse_delay & pulse_delay2 & pulse_delay3;

//根据触发电平,将输入的AD采样值转换成高低电平
always @ (posedge ad_clk or negedge rst_n)begin
    if(!rst_n)
        pulse <= 1'b0;
    else
        if(ad_data < trig_level)
            pulse <= 1'b0;
        else
            pulse <= 1'b1;
end

always@(posedge ad_clk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt <= 20'b0;
    else    if(pulse == 1'b0)
        cnt <= 20'b0;
    else    if(cnt == CNT_MAX && pulse == 1'b1)
        cnt <= cnt;
    else
        cnt <= cnt + 1'b1;

//延时一个时钟周期,用于消除抖动
always @ (posedge ad_clk or negedge rst_n)begin
    if(!rst_n)
        pulse_delay <= 1'b0;
    else
        pulse_delay <= pulse;
end

//延时一个时钟周期,用于消除抖动
always @ (posedge ad_clk or negedge rst_n)begin
    if(!rst_n)
        pulse_delay2 <= 1'b0;
    else
        pulse_delay2 <= pulse_delay;
end

//延时一个时钟周期,用于消除抖动
always @ (posedge ad_clk or negedge rst_n)begin
    if(!rst_n)
        pulse_delay3 <= 1'b0;
    else
        pulse_delay3 <= pulse_delay2;
end


endmodule 

你可能感兴趣的:(fpga开发)