mirror of
https://github.com/marqs85/ossc.git
synced 2024-12-28 18:29:28 +00:00
186 lines
5.7 KiB
Verilog
186 lines
5.7 KiB
Verilog
//
|
|
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
|
//
|
|
// This file is part of Open Source Scan Converter project.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
`define STATE_IDLE 2'b00
|
|
`define STATE_LEADVERIFY 2'b01
|
|
`define STATE_DATARCV 2'b10
|
|
|
|
module ir_rcv (
|
|
input clk27,
|
|
input reset_n,
|
|
input ir_rx,
|
|
output reg [15:0] ir_code,
|
|
output reg ir_code_ack,
|
|
output reg [7:0] ir_code_cnt
|
|
);
|
|
|
|
// ~37ns clock period
|
|
|
|
parameter LEADCODE_LO_THOLD = 200000; //7.4ms
|
|
parameter LEADCODE_HI_THOLD = 100000; //3.7ms
|
|
parameter LEADCODE_HI_TIMEOUT = 160000; //5.9ms
|
|
parameter LEADCODE_HI_RPT_THOLD = 54000; //2.0ms
|
|
parameter RPT_RELEASE_THOLD = 3240000; //120ms
|
|
parameter BIT_ONE_THOLD = 27000; //1.0ms
|
|
parameter BIT_DETECT_THOLD = 7628; //0.28ms
|
|
parameter IDLE_THOLD = 141480; //5.24ms
|
|
|
|
reg [1:0] state; // 3 states
|
|
reg [31:0] databuf; // temp. buffer
|
|
reg [5:0] bits_detected; // max. 63, effectively between 0 and 33
|
|
reg [17:0] act_cnt; // max. 9.7ms
|
|
reg [17:0] leadvrf_cnt; // max. 9.7ms
|
|
reg [17:0] datarcv_cnt; // max. 9.7ms
|
|
reg [21:0] rpt_cnt; // max. 155ms
|
|
|
|
// activity when signal is low
|
|
always @(posedge clk27 or negedge reset_n)
|
|
begin
|
|
if (!reset_n)
|
|
act_cnt <= 0;
|
|
else
|
|
begin
|
|
if ((state == `STATE_IDLE) & (~ir_rx))
|
|
act_cnt <= act_cnt + 1'b1;
|
|
else
|
|
act_cnt <= 0;
|
|
end
|
|
end
|
|
|
|
// lead code verify counter
|
|
always @(posedge clk27 or negedge reset_n)
|
|
begin
|
|
if (!reset_n)
|
|
leadvrf_cnt <= 0;
|
|
else
|
|
begin
|
|
if ((state == `STATE_LEADVERIFY) & ir_rx)
|
|
leadvrf_cnt <= leadvrf_cnt + 1'b1;
|
|
else
|
|
leadvrf_cnt <= 0;
|
|
end
|
|
end
|
|
|
|
|
|
// '0' and '1' are differentiated by high phase duration preceded by constant length low phase
|
|
always @(posedge clk27 or negedge reset_n)
|
|
begin
|
|
if (!reset_n)
|
|
begin
|
|
datarcv_cnt <= 0;
|
|
bits_detected <= 0;
|
|
databuf <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if (state == `STATE_DATARCV)
|
|
begin
|
|
if (ir_rx)
|
|
datarcv_cnt <= datarcv_cnt + 1'b1;
|
|
else
|
|
datarcv_cnt <= 0;
|
|
|
|
if (datarcv_cnt == BIT_DETECT_THOLD)
|
|
bits_detected <= bits_detected + 1'b1;
|
|
|
|
if (datarcv_cnt == BIT_ONE_THOLD)
|
|
databuf[32-bits_detected] <= 1'b1;
|
|
end
|
|
else
|
|
begin
|
|
datarcv_cnt <= 0;
|
|
bits_detected <= 0;
|
|
databuf <= 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
// read and validate data after 32 bits detected (last bit may change to '1' at any time)
|
|
always @(posedge clk27 or negedge reset_n)
|
|
begin
|
|
if (!reset_n)
|
|
begin
|
|
ir_code_ack <= 1'b0;
|
|
ir_code <= 16'h00000000;
|
|
end
|
|
else
|
|
begin
|
|
if ((bits_detected == 32) & (databuf[31:24] == ~databuf[23:16]) & (databuf[15:8] == ~databuf[7:0]))
|
|
begin
|
|
ir_code <= {databuf[31:24], databuf[15:8]};
|
|
ir_code_ack <= 1'b1;
|
|
end
|
|
else if (rpt_cnt >= RPT_RELEASE_THOLD)
|
|
begin
|
|
ir_code <= 16'h00000000;
|
|
ir_code_ack <= 1'b0;
|
|
end
|
|
else
|
|
ir_code_ack <= 1'b0;
|
|
end
|
|
end
|
|
|
|
always @(posedge clk27 or negedge reset_n)
|
|
begin
|
|
if (!reset_n)
|
|
begin
|
|
state <= `STATE_IDLE;
|
|
rpt_cnt <= 0;
|
|
ir_code_cnt <= 0;
|
|
end
|
|
else
|
|
begin
|
|
rpt_cnt <= rpt_cnt + 1'b1;
|
|
|
|
case (state)
|
|
`STATE_IDLE:
|
|
begin
|
|
if ((act_cnt >= LEADCODE_LO_THOLD) & ir_rx)
|
|
state <= `STATE_LEADVERIFY;
|
|
if (rpt_cnt >= RPT_RELEASE_THOLD)
|
|
ir_code_cnt <= 0;
|
|
end
|
|
`STATE_LEADVERIFY:
|
|
begin
|
|
if (leadvrf_cnt == LEADCODE_HI_RPT_THOLD)
|
|
begin
|
|
if (ir_code != 0)
|
|
ir_code_cnt <= ir_code_cnt + 1'b1;
|
|
rpt_cnt <= 0;
|
|
end
|
|
if (!ir_rx)
|
|
state <= (leadvrf_cnt >= LEADCODE_HI_THOLD) ? `STATE_DATARCV : `STATE_IDLE;
|
|
else if (leadvrf_cnt >= LEADCODE_HI_TIMEOUT)
|
|
state <= `STATE_IDLE;
|
|
end
|
|
`STATE_DATARCV:
|
|
begin
|
|
if (ir_code_ack == 1'b1)
|
|
ir_code_cnt <= 1;
|
|
if ((datarcv_cnt >= IDLE_THOLD)|bits_detected >= 33)
|
|
state <= `STATE_IDLE;
|
|
end
|
|
default:
|
|
state <= `STATE_IDLE;
|
|
endcase
|
|
end
|
|
end
|
|
|
|
endmodule
|