信號監測---verilogspa
此模塊用於監測某一信號源是否持續穩定的傳送。code
監測思路:監測信號源高電平或者低電平的寬度是否始終保持一致(必定範圍內容許有偏差)視頻
`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
仿真結果:blog