首页 > 代码库 > 测量占空比

测量占空比

最近尝试了很多方法测量占空比,虽然说原理简单,但是测量的时候误差还是挺大的,凡是没呢么容易,

最后终于实现了1HZ-5M 占空比的测量,精度小于%0.1

另外发现了一个问题,fpga一条语句如果很复杂的话,可能会出现问题。

例如 assign  duty_altera = pinlv << 1 + pinlv;也就是pinlv_altera 是频率的三倍,在sigtab仿真时出错了,如果把这两条语句分开写就没毛病了。

程序思路:

设定一个1S钟的闸门,在闸门有效期间测量高电平持续时间和低电平持续时间,需要注意的是:

在测量时间时需要以边沿做为开始计数的标志,否则程序容易崩溃。然而实际测量出来,还是有误差的,经过测量多组数据发现:高电平测量的时间所记录的个数比实际上少记录了2*pinlv个,而低电平恰恰相反。经过补偿,满足题目的要求。

module    duty(
        //system    interface
        input                clk,
        input                rst_n,
        //sig        interface
        input                sig_in,
        //pinlv        interface
        input        [31:0]    pinlv,
        //user        interface
        output    reg    [15:0]    duty,
        output    reg    [31:0]    cnt_high,
        output    reg    [31:0]    cnt_low,
        output                high_pulse,
        output                low_pulse,
        output        [31:0]    duty_alter
);

//buffer
reg        sig_in_buffer;
reg        sig_in_buffer1;
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
    begin
        sig_in_buffer  <= 0;
        sig_in_buffer1 <= 0;
    end
    else
    begin
        sig_in_buffer  <= sig_in;
        sig_in_buffer1 <= sig_in_buffer;
    end
end
assign        high_pulse =  (sig_in_buffer == 1 && sig_in_buffer1 == 0) ? 1 : 0;
assign        low_pulse  =  (sig_in_buffer == 0 && sig_in_buffer1 == 1) ? 1 : 0;
//parameter        CNT_1S = 32‘d199_9;
parameter        CNT_1S = 32d199_999_999;
reg        [31:0]    cnt_1s;
reg                fgate;

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt_1s <= 0;
    else if(cnt_1s >= CNT_1S)
        cnt_1s <= 0;
    else 
        cnt_1s <= cnt_1s + 1;
end

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        fgate <= 0;
    else if(cnt_1s == CNT_1S)
        fgate <= ~fgate;
    else
        fgate <= fgate;
end


reg        fstart;
always @(posedge sig_in_buffer1 or negedge rst_n)
begin
    if(!rst_n)
        fstart <= 0;
    else if(fgate)
        fstart <= 1;
    else
        fstart <= 0;
end
reg        [2:0]        state_high;
reg        [2:0]        state_low;
//cnt
reg        [31:0]        cnt_high_temp;
reg        [31:0]        cnt_low_temp;

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        state_high <= 0;
    else
    case(state_high)
    2d0 :
    begin
        if(high_pulse)
            state_high <= 2d1;
        else
            state_high <= 2d0;
    end
    
    2d1 :
    begin
        if(low_pulse)
            state_high <= 2d0;
        else
            state_high <= 2d1;
    end
    
    default : ;
    endcase
end

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        state_low <= 0;
    else
    case(state_low)
    2d0 :
    begin
        if(low_pulse)
            state_low <= 2d1;
        else
            state_low <= 2d0;
    end
    
    2d1 :
    begin
        if(high_pulse)
            state_low <= 2d0;
        else
            state_low <= 2d1;
    end

    default : ;
    endcase
end
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt_high_temp <= 0;
    else if(fstart)
    begin
        if(state_high == 1)
            cnt_high_temp <= cnt_high_temp + 1;
        else
            cnt_high_temp <= cnt_high_temp;
    end
    else
        cnt_high_temp <= 0;    
end

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt_low_temp <= 0;
    else if(fstart)
    begin
        if(state_low == 1)
            cnt_low_temp <= cnt_low_temp + 1;
        else
            cnt_low_temp <= cnt_low_temp;
    end
    else
        cnt_low_temp <= 0;    
end
wire    [31:0]    pinlv1;
assign    pinlv1     = pinlv << 1;
assign    duty_alter =  pinlv << 1;

always @(negedge fstart or negedge rst_n)
begin
    if(!rst_n)
    begin
        cnt_high <= 0;
        cnt_low <= 0;
    end
    else
    begin
        cnt_high <= cnt_high_temp + duty_alter ;
        cnt_low  <= cnt_low_temp  - duty_alter ; 
    end
end






endmodule

 

测量占空比