#ifdef VHDL
/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Generic/Queue/include/Queue.h"

namespace morpheo                    {
namespace behavioural {
namespace generic {
namespace queue {


#undef  FUNCTION
#define FUNCTION "Queue::vhdl_body"
  void Queue::vhdl_body (Vhdl * & vhdl)
  {
    log_printf(FUNC,Queue,FUNCTION,"Begin");
    vhdl->set_body ("-----------------------------------------------------------------------------");
    vhdl->set_body ("-- Output");
    vhdl->set_body ("-----------------------------------------------------------------------------");
    vhdl->set_body ("out_INSERT_ACK        <= not reg_FULL;");
    vhdl->set_body ("out_RETIRE_VAL        <= not reg_EMPTY;");
	
    if (_param->_size_queue > 1)
      vhdl->set_body ("out_RETIRE_DATA       <= reg_DATA(conv_integer(reg_PTR_READ));");
    else
      vhdl->set_body ("out_RETIRE_DATA       <= reg_DATA(0);");

    vhdl->set_body ("");
    vhdl->set_body ("-----------------------------------------------------------------------------");
    vhdl->set_body ("-- Signal");
    vhdl->set_body ("-----------------------------------------------------------------------------");
    vhdl->set_body ("");
    vhdl->set_body ("signal_PTR_EQUAL      <=");
    if (_param->_size_queue > 1)
      {
	vhdl->set_body ("\t'1' when signal_NEXT_PTR_READ = signal_NEXT_PTR_WRITE else");
	vhdl->set_body ("\t'0';");
      }
    else
      vhdl->set_body ("\t'1';");
    vhdl->set_body ("signal_NEXT_FULL      <=");
    vhdl->set_body ("\t'1' when signal_WRITE='1' and signal_PTR_EQUAL='1' else");
    vhdl->set_body ("\t'0' when signal_READ ='1'                          else");
    vhdl->set_body ("\treg_FULL ;");
    vhdl->set_body ("signal_NEXT_EMPTY     <=");
    vhdl->set_body ("\t'1' when signal_READ ='1' and signal_PTR_EQUAL='1' else");
    vhdl->set_body ("\t'0' when signal_WRITE='1'                          else");
    vhdl->set_body ("\treg_EMPTY;");
    vhdl->set_body ("");
    vhdl->set_body ("-- read");
    vhdl->set_body ("signal_READ           <= (not reg_EMPTY) and in_RETIRE_ACK;");

    if (_param->_size_queue > 1)
      {  
	vhdl->set_body ("signal_NEXT_PTR_READ  <= ");
	vhdl->set_body ("\treg_PTR_READ   when signal_READ='0' else");
	if (is_log2(_param->_size_queue) == false)
	  vhdl->set_body ("\tconst_PTR_INIT when reg_PTR_READ  = const_PTR_MAX else");

	if (_param->_size_queue > 2)
	  vhdl->set_body ("\treg_PTR_READ +'1';");
	else
	  vhdl->set_body ("\tnot reg_PTR_READ;");
      }
    vhdl->set_body ("");
    vhdl->set_body ("-- write");
    vhdl->set_body ("signal_WRITE          <= (not reg_FULL ) and in_INSERT_VAL;");
    if (_param->_size_queue > 1)
      {
	vhdl->set_body ("signal_NEXT_PTR_WRITE <= ");
	vhdl->set_body ("\treg_PTR_WRITE  when signal_WRITE='0' else");
	if (is_log2(_param->_size_queue) == false)
	  vhdl->set_body ("\tconst_PTR_INIT when reg_PTR_WRITE = const_PTR_MAX else");
	if (_param->_size_queue > 2)
	  vhdl->set_body ("\treg_PTR_WRITE+'1';");
	else
	  vhdl->set_body ("\tnot reg_PTR_WRITE;");
      }
    vhdl->set_body ("");
    vhdl->set_body ("-----------------------------------------------------------------------------");
    vhdl->set_body ("-- Registers");
    vhdl->set_body ("-----------------------------------------------------------------------------");
    vhdl->set_body ("");
    vhdl->set_body ("queue_write: process (in_CLOCK)");
    vhdl->set_body ("begin  -- process queue_write");
    vhdl->set_body ("\tif in_CLOCK'event and in_CLOCK = '1' then");
    vhdl->set_body ("");
    vhdl->set_body ("\t\tif (in_NRESET = '0') then");    
    if (_param->_size_queue > 1)
      {
	vhdl->set_body ("\t\t\treg_PTR_READ  <= const_PTR_INIT;");
	vhdl->set_body ("\t\t\treg_PTR_WRITE <= const_PTR_INIT;");
      }
    vhdl->set_body ("\t\t\treg_FULL      <= '0';");
    vhdl->set_body ("\t\t\treg_EMPTY     <= '1';");
    vhdl->set_body ("\t\telse");
    if (_param->_size_queue > 1)
      {
	vhdl->set_body ("\t\t\treg_PTR_READ  <= signal_NEXT_PTR_READ ;");
	vhdl->set_body ("\t\t\treg_PTR_WRITE <= signal_NEXT_PTR_WRITE;");
      }
    vhdl->set_body ("\t\t\treg_FULL      <= signal_NEXT_FULL ;");
    vhdl->set_body ("\t\t\treg_EMPTY     <= signal_NEXT_EMPTY;");
    vhdl->set_body ("");
    vhdl->set_body ("\t\t\tif (signal_WRITE = '1') then");    
    if (_param->_size_queue > 1)
      vhdl->set_body ("\t\t\t\treg_DATA(conv_integer(reg_PTR_WRITE)) <= in_INSERT_DATA;");
    else
      vhdl->set_body ("\t\t\t\treg_DATA(0) <= in_INSERT_DATA;");
    vhdl->set_body ("\t\t\tend if;");
    vhdl->set_body ("\t\tend if;");
    vhdl->set_body ("");
    vhdl->set_body ("\tend if;");
    vhdl->set_body ("end process queue_write;");

    log_printf(FUNC,Queue,FUNCTION,"End");
  };

}; // end namespace queue
}; // end namespace generic

}; // end namespace behavioural
}; // end namespace morpheo              
#endif
