一、Verilog HDL代码
////////////////////////////////////////////////////////
module Infra(
clock,
reset_n,
IR,
Infra
);
input clock;
input reset_n;
input IR;
output reg [7:0] Infra;
reg [31:0] get_data; // use for saving 32 bytes irda data
reg [5:0] data_cnt; // 32 bytes irda data counter
reg [2:0] cs,ns;
reg error_flag; // 32 bytes data期间,数据错误标志
//----------------------------------------------------------------------------
reg irda_reg0; //为了避免亚稳态,避免驱动多个寄存器,这一个不使用。
reg irda_reg1; //这个才可以使用,以下程序中代表irda的状态
reg irda_reg2; //为了确定irda的边沿,再打一次寄存器,以下程序中代表irda的前一状态
wire irda_neg_pulse; //确定irda的下降沿
wire irda_pos_pulse; //确定irda的上升沿
wire irda_chang; //确定irda的跳变沿
always@(posedge clock or negedge reset_n) //在此采用跟随寄存器
if(!reset_n)
begin
irda_reg0 <= 1'b0;
irda_reg1 <= 1'b0;
irda_reg2 <= 1'b0;
end
else
begin
irda_reg0 <= IR;
irda_reg1 <= irda_reg0;
irda_reg2 <= irda_reg1;
end
assign irda_chang = irda_neg_pulse | irda_pos_pulse; //IR接收信号的改变,上升或者下降
assign irda_neg_pulse = irda_reg2 & (~irda_reg1); //IR接收信号irda下降沿
assign irda_pos_pulse = (~irda_reg2) & irda_reg1; //IR接收信号irda上升沿
reg [10:0] counter; //分频1750次
reg [8:0] counter2; //计数分频后的点数
wire check_9ms; // check leader 9ms time
wire check_4ms; // check leader 4.5ms time
wire low; // check data="0" time
wire high; // check data="1" time
//----------------------------------------------------------------------------
//分频1750计数
always@(posedge clock or negedge reset_n)
begin
if (!reset_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;
end
//----------------------------------------------------------------------------
always@(posedge clock or negedge reset_n)
begin
if(!reset_n) counter2 <= 9'd0;
else if (irda_chang) counter2 <= 9'd0; //irda电平跳变了,就重新开始计点
else if (counter == 11'd1750) counter2 <= counter2 +1'b1;
end
assign check_9ms = ((9'd217 < counter2) && (counter2 < 9'd297)); //257 为了增加稳定性,取一定范围
assign check_4ms = ((9'd88 < counter2) && (counter2 < 9'd168)); //128
assign low = ((9'd6 < counter2) && (counter2 < 9'd26)); // 16
assign high = ((9'd38 < counter2) && (counter2 < 9'd58)); // 48
//----------------------------------------------------------------------------
// generate statemachine 状态机
parameter IDLE = 3'b000, //初始状态
LEADER_9 = 3'b001, //9ms
LEADER_4 = 3'b010, //4ms
DATA_STATE = 3'b100; //传输数据
always@(posedge clock or negedge reset_n)
begin
if(!reset_n) cs <= IDLE;
else cs <= ns; //状态位
end
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 ns =LEADER_9; //完备的if---else--- ;防止生成latch
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 clock or negedge reset_n)
if (!reset_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 clock or negedge reset_n)
begin
if (!reset_n) Infra <= 8'bzzzz_zzzz;
else if ((data_cnt ==6'd32) & irda_reg1)
Infra <= {get_data[8],get_data[9],get_data[10],get_data[11],get_data[12],get_data[13],get_data[14],get_data[15]};
end
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////////////
二、顶层工程文件

三、C语言代码
#include"io.h"
#include"system.h"
#include"alt_types.h"
#include"sys/alt_irq.h"
#include"avalon_slave_SEG7.h"
void HX1838_Init();
void HX1838_ISR(void* context, alt_u32 id);
int main(void)
{
alt_u8 i;
for(i=0;i<8;i++) seg7(SEG7_BASE,0,i);
HX1838_Init();
while(1)
{
};
return 0;
}
void HX1838_Init()
{
IOWR(IR_BASE,2,0xFF);
alt_irq_register(IR_IRQ,0,HX1838_ISR);
}
void HX1838_ISR(void* context, alt_u32 id)
{
alt_u8 data;
data = IORD_8DIRECT(IR_BASE,0);
seg7_show(SEG7_BASE,data);
}
浙公网安备 33010602011771号