2020-09-29在线检测模块 有时钟和脉冲两种模式 学习笔记

在线检测模块    有时钟和脉冲两种模式测试

module online_detect #(
    parameter                    SYS_CLK_period    = 100        ,    //系统时钟周期
    parameter                    DETECT_period    = 100        ,    //检测周期
    parameter                    MODE_select        = 1                //模式选择                                                            
    )                                                       
    (                                                       
    input                         i_sys_clk                    ,    //输入系统时钟
    input                        i_sys_rst                    ,    //输入系统复位
    input                        i_det_sig                    ,    //输入被测信号
    output                        o_det_state                        //输出被检测信号
    );                                                      
    reg                            oline_flag        = 1'b0        ;   //在线标志,若是在线,信号正常,反之不正常                                                  
    reg    [31:0]                    cnt_1pps        = 32'd0        ;    //1pps的计数器
    reg                            div_1pps        = 1'b0        ;    //1pps脉冲
    reg    [1:0]                    mux_reg            = 2'b0        ;    //检测信号被打两拍以后的信号
    wire                        mux_select_sig                ;    //模式选择以后的信号
    wire                        mux_sig_pose                ;    //最终被检测信号的上升沿
    wire[31:0]                    div_param                    ;   //偏差容许范围                                                   
    reg    [31:0]                    pulse_cnt        = 32'd0        ;    //脉冲计数器
    reg    [3:0]                    online_state    = 4'd0        ;    //状态机
    reg                            runout_flag        = 0            ;   //溢出标志    
    wire [31:0]                    MAX_TAGE                    ;    //偏差上限
    wire [31:0]                    MIX_TAGE                    ;   //偏差下限                      
    parameter                    FSM_online_no     = 4'd0        ;    //不在线状态
    parameter                    FSM_MID1        = 4'd1        ;    //中间状态1
    parameter                    FSM_MID2         = 4'd2        ;    //中间状态2
    parameter                    FSM_online_ok     = 4'd3        ;    //在线状态    
    parameter    [31:0]            DIV_1S            = 32'd200    ;    //1s时间间隔
    parameter    [31:0]            DIV_F_10M        = 32'd200    ;    //10M信号检测
    parameter                    test_period        = 4*DIV_1S    ;    //测试周期
        
    assign        o_det_state        = oline_flag                            ;    //在线标志赋值给输出端口
    assign        mux_select_sig    = MODE_select    ? div_1pps    : i_det_sig    ;    //选择在线检测仍是1pps分频以后检测
    assign        mux_sig_pose    = !mux_reg[1]     && mux_reg[0]            ;    //被检测信号的上升沿信号
    assign        div_param        = MODE_select    ? DIV_1S    : DIV_F_10M    ;    //选择检测模式是时钟仍是脉冲,这里选择脉冲
    assign        MAX_TAGE        = div_param    + div_param/10_000_000        ;    //偏差上限
    assign        MIX_TAGE        = div_param    - div_param/10_000_000        ;    //偏差下限input

 

    always @ (posedge i_det_sig or posedge i_sys_rst)    //i_det_sig信号1s分频
    begin
        if(i_sys_rst)
        begin
            div_1pps    <= 0                        ;
            cnt_1pps    <= DETECT_period            ;
        end 
        else if(cnt_1pps == DIV_1S)        //计数到1s时输出一个1pps
        begin
            div_1pps    <= 1                        ;
            cnt_1pps    <= DETECT_period            ;
        end 
        else 
        begin
            div_1pps    <= 0                        ;
            cnt_1pps    <= cnt_1pps + DETECT_period    ;
        end
    end 
    
    always @ (posedge i_sys_clk)            //被检测信号打两拍
    begin
        mux_reg            <= {mux_reg[0],mux_select_sig}    ;
    end 
        
    always @ (posedge i_sys_clk or posedge i_sys_rst)//溢出标志和脉冲计数
    begin
        if(i_sys_rst)
        begin
            pulse_cnt        <= SYS_CLK_period    ;    //脉冲计数清零
            runout_flag        <= 0                ;    //溢出标志拉低
        end 
        else if(mux_sig_pose)
        begin
            pulse_cnt        <= SYS_CLK_period    ;    //上升沿来的时候计数器清零
            runout_flag        <= 0                ;    //上升沿来的时候溢出标志拉低
        end 
        else if(pulse_cnt >=  test_period)            //计数器大于检测周期的时候溢出标志拉高,计数器保持不变
        begin
            pulse_cnt        <= pulse_cnt        ;    
            runout_flag        <= 1                ;    
        end 
        else 
        begin
            pulse_cnt         <= pulse_cnt + SYS_CLK_period    ;
            runout_flag        <= 0            ;
        end 
    end     
        
    always @ (posedge i_sys_clk or posedge i_sys_rst)    //状态机
    begin
        if (i_sys_rst)
        begin
            online_state    <= FSM_online_no    ;
        end 
        else 
        begin
        case(online_state)
        FSM_online_no    :
            begin
            if( !runout_flag && mux_sig_pose )        //若是没有溢出而且上升沿来到的时候
            begin
                if( (pulse_cnt >=MIX_TAGE) && pulse_cnt <=MIX_TAGE) //而且脉冲计数器在偏差范围以内的时候,调到下一个状态
                begin
                online_state    <= FSM_MID1    ;
                end     
                else 
                begin
                online_state    <= FSM_online_no    ;
                end     
            end
            else  
            begin
                online_state    <= FSM_online_no    ;
            end
            end      
        FSM_MID1    :
            begin
            if(runout_flag ) //若是溢出,跳到不在线状态
            begin
                    online_state    <= FSM_online_no    ;
            end 
            else if(mux_sig_pose)
            begin
                if(pulse_cnt >=MIX_TAGE && pulse_cnt <=MIX_TAGE) //若是上升沿来的时候而且脉冲计数器在偏差范围内跳到下一个状态
                begin
                    online_state    <= FSM_MID2    ;
                end     
                else 
                begin
                    online_state    <= FSM_online_no    ;
                end 
            end     
            else         
            begin
                    online_state    <= FSM_MID1            ;
            end         
            end 
        FSM_MID2    :
            begin
            if(runout_flag) //若是溢出,跳到不在线状态
            begin
                    online_state    <= FSM_online_no    ;
            end 
            else if(mux_sig_pose)
            begin
                if(pulse_cnt >=MIX_TAGE && pulse_cnt <=MIX_TAGE) //若是上升沿来的时候而且脉冲计数器在偏差范围内跳到下一个状态
                begin
                    online_state    <= FSM_online_ok    ;
                end     
                else         
                begin
                    online_state    <= FSM_MID1            ;    //若是上升沿没有来返回到上一个状态从新检测
                end 
            end     
            else 
            begin
                    online_state    <= FSM_MID2    ;
            end         
            end 
        FSM_online_ok    :
            begin
            if(runout_flag) //若是溢出,跳到不在线状态
            begin
                    online_state    <= FSM_online_no    ;
            end 
            else if(mux_sig_pose)
            begin
                if((pulse_cnt >=MIX_TAGE) && (pulse_cnt <=MIX_TAGE))  //若是上升沿来的时候而且脉冲计数器在偏差范围内跳到下一个状态
                begin
                    online_state    <= FSM_online_ok    ;
                end     
                else 
                begin
                    online_state    <= FSM_MID2            ;    //若是上升沿没有来返回到上一个状态从新检测
                end 
            end     
            else 
            begin
                    online_state    <= FSM_MID1    ;
            end         
            end
        default        :
            begin
                    online_state    <= FSM_online_no    ;
            end 
    endcase
    end 
    end 
    
    always @ (posedge i_sys_clk )    //信号在线标志模块
    begin
        case(online_state)
        FSM_online_no    :
        begin
            oline_flag    <= 1'b0            ;
        end 
        FSM_online_ok    :
        begin
            oline_flag    <= 1'b1            ;
        end 
        default     :
        begin
            oline_flag    <= oline_flag    ;
        end 
        endcase    
    end 
endmodule
 it


  测试代码部分io

 

module online_ddetect_tb();
    reg                i_sys_clk    ;
    reg                i_sys_rst    ;
    reg                i_det_sig    ;
    wire            o_det_state    ;
    initial
    begin
        i_sys_clk    =    0    ;
        i_sys_rst    =     0    ;
        i_det_sig    =     0    ;
    #100 i_sys_rst    =     1    ; 
    #20  i_sys_rst    =     0    ;           
    end 
    
    always # 50    i_sys_clk = ~i_sys_clk      ;
    always    #50    i_det_sig = ~i_det_sig        ;test

    online_detect #(
    .SYS_CLK_period    (100    ),//系统时钟周期
    .DETECT_period    (100    ),    //检测周期
    .MODE_select    (1        )    //模式选择
    
    )
     online_detect_inst    (
    .i_sys_clk    (i_sys_clk),//输入系统时钟
    .i_sys_rst    (i_sys_rst),//输入系统复位
    .i_det_sig    (i_det_sig),//输入被测信号
    .o_det_state(o_det_state)    //输出被检测信号
    );module

endmodule
 sed