library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity midi_uart is
	port (
		CLOCK_27,                                      -- 27 MHz
		CLOCK_50,                                      -- 50 MHz
		EXT_CLOCK : in std_logic;                      -- External Clock
		
		-- Buttons and switches
    
		KEY : in std_logic_vector(3 downto 0);         -- Push buttons
		SW : in std_logic_vector(17 downto 0);         -- DPDT switches
		
		-- LED displays

		HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7 -- 7-segment displays
			: out std_logic_vector(6 downto 0);        -- (active low)
		LEDG: out std_logic_vector(7 downto 0);        -- Green LEDs (active high)
		LEDR : out std_logic_vector(17 downto 0);      -- Red LEDs (active high)
		
		-- RS-232 interface

		UART_TXD : out std_logic;                      -- UART transmitter   
		UART_RXD : in std_logic;                       -- UART receiver

		-- SDRAM
   
		DRAM_DQ : inout std_logic_vector(15 downto 0); -- Data Bus
		DRAM_ADDR : out std_logic_vector(11 downto 0); -- Address Bus    
		DRAM_LDQM,                                     -- Low-byte Data Mask 
		DRAM_UDQM,                                     -- High-byte Data Mask
		DRAM_WE_N,                                     -- Write Enable
		DRAM_CAS_N,                                    -- Column Address Strobe
		DRAM_RAS_N,                                    -- Row Address Strobe
		DRAM_CS_N,                                     -- Chip Select
		DRAM_BA_0,                                     -- Bank Address 0
		DRAM_BA_1,                                     -- Bank Address 0
		DRAM_CLK,                                      -- Clock
		DRAM_CKE : out std_logic;                      -- Clock Enable
		
		-- FLASH
    
		FL_DQ : inout std_logic_vector(7 downto 0);      -- Data bus
		FL_ADDR : out std_logic_vector(21 downto 0);  -- Address bus
		FL_WE_N,                                         -- Write Enable
		FL_RST_N,                                        -- Reset
		FL_OE_N,                                         -- Output Enable
		FL_CE_N : out std_logic;                         -- Chip Enable
		
		-- USB controller
    
		OTG_DATA : inout std_logic_vector(15 downto 0); -- Data bus
		OTG_ADDR : out std_logic_vector(1 downto 0);    -- Address
		OTG_CS_N,                                       -- Chip Select
		OTG_RD_N,                                       -- Write
		OTG_WR_N,                                       -- Read
		OTG_RST_N,                                      -- Reset
		OTG_FSPEED,                     -- USB Full Speed, 0 = Enable, Z = Disable
		OTG_LSPEED : out std_logic;     -- USB Low Speed, 0 = Enable, Z = Disable
		OTG_INT0,                                       -- Interrupt 0
		OTG_INT1,                                       -- Interrupt 1
		OTG_DREQ0,                                      -- DMA Request 0
		OTG_DREQ1 : in std_logic;                       -- DMA Request 1   
		OTG_DACK0_N,                                    -- DMA Acknowledge 0
		OTG_DACK1_N : out std_logic;                    -- DMA Acknowledge 1
		
		-- 16 X 2 LCD Module
		
		LCD_ON,                     -- Power ON/OFF
		LCD_BLON,                   -- Back Light ON/OFF
		LCD_RW,                     -- Read/Write Select, 0 = Write, 1 = Read
		LCD_EN,                     -- Enable
		LCD_RS : out std_logic;     -- Command/Data Select, 0 = Command, 1 = Data
		LCD_DATA : inout std_logic_vector(7 downto 0); -- Data bus 8 bits

		-- SD card interface
		
		SD_DAT : in std_logic;      -- SD Card Data      SD pin 7 "DAT 0/DataOut"
		SD_DAT3 : out std_logic;    -- SD Card Data 3    SD pin 1 "DAT 3/nCS"
		SD_CMD : out std_logic;     -- SD Card Command   SD pin 2 "CMD/DataIn"
		SD_CLK : out std_logic;     -- SD Card Clock     SD pin 5 "CLK"

		-- USB JTAG link
		
		TDI,                        -- CPLD -> FPGA (data in)
		TCK,                        -- CPLD -> FPGA (clk)
		TCS : in std_logic;         -- CPLD -> FPGA (CS)
		TDO : out std_logic;        -- FPGA -> CPLD (data out)

		-- I2C bus
		
		I2C_SDAT : inout std_logic; -- I2C Data
		I2C_SCLK : out std_logic;   -- I2C Clock

		-- PS/2 port

		PS2_DAT,                    -- Data
		PS2_CLK : in std_logic;     -- Clock

		-- VGA output
		
		VGA_CLK,                            -- Clock
		VGA_HS,                             -- H_SYNC
		VGA_VS,                             -- V_SYNC
		VGA_BLANK,                          -- BLANK
		VGA_SYNC : out std_logic;           -- SYNC
		VGA_R,                              -- Red[9:0]
		VGA_G,                              -- Green[9:0]
		VGA_B : out unsigned(9 downto 0);   -- Blue[9:0]

		--  Ethernet Interface
		
		ENET_DATA : inout unsigned(15 downto 0);    -- DATA bus 16 Bits
		ENET_CMD,           -- Command/Data Select, 0 = Command, 1 = Data
		ENET_CS_N,                                  -- Chip Select
		ENET_WR_N,                                  -- Write
		ENET_RD_N,                                  -- Read
		ENET_RST_N,                                 -- Reset
		ENET_CLK : out std_logic;                   -- Clock 25 MHz
		ENET_INT : in std_logic;                    -- Interrupt
		
		-- Audio CODEC
		
		AUD_ADCLRCK : inout std_logic;                      -- ADC LR Clock
		AUD_ADCDAT : in std_logic;                          -- ADC Data
		AUD_DACLRCK : inout std_logic;                      -- DAC LR Clock
		AUD_DACDAT : out std_logic;                         -- DAC Data
		AUD_BCLK : inout std_logic;                         -- Bit-Stream Clock
		AUD_XCK : out std_logic;                            -- Chip Clock
		
		-- Video Decoder
		
		TD_DATA : in std_logic_vector(7 downto 0);  -- Data bus 8 bits
		TD_HS,                                      -- H_SYNC
		TD_VS : in std_logic;                       -- V_SYNC
		TD_RESET : out std_logic;                   -- Reset
		
		-- General-purpose I/O
		
		GPIO_0,                                      -- GPIO Connection 0
		GPIO_1 : inout std_logic_vector(35 downto 0); -- GPIO Connection 1   
		
		SRAM_DQ : inout std_logic_vector(15 downto 0);
		SRAM_ADDR : out std_logic_vector(17 downto 0);
		SRAM_UB_N, SRAM_LB_N, SRAM_WE_N, SRAM_CE_N, SRAM_OE_N : out std_logic
		
		
		);
end midi_uart;

architecture arch of midi_uart is
	-- signals for the MIDI decoder
	signal databyte, statusbyte : std_logic_vector (7 downto 0);
	signal writebyte : std_logic_vector (7 downto 0);
	
	signal note_data1 : std_logic_vector(15 downto 0);
	signal note_data2 : std_logic_vector(15 downto 0);
	signal note_data3 : std_logic_vector(15 downto 0);
	signal note_data4 : std_logic_vector(15 downto 0);
	signal note_data5 : std_logic_vector(15 downto 0);
	signal note_enable1, note_enable2, note_enable3, note_enable4, note_enable5 : std_logic;
		
	--Synthesizer declaration
	component synthesizer is
	port(
		clk, reset_n : in std_logic;
		
		--FM synthesis inputs (from NIOS processor via Avalon bus)
		fm_dat_1, fm_dat_2, fm_dat_3, fm_dat_4, fm_dat_5 : in std_logic_vector(15 downto 0);
		fm_en_1,  fm_en_2,  fm_en_3,  fm_en_4,  fm_en_5  : in std_logic;  
		
		--Select output (synthesizer or vocoder)
		select_out : std_logic;
		
		-- Switch data
		SW  : in std_logic_vector(17 downto 0);
		
		-- I2C bus (from pins)    
		I2C_SDAT : inout std_logic; -- I2C Data
		I2C_SCLK : out std_logic;   -- I2C Clock

		--Audio CODEC (from pins)
		AUD_ADCLRCK : inout std_logic; --ADC LR Clock
		AUD_ADCDAT : in std_logic;                          -- ADC Data
		AUD_DACLRCK : inout std_logic;                      -- DAC LR Clock
		AUD_DACDAT : out std_logic;                         -- DAC Data
		AUD_BCLK : inout std_logic;                         -- Bit-Stream Clock
		AUD_XCK : out std_logic                            -- Chip Clock
	);
	end component;

begin
		nios: entity work.nios_system port map (
		clk => CLOCK_50,
		reset_n => KEY(0),
		
		in_port_to_the_data_pio => databyte,
		
		out_port_from_the_status_pio => writebyte,
		in_port_to_the_status_pio => statusbyte,
		
		--note info

        out_port_from_the_note_1_pio => note_data1,
		out_port_from_the_note_2_pio => note_data2,
		out_port_from_the_note_3_pio => note_data3,
		out_port_from_the_note_4_pio => note_data4,
		out_port_from_the_note_5_pio => note_data5,
		
		SRAM_ADDR_from_the_sram => SRAM_ADDR,
		SRAM_CE_N_from_the_sram => SRAM_CE_N,
		SRAM_DQ_to_and_from_the_sram => SRAM_DQ,
		SRAM_LB_N_from_the_sram => SRAM_LB_N,
		SRAM_OE_N_from_the_sram => SRAM_OE_N,
		SRAM_UB_N_from_the_sram => SRAM_UB_N,
		SRAM_WE_N_from_the_sram => SRAM_WE_N
		);
		
		-- Set note enables
		note_enable1 <= '0' when note_data1 = x"0000" else '1';		
		note_enable2 <= '0' when note_data2 = x"0000" else '1';
		note_enable3 <= '0' when note_data3 = x"0000" else '1';
		note_enable4 <= '0' when note_data4 = x"0000" else '1';
		note_enable5 <= '0' when note_data5 = x"0000" else '1';
		

		-- Instantiate synthesizer
		syn : synthesizer port map (
			clk => CLOCK_50,
			reset_n => KEY(0),
		
			select_out => SW(0),
		
			-- pitch data
			--fm_dat_1 => x"01B8",
			fm_dat_1 => note_data1,
			fm_dat_2 => note_data2,
			fm_dat_3 => note_data3,
			fm_dat_4 => note_data4,
			fm_dat_5 => note_data5,
		
			-- voice enable
			fm_en_1  => note_enable1,
			fm_en_2  => note_enable2,
			fm_en_3  => note_enable3,
			fm_en_4  => note_enable4,
			fm_en_5  => note_enable5,
		
			-- Switch data
			SW => SW,
		
			-- I2C bus (from pins)    
			I2C_SDAT => I2C_SDAT,
			I2C_SCLK => I2C_SCLK,

			--Audio CODEC (from pins)
			AUD_ADCLRCK => AUD_ADCLRCK,
			AUD_ADCDAT  => AUD_ADCDAT,
			AUD_DACLRCK => AUD_DACLRCK,
			AUD_DACDAT  => AUD_DACDAT,
			AUD_BCLK 	=> AUD_BCLK,
			AUD_XCK     => AUD_XCK		
		);

		the_uart : entity work.Midi_interface port map (
		clk => CLOCK_50,
		rst => not KEY(0),
		rx => PS2_DAT,
		clr_flag => writebyte(0),
		data_out => databyte,
		status_out => statusbyte
		);
		
		HEX7     <= "0001001"; -- Leftmost
		HEX6     <= "0000110";
		HEX5     <= "1000111";
		HEX4     <= "1000111";
		HEX3     <= "1000000";
		HEX2     <= (others => '1');
		HEX1     <= (others => '1');
		HEX0     <= (others => '1');          -- Rightmost
		
		LEDG	 <= databyte;
		
		LEDR <= SW;
		
		LCD_ON   <= '1';
		LCD_BLON <= '1';
		LCD_RW <= '1';
		LCD_EN <= '0';
		LCD_RS <= '0';

		VGA_CLK <= '0';
		VGA_HS <= '0';
		VGA_VS <= '0';
		VGA_BLANK <= '0';
		VGA_SYNC <= '0';
		VGA_R <= (others => '0');
		VGA_G <= (others => '0');
		VGA_B <= (others => '0');

		SD_DAT3 <= '1';  
		SD_CMD <= '1';
		SD_CLK <= '1';
		
		UART_TXD <= '0';
		DRAM_ADDR <= (others => '0');
		DRAM_LDQM <= '0';
		DRAM_UDQM <= '0';
		DRAM_WE_N <= '1';
		DRAM_CAS_N <= '1';
		DRAM_RAS_N <= '1';
		DRAM_CS_N <= '1';
		DRAM_BA_0 <= '0';
		DRAM_BA_1 <= '0';
		DRAM_CLK <= '0';
		DRAM_CKE <= '0';
		FL_ADDR <= (others => '0');
		FL_WE_N <= '1';
		FL_RST_N <= '0';
		FL_OE_N <= '1';
		FL_CE_N <= '1';
		OTG_ADDR <= (others => '0');
		OTG_CS_N <= '1';
		OTG_RD_N <= '1';
		OTG_RD_N <= '1';
		OTG_WR_N <= '1';
		OTG_RST_N <= '1';
		OTG_FSPEED <= '1';
		OTG_LSPEED <= '1';
		OTG_DACK0_N <= '1';
		OTG_DACK1_N <= '1';

		TDO <= '0';

		--I2C_SCLK <= '0';
		
		ENET_CMD <= '0';
		ENET_CS_N <= '1';
		ENET_WR_N <= '1';
		ENET_RD_N <= '1';
		ENET_RST_N <= '1';
		ENET_CLK <= '0';

		--AUD_DACDAT <= '0';
		--AUD_XCK <= '0';
		
		TD_RESET <= '0';

		-- Set all bidirectional ports to tri-state
		DRAM_DQ     <= (others => 'Z');
		FL_DQ       <= (others => 'Z');
		OTG_DATA    <= (others => 'Z');
		LCD_DATA    <= (others => 'Z');
		--I2C_SDAT    <= 'Z';
		ENET_DATA   <= (others => 'Z');
		--AUD_ADCLRCK <= 'Z';
		--AUD_DACLRCK <= 'Z';
		--AUD_BCLK    <= 'Z';
		GPIO_0      <= (others => 'Z');
		GPIO_1      <= (others => 'Z');

end arch;