设为首页收藏本站淘宝杂货铺

从F到0 - From F to 0

 找回密码
 注册已关闭
搜索
查看: 172|回复: 2
收起左侧

Quartus Verilog HDL/FPGA 状态机实现红外遥控器 VS1838B 接收头 NEC格式协议解码算法

[复制链接]
发表于 2023-7-4 09:19:51 | 显示全部楼层 |阅读模式
main.png
  1. //例:参数1:9000 参数2范围:8780~9220 在时间允许误差范围 返回1,否则为误码 返回0
  2. `define time_allow(setup,actual) (((actual) >= (setup) - 220) && ((actual) <= (setup) + 220) ? 1'b1 : 1'b0)
  3. module nec_count(                //红外接收电平时间计数模块
  4.         input clk,                        //1Mhz 时钟输入
  5.         input start,                //上升沿开始计数
  6.         input ir,                        //红外接收头
  7.         input hl,                        //1:计数高电平时间 0:低电平
  8.         output stop,                //ir电平发生翻转,发出上升沿脉冲,计数完成
  9.         output reg [15:0] count                //[16位宽] 计数微秒 (最大65535)
  10. );

  11. initial count = 16'd0;
  12. reg j = 1'b0;
  13. reg k = 1'b0;
  14. assign stop = (j && !k) ? 1'b1 : 1'b0;
  15. reg [15:0] i = 16'd0;
  16. reg run = 1'b0;
  17. always @(posedge start or posedge stop) begin
  18.         if(stop) begin
  19.                 run <= 1'b0;
  20.         end else if(start) begin
  21.                 run <= 1'b1;
  22.         end
  23. end

  24. always @(posedge clk) begin
  25.         j <= 1'b0;
  26.         if(ir == hl) begin
  27.                 if(run && !(&i)) begin
  28.                         i <= i + 16'd1;
  29.                 end
  30.         end else begin
  31.                 count <= i;
  32.                 i <= 16'd0;
  33.                 j <= 1'b1;
  34.         end
  35.         k <= j;
  36. end
  37. endmodule

  38. module clk_div(                        //时钟分频模块 输出频率=输入频率/分频系数/2
  39.         input clk,                                //时钟输入
  40.         input [15:0] div,                //[16位宽]分配系数
  41.         output reg out                        //分频输出
  42. );
  43. initial out = 1'd0;
  44. reg [15:0] i = 0;
  45. always @(posedge clk) begin
  46.         i = i + 16'd1;
  47.         if(i >= div) begin
  48.                 i = 0;
  49.                 out <= !out;
  50.         end
  51. end
  52. endmodule

  53. module nec_decode(                                //NEC红外遥控器解码模块
  54.         input clk,                                                //1Mhz时钟输入
  55.         input ir,                                                //红外遥控接收头 VS1838B
  56.         output reg [15:0] user,                //[16位宽] 接收到的用户码
  57.         output reg [7:0] key,                //[8位宽]  接收到的按键码
  58.         output hold,                                        //遥控器按键长按 持续输出高电平 松开低电平
  59.         output reg press,                                //遥控器按键按下 并解码正确后 发出一个上升沿脉冲
  60.         output reg cyclic                                //遥控器按键长按 发出重复码的上升沿脉冲
  61. );

  62. initial begin
  63.         user = 16'd0;
  64.         key = 8'd0;
  65.         press = 1'b0;
  66.         cyclic = 1'b0;
  67. end

  68. reg start = 1'b0;
  69. reg hl = 1'b0;
  70. wire stop;
  71. wire [15:0] count;

  72. nec_count nec_count(
  73.         .clk(clk),
  74.         .start(start),
  75.         .ir(ir),
  76.         .hl(hl),
  77.         .stop(stop),
  78.         .count(count)
  79. );

  80. reg [3:0] state = 0;
  81. reg [31:0] dat = 32'd0;
  82. reg [4:0] pc = 5'd0;
  83. reg [16:0] leave = 17'd131071;
  84. assign hold = !(&leave);
  85. always @(posedge clk) begin
  86.         case(state)
  87.                 4'd0:begin
  88.                         if(!(&leave)) begin
  89.                                 leave <= leave + 17'd1;
  90.                         end
  91.                         cyclic <= 1'b0;
  92.                         state <= ir ? 4'd0 : 4'd1;
  93.                 end
  94.                        
  95.                 4'd1:begin
  96.                         {hl,start} <= 2'b01;
  97.                         state <= 4'd2;
  98.                 end
  99.                        
  100.                 4'd2:begin
  101.                         start <= 1'b0;
  102.                         if(stop) begin
  103.                                 if(`time_allow(9000,count)) begin
  104.                                         state <= 4'd3;
  105.                                 end else begin
  106.                                         state <= 4'd0;
  107.                                 end
  108.                         end else begin
  109.                                 state <= 4'd2;
  110.                         end
  111.                 end
  112.                        
  113.                 4'd3:begin
  114.                         {hl,start} <= 2'b11;
  115.                         state <= 4'd4;
  116.                 end
  117.                        
  118.                 4'd4:begin
  119.                         start <= 1'b0;
  120.                         if(stop) begin
  121.                                 if(`time_allow(4500,count)) begin
  122.                                         pc <= 5'd0;
  123.                                         state <= 4'd7;
  124.                                 end else if(`time_allow(2250,count)) begin
  125.                                                 state <= 4'd5;
  126.                                         end else begin
  127.                                                 state <= 4'd0;
  128.                                         end
  129.                         end else begin
  130.                                 state <= 4'd4;
  131.                         end
  132.                 end
  133.                        
  134.                 4'd5:begin
  135.                         {hl,start} <= 2'b01;
  136.                         state <= 4'd6;               
  137.                 end
  138.                        
  139.                 4'd6:begin
  140.                         start <= 1'b0;
  141.                         if(stop) begin
  142.                                 if(`time_allow(560,count) && hold) begin
  143.                                         leave <= 17'd0;
  144.                                         cyclic <= 1'b1;
  145.                                 end
  146.                                 state <= 4'd0;
  147.                         end else begin
  148.                                 state <= 4'd6;
  149.                         end
  150.                 end
  151.                        
  152.                 4'd7:begin
  153.                         {hl,start} <= 2'b01;
  154.                         state <= 4'd8;
  155.                 end
  156.                        
  157.                 4'd8:begin
  158.                         start <= 1'b0;
  159.                         if(stop) begin
  160.                                 if(`time_allow(560,count)) begin
  161.                                         state <= 4'd9;
  162.                                 end else begin
  163.                                         state <= 4'd0;
  164.                                 end
  165.                         end else begin
  166.                                 state <= 8;
  167.                         end
  168.                 end
  169.                        
  170.                 4'd9:begin
  171.                         {hl,start} <= 2'b11;
  172.                         state <= 4'd10;
  173.                 end
  174.                        
  175.                 4'd10:begin
  176.                         start <= 1'b0;
  177.                         if(stop) begin
  178.                                 if(`time_allow(560,count)) begin
  179.                                         dat[pc] = 1'b0;
  180.                                 end else if(`time_allow(1680,count)) begin
  181.                                         dat[pc] = 1'b1;
  182.                                 end else begin
  183.                                         state <= 4'd0;
  184.                                 end
  185.                                 pc <= pc + 5'd1;
  186.                                 if(&pc) begin
  187.                                         state <= 4'd11;
  188.                                 end else begin
  189.                                         state <= 4'd7;
  190.                                 end
  191.                         end else begin
  192.                                 state <= 4'd10;
  193.                         end
  194.                 end
  195.                        
  196.                 4'd11:begin
  197.                         if(~dat[31:24] == dat[23:16]) begin
  198.                                 user[15:8] <= dat[7:0];
  199.                                 user[7:0] <= dat[15:8];
  200.                                 key <= dat[23:16];
  201.                                 state <= 4'd12;
  202.                         end else begin
  203.                                 state <= 4'd0;
  204.                         end
  205.                 end
  206.                        
  207.                 4'd12:begin
  208.                         press <= 1'b1;
  209.                         leave <= 17'd0;
  210.                         state <= 4'd13;
  211.                 end
  212.                 4'd13:begin
  213.                         press <= 1'b0;
  214.                         state <= 4'd0;
  215.                 end
  216.                 default:state <= 4'd0;
  217.         endcase
  218. end
  219. endmodule

  220. module main(
  221.         input clk,                //50Mhz 有源晶振 时钟输入 Pin17
  222.         input ir,                //红外遥控接收头 VS1838B Pin40
  223.         output reg led1,        //LED1 低电平点亮 高电平熄灭 Pin3
  224.         output reg led2,        //LED2 Pin7
  225.         output reg led3        //LED3 Pin9
  226. );

  227. wire clkb;
  228. initial {led1,led2,led3} = 3'b111;        //初始灭灯

  229. clk_div clk_50Mhz_1Mhz(                //50Mhz分频1Mhz
  230.         .clk(clk),
  231.         .div(16'd25),
  232.         .out(clkb)
  233. );

  234. wire press;
  235. wire cyclic;
  236. wire hold;
  237. wire [15:0] user;
  238. wire [7:0] key;

  239. nec_decode nec_decode(
  240.         .clk(clkb),
  241.         .ir(ir),
  242.         .user(user),
  243.         .key(key),
  244.         .hold(hold),
  245.         .press(press),
  246.         .cyclic(cyclic)
  247. );

  248. always @(posedge press) begin                //遥控器有按键按下
  249.         if(user == 16'h00FF) begin
  250.                 case(key)
  251.                         8'h45:led1 <= !led1;                //按键1
  252.                         8'h46:led2 <= !led2;                //按键2
  253.                         8'h47:led3 <= !led3;                //按键3
  254.                 endcase
  255.         end
  256. end

  257. endmodule
复制代码

相关帖子

您需要登录后才可以回帖 登录 | 注册已关闭

本版积分规则

QQ|手机版|Archiver|从F到0 ( 蒙ICP备17002595号-1 )
蒙公网安备15010402000325号

腾讯云安全认证

GMT+8, 2024-4-28 20:39 , Processed in 0.699040 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表