仿真验证已通过,有问题欢迎指正和讨论
//
// Company:
// Engineer: Deng zhuo bin(邓工)
//
// Create Date: 2023/6/02 10:00:16
// Design Name:
// Module Name: infrared_decode
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module infrared_decode#
(
parameter GUIDE_CODE_9MS_H = 19'd450_000,
parameter GUIDE_CODE_4_5MS_L = 18'd225_000,
parameter A_D_R_CODE_560US_H = 15'd280_00,
parameter A_D_CODE_1690US_L = 17'd845_00,
parameter A_D_CODE_560US_L = 15'd280_00,
parameter REPEAT_CODE_TIME_INTERVAL_110MS = 23'd5_500_000,
parameter REPEAT_CODE_9MS_H = 19'd450_000,
parameter REPEAT_CODE_2250US_L = 17'd112_500,
parameter REPEAT_CODE_560US_H = 15'd280_00
)
(
input sys_clk,
input sys_rst_n,
input i_infrared,
output reg [7:0] o8_decode_data
);
localparam SM00 = 5'd0,
SM01 = 5'd1,
SM02 = 5'd2,
SM03 = 5'd3,
SM04 = 5'd4,
SM05 = 5'd5,
SM06 = 5'd6,
SM07 = 5'd7,
SM08 = 5'd8,
SM09 = 5'd9,
SM10 = 5'd10,
SM11 = 5'd11,
SM12 = 5'd12,
SM13 = 5'd13,
SM14 = 5'd14,
SM15 = 5'd15,
SM16 = 5'd16,
SM17 = 5'd17,
SM18 = 5'd18,
SM19 = 5'd19;
parameter A_D_NUM_MAX = 4'd8;
reg r_infrared_cur;
reg r_infrared_pre;
wire w_infrared_fall;
wire w_infrared_rise;
reg [4:0] r5_state_cur;
reg [4:0] r5_state_next;
reg [14:0] r15_560us_cnt;
reg [16:0] r17_1690_560us_cnt;
reg [17:0] r18_4_5ms_cnt;
reg [18:0] r19_9ms_cnt;
reg [3:0] r4_a_d_cnt;
reg [31:0] r32_a_d_data;
reg [7:0] r8_addr_inv_data;
reg r_addr_inv_receive_finish;
reg r_addr_receive_finish;
reg r_data_receive_finish;
reg [7:0] r8_data_data;
reg [7:0] r8_data_inv_data;
reg r_data_inv_receive_finish;
reg [7:0] r8_addr_data;
reg [16:0] r17_2_25ms_cnt;
reg [22:0] r23_repeat_time_cnt;
reg r_addr_check;
reg r_data_check;
wire w_560us_h;
wire w_g_code_4_5ms_l;
wire w_g_code_9ms_h;
//wire w_addr_receive_finish;
wire w_a_d_value;
//wire w_addr_inv_receive_finish;
wire w_r_code_9ms_h;
wire w_r_code_2_25ms_l;
wire w_r_code_560us_h;
/*generate fall and rise edge*/
assign w_infrared_fall = ((r_infrared_pre == 1'b1)&&(r_infrared_cur == 1'b0)) ? 1'b1 : 1'b0;
assign w_infrared_rise = ((r_infrared_pre == 1'b0)&&(r_infrared_cur == 1'b1)) ? 1'b1 : 1'b0;
/*Synchronization from asynchronous clock signals,at the same time,generate fall and rise condition */
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
r_infrared_pre <= 1'b0;
r_infrared_cur <= 1'b0;
end
else begin
r_infrared_cur <= i_infrared;
r_infrared_pre <= r_infrared_cur;
end
end
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
r5_state_cur <= SM00;
end
else begin
r5_state_cur <= r5_state_next;
end
end
/*state motor*/
always@(*)begin
case(r5_state_cur)
SM00 : //wait guide code 9ms rise edge arrive
begin
if(w_infrared_rise == 1'b1)
begin
r5_state_next = SM01;
end
else
begin
r5_state_next = SM00;
end
end
SM01 : //wait guide code 9ms high pulse count finish and guide code 9ms high pulse fall edge arrive
begin
if((w_g_code_9ms_h == 1'b1)&&(w_infrared_fall == 1'b1))
begin
r5_state_next = SM02;
end
else
begin
r5_state_next = SM01;
end
end
SM02 : //wait guide code 4.5ms rise edge arrive and guide code 4.5ms low pulse count finish
begin
if((w_infrared_rise == 1'b1)&&(w_g_code_4_5ms_l == 1'b1))
begin
r5_state_next = SM03;
end
else
begin
r5_state_next = SM02;
end
end
SM03 : //wait address code 560us high pulse count finish and address code 560us fall edge arrive
begin
if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
begin
r5_state_next = SM04;
end
else
begin
r5_state_next = SM03;
end
end
SM04 :
begin
//wait address code 560us or 1690us rise arrive and address code 560us or 1690us low count finish
if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM03;
end
//wait address code 560us or 1690us rise arrive and address code 560us or 1690us low count finish and 8 bits address code receive finish
else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM05;
end
else
begin
r5_state_next = SM04;
end
end
SM05 : //address inversion code
begin
if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
begin
r5_state_next = SM06;
end
else
begin
r5_state_next = SM05;
end
end
SM06 :
begin
if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM05;
end
else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM07;
end
else
begin
r5_state_next = SM06;
end
end
SM07 : //data code
begin
if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
begin
r5_state_next = SM08;
end
else
begin
r5_state_next = SM07;
end
end
SM08 :
begin
if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM07;
end
else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM09;
end
else
begin
r5_state_next = SM08;
end
end
SM09 : //data inversion code
begin
if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
begin
r5_state_next = SM10;
end
else
begin
r5_state_next = SM09;
end
end
SM10 :
begin
if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM09;
end
else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
begin
r5_state_next = SM11;
end
else
begin
r5_state_next = SM10;
end
end
SM11 : //send repeat code 110ms time interval
begin
if(r23_repeat_time_cnt == REPEAT_CODE_TIME_INTERVAL_110MS - 1'b1)
begin
r5_state_next = SM12;
end
else
begin
r5_state_next = SM11;
end
end
SM12 : //wait repeat code 9ms rise edge arrive
begin
if(w_infrared_rise == 1'b1)
begin
//detecte repeat code
r5_state_next = SM13;
end
else
begin
//not detecte repeat code
r5_state_next = SM16;
end
end
SM13 : //wait repeat code 9ms high pulse count finish and wait repeat code 9ms fall edge arrive
begin
if((w_r_code_9ms_h == 1'b1)&&(w_infrared_fall == 1'b1))
begin
r5_state_next = SM14;
end
else
begin
r5_state_next = SM13;
end
end
SM14 : //wait repeat code 2.25ms low pulse count finish and wait repeat code 2.25ms rise edge arrive
begin
if((w_infrared_rise == 1'b1)&&(w_r_code_2_25ms_l == 1'b1))
begin
r5_state_next = SM15;
end
else
begin
r5_state_next = SM14;
end
end
SM15 : //wait repeat code 560us high pulse count finish and wait repeat code 560us fall edge arrive
begin
if((w_infrared_fall == 1'b1)&&(w_r_code_560us_h == 1'b1))
begin
r5_state_next = SM11;
end
else
begin
r5_state_next = SM15;
end
end
SM16 : //receive a frame data finish
begin
r5_state_next = SM00;
end
default :
begin
r5_state_next = SM00;
end
endcase
end
assign w_g_code_9ms_h = ((r5_state_cur == SM01)&&(r19_9ms_cnt == GUIDE_CODE_9MS_H - 1'b1)) ? 1'b1 : 1'b0;
assign w_g_code_4_5ms_l = ((r5_state_cur == SM02)&&(r18_4_5ms_cnt == GUIDE_CODE_4_5MS_L - 1'b1)) ? 1'b1 : 1'b0;
assign w_560us_h = (((r5_state_cur == SM03)||(r5_state_cur == SM05)
||(r5_state_cur == SM07)||(r5_state_cur == SM09))
&&(r15_560us_cnt == A_D_R_CODE_560US_H - 1'b1)) ? 1'b1 : 1'b0;
assign w_a_d_value = (((r5_state_cur == SM04)||(r5_state_cur == SM06)
||(r5_state_cur == SM08)||(r5_state_cur == SM10))
&&(r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)) ? 1'b1 : 1'b0;
// assign w_addr_receive_finish = ((r5_state_cur == SM04)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1))) ? 1'b1 : 1'b0;
// assign w_addr_inv_receive_finish = ((r5_state_cur == SM06)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1))) ? 1'b1 : 1'b0;
assign w_r_code_9ms_h = ((r5_state_cur == SM13)&&(r19_9ms_cnt == REPEAT_CODE_9MS_H - 1'b1)) ? 1'b1 : 1'b0;
assign w_r_code_2_25ms_l = ((r5_state_cur == SM14)&&(r17_2_25ms_cnt == REPEAT_CODE_2250US_L - 1'b1)) ? 1'b1 : 1'b0;
assign w_r_code_560us_h = ((r5_state_cur == SM15)&&(r15_560us_cnt == REPEAT_CODE_560US_H - 1'b1)) ? 1'b1 : 1'b0;
/*address code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r_addr_receive_finish <= 1'b0;
end
else
begin
if((r5_state_cur == SM04)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
begin
r_addr_receive_finish <= 1'b1;
end
else
begin
r_addr_receive_finish <= 1'b0;
end
end
end
/*address inversion code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r_addr_inv_receive_finish <= 1'b0;
end
else
begin
if((r5_state_cur == SM06)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
begin
r_addr_inv_receive_finish <= 1'b1;
end
else
begin
r_addr_inv_receive_finish <= 1'b0;
end
end
end
/*data code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r_data_receive_finish <= 1'b0;
end
else
begin
if((r5_state_cur == SM08)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
begin
r_data_receive_finish <= 1'b1;
end
else
begin
r_data_receive_finish <= 1'b0;
end
end
end
/*data inversion code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r_data_inv_receive_finish <= 1'b0;
end
else
begin
if((r5_state_cur == SM10)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
begin
r_data_inv_receive_finish <= 1'b1;
end
else
begin
r_data_inv_receive_finish <= 1'b0;
end
end
end
/*counter*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r19_9ms_cnt <= 19'd0;
r18_4_5ms_cnt <= 18'd0;
r15_560us_cnt <= 15'd0;
r17_1690_560us_cnt <= 17'd0;
r4_a_d_cnt <= 4'd0;
r23_repeat_time_cnt <= 23'd0;
r17_2_25ms_cnt <= 17'd0;
end
else
begin
if((r5_state_cur == SM01)&&(r19_9ms_cnt < GUIDE_CODE_9MS_H - 1'b1))
begin
r19_9ms_cnt <= r19_9ms_cnt + 1'b1;
end
else if((r5_state_cur == SM01)&&(r19_9ms_cnt == GUIDE_CODE_9MS_H - 1'b1))
begin
r19_9ms_cnt <= 19'd0;
end
else if((r5_state_cur == SM02)&&(r18_4_5ms_cnt < GUIDE_CODE_4_5MS_L - 1'b1))
begin
r18_4_5ms_cnt <= r18_4_5ms_cnt + 1'b1;
end
else if((r5_state_cur == SM02)&&(r18_4_5ms_cnt == GUIDE_CODE_4_5MS_L - 1'b1))
begin
r18_4_5ms_cnt <= 18'd0;
end
else if(((r5_state_cur == SM03)||(r5_state_cur == SM05)
||(r5_state_cur == SM07)||(r5_state_cur == SM09))
&&(r15_560us_cnt < A_D_R_CODE_560US_H - 1'b1))
begin
r15_560us_cnt <= r15_560us_cnt + 1'b1;
end
else if(((r5_state_cur == SM03)||(r5_state_cur == SM05)
||(r5_state_cur == SM07)||(r5_state_cur == SM09))
&&(r15_560us_cnt == A_D_R_CODE_560US_H - 1'b1))
begin
r15_560us_cnt <= 15'd0;
end
else if(((r5_state_cur == SM04)||(r5_state_cur == SM06)
||(r5_state_cur == SM08)||(r5_state_cur == SM10))
&&(r_infrared_cur == 1'b0)&&(r17_1690_560us_cnt < A_D_CODE_1690US_L - 1'b1))
begin
r17_1690_560us_cnt <= r17_1690_560us_cnt + 1'b1;
end
else if(((r5_state_cur == SM04)||(r5_state_cur == SM06)
||(r5_state_cur == SM08)||(r5_state_cur == SM10))
&&(r_infrared_cur == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)
||(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
begin
r17_1690_560us_cnt <= 17'd0;
r4_a_d_cnt <= r4_a_d_cnt + 1'b1;
end
else if(((r5_state_cur == SM04)||(r5_state_cur == SM06)
||(r5_state_cur == SM08)||(r5_state_cur == SM10))
&&(r_infrared_cur == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)
||(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
begin
r17_1690_560us_cnt <= 17'd0;
r4_a_d_cnt <= 4'd0;
end
else if((r5_state_cur == SM11)&&(r23_repeat_time_cnt < REPEAT_CODE_TIME_INTERVAL_110MS - 1'b1))
begin
r23_repeat_time_cnt <= r23_repeat_time_cnt + 1'b1;
end
else if((r5_state_cur == SM11)&&(r23_repeat_time_cnt == REPEAT_CODE_TIME_INTERVAL_110MS - 1'b1))
begin
r23_repeat_time_cnt <= 23'd0;
end
else if((r5_state_cur == SM13)&&(r19_9ms_cnt < REPEAT_CODE_9MS_H - 1'b1))
begin
r19_9ms_cnt <= r19_9ms_cnt + 1'b1;
end
else if((r5_state_cur == SM13)&&(r19_9ms_cnt == REPEAT_CODE_9MS_H - 1'b1))
begin
r19_9ms_cnt <= 19'd0;
end
else if((r5_state_cur == SM14)&&(r17_2_25ms_cnt < REPEAT_CODE_2250US_L - 1'b1))
begin
r17_2_25ms_cnt <= r17_2_25ms_cnt + 1'b1;
end
else if((r5_state_cur == SM14)&&(r17_2_25ms_cnt == REPEAT_CODE_2250US_L - 1'b1))
begin
r17_2_25ms_cnt <= 17'd0;
end
else if((r5_state_cur == SM15)&&(r15_560us_cnt < REPEAT_CODE_560US_H - 1'b1))
begin
r15_560us_cnt <= r15_560us_cnt + 1'b1;
end
else if((r5_state_cur == SM15)&&(r15_560us_cnt == REPEAT_CODE_560US_H - 1'b1))
begin
r15_560us_cnt <= 15'd0;
end
else
begin
r19_9ms_cnt <= 19'd0;
r18_4_5ms_cnt <= 18'd0;
r15_560us_cnt <= 15'd0;
r17_1690_560us_cnt <= 17'd0;
r4_a_d_cnt <= 4'd0;
r23_repeat_time_cnt <= 23'd0;
end
end
end
/*receive 8 bits address code, address inversion code, data code, data inversion code*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r8_addr_data <= 8'd0;
r8_addr_inv_data <= 8'd0;
r8_data_data <= 8'd0;
r8_data_inv_data <= 8'd0;
end
else
begin
if(r5_state_cur == SM04)
begin
r8_addr_data[r4_a_d_cnt] <= w_a_d_value;
end
else if(r5_state_cur == SM06)
begin
r8_addr_inv_data[r4_a_d_cnt] <= w_a_d_value;
end
else if(r5_state_cur == SM08)
begin
r8_data_data[r4_a_d_cnt] <= w_a_d_value;
end
else if(r5_state_cur == SM10)
begin
r8_data_inv_data[r4_a_d_cnt] <= w_a_d_value;
end
else
begin
r8_addr_data <= r8_addr_data;
r8_addr_inv_data <= r8_addr_inv_data;
r8_data_data <= r8_data_data;
r8_data_inv_data <= r8_data_inv_data;
end
end
end
/*latch a frame 32bits data(8 bits address code, address inversion code, data code, data inversion code)*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r32_a_d_data <= 32'd0;
end
else
begin
if(r_addr_receive_finish == 1'b1)
begin
r32_a_d_data[7:0] <= r8_addr_data;
end
else if(r_addr_inv_receive_finish == 1'b1)
begin
r32_a_d_data[15:8] <= r8_addr_inv_data;
end
else if(r_data_receive_finish == 1'b1)
begin
r32_a_d_data[23:16] <= r8_data_data;
end
else if(r_data_inv_receive_finish == 1'b1)
begin
r32_a_d_data[31:24] <= r8_data_inv_data;
end
else
begin
r32_a_d_data <= r32_a_d_data;
end
end
end
/*address check*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r_addr_check <= 1'b0;
end
else
begin
if(r5_state_cur == SM11)
begin
if(r32_a_d_data[7:0] == ~r32_a_d_data[15:8])
begin
r_addr_check <= 1'b1;
end
else
begin
r_addr_check <= 1'b0;
end
end
else
begin
r_addr_check <= r_addr_check;
end
end
end
/*data check*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
r_data_check <= 1'b0;
end
else
begin
if(r5_state_cur == SM11)
begin
if(r32_a_d_data[23:16] == ~r32_a_d_data[31:24])
begin
r_data_check <= 1'b1;
end
else
begin
r_data_check <= 1'b0;
end
end
else
begin
r_data_check <= r_data_check;
end
end
end
/*output 8 bits effective data*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
o8_decode_data <= 8'd0;
end
else
begin
if((r5_state_cur == SM11)&&(r_data_check == 1'b1))
begin
o8_decode_data <= r32_a_d_data[23:16];
end
else
begin
o8_decode_data <= o8_decode_data;
end
end
end
endmodule
分享一个手撕红外解码模块源码
于 2023-07-19 10:01:34 首次发布