当前位置: 首页 > news >正文

#FPGA(IRDA)

1.IDE:Quartus II


2.设备:Cyclone II  EP2C8Q208C8N  


3.实验:IRDA(仿真接收一个来自0x57地址的数据0x22  (十进制34))


4.时序图:

 


5.步骤


6.代码:

irda_receive.v

module irda_receive
(
input      wire               sys_clk      ,
input      wire               sys_rst_n    ,
input      wire               irda_in      ,        //irda接收端引脚输入output     reg      [19:0]     data         ,        //数据输出
output     reg                 repeat_en             //重复使能
);/**状态*/
parameter  IDLE          =    5'b00001     ;     //空闲
parameter  TIME_9MS      =    5'b00010     ;     //引导或者重复的9ms低电平
parameter  ARBIT         =    5'b00100     ;     //地址
parameter  DATA          =    5'b01000     ;     //数据
parameter  REPEAT        =    5'b10000     ;     //重复/**时间范围*/
parameter  CNT_560US_MIN         =        19'd20000         ; 
parameter  CNT_560US_MAX         =        19'd35000         ; 
parameter  CNT_1_69MS_MIN        =        19'd80000         ; 
parameter  CNT_1_69MS_MAX        =        19'd90000         ; 
parameter  CNT_2_25MS_MIN        =        19'd100000        ; 
parameter  CNT_2_25MS_MAX        =        19'd125000        ; 
parameter  CNT_4_5MS_MIN         =        19'd175000        ; 
parameter  CNT_4_5MS_MAX         =        19'd275000        ; 
parameter  CNT_9MS_MIN           =        19'd400000        ; 
parameter  CNT_9MS_MAX           =        19'd490000        ; /**寄存器*/
reg      [4:0]        state                ;     //状态   
reg                   inf_in_dly1          ;     //用于电平跳转判断(下一时刻)
reg                   inf_in_dly2          ;     //用于电平跳转判断(上一时刻)
wire                  inf_in_fall          ;     //下降沿标志位
wire                  inf_in_rise          ;     //上升沿标志位reg      [18:0]       cnt                  ;     //计数器reg                   flag_9ms             ;     //9ms标志位
reg                   flag_4_5ms           ;     //4.5ms标志位
reg                   flag_560us           ;     //560us标志位
reg                   flag_1_69ms          ;     //1.69ms标志位
reg                   flag_2_25ms          ;     //2.25ms标志位reg      [5:0]        cnt_data             ;     //记录接收的数据个数
reg      [31:0]       data_reg             ;     //数据记录/**状态跳转*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)state <= IDLE;else  case(state)IDLE    :begin if(inf_in_fall == 1'b1)      //引导信号下降沿到来state <= TIME_9MS;elsestate <= IDLE;endTIME_9MS:beginif((inf_in_rise == 1'b1)&&(flag_9ms == 1'b1))      //引导信号到来后持续低电平再拉高,低电平时间达到9ms(进入接收地址码状态)state <= ARBIT;                                   else if((inf_in_rise == 1'b1)&&(flag_9ms == 1'b0)) //引导信号到来后持续低电平再拉高,低电平时间未达到9ms(恢复空闲状态)state <= IDLE;else                                             //引导信号到来后持续低电平未检测到高电平时期(还未拉高,等待中,保持状态不变)state <= TIME_9MS;end	ARBIT   :beginif((inf_in_fall==1'b1)&&(flag_2_25ms == 1'b1))     //下降沿到来接收到重复码(高电平时间未2.25ms,则为重复码,高电平时间为4.5ms则为引导码)state <= REPEAT;else if((inf_in_fall==1'b1)&&(flag_4_5ms == 1'b1)) state <= DATA ;else if((inf_in_fall==1'b1)&&(flag_4_5ms == 1'b0)&&(flag_2_25ms == 1'b0))  //下降沿到来,高电平不满足2.25ms和4.5ms  state <= IDLE;else                                               //保持原状态state <= ARBIT;endDATA    :beginif((inf_in_rise == 1'b1) && (flag_560us == 1'b0))  //数据信号低电平不满足“0”要求state <= IDLE;else if((inf_in_fall == 1'b1)&&(flag_560us == 1'b0)&&(flag_1_69ms == 1'b0))  //下降沿到来,但是高电平不足560usstate <= IDLE;else if((inf_in_rise == 1'b1)&&(cnt_data == 6'd32)) //结束信号是拉高,计数到32个数据state <= IDLE;elsestate <= DATA;end		 REPEAT  :beginif(inf_in_rise == 1'b1)state <= IDLE;elsestate <= REPEAT;enddefault :beginstate <= IDLE; endendcase	 
end/**电平翻转记录*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)begininf_in_dly1 <= 1'b0;inf_in_dly2 <= 1'b0;endelsebegininf_in_dly1 <= irda_in;  //记录当前电平inf_in_dly2 <= inf_in_dly1; //记录上一时刻电平end
end/**下降沿上升沿标志位赋值*/
assign inf_in_fall = ((inf_in_dly1 == 1'b0)&&(inf_in_dly2 == 1'b1)) ? 1'b1 : 1'b0;  //上一时刻高电平,当前时刻低电平(下降沿标志位拉高)
assign inf_in_rise = ((inf_in_dly1 == 1'b1)&&(inf_in_dly2 == 1'b0)) ? 1'b1 : 1'b0;  //上一时刻低电平,当前时刻高电平(上升沿标志位拉高)/**cnt控制*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)cnt <= 19'd0;else case(state)IDLE         : cnt <= 19'd0;TIME_9MS     :beginif((inf_in_rise == 1'b1)&&(flag_9ms == 1'b1))cnt <= 19'd0;elsecnt <= cnt + 1'b1;endARBIT        :beginif((inf_in_fall == 1'b1) && ((flag_4_5ms == 1'b1)||(flag_2_25ms == 1'b1)))         //仲裁(引导信号还是重复信号)cnt <= 19'd0;elsecnt <= cnt + 1'b1;endDATA         :beginif((inf_in_rise == 1'b1)&&(flag_560us == 1'b1))cnt <= 19'd0;else if((inf_in_fall == 1'b1)&&((flag_560us == 1'b1)||(flag_1_69ms == 1'b1)))      // 0/1cnt <= 19'd0;elsecnt <= cnt + 1'b1; enddefault      : cnt <= 19'd0;endcase
end/**时间标志位控制*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)flag_9ms <= 1'b0;else if((state == TIME_9MS)&&(cnt >= CNT_9MS_MIN)&&(cnt <= CNT_9MS_MAX))flag_9ms <= 1'b1;elseflag_9ms <= 1'b0;
endalways @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)flag_4_5ms <= 1'b0;else if((state == ARBIT)&&(cnt >= CNT_4_5MS_MIN)&&(cnt <= CNT_4_5MS_MAX))flag_4_5ms <= 1'b1;elseflag_4_5ms <= 1'b0;
endalways @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)flag_560us <= 1'b0;else if((state == DATA)&&(cnt >= CNT_560US_MIN)&&(cnt <= CNT_560US_MAX))flag_560us <= 1'b1;elseflag_560us <= 1'b0;
endalways @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)flag_1_69ms <= 1'b0;else if((state == DATA)&&(cnt >= CNT_1_69MS_MIN)&&(cnt <= CNT_1_69MS_MAX))flag_1_69ms <= 1'b1;elseflag_1_69ms <= 1'b0;
endalways @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)flag_2_25ms <= 1'b0;else if((state == ARBIT)&&(cnt >= CNT_2_25MS_MIN)&&(cnt <= CNT_2_25MS_MAX))flag_2_25ms <= 1'b1;elseflag_2_25ms <= 1'b0;
end/**接收数据计数*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)cnt_data <= 6'd0;else if((inf_in_rise == 1'b1)&&(cnt_data == 6'd32))cnt_data <= 6'd0;else if((inf_in_fall == 1'b1)&&(state == DATA))cnt_data <= cnt_data + 1'b1;elsecnt_data <= cnt_data;
end/**接收的数据*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)data_reg <= 32'b0;else if((state == DATA)&&(inf_in_fall == 1'b1)&&(flag_560us == 1'b1))data_reg[cnt_data] <= 1'b0;else if((state == DATA)&&(inf_in_fall == 1'b1)&&(flag_1_69ms == 1'b1))data_reg[cnt_data] <= 1'b1;elsedata_reg <= data_reg;
end/**数据倒排(LSB)*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)data <= 20'b0;else if((cnt_data == 6'd32)&&(~data_reg[23:16] == data_reg[31:24])&&(~data_reg[15:8] == data_reg[7:0]))data <= {12'b0,data_reg[23:16]};elsedata <= data;
end/**重复信号使能控制*/
always @ (posedge sys_clk or negedge sys_rst_n) beginif(sys_rst_n == 1'b0)repeat_en <= 1'b0;else if((state ==REPEAT)&&(~data_reg[23:16] == data_reg[31:24]))repeat_en <= 1'b1;elserepeat_en <= 1'b0;
endendmodule

 仿真代码:

`timescale 1ns/1ns
module tb_irda_receive();reg        sys_clk             ;
reg        sys_rst_n           ;
reg        inf_in             ;wire       [19:0]   data       ;
wire                repeat_en  ;initial beginsys_clk = 1'b1;sys_rst_n = 1'b0;inf_in <= 1'b1;#30sys_rst_n <= 1'b1;#1000
//引导码    inf_in <= 1'b0;#9000_000inf_in <= 1'b1;#4500_000
//地址码(8'h57     0101_0111         1110_1010)inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0
//地址反码(1110_1010     0001_0101)inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1
//数据码(8'h22  0010_0010   0100_0100)inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000             //逻辑0
//数据反码(0100_0100   1011_1011)inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #560_000            //逻辑0inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1inf_in <= 1'b0;#560_000inf_in <= 1'b1;     #1690_000            //逻辑1
//结束位inf_in <= 1'b0;#560_000
//高电平保持			  inf_in <= 1'b1;#4200_0000
//重复码inf_in <= 1'b0;#9000_000inf_in <= 1'b1;#2250_000			
//结束位inf_in <= 1'b0;#560_000inf_in <= 1'b1;			  endalways #10 sys_clk = ~ sys_clk;/**实例化*/
irda_receive irda_receive_inst
(
.sys_clk            (sys_clk  )    ,
.sys_rst_n          (sys_rst_n)    ,
.irda_in            (inf_in  )    ,        //irda接收端引脚输入.data               (data     )    ,        //数据输出
.repeat_en          (repeat_en)             //重复使能
);endmodule

http://www.lryc.cn/news/305592.html

相关文章:

  • Sora—openai最新大模型文字生成视频
  • VoIP(Voice over Internet Protocol 基于IP的语音传输)介绍(网络电话、ip电话)
  • 编程笔记 Golang基础 027 结构体
  • opencascade15解析导出为step格式
  • 【软件设计模式之模板方法模式】
  • Spring Boot项目怎么对System.setProperty(key, value)设置的属性进行读取加解密
  • Linux理解
  • 常用芯片学习——YC688语音芯片
  • C语言:指针的进阶讲解
  • 基于SSM的车位租赁系统(有报告)。Javaee项目。ssm项目。
  • Java pyhon C C++ R JS 主流语言的区别-03
  • 5 buuctf解题
  • 微服务三十五关
  • 第一个 Angular 项目 - 添加服务
  • 红日靶场3
  • B树的介绍
  • 《The Art of InnoDB》第二部分|第4章:深入结构-磁盘结构-撕裂的页面(doublewrite buffer)
  • 提示工程(Prompt Engineering)、微调(Fine-tuning) 和 嵌入(Embedding)
  • 【Flink精讲】Flink 内存管理
  • 正则化概念及使用
  • 让程序员设计B端界面,好比武大郎招聘:向我看齐。不忍直视!
  • 使用python构建Android,探索跨平台应用开发Kivy框架
  • 08 Redis之集群的搭建和复制原理+哨兵机制+CAP定理+Raft算法
  • *MYSQL--索引--内部原理
  • docker安装kafka和kafka-console-ui
  • Linux:gitlab创建组,创建用户,创建项目
  • 相机选型介绍
  • SQL创建数据库
  • 读书笔记-增强型分析:AI驱动的数据分析、业务决策与案例实践
  • NXP实战笔记(十):S32K3xx基于RTD-SDK在S32DS上配置CAN通信