-- Provides information about the firmware.
-- This block is written as a generic memory that sends data based on the requested address.
--
-- Generally this block is connected to the 'control' interface in the userlogiccmp_forxilly block and the user interacts with it using the 'control' files.
-- The information_data package should contain several mandatory constants as well as the contents of the memory. Generally, the first four 32-bit-tuples are occupied by a unique GUID that identifies the firmware.

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

library utilities;
use utilities.utilities.all;

library information;
use information.information_data.all;

----------------------------------------------------------------
-- NOTE: No range check on the i_data requested address. 

entity information_block is
        
port (

        clk : in std_logic;
        rst : in std_logic;
        
        -- Input side:
        i_data   : in  std_logic_vector( 31 downto 0 );
        i_valid  : in  std_logic;
        o_enable : out std_logic;
        
        -- Output side:
        o_data   : out std_logic_vector( 31 downto 0 );
        o_valid  : out std_logic;
        i_enable : in  std_logic
                
        );
                
end entity;

architecture rtl of information_block is

        -- data in buffer
        signal buffer_valid : std_logic;
        signal buffer_data : std_logic_vector( o_data'range );
        -- data from the memory
        signal mem_valid : std_logic;
        signal mem_data : std_logic_vector( o_data'range );
        
        signal oo_valid : std_logic;
        
        signal addr : unsigned( log2( C_INFO_NUMDATA ) - 1 downto 0 );
        --signal i_valid_d : std_logic;

        constant C_RESVAL : std_logic_vector( C_INFO_BITWIDTH -1 downto 0 ) := ( others => '0' );

        -- Memory content:
        subtype t_memdata is t_twodim_stdlogic( C_INFO_NUMDATA - 1 downto 0, C_INFO_BITWIDTH - 1 downto 0 );
        constant C_MEMDATA : t_memdata := stdlogicvector_to_twodim( C_INFO_DATA, C_INFO_NUMDATA, C_INFO_BITWIDTH );

begin

        o_enable <= i_enable;
        o_valid <= oo_valid and i_enable;
        
        o_data <= buffer_data when buffer_valid = '1' else
                                                mem_data;
        oo_valid <= buffer_valid when buffer_valid = '1' else
                                                        mem_valid;
        
        valid_handling: process( clk )
        begin
                if( rising_edge(clk) ) then
                        mem_valid <= i_valid;
                end if;
        end process;
        
        addr <= unsigned( i_data( addr'range ) );
        
        -- inferred bram:
        inferred_bram_inst : entity utilities.inferred_bram
                generic map( 
                        G_RAM_CONTENT => C_MEMDATA,
                        G_WIDTH => C_INFO_BITWIDTH,
                        G_SIZE => C_INFO_NUMDATA,
                        G_RESVAL_A => C_RESVAL
                )
                port map(
                        i_clka => clk,
                        i_ena => '1',
                        i_wea => '0',
                        i_resa => '0',
                        i_addra => addr,
                        i_dataa => ( C_INFO_BITWIDTH - 1 downto 0 => '0' ),
                        o_dataa => mem_data
                );
        
        outp_data : process( clk )
        begin
                if( rising_edge(clk) ) then
                        if( rst = '1' ) then
                                buffer_valid <= '0';
                        else
                        
                                if( i_enable = '1' ) then
                                        buffer_valid <= '0';
                                elsif( buffer_valid = '0' ) then
                                        buffer_valid <= mem_valid;
                                        buffer_data <= mem_data;
                                end if;
                                        
                        end if;
                end if;
        end process;
        
                                                
end architecture;