module etx_arbiter (/*AUTOARG*/
   // Outputs
   txwr_wait, txrd_wait, txrr_wait, etx_access, cfg_access,
   etx_packet,
   // Inputs
   clk, nreset, txwr_access, txwr_packet, txrd_access, txrd_packet,
   txrr_access, txrr_packet, etx_wait, etx_cfg_wait
   );

   parameter AW = 32;   
   parameter PW = 2*AW+40;
   parameter ID = 0;
   
   //tx clock and reset
   input          clk;
   input          nreset;
   
   //Write Request (from slave)
   input 	   txwr_access;
   input [PW-1:0]  txwr_packet;
   output          txwr_wait;
   
   //Read Request (from slave)
   input 	   txrd_access;
   input [PW-1:0]  txrd_packet;
   output          txrd_wait;
   
   //Read Response (from master)
   input 	   txrr_access;
   input [PW-1:0]  txrr_packet;
   output          txrr_wait;

   //Wait signal inputs
   input 	   etx_wait;   
   input 	   etx_cfg_wait;
   
   //Outgoing transaction
   output          etx_access;      //for IO
   output 	   cfg_access;      //for RX/RX configuration
   output [PW-1:0] etx_packet;
    
   //regs
   reg 		   etx_access;
   reg [PW-1:0]    etx_packet;
   reg 		   cfg_access;  //config access
   reg [PW-1:0]    cfg_packet;  //config packet
   
   //wires  
   wire [3:0] 	   txrd_ctrlmode;
   wire [3:0] 	   txwr_ctrlmode;
   wire 	   access_in;   
   wire [PW-1:0]   etx_packet_mux;
   wire 	   txrr_grant;
   wire 	   txrd_grant;
   wire 	   txwr_grant;  
   wire [PW-1:0]   etx_mux;
   wire [31:0] 	   dstaddr_mux;
   
   //########################################################################
   //# Arbiter
   //########################################################################
   //TODO: change to round robin!!! (live lock hazard)
   
   oh_arbiter #(.N(3)) arbiter (.grants({txrd_grant,
					 txwr_grant, //highest priority
					 txrr_grant	
					 }),
				.requests({txrd_access,
					   txwr_access,
					   txrr_access	
					   })
				);
   oh_mux3 #(.DW(PW))
   mux3(.out	(etx_mux[PW-1:0]),
	.in0	(txwr_packet[PW-1:0]),.sel0 (txwr_grant),
	.in1	(txrd_packet[PW-1:0]),.sel1 (txrd_grant),
	.in2	(txrr_packet[PW-1:0]),.sel2 (txrr_grant)
	);

   //######################################################################
   //Pushback (stall) Signals
   //######################################################################
   assign etx_all_wait = (etx_wait     & ~cfg_match) |
			 (etx_cfg_wait &  cfg_match);
      
   //Read response
   assign txrr_wait = etx_all_wait;

   //Write waits on pin wr wait or cfg_wait
   assign txwr_wait = etx_all_wait |
		      txrr_access;

   //Host read request (self throttling, one read at a time)
   assign txrd_wait = etx_all_wait |
		      txrr_access  |
		      txwr_access;
   
   //#####################################################################
   //# Pipeline stage (arbiter+mux takes time..)
   //#####################################################################
   assign access_in = txwr_grant |
		      txrd_grant |
		      txrr_grant;

/*   assign access_in = (txwr_grant & ~txwr_wait) |
		      (txrd_grant & ~txrd_wait) |
		      (txrr_grant & ~txrr_wait);

  */ 
   
   packet2emesh #(.AW(AW))
   p2e (.write_in	(),
	.datamode_in	(),
	.ctrlmode_in	(),
	.dstaddr_in	(dstaddr_mux[31:0]),
	.srcaddr_in	(),
	.data_in	(),
	.packet_in	(etx_mux[PW-1:0]));
   
   assign cfg_match = (dstaddr_mux[31:20]==ID);

   //access decode
    always @ (posedge clk)
      if (!nreset)
	etx_access    <= 1'b0;   
      else if (~etx_wait)
	//for loopback, send cfg to RX (mostly for mailbox)
	etx_access   <= access_in & ~cfg_match;

   //config access
   always @ (posedge clk)
     if (!nreset)
       cfg_access  <= 1'b0;	   
     else if (~etx_cfg_wait)
       cfg_access  <= (txwr_grant | txrd_grant) & cfg_match;

   //packet
   always @ (posedge clk)
     if (access_in & ~etx_all_wait)
       etx_packet[PW-1:0] <= etx_mux[PW-1:0];	 
   
endmodule // etx_arbiter