-- ----------------------------------------------------------------
-- client_server_pkg.vhd
--
-- 6/24/2015 D. W. Hawkins (dwh@caltech.edu)
--
-- A simple client/server communications package that uses a
-- global handshake.
--
-- NOTE:
-- I do not recommend using this technique. Using a resolved
-- signal is a much nicer solution.
--
-- The read/write procedures must use an argument for the request
-- signal, even though it is global. The response signal can
-- however, be accessed directly.
--
-- The procedures are similar to those used by the Altera
-- Avalon-MM Master BFM VHDL wrappers. This format is inconsistent
-- with the recommendations in Bergeron's book where both the
-- request and response are passed as signals.
--
-- See client_server_pkg_v1.txt for additional comments.
--
-- ----------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

-- ----------------------------------------------------------------

package client_server_pkg is

	-- Client/server operations
    type client_server_operation_t is (
    	OP_WRITE,
    	OP_READ
    );

	-- Client/server command/response data
	type client_server_data_t is record
		bit  : std_logic; -- request/acknowledge
		op   : client_server_operation_t;
		addr : std_logic_vector(31 downto 0);
		data : std_logic_vector(31 downto 0);
	end record;

	-- Client/server handshake and command/response
	-- via global signals
	signal client_server_req : client_server_data_t;
	signal client_server_ack : client_server_data_t;

	-- Client/server procedures
	procedure write (
		signal   p_req  : inout client_server_data_t;
		constant p_addr : in    std_logic_vector(31 downto 0);
		constant p_data : in    std_logic_vector(31 downto 0)
	);
	procedure read (
		signal   p_req  : inout client_server_data_t;
		constant p_addr : in    std_logic_vector(31 downto 0);
		variable p_data : out   std_logic_vector(31 downto 0)
	);
end package;

-- ----------------------------------------------------------------

package body client_server_pkg is

	-- Client/server handshake
	procedure handshake (
		signal   p_req  : inout client_server_data_t
	) is
	begin
		p_req.bit <= '1';
		wait until client_server_ack.bit = '1';
		p_req.bit <= '0';
		wait until client_server_ack.bit = '0';
	end procedure;

	-- Client/server communications
	procedure write (
		signal   p_req  : inout client_server_data_t;
		constant p_addr : in    std_logic_vector(31 downto 0);
		constant p_data : in    std_logic_vector(31 downto 0)
	) is
	begin
		p_req.op   <= OP_WRITE;
		p_req.addr <= p_addr;
		p_req.data <= p_data;
		handshake(p_req);
	end procedure;

	procedure read (
		signal   p_req  : inout client_server_data_t;
		constant p_addr : in    std_logic_vector(31 downto 0);
		variable p_data : out   std_logic_vector(31 downto 0)
	) is
	begin
		p_req.op   <= OP_WRITE;
		p_req.addr <= p_addr;
		p_req.data <= (others => '0');
		handshake(p_req);
		p_data := client_server_ack.data;
	end procedure;

end package body;


