module hs0038_irq(clk_100k, rstn, irq, data, rd_suc)/*synthesis noprune*/;
input clk_100k; //T=0.01ms
input rstn;
input irq;
output [31:0] data; //16位地址码,16位操作码
output rd_suc; //成功标志,维持0.01ms的高电平
parameter T9ms=10'd899;
parameter T4ms5=10'd449;
parameter Tms84=7'd83; //0.84ms
parameter error=8'd19; //0.2ms
reg [1:0] irq_tmp;
wire irq_up;
wire irq_down;
//捕捉红外信号的上下沿
always @(negedge clk_100k or negedge rstn)
begin
if (!rstn)
begin
irq_tmp <= 2'd0;
end
else
begin
irq_tmp[0] <= irq;
irq_tmp[1] <= irq_tmp[0];
end
end
assign irq_up = ~irq_tmp[1] & irq_tmp[0]; //上升沿为1
assign irq_down = irq_tmp[1] & ~irq_tmp[0]; //下降沿为1
/**********************************************************/
reg irq_suc;
reg [31:0] irq_buf;//提取出的32位数据,地址码,其反码,操作码,其反码
reg [9:0] irq_cnt;
reg [3:0] step; //状态机,解析红外的处理状态
reg [7:0] i; //引导码后的数据位计数
//上下沿的计数
always @(negedge clk_100k or negedge rstn)
begin
if (!rstn)
begin
irq_cnt <= 10'd0;
step <= 4'd0;
irq_buf <= 32'd0;
i <= 8'd0;
irq_suc <= 1'b0;
end
else
begin
case (step)
4'd0 : //开始等待捕捉引导码的上升沿
begin
if (irq_up) //第一次上升沿,过滤掉第一个上升沿
begin
step <= step + 1'd1;
irq_cnt <= 10'd0;
end
end
4'd1 : //引导码上升沿后开始计数
begin
irq_cnt <= irq_cnt + 1'd1;
if (irq_down) //下降沿截止计数
step <= step + 4'd1;
end
4'd2 : //判断引导码的高电平合法性
begin
if (irq_cnt <= (T9ms+error) && irq_cnt >= (T9ms-error))//引导码的9ms高电平
begin
step <= step + 4'd1;
irq_cnt <= 10'd0;
end
else
step <= 4'd0;
end
4'd3 : //引导码的下降沿开始计数至上升沿
begin
irq_cnt <= irq_cnt + 1'd1;
if (irq_up)
step <= step + 4'd1;
end
4'd4 : //判断引导码的低电平4.5ms
begin
if (irq_cnt <= (T4ms5+error) && irq_cnt >= (T4ms5-error))//引导码确认完成
begin
step <= step + 4'd1;
i <= 8'd0;
end
else
step <= 4'd0;
end
4'd5 : //引导码正确后开始提取数据
begin
if (irq_down)
begin
step <= step + 4'd1;
irq_cnt <= 10'd0;
end
end
4'd6 : //提取每个下降沿后0.84ms时的IRQ状态,为高是表示数据0,为低时表示数据1
begin
irq_cnt <= irq_cnt + 1'd1;
if (irq_cnt == Tms84) //捕捉数据部分每个下降沿后0.84ms的值
begin
irq_buf[i] <= ~irq;
i <= i + 8'd1;
if (i==8'd31) //所有数据提取完
step <= step + 4'd1;
else //捕捉下个位的下降沿
step <= 4'd5;
end
end
4'd7 : //提取完数据发送成功标志
begin
step <= step + 4'd1;
irq_suc <= 1'b1;
end
4'd8 :
begin
irq_suc <= 1'b0;
step <= 4'd0;
end
default : ;
endcase
end
end
assign rd_suc = irq_suc;
assign data = irq_buf;
endmodule
有必要说明一下,module后面的注释语句/*synthesis noprune*/是避免综合时候系统优化掉一些变量,导致在仿真里面看不到现象。
我自己调试的时候因为红外信号进来的没有取反,所以引导码是9ms低电平,4.5ms高电平,自己没注意导致调试费了一些时间.....需要在上层把红外信号取反之后送进来,这样就能正常工作了,注释很详细,不多解释了...
以后我会抽时间把自己调试的小功能程序分享出来,留作备用以及纪念。