module IR(clk,rst_n,IR,led_cs,led_db);
clk;
rst_n;
IR;
input
input
input
output [3:0] led_cs;
output [7:0] led_db;
reg [3:0] led_cs;
reg [7:0] led_db;
reg [7:0] led1,led2,led3,led4;
reg [15:0] irda_data;
reg [31:0] get_data;
reg [5:0] data_cnt;
reg [2:0]
reg error_flag;
cs,ns;
// save irda data,than send to 7 segment led
// use for saving 32 bytes irda data
// 32 bytes irda data counter
// 32 bytes data 期间,数据错误标志
//----------------------------------------------------------------------------
reg irda_reg0;
reg irda_reg1;
reg irda_reg2;
//为了避免亚稳态,避免驱动多个寄存器,这一个不使用。
//这个才可以使用,以下程序中代表 irda 的状态
//为了确定 irda 的边沿,再打一次寄存器,以下程序中代表 irda 的前
一状态
wire irda_neg_pulse; //确定 irda 的下降沿
wire irda_pos_pulse; //确定 irda 的上升沿
wire irda_chang;
//确╥rda 的跳变沿
reg[15:0] cnt_scan;//扫描频率计数器
always @ (posedge clk) //在此采用跟随寄存器
if(!rst_n)
begin
irda_reg0 <= 1'b0;
irda_reg1 <= 1'b0;
irda_reg2 <= 1'b0;
end
else
begin
led_cs <= 4'b0000; //是数码管的位选择处于导通状态
irda_reg0 <= IR;
irda_reg1 <= irda_reg0;
irda_reg2 <= irda_reg1;
end
assign irda_chang = irda_neg_pulse | irda_pos_pulse;
assign irda_neg_pulse = irda_reg2 & (~irda_reg1);
assign irda_pos_pulse = (~irda_reg2) & irda_reg1;
//IR 接收信号的改变,上升或者下降
//IR 接收信号 irda 下降沿
//IR 接收信号 irda 上升沿
//分频 1750 次
reg [10:0] counter;
reg [8:0]
wire check_9ms;
wire check_4ms;
wire low;
wire high;
counter2; //计数分频后的点数
// check leader 9ms time
// check leader 4.5ms time
// check data="0" time
data="1" time
// check
//----------------------------------------------------------------------------
//分频 1750 计数
always @ (posedge clk)
if (!rst_n)
counter <= 11'd0;
else if (irda_chang)
counter <= 11'd0;
//irda 电平跳变了,就重新开始计数
else if (counter == 11'd1750)
counter <= 11'd0;
else
counter <= counter + 1'b1;
//----------------------------------------------------------------------------
always @ (posedge clk)
if (!rst_n)
counter2 <= 9'd0;
else if (irda_chang)
counter2 <= 9'd0;
//irda 电平跳变了,就重新开始计点
else if (counter == 11'd1750)
counter2 <= counter2 +1'b1;
assign check_9ms = ((217 < counter2) & (counter2 < 297));
//257 为了增加稳定性,取一定范围
assign check_4ms = ((88 < counter2) & (counter2 < 168));
assign low = ((6 < counter2) & (counter2 < 26));
assign high = ((38 < counter2) & (counter2 < 58));
//128
// 16
// 48
//----------------------------------------------------------------------------
// generate statemachine 状态机
parameter IDLE
= 3'b000, //初始状态
LEADER_9
= 3'b001, //9ms
LEADER_4
DATA_STATE = 3'b100; //传输数据
= 3'b010, //4ms
always @ (posedge clk)
if (!rst_n)
cs <= IDLE;
else
cs <= ns; //状态位
always @ ( * )
case (cs)
IDLE:
if (~irda_reg1)
ns = LEADER_9;
else
ns = IDLE;
LEADER_9:
if (irda_pos_pulse)
//leader 9ms check
begin
if (check_9ms)
ns = LEADER_4;
else
ns = IDLE;
end
else
//完备的 if---else--- ;防止生成 latch
ns =LEADER_9;
LEADER_4:
if (irda_neg_pulse)
// leader 4.5ms check
begin
if (check_4ms)
ns = DATA_STATE;
else
ns = IDLE;
end
else
ns = LEADER_4;
DATA_STATE:
if ((data_cnt == 6'd32) & irda_reg2 & irda_reg1)
ns = IDLE;
else if (error_flag)
ns = IDLE;
else
ns = DATA_STATE;
default:
ns = IDLE;
endcase
//状态机中的输出,用时序电路来描述
always @ (posedge clk)
if (!rst_n)
begin
data_cnt <= 6'd0;
get_data <= 32'd0;
error_flag <= 1'b0;
end
else if (cs == IDLE)
begin
data_cnt <= 6'd0;
get_data <= 32'd0;
error_flag <= 1'b0;
end
else if (cs == DATA_STATE)
begin
if (irda_pos_pulse)
// low 0.56ms check
begin
if (!low)
//error
error_flag <= 1'b1;
end
else if (irda_neg_pulse)
//check 0.56ms/1.68ms data 0/1
begin
if (low)
get_data[0] <= 1'b0;
else if (high)
get_data[0] <= 1'b1;
else
error_flag <= 1'b1;
get_data[31:1] <= get_data[30:0];
data_cnt <= data_cnt + 1'b1;
end
end
always @ (posedge clk)
if (!rst_n)
irda_data <= 16'd0;
else if ((data_cnt ==6'd32) & irda_reg1)
//数据反码
begin
led1 <= get_data[7:0];
led2 <= get_data[15:8]; //数据码
led3 <= get_data[23:16];//用户码
led4 <= get_data[31:24];
end
//把遥控器的按下的键在数码管上面显示出来
always@(led2)
begin
case(led2)
//在数码管上面显示 0 到 9
8'b01101000: //遥控板 0 的码值
led_db=8'b1100_0000;
//显示 0
8'b00110000: //遥控板 1 的码值
led_db=8'b1111_1001;
//显示 1
8'b00011000: //遥控板 2 的码值
led_db=8'b1010_0100;
//显示 2
8'b01111010: //遥控板 3 的码值
led_db=8'b1011_0000;
//显示 3
8'b00010000: //遥控板 4 的码值
led_db=8'b1001_1001;
//显示 4
8'b00111000: //遥控板 5 的码值
led_db=8'b1001_0010;
//显示 5
8'b01011010: //遥控板 6 的码值
led_db=8'b1000_0010;
//显示 6
8'b01000010: //遥控板 7 的码值
led_db=8'b1111_1000;
//显示 7
8'b01001010: //遥控板 8 的码值
led_db=8'b1000_0000;
//显示 8
8'b01010010: //遥控板 9 的码值
led_db=8'b1001_0000;
//显示 9
//在没有按下键时,显示 F
default: led_db=8'b1000_1110;
endcase
end
endmodule