|
- //例:参数1:9000 参数2范围:8780~9220 在时间允许误差范围 返回1,否则为误码 返回0
- `define time_allow(setup,actual) (((actual) >= (setup) - 220) && ((actual) <= (setup) + 220) ? 1'b1 : 1'b0)
- module nec_count( //红外接收电平时间计数模块
- input clk, //1Mhz 时钟输入
- input start, //上升沿开始计数
- input ir, //红外接收头
- input hl, //1:计数高电平时间 0:低电平
- output stop, //ir电平发生翻转,发出上升沿脉冲,计数完成
- output reg [15:0] count //[16位宽] 计数微秒 (最大65535)
- );
- initial count = 16'd0;
- reg j = 1'b0;
- reg k = 1'b0;
- assign stop = (j && !k) ? 1'b1 : 1'b0;
- reg [15:0] i = 16'd0;
- reg run = 1'b0;
- always @(posedge start or posedge stop) begin
- if(stop) begin
- run <= 1'b0;
- end else if(start) begin
- run <= 1'b1;
- end
- end
- always @(posedge clk) begin
- j <= 1'b0;
- if(ir == hl) begin
- if(run && !(&i)) begin
- i <= i + 16'd1;
- end
- end else begin
- count <= i;
- i <= 16'd0;
- j <= 1'b1;
- end
- k <= j;
- end
- endmodule
- module clk_div( //时钟分频模块 输出频率=输入频率/分频系数/2
- input clk, //时钟输入
- input [15:0] div, //[16位宽]分配系数
- output reg out //分频输出
- );
- initial out = 1'd0;
- reg [15:0] i = 0;
- always @(posedge clk) begin
- i = i + 16'd1;
- if(i >= div) begin
- i = 0;
- out <= !out;
- end
- end
- endmodule
- module nec_decode( //NEC红外遥控器解码模块
- input clk, //1Mhz时钟输入
- input ir, //红外遥控接收头 VS1838B
- output reg [15:0] user, //[16位宽] 接收到的用户码
- output reg [7:0] key, //[8位宽] 接收到的按键码
- output hold, //遥控器按键长按 持续输出高电平 松开低电平
- output reg press, //遥控器按键按下 并解码正确后 发出一个上升沿脉冲
- output reg cyclic //遥控器按键长按 发出重复码的上升沿脉冲
- );
- initial begin
- user = 16'd0;
- key = 8'd0;
- press = 1'b0;
- cyclic = 1'b0;
- end
- reg start = 1'b0;
- reg hl = 1'b0;
- wire stop;
- wire [15:0] count;
- nec_count nec_count(
- .clk(clk),
- .start(start),
- .ir(ir),
- .hl(hl),
- .stop(stop),
- .count(count)
- );
- reg [3:0] state = 0;
- reg [31:0] dat = 32'd0;
- reg [4:0] pc = 5'd0;
- reg [16:0] leave = 17'd131071;
- assign hold = !(&leave);
- always @(posedge clk) begin
- case(state)
- 4'd0:begin
- if(!(&leave)) begin
- leave <= leave + 17'd1;
- end
- cyclic <= 1'b0;
- state <= ir ? 4'd0 : 4'd1;
- end
-
- 4'd1:begin
- {hl,start} <= 2'b01;
- state <= 4'd2;
- end
-
- 4'd2:begin
- start <= 1'b0;
- if(stop) begin
- if(`time_allow(9000,count)) begin
- state <= 4'd3;
- end else begin
- state <= 4'd0;
- end
- end else begin
- state <= 4'd2;
- end
- end
-
- 4'd3:begin
- {hl,start} <= 2'b11;
- state <= 4'd4;
- end
-
- 4'd4:begin
- start <= 1'b0;
- if(stop) begin
- if(`time_allow(4500,count)) begin
- pc <= 5'd0;
- state <= 4'd7;
- end else if(`time_allow(2250,count)) begin
- state <= 4'd5;
- end else begin
- state <= 4'd0;
- end
- end else begin
- state <= 4'd4;
- end
- end
-
- 4'd5:begin
- {hl,start} <= 2'b01;
- state <= 4'd6;
- end
-
- 4'd6:begin
- start <= 1'b0;
- if(stop) begin
- if(`time_allow(560,count) && hold) begin
- leave <= 17'd0;
- cyclic <= 1'b1;
- end
- state <= 4'd0;
- end else begin
- state <= 4'd6;
- end
- end
-
- 4'd7:begin
- {hl,start} <= 2'b01;
- state <= 4'd8;
- end
-
- 4'd8:begin
- start <= 1'b0;
- if(stop) begin
- if(`time_allow(560,count)) begin
- state <= 4'd9;
- end else begin
- state <= 4'd0;
- end
- end else begin
- state <= 8;
- end
- end
-
- 4'd9:begin
- {hl,start} <= 2'b11;
- state <= 4'd10;
- end
-
- 4'd10:begin
- start <= 1'b0;
- if(stop) begin
- if(`time_allow(560,count)) begin
- dat[pc] = 1'b0;
- end else if(`time_allow(1680,count)) begin
- dat[pc] = 1'b1;
- end else begin
- state <= 4'd0;
- end
- pc <= pc + 5'd1;
- if(&pc) begin
- state <= 4'd11;
- end else begin
- state <= 4'd7;
- end
- end else begin
- state <= 4'd10;
- end
- end
-
- 4'd11:begin
- if(~dat[31:24] == dat[23:16]) begin
- user[15:8] <= dat[7:0];
- user[7:0] <= dat[15:8];
- key <= dat[23:16];
- state <= 4'd12;
- end else begin
- state <= 4'd0;
- end
- end
-
- 4'd12:begin
- press <= 1'b1;
- leave <= 17'd0;
- state <= 4'd13;
- end
- 4'd13:begin
- press <= 1'b0;
- state <= 4'd0;
- end
- default:state <= 4'd0;
- endcase
- end
- endmodule
- module main(
- input clk, //50Mhz 有源晶振 时钟输入 Pin17
- input ir, //红外遥控接收头 VS1838B Pin40
- output reg led1, //LED1 低电平点亮 高电平熄灭 Pin3
- output reg led2, //LED2 Pin7
- output reg led3 //LED3 Pin9
- );
- wire clkb;
- initial {led1,led2,led3} = 3'b111; //初始灭灯
- clk_div clk_50Mhz_1Mhz( //50Mhz分频1Mhz
- .clk(clk),
- .div(16'd25),
- .out(clkb)
- );
- wire press;
- wire cyclic;
- wire hold;
- wire [15:0] user;
- wire [7:0] key;
- nec_decode nec_decode(
- .clk(clkb),
- .ir(ir),
- .user(user),
- .key(key),
- .hold(hold),
- .press(press),
- .cyclic(cyclic)
- );
- always @(posedge press) begin //遥控器有按键按下
- if(user == 16'h00FF) begin
- case(key)
- 8'h45:led1 <= !led1; //按键1
- 8'h46:led2 <= !led2; //按键2
- 8'h47:led3 <= !led3; //按键3
- endcase
- end
- end
- endmodule
复制代码 |
|