FPGA -HT6221红外遥控解码
编码协议中“1”和“0”的编码波形:(红外遥控发射头发出的波形)
接收头与发射头发出的波形反向。
对连按信号的处理
识别9ms的低电平之后,如果之后检测到的高电平的时间小于4.5ms,则为错误信号。 9ms的低电平与4.5ms的高电平引导为引导码。
首先发送地址低八位码,之后发送数据码。
解码状态:数据码中如果有560us的高电平必为0,如果有1960us的高电平必为1,数据码前16位为地址位,后16位为数据位。后16位中前8位是数据码,后8位是数据反码。
信号接收解码模块
module IR_IR(
Clk,
Rst_n,
IR, //接收数据端口
Data_flag,//解码成功标志信号
Data_out,//解码完成的16位数据位
Data_address //解码完成后的16位地址位
);
input Clk;
input Rst_n;
input IR;
output Data_flag;
output [15:0] Data_out;
output [15:0] Data_address;
reg [18:0]count; //计数器
reg con_count; //计数使能信号
reg T9_ms; //识别9ms标志信号
reg T4_5ms; //识别4.5ms标志信号
reg T0_56ms;//识别0.56ms标志信号
reg T1_69ms;//识别1.69ms标志信号
reg IR0,IR1; //异步信号寄存器
reg IR_0,IR_1;//上升下降沿寄存器
wire rise,low;
reg [3:0]state;
reg [31:0]data_between;//中间数据寄存器
reg timeout;//超出10ms标志信号
reg Get_done;
reg [5:0]ir_count; //计数33个ir信号低电平
assign Data_address = data_between[15:0];
assign Data_out = data_between[31:16];
localparam
free_condition = 4'b0001, //空闲状态
distinguish_9ms = 4'b0010, //识别9ms低电平状态
distinguish_4_5ms = 4'b0100, //识别4.5ms高电平状态
decode = 4'b1000; //解码状态
always @(posedge Clk or negedge Rst_n) //异步信号的处理
if(!Rst_n)
begin
IR0 <= 1'b0;
IR1 <= 1'b0;
end
else begin
IR0 <= IR;
IR1 <= IR0;
end
always @(posedge Clk or negedge Rst_n) //上升沿下降沿检测
if(!Rst_n) begin
IR_0 <= 1'b0;
IR_1 <= 1'b0;
end else
begin
IR_0 <= IR1;
IR_1 <= IR_0;
end
assign rise = IR_0 && !IR_1;
assign low = !IR_0 && IR_1;
always @(posedge Clk or negedge Rst_n) //使能计数
if(!Rst_n)
count <= 19'b0;
else if(con_count == 1'b1)
count <= count + 19'b1;
else count <= 19'b0;
always @(posedge Clk or negedge Rst_n) //识别9ms时间脉冲
if(!Rst_n)
T9_ms <= 1'b0;
else if(19'd325000< count && count < 19'd495000)
T9_ms <= 1'b1;
else T9_ms <= 1'b0;
always @(posedge Clk or negedge Rst_n) //识别4.5ms时间脉冲
if(!Rst_n)
T4_5ms <= 1'b0;
else if(19'd152500 < count && count < 19'd277500)
T4_5ms <= 1'b1;
else T4_5ms <= 1'b0;
always @(posedge Clk or negedge Rst_n) //识别0.56ms时间脉冲
if(!Rst_n)
T0_56ms <= 1'b0;
else if(19'd20000 < count && count < 19'd35000)
T0_56ms <= 1'b1;
else T0_56ms <= 1'b0;
always @(posedge Clk or negedge Rst_n) //识别1.69ms时间脉冲
if(!Rst_n)
T1_69ms <= 1'b0;
else if(19'd75000 < count && count < 19'd90000)
T1_69ms <= 1'b1;
else T1_69ms <= 1'b0;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
timeout <= 1'b0;
else if(count >= 19'd500000)
timeout <= 1'b1;
else
timeout <= 1'b0;
//一段式状态机
always @(posedge Clk or negedge Rst_n)
if(!Rst_n) begin
state <= free_condition;
con_count <= 1'b0;
end
else if(!timeout) begin
case(state)
free_condition : //空闲状态
if(low) begin
con_count <= 1'b1;
state <= distinguish_9ms;
end
else begin
state <= free_condition;
con_count <= 1'b0;
end
distinguish_9ms: //识别9ms脉冲低电平
if(rise) begin
if(T9_ms) begin
state <= distinguish_4_5ms;
con_count <= 1'b0;
end
else state <= free_condition;
end
else begin
state <= distinguish_9ms;
con_count <= 1'b1;
end
distinguish_4_5ms: //识别4.5ms时间脉冲
if(low) begin
if(T4_5ms) begin
state <= decode;
con_count <= 1'b0;
end
else
state <= free_condition;
end
else begin
state <= distinguish_4_5ms;
con_count <= 1'b1;
end
decode: //识别0和脉冲数据 有1.69ms的高脉冲就是1,有0.56ms的高脉冲就是0
if(rise && !T0_56ms)
state <= free_condition;
else if(low && (!T1_69ms && !T0_56ms))
state <= free_condition;
else if(Get_done)
state <= free_condition;
else if(rise && T0_56ms)
con_count <= 1'b0;
else if(low && (T1_69ms || T0_56ms))
con_count <= 1'b0;
else
con_count <= 1'b1;
default : ;
endcase
end
else begin
con_count <= 1'b0;
state <= free_condition;
end
always @(posedge Clk or negedge Rst_n)
if(!Rst_n) begin
Get_done <= 1'b0;
ir_count <= 6'b0;
data_between <= 32'b0;
end
else if(state == decode) begin
if(rise && (ir_count == 6'd32)) begin
Get_done <= 1'b1;
ir_count <= 6'b0;
end
else begin
if(low)
ir_count <= ir_count + 1'b1;
if(low && T0_56ms)
data_between[ir_count] <= 1'b0;
else if(low && T1_69ms)
data_between[ir_count] <= 1'b1;
Get_done <= 1'b0;
end
end
assign Data_flag = Get_done;
endmodule
仿真模块
`timescale 1ns/1ns
`define Clk_period 20
module IR_IR_tb;
reg Clk;
reg Rst_n;
reg IR;
wire Data_flag;
wire [15:0] Data_out;
wire [15:0] Data_address;
integer i;
IR_IR IR_IR0(
.Clk(Clk),
.Rst_n(Rst_n),
.IR(IR), //接收数据端口
.Data_flag(Data_flag), //解码成功标志信号
.Data_out(Data_out), //解码完成的16位数据位
.Data_address(Data_address) //解码完成后的16位地址位
);
initial Clk =1;
always #(`Clk_period/2) Clk =~Clk;
initial begin
i=0;
Rst_n = 0;
IR = 0;
#(`Clk_period*2);
Rst_n = 1;
#3000;
IR = 1;
#(`Clk_period*5);
send_data(1,8'hae);
#60000000;
send_data(1,8'h1f);
#60000000;
$stop;
end
task send_data;
input [15:0]address;
input [7:0] data;
begin
IR = 0;
#9000000; //引导码
IR = 1;
#4500000;
for(i=0;i<=15;i=i+1)
send_byte(address[i]);
for(i=0;i<=7;i=i+1)
send_byte(data[i]);
for(i=0;i<=7;i=i+1)
send_byte(~data[i]);
IR = 0;#560000;
IR = 1;
end
endtask
task send_byte;
input one_bite;
begin
IR = 0;
#560000;
IR = 1;
if(one_bite)
#1690000;
else
#560000;
end
endtask
endmodule
顶层设计
使用tools生成IP核,In-System Sources and Probes。探针为32位(将模块输出数据放入到IP核中,查看数据)。source(来源)为0位。
module IR_look(
Clk,
Rst_n,
IR, //接收数据端口
Data_flag,//解码成功标志信号
Data_out,//解码完成的16位数据位
Data_address //解码完成后的16位地址位
);
input Clk;
input Rst_n;
input IR;
output Data_flag;
output [15:0] Data_out;
output [15:0] Data_address;
IR_IR IR_IR0(
.Clk(Clk),
.Rst_n(Rst_n),
.IR(IR), //接收数据端口
.Data_flag(Data_flag), //解码成功标志信号
.Data_out(Data_out), //解码完成的16位数据位
.Data_address(Data_address) //解码完成后的16位地址位
);
IR_see IR_see0(
.probe({Data_out,Data_address}), //探针
.source()
);
endmodule