信号监测---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
仿真结果: