--! @file
--
---------------------------------------------------------------------------------------------------
--! @brief  Simulation of a IPBus master ( subset of Wishbone master  )                               --
---------------------------------------------------------------------------------------------------
--
-- unit name: testbench (main_tb.vhd)
--
-- @author David Cussans
--
--! @details
--! based on code by Miguel Mendez (mmendez@sevensols.com),
--! http://svn.ohwr.org/qdr2-v6-core/trunk/hdl/sim/main_tb.vhd 
--
-- @date 29-2-2012
--
-- version: 0.1
--
-- dependencies: 
--
---------------------------------------------------------------------------------------------------
-- last changes: see svn log.
---------------------------------------------------------------------------------------------------
-- TODO: - .
---------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------
--                               GNU LESSER GENERAL PUBLIC LICENSE                                |
--                              ------------------------------------                              |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either     |
-- version 2.1 of the License, or (at your option) any later version.                             |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;       |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.      |
-- See the GNU Lesser General Public License for more details.                                    |
-- You should have received a copy of the GNU Lesser General Public License along with this       |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html                     |
---------------------------------------------------------------------------------------------------


--=================================================================================================
--                                      Libraries & Packages
--=================================================================================================
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
use STD.TEXTIO.all;


--! Declaration of transaction types for Bus Functional Model
use work.BFMTypes.all;                  
                                       
use work.ipbus.all;                     --! Declarations of IPBus records

entity ipbusTransactor is
  
  port (
    -- interface to transaction generator
    Trans : in t_wbTransaction;               --! Transaction from transaction generator
    returnedData : out t_wbTransactionReturn; --! Signal end-of-cycle by making a transaction on this port

    -- interface to "physical" ports
    clk_i : in std_logic;               --! System clock, active high
    ipb_to_slave : out ipb_wbus;        --! Signals from master to slave
    ipb_from_slave : in ipb_rbus        --! Signals from slave to master
    );

end ipbusTransactor;
    
architecture behavioural of ipbusTransactor is

    
begin  -- behavioural


  p_commandloop: process

    variable v_addr          : integer;
    variable v_addr_ack      : integer;
    variable outline         : line;
    variable v_data_from_slave : t_wbTransactionReturn := ( others => '0');  --! Temporary store for data
                                                --read from slave.
    variable v_receivedAck : boolean := false;  -- set true when strobe goes high...
    
  begin  -- process p_commandloop

    -- set the bus idle
    ipb_to_slave.ipb_strobe   <= '0';
    ipb_to_slave.ipb_write    <= '0';

    ipb_to_slave.ipb_addr <= ( others => '1');  --! Set to a dummy value....
    
    wait on Trans'TRANSACTION;
    report "wishboneMasterBFM: Got transaction" severity note;
        
    ipb_to_slave.ipb_strobe   <= '1';
    if( Trans.r_read_write = WRITE_TO_SLAVE ) then 
      -- Write data
      ipb_to_slave.ipb_write      <= '1';
      ipb_to_slave.ipb_wdata <= Trans.r_data;
    else 
      -- Read  data
      ipb_to_slave.ipb_write  <= '0'; 
    end if;

    -- Addr for writing and reading
    ipb_to_slave.ipb_addr <= Trans.r_addr;

    v_receivedAck := false;
    -- Loop until the slave raises ack.
    while v_receivedAck = false loop
      wait until rising_edge(clk_i); -- s_wb_clk'event and s_wb_clk = '1';     

      --got ack? 
      if(ipb_from_slave.ipb_ack = '1') then
        v_receivedAck := true;
        --read data
        if(Trans.r_read_write=READ_FROM_SLAVE) or (Trans.r_read_write=READ_FROM_SLAVE_WITH_CHECK)  then
          -- the read data is stored
          v_data_from_slave := ipb_from_slave.ipb_rdata;
          report "Read from slave. Data = " & to_hstring(v_data_from_slave) severity note;
        else -- if a write then ....
          v_data_from_slave := Trans.r_data;  -- just return what we were given
        end if;
      end if;
  
    end loop;
  
    -- terminate the cycle
    ipb_to_slave.ipb_strobe   <= '0';
    ipb_to_slave.ipb_write    <= '0';

    report "returning data = " & to_hstring(v_data_from_slave) severity note;
    returnedData <= v_data_from_slave;    -- This event is what signals the end
                                        -- of transaction.

  end process p_commandloop;
end behavioural;
