博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

信号监测---verilog

Posted on 2018-10-16 16:43  沉默改良者  阅读(925)  评论(0编辑  收藏  举报

信号监测---verilog

此模块用于监测某一信号源是否持续稳定的传送。

监测思路:监测信号源高电平或者低电平的宽度是否始终保持一致(一定范围内允许有误差)

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: chensimin
// 
// Create Date: 2018/10/12 14:43:57
// Design Name: 
// Module Name: signal_detection
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module signal_detection #(
    parameter WIDTH             = 32 ,
    parameter MAXIMUM_ERROR     = 10 ,
    parameter CNT_CLK_FREQUENCY = 27 ,
    parameter DELAY_SIGNAL_OUT  = 3,
    parameter TOTAL_TIME_HIGH   = 100000,
    parameter TOTAL_TIME_LOW    = 100000
    )
(
    input   wire               clk ,
    input   wire               clk_out_syn ,
    input   wire               rst ,
    input   wire               signal_src ,
    output  wire               lock
);

//----------------------------------------------------------------------

// Signal source synchronization

reg signal_src_delay_1 = 0 ;
reg signal_src_delay_2 = 0 ;

always @(posedge clk or posedge rst)
begin
    if(rst)
    begin
        signal_src_delay_1 <= 1'b0 ;
        signal_src_delay_2 <= 1'b0 ;
    end
    else 
    begin
        signal_src_delay_1 <= signal_src ;
        signal_src_delay_2 <= signal_src_delay_1 ;
    end
end

//----------------------------------------------------------------------

//Rising edge detection

assign rising_edge  =   signal_src_delay_1  && (!signal_src_delay_2) ; 
assign falling_edge = (!signal_src_delay_1) &&   signal_src_delay_2  ; 

//----------------------------------------------------------------------

//count enable 信号上升沿开始计数,下降沿停止计数,此模块采用的是计算高电平的宽度

reg cnt_en = 0 ;

always @(posedge clk or posedge rst)
begin
    if(rst)
        cnt_en <= 1'b0 ;
    else if(rising_edge)
        cnt_en <= 1'b1 ;
    else if(falling_edge)
        cnt_en <= 1'b0 ;
end

//----------------------------------------------------------------------

//count clock period

reg [15:0] cnt = 0;

always @(posedge clk or posedge rst)
begin
    if(rst)
        cnt <= 16'd0 ;
    else if(cnt_en)
        cnt <= cnt + 1'b1 ;
    else 
        cnt <= 16'd0 ;
end


//----------------------------------------------------------------------

//total 存储两个相邻高电平的宽度

reg [15:0] total_number = 0;
reg [15:0] total_number_delay = 0;
reg [15:0] total_number_delay_1 = 0;
always @(posedge clk or posedge rst)
begin
    if(rst)
    begin
        total_number <= 16'd0 ;
        total_number_delay <= 16'd0 ;
        total_number_delay_1 <= 16'd0 ;
    end
    else if(falling_edge)
    begin
        total_number <= cnt ;
        total_number_delay <= total_number ;
        total_number_delay_1 <= total_number_delay ;
    end
    else if(get_total_time_high || get_total_time_low)
    begin 
        total_number <= 16'd0 ;
        total_number_delay <= 16'd0 ;
        total_number_delay_1 <= 16'd0 ;

    end
end
//此处或得了相邻三个高电平的宽度值
//----------------------------------------------------------------------

localparam UNLOCK = 1'b0;
localparam LOCK   = 1'b1;

//----------------------------------------------------------------------

wire   lock_state_1 ;
wire   lock_state_2 ; 

//考虑高电平宽度误差量
assign lock_state_1 = (total_number >= total_number_delay_1) && ((total_number - total_number_delay_1) <= MAXIMUM_ERROR) && (total_number > 16'd100) ; assign lock_state_2 = (total_number < total_number_delay_1) && ((total_number_delay_1 - total_number) <= MAXIMUM_ERROR) && (total_number > 16'd100) ; //用total_number 与 total_number_delay_1 两个值来参与运算,是考虑到了隔行视频,相邻两个高电平的宽度是不一样的,因为一帧有两场,即一帧中有两个V信号的有效区间 //---------------------------------------------------------------------- // 1us reg get_time_1us ; reg [WIDTH-1:0] m ; always @ ( posedge clk or posedge rst ) begin if( rst ) begin get_time_1us <= 1'b0; m <= 0; end else if( m == CNT_CLK_FREQUENCY - 1 ) begin get_time_1us <= 1'b1; m <= 0; end else begin get_time_1us <= 1'b0; m <= m + 1'b1; end end //---------------------------------------------------------------------- reg get_total_time_high ; reg get_total_time_low ; reg [WIDTH-1:0] i ; reg [WIDTH-1:0] k ; always @ (posedge clk or posedge rst) begin if(rst) begin get_total_time_high <= 1'b0 ; get_total_time_low <= 1'b0 ; i <= 0 ; k <= 0 ; end else begin get_total_time_high <= 1'b0 ; get_total_time_low <= 1'b0 ; if(signal_src_delay_2 == 1'b0) begin if( i == TOTAL_TIME_LOW -1 ) begin get_total_time_low <= 1'b1 ; i <= 0 ; end else if(get_time_1us) i <= i + 1'b1 ; end else i <= 0; if(signal_src_delay_2 == 1'b1) begin if( k == TOTAL_TIME_HIGH -1 ) begin get_total_time_high <= 1'b1 ; k <= 0; end else if(get_time_1us) k <= k + 1'b1 ; end else k <= 0 ; end end //---------------------------------------------------------------------- reg current_state ; reg next_state ; always @ ( posedge clk or posedge rst ) begin if( rst ) current_state <= UNLOCK; else current_state <= next_state; end //---------------------------------------------------------------------- always @ ( * ) begin case( current_state ) UNLOCK: if( lock_state_1 || lock_state_2 ) next_state = LOCK; else next_state = UNLOCK; LOCK: if( get_total_time_high || get_total_time_low ) next_state = UNLOCK; else next_state = LOCK; endcase end //---------------------------------------------------------------------- //output reg reg lock_r; always @ (posedge clk or posedge rst) begin if(rst) lock_r <= 1'b0 ; else begin case(current_state) UNLOCK: lock_r <= 1'b0; LOCK : lock_r <= 1'b1; endcase end end reg dly_reg[0:DELAY_SIGNAL_OUT-1]; genvar var_i; generate for (var_i=0;var_i<=DELAY_SIGNAL_OUT-1;var_i=var_i+1) begin:delay_generate_block if (var_i==0) begin always @ (posedge clk_out_syn or posedge rst) if (rst) dly_reg[var_i] <= 0; else dly_reg[var_i] <= lock_r; end else begin always @ (posedge clk_out_syn or posedge rst) if (rst) dly_reg[var_i] <= 0; else dly_reg[var_i] <= dly_reg[var_i-1]; end end endgenerate assign lock = dly_reg[DELAY_SIGNAL_OUT-1]; endmodule

仿真结果: