blob: badae107f1c14ba2ea136aaae1a175b60cdf5d97 [file] [log] [blame]
//////////////////////////////////////////////////////////////////////////////
// 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