////////////////////////////////////////////////////////////////////////////// | |
// SPDX-FileCopyrightText: 2021 , Dinesh Annayya | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// SPDX-License-Identifier: Apache-2.0 | |
// SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org> | |
// | |
////////////////////////////////////////////////////////////////////// | |
/********************************************************************** | |
NEC IR Top | |
This file is part of the riscduino cores project | |
https://github.com/dineshannayya/riscduino.git | |
Description: | |
This block integrate | |
A. NEC IR Transmitter | |
B. NEC IR Reciver | |
C. Prescalar | |
D. Register Block | |
E. FIFO Block | |
To Do: | |
nothing | |
Author(s): | |
- Dinesh Annayya, dinesh.annayya@gmail.com | |
Revision : | |
0.1 - 11 Dec 2022, Dinesh A | |
initial version | |
0.2 - 13 Dec 2022, Dinesh A | |
A. Bug fix, Read access clearing the register content | |
B. FIFO Occpancy added | |
C. Support for IR Transmitter | |
***************************************************************************/ | |
/************************************************************************************* | |
Documentation Collection by Dinesh-A - dinesh.annayya@gmail.com | |
Reference: https://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol | |
The NEC IR transmission protocol uses pulse distance encoding of the message bits. Each pulse burst (mark – RC transmitter ON) is | |
562.5µs in length, at a carrier frequency of 38kHz (26.3µs). Logical bits are transmitted as follows: | |
Logical '0' – a 562.5µs pulse burst followed by a 562.5µs space, with a total transmit time of 1.125ms | |
Logical '1' – a 562.5µs pulse burst followed by a 1.6875ms space, with a total transmit time of 2.25ms | |
When a key is pressed on the remote controller, the message transmitted consists of the following, in order: | |
* 9ms leading pulse burst (16 times the pulse burst length used for a logical data bit) | |
* 4.5ms space | |
* the 8-bit address for the receiving device | |
* the 8-bit logical inverse of the address | |
* the 8-bit command | |
* the 8-bit logical inverse of the command | |
* final 562.5µs pulse burst to signify the end of message transmission. | |
Repeat Codes | |
If the key on the remote controller is kept depressed, a repeat code will be issued, typically around 40ms after | |
the pulse burst that signified the end of the message. A repeat code will continue to be sent out at 108ms intervals, | |
until the key is finally released. The repeat code consists of the following, in order: | |
* 9ms leading pulse burst | |
* 2.25ms space | |
* 562.5µs pulse burst to mark the end of the space (and hence end of the transmitted repeat code). | |
*************************************************************************************/ | |
module nec_ir_top #( | |
parameter NB_STAGES = 3 , // Number of metastability filter stages | |
parameter PSIZE = 32 , // Size of prescaler counter(bits) | |
parameter DSIZE = 32 , // Size of delay counter (bits) | |
parameter ASIZE = 3 , // FIFO size (FIFO_size=(2**ASIZE)-1) | |
parameter DP = 8 // FIFO DEPTH = 2**SIZE | |
)( | |
input logic rst_n , // Asynchronous reset (active low) | |
input logic clk , // Clock (rising edge) | |
// Wishbone bus | |
input logic wbs_cyc_i , // Wishbone strobe/request | |
input logic wbs_stb_i , // Wishbone strobe/request | |
input logic [4:0] wbs_adr_i , // Wishbone address | |
input logic wbs_we_i , // Wishbone write (1:write, 0:read) | |
input logic [31:0] wbs_dat_i , // Wishbone data output | |
input logic [3:0] wbs_sel_i , // Wishbone byte enable | |
output logic [31:0] wbs_dat_o , // Wishbone data input | |
output logic wbs_ack_o , // Wishbone acknowlegement | |
input logic ir_rx , | |
output logic ir_tx , | |
output logic irq // Interrupt | |
); | |
//----------------------------------------------- | |
// Reg Interface | |
//------------------------------------------------ | |
logic cfg_ir_en ; | |
logic cfg_ir_tx_en ; | |
logic cfg_ir_rx_en ; | |
logic cfg_repeat_en ; | |
logic cfg_tx_polarity ; | |
logic cfg_rx_polarity ; | |
logic [PSIZE-1:0] cfg_multiplier ; | |
logic [PSIZE-1:0] cfg_divider ; | |
logic [DSIZE-1:0] reload_offset ; | |
logic [DSIZE-1:0] delay_mask ; | |
//--------------------------------------------- | |
// Prescal Output | |
//---------------------------------------------- | |
logic tick8 ; // 562.5µs/8 Pulse | |
logic tick1 ; // 562.5µs pulse | |
//--------------------------------------------- | |
// FIFO RX I/F | |
// <IR RECEIVER> => <RX FIFO> => WB | |
//---------------------------------------------- | |
logic fifo_rx_full ; | |
logic fifo_rx_empty ; | |
logic fifo_rx_write ; | |
logic [16:0] fifo_rx_wdata ; | |
logic [16:0] fifo_rx_rdata ; | |
logic fifo_rx_read ; | |
logic [ASIZE:0] fifo_rx_occ ; | |
//--------------------------------------------- | |
// FIFO TX I/F | |
// <WB> => <TX FIFO> => <IR Transmitter> | |
//---------------------------------------------- | |
logic fifo_tx_full ; | |
logic fifo_tx_empty ; | |
logic fifo_tx_write ; | |
logic [15:0] fifo_tx_wdata ; | |
logic [15:0] fifo_tx_rdata ; | |
logic fifo_tx_read ; | |
logic [ASIZE:0] fifo_tx_occ ; | |
// --- Prescaler --- | |
prescaler #( | |
.BITS(PSIZE) | |
) i_prescaler ( | |
.rst_n (rst_n ), | |
.clk (clk ), | |
.clear_n (cfg_ir_en ), | |
.multiplier (cfg_multiplier ), | |
.divider (cfg_divider ), | |
.tick (tick8 ) | |
); | |
// --- Register --- | |
nec_ir_regs #( | |
.PSIZE(PSIZE), | |
.DSIZE(DSIZE), | |
.ASIZE(ASIZE) | |
) i_ir_regs ( | |
.rst_n (rst_n ), | |
.clk (clk ), | |
// Configuration | |
.cfg_ir_en (cfg_ir_en ), | |
.cfg_ir_tx_en (cfg_ir_tx_en ), | |
.cfg_ir_rx_en (cfg_ir_rx_en ), | |
.cfg_repeat_en (cfg_repeat_en ), | |
.cfg_tx_polarity (cfg_tx_polarity ), | |
.cfg_rx_polarity (cfg_rx_polarity ), | |
.cfg_multiplier (cfg_multiplier ), | |
.cfg_divider (cfg_divider ), | |
.reload_offset (reload_offset ), | |
.delay_mask (delay_mask ), | |
// Wishbone bus | |
.wbs_cyc_i (wbs_cyc_i ), | |
.wbs_stb_i (wbs_stb_i ), | |
.wbs_adr_i (wbs_adr_i ), | |
.wbs_we_i (wbs_we_i ), | |
.wbs_dat_i (wbs_dat_i ), | |
.wbs_sel_i (wbs_sel_i ), | |
.wbs_dat_o (wbs_dat_o ), | |
.wbs_ack_o (wbs_ack_o ), | |
// <IR RECEIVER> => <RX FIFO> => WB | |
.rx_frame_new (fifo_rx_write ), | |
.fifo_rx_full (fifo_rx_full ), | |
.fifo_rx_rdata (fifo_rx_rdata ), | |
.fifo_rx_read (fifo_rx_read ), | |
.fifo_rx_occ (fifo_rx_occ ), | |
// <WB> => <TX FIFO> => <IR Transmitter> | |
.fifo_tx_full (fifo_tx_full ), | |
.fifo_tx_wdata (fifo_tx_wdata ), | |
.fifo_tx_write (fifo_tx_write ), | |
.fifo_tx_occ (fifo_tx_occ ), | |
// Interrupt | |
.irq (irq ) | |
); | |
// --- RX FIFO --- | |
sync_fifo_occ #( | |
.DP(DP), | |
.WD(17), | |
.AW(ASIZE) | |
) i_rx_fifo ( | |
.reset_n (rst_n ), | |
.clk (clk ), | |
.sreset_n (cfg_ir_en ), | |
.wr_data (fifo_rx_wdata ), | |
.wr_en (fifo_rx_write ), | |
.full (fifo_rx_full ), | |
.empty (fifo_rx_empty ), | |
.rd_data (fifo_rx_rdata ), | |
.rd_en (fifo_rx_read ), | |
.occupancy (fifo_rx_occ ) | |
); | |
// --- IR Receiver --- | |
nec_ir_rx #( | |
.NB_STAGES (NB_STAGES), // Number of metastability filter stages | |
.PSIZE (PSIZE ), // Size of prescaler counter(bits) | |
.DSIZE (DSIZE ), // Size of delay counter (bits) | |
.ASIZE (ASIZE ) // FIFO size (FIFO_size=(2**ASIZE)-1) | |
) u_ir_rx ( | |
.rst_n (rst_n ), // Asynchronous reset (active low) | |
.clk (clk ), // Clock (rising edge) | |
.ir_rx (ir_rx ), | |
.tick8 (tick8 ), | |
.cfg_receiver_en (cfg_ir_rx_en ), | |
.cfg_polarity (cfg_rx_polarity ), | |
.cfg_repeat_en (cfg_repeat_en ), | |
.reload_offset (reload_offset ), | |
.delay_mask (delay_mask ), | |
.fifo_rx_wdata (fifo_rx_wdata ), | |
.fifo_rx_write (fifo_rx_write ) | |
); | |
// --- IR Transmitter ---- | |
// Div8 module | |
nec_div8 u_div8 ( | |
.rst_n (rst_n ), // Asynchronous reset (active low) | |
.clk (clk ), // Clock (rising edge) | |
.tick (tick8 ), | |
.tick_div8 (tick1 ) | |
); | |
nec_ir_tx u_ir_tx( | |
.rst_n (rst_n ), // Asynchronous reset (active low) | |
.clk (clk ), // Clock (rising edge) | |
// Configuration Input | |
.tx_en (cfg_ir_tx_en ), // Transmitter enable | |
.tx_event (tick1 ), // Transmit event at every 562.5µs | |
.p_polarity (cfg_tx_polarity ), | |
// FIFO Interface | |
.fifo_valid (!fifo_tx_empty ), | |
.fifo_tx_rdata (fifo_tx_rdata ), | |
.fifo_read (fifo_tx_read ), | |
// To Pad | |
.ir_tx (ir_tx ) | |
); | |
// --- TX FIFO --- | |
sync_fifo_occ #( | |
.DP(DP), | |
.WD(16), | |
.AW(ASIZE) | |
) i_tx_fifo ( | |
.reset_n (rst_n ), | |
.clk (clk ), | |
.sreset_n (cfg_ir_en ), | |
.wr_data (fifo_tx_wdata ), | |
.wr_en (fifo_tx_write ), | |
.full (fifo_tx_full ), | |
.empty (fifo_tx_empty ), | |
.rd_data (fifo_tx_rdata ), | |
.rd_en (fifo_tx_read ), | |
.occupancy (fifo_tx_occ ) | |
); | |
endmodule |