----------------------------------------------------------------------------------
-- Company: IJS 
-- Engineer: Gasper Kojek
-- 
-- Create Date:    15:02:12 02/25/2014 
-- Last edit:      12:35    03/04/2014
-- Design Name:    BRAM wrapper
-- Module Name:    ram_wrap - Behavioral 
-- Project Name: 
-- Target Devices:  Xilinx Virtex 5
-- Tool versions:   Xilinx ISE 14.7
-- Description: 
--
-- Dependencies: reg_bram.vhd
--
-- Revision: 1.0
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;

entity ram_wrap is
    port (
        clk         : in std_logic;
        
        --Primary port :  (pcie)
        addr_wr1    : in std_logic_vector (3 downto 0);              --4 bit write address
        write_en1   : in std_logic;                                  --write enable (primary) - active high
        write_data1 : in std_logic_vector (63 downto 0);             --64 bit write data
        addr_rd1    : in std_logic_vector (3 downto 0);              --4 bit read address
        out1        : out std_logic_vector (63 downto 0);            --64 bit read data   
        busy1       : out std_logic;                                 --read bram is busy (output data not valid)
        
        --Dual port :   (iz kompresor core) 
        addr_wr2    : in std_logic_vector (5 downto 0);              --6 bit write address - (5 downto 2) goes to BRAM, (1 downto 0) chooses which 16 bits are chosen from BRAM address 
        write_en2   : in std_logic;                                  --write enable (dual) - active high
        write_data2 : in std_logic_vector (15 downto 0);             --16 bit write data from compressor core
        addr_rd2    : in std_logic_vector (5 downto 0);              --6 bit read address - (5 downto 2) goes to BRAM, (1 downto 0) chooses which 16 bits are chosen from BRAM address
        out2        : out std_logic_vector (15 downto 0);            --16 bit read data output for compressor core
        busy2       : out std_logic                                  --read bram is busy (output data not valid)
        );
end ram_wrap;

-- BRAM, 16 x 64 bit
architecture Behavioral of ram_wrap is
component rams_11 
   port( 
         clk        : in std_logic;
          
        --primary (PCIe)
        addr1       : in std_logic_vector (3 downto 0);
        out1A       : out std_logic_vector (63 downto 0);
        write_en1   : in std_logic;
        write_data1 : in std_logic_vector (63 downto 0);

        --dual (compressor core)
        addr2       : in std_logic_vector (3 downto 0);
        out2A       : out std_logic_vector (63 downto 0)
        );
end component;

signal dout2	: std_logic_vector (63 downto 0);	
signal din2		: std_logic_vector (63 downto 0); 	
signal addr1	: std_logic_vector (3 downto 0);
signal addr2  	: std_logic_vector (5 downto 0);

--	mux signals
signal mux_addr1, mux_addr2             : std_logic_vector (3 downto 0);
signal mux_write_data1                  : std_logic_vector (63 downto 0);
signal mux_out1, mux_out2               : std_logic_vector (63 downto 0);
signal mux_write_en1                    : std_logic;

begin
ram: rams_11 port map (
	clk         => clk,
	
	addr1       => mux_addr1,
	out1A       => mux_out1,
	write_en1   => mux_write_en1,
	write_data1 => mux_write_data1,
	
	addr2       => mux_addr2,
	out2A       => mux_out2
);

busy1 <= write_en1;
busy2 <= write_en2;

--	address mux glede na write			
addr1 <= addr_wr1 when write_en1='1' else addr_rd1;
addr2 <= addr_wr2 when write_en2='1' else addr_rd2;

--	16-64 bit adaptation - dual read
out2 <= dout2(15 downto 0)  when addr2(1 downto 0)="00" else
        dout2(31 downto 16) when addr2(1 downto 0)="01" else
        dout2(47 downto 32) when addr2(1 downto 0)="10" else
        dout2(63 downto 48);
--	16-64 bit adaptation - dual write
din2 <= (dout2(63 downto 16) & write_data2) 					 when addr2(1 downto 0)="00" else
        (dout2(63 downto 32) & write_data2 & dout2(15 downto 0)) when addr2(1 downto 0)="01" else
        (dout2(63 downto 48) & write_data2 & dout2(31 downto 0)) when addr2(1 downto 0)="10" else
        (write_data2 & dout2(47 downto 0));

-- bram input mux
mux_addr1       <= addr2(5 downto 2) when write_en2='1' else addr1;
mux_addr2       <= addr1 when write_en2='1' else addr2(5 downto 2);
mux_write_data1 <= din2  when write_en2='1' else write_data1;
mux_write_en1   <= write_en1 or write_en2;

--bram output mux
dout2 <= mux_out1 when write_en2='1' else mux_out2;
out1  <= mux_out2 when write_en2='1' else mux_out1;

end Behavioral;

