HierarchyFilesModulesSignalsTasksFunctionsHelp

/******************************************************************************/ 
/*                                                                            */ 
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved.             */ 
/*                                                                            */ 
/* The contents of this file are subject to the current version of the Sun    */ 
/* Community Source License, microSPARCII ("the License"). You may not use    */ 
/* this file except in compliance with the License.  You may obtain a copy    */ 
/* of the License by searching for "Sun Community Source License" on the      */ 
/* World Wide Web at http://www.sun.com. See the License for the rights,      */ 
/* obligations, and limitations governing use of the contents of this file.   */ 
/*                                                                            */ 
/* Sun Microsystems, Inc. has intellectual property rights relating to the    */ 
/* technology embodied in these files. In particular, and without limitation, */ 
/* these intellectual property rights may include one or more U.S. patents,   */ 
/* foreign patents, or pending applications.                                  */ 
/*                                                                            */ 
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos,   */ 
/* Solaris, Java and all Java-based trademarks and logos are trademarks or    */ 
/* registered trademarks of Sun Microsystems, Inc. in the United States and   */ 
/* other countries. microSPARC is a trademark or registered trademark of      */ 
/* SPARC International, Inc. All SPARC trademarks are used under license and  */ 
/* are trademarks or registered trademarks of SPARC International, Inc. in    */ 
/* the United States and other countries. Products bearing SPARC trademarks   */ 
/* are based upon an architecture developed by Sun Microsystems, Inc.         */ 
/*                                                                            */ 
/******************************************************************************/ 
/***************************************************************************
****************************************************************************
***
***  Program File:  @(#)arbiter.v
***
***  Description:
***  This file contains the arbiter module for falcon. I accepts 4 requests
***  from external sources, and one from the host. In responce, a single
***  grant goes out on the following clock edge.
*** 
*** 
***       Revision: Delete Lock pin and functionality. Pin needed for 208
***       pin package, and functionality limited because of afx bus locking
***       on read requests while pci locking at the same time (deadlock).
***       In order to gain more pins in a 208 pin package, the idsels which
***       had dedicated pins, are being deleted. A new request (req_conf) is
***       being added as an input to the arbiter, which is from the host
***       interface. When it is active, the host is requesting that the arbiter
***       stick to the grant for several clocks (like done in state WAITF
***       already). When the arbiter is in state WAITF with the host grant,
***       the grant_conf will go active. This is used to precharge the idle
***       pci bus with an address that is resistively coupled to the idsel's
***       of the slave pci interfaces. (Note. other subsystems are also
***       capable of configuring subsystems that available on the pci bus).
***       Revision: Add an arbiter disable input pin, which when disabled,
***       the internal arbiter is not used, and an external arbiter is used.
***       In this case, the falcon could act as a slave device, or it could
***       still be a master, but does not include arbitration. When the
***       arbiter is disabled the req_conf_ operations will not work, so
***       configuration cycles should not be made by the master or slave.
***       The req_ in will reflect the grant to the falcon, and the granto_
***       pin will reflect the request of the falcon host when the internal
***       arbiter is disabled.
***       Revision: ? added ability to programmably assign the priority to
***       each request/grant pair.
***       Revision: ? added standby logic, that monitors for any external pci
***	  activity, and causes go_standby to go off. Also added the quiencensce
***	  input, that will cause the arbitration to go into a slow down mode,
***	  and preventing some external master from retrying too quickly when
***	  the quiecense control is set (like during iotlb updating).       
***	  NOTE: the programmable assignment of priorities may (probably will)
***	  not cause the standby function to work.
***	  Corrected single cycle error edge case, where bus was parked on an
***	  external master, which just started a transfer (wiht out raising 
***	  request, since it had the grant already) and went into standby AND
***	  pcic_idle, then transcation started. Fix is to delay going into 
***	  standby until one clock after bus park request is generated.
***
****************************************************************************
****************************************************************************/
[Up: pcic arbiter]
module arbiter(
	req_,			// PCI requests from the external slots
	req_host_,		// request from the host
	granto_,		// PCI grants to external slots
	granto_host_,		// grant to the host
	req_conf_,		// Request from AFX slave interface, asking
				// for notification of sticking on host grant.
	grant_conf_,		// Notification to AFX slave interface, that
				// the pci bus is stuck (WAITF) at the host.
	arb_lvl_en,		// Configuration register, enable additional
				// levels of arbitration.
	reset,			// PCI reset
	clock,			// PCI clock
	bus_idle,		// _frame_i & _irdy_i, bus idle from pci_core
	new_frame,		// ~_frame_i & _frame_in, new frame pulse,
				// 	when frame first goes active.
	arb_disable,		// disable internal arbiter, turn around req/gnt
	arb_asgn_reg,		// arbiter assignment of req/grnt priorities
	req_quiescence,		// bus going to signal retry while quiescent,
				// therefore slow down arbitration.
	mm_go_standby,		// bit of MID, causing programmable standby
	turn_off_standby,	// reset of MID register bit with external activity.
	pin_go_standby,		// external pin of package 
	go_standby,		// qualified OR of pin and programmable bit
	pcic_idle,		// AND of all pcic idles, and delayed turn on too.
	any_xint,		// any interrupt, turns go_standby off
	sm_idle,		// afx slave state machine idle (on gclk)
	mas_idle,		// pci master state machine idle (on pci clk)
	afx_m_idle,		// afx master state machine idle (also on pci clk!)
				//   includes both fifo's empty for xmit and rcv
// add to support pci configuration operations
        pci_slave_mode,
	pci_slave_idsel,

	pci_clk_sync,		// pci clock, for resyncing
	pci_clk_sync_,		// pci clock, for resyncing
	slave_idle		// pci slave state machine idle (on pci clk)
	);

// The arbiter is used to select between all requests to use the PCI bus.
// It is not defined as part of the PCI bus specification. It must
// exhibit "fairness" as required as part of the PCI spec. This arbiter
// does not provide the "lock" function.

input		reset;
input		clock;
input		arb_lvl_en;
input		req_conf_;
input		req_host_;
input		bus_idle;
input		new_frame;
input		arb_disable;
input	[14:0]	arb_asgn_reg;
input		req_quiescence;
input		mm_go_standby;
input		pin_go_standby;
input		any_xint;
input		sm_idle;
input		mas_idle;
input		afx_m_idle;

input		pci_slave_mode;
output		pci_slave_idsel;
wire		pci_slave_idsel;

input		slave_idle;
input		pci_clk_sync;
input		pci_clk_sync_;
output		go_standby;
output		turn_off_standby;
output		pcic_idle;

input	[3:0]	req_;

output		granto_host_;
output	[3:0]	granto_;
output		grant_conf_;

`define ARB_IDLE    2'b00
`define ARB_WAIT1   2'b01
`define ARB_WAITF   2'b11
`define ARB_BUSY    2'b10

reg	any_x_req_ff;
reg	any_x_act_d1;
reg	any_x_act_d2;
reg	any_x_act_d3;
reg	any_x_act_d4;
reg	going_d1;
reg	going_d2;
reg	going_d3;
reg	going_d4;
reg	standby_park_req_d1;
reg	standby_park_req_d2;

wire	any_x_active = any_x_req_ff | any_xint ;
wire	turn_off_standby = any_x_active | any_x_act_d1 | any_x_act_d2 
					| any_x_act_d3 | any_x_act_d4 ;
wire	hold_off_standby = turn_off_standby | ~standby_park_req_d1 
					| ~standby_park_req_d2;  
wire	prog_go_standby;
wire	standby_park_req = ~turn_off_standby & (prog_go_standby | pin_go_standby);
wire	go_standby = ~hold_off_standby & (prog_go_standby | pin_go_standby);
wire	any_x_req = ~req_[3] | ~req_[2] | ~(req_[1] | pci_slave_mode)| ~req_[0];
wire	pcic_going_idle = sm_idle & mas_idle & afx_m_idle & slave_idle;
wire	pcic_idle = pcic_going_idle & going_d1 & going_d2 & going_d3 & going_d4 ;

sync sync_mm(	.out	(prog_go_standby),
		.in_clk (pci_clk_sync_),
		.out_clk(pci_clk_sync),
		.in	(mm_go_standby)
);

always @(posedge clock)
begin
if (reset)
  begin
  any_x_req_ff <= #1 1'b0;
  any_x_act_d1 <= #1 1'b0;
  any_x_act_d2 <= #1 1'b0;
  any_x_act_d3 <= #1 1'b0;
  any_x_act_d4 <= #1 1'b0;
  going_d1 <= #1 1'b1;
  going_d2 <= #1 1'b1;
  going_d3 <= #1 1'b1;
  going_d4 <= #1 1'b1;
  standby_park_req_d1 <= #1 1'b0;
  standby_park_req_d2 <= #1 1'b0;
  end
else 
  begin
  any_x_req_ff <= #1 any_x_req ;
  any_x_act_d1 <= #1 any_x_active ;
  any_x_act_d2 <= #1 any_x_act_d1;
  any_x_act_d3 <= #1 any_x_act_d2;
  any_x_act_d4 <= #1 any_x_act_d3;
  going_d1 <= #1 pcic_going_idle;
  going_d2 <= #1 going_d1;
  going_d3 <= #1 going_d2;
  going_d4 <= #1 going_d3;
  standby_park_req_d1 <= #1 standby_park_req;
  standby_park_req_d2 <= #1 standby_park_req_d1;
  end
end 


 
// Revision: The input arb_asgn_reg[14:0] is used to assign the input
// requests (and grant outputs too) to a different signal in this module.
// In that way, the design of this module does not really change, but 
// instead a new funciton is added, that reroutes the input request
// to other input requests before the fixed priorities are used. This
// makes the priorities appear programmable. (note the outputs have to
// be routed also, to match the requests).
//
// This is the monitoring for who used the bus last, in order to determine
// who will be given priority in the future. The saving of who used the 
// bus last is established each time the frame signal is asserted after 
// being deasserted. This is the start of a new transaction. The grants
// that were asserted in the cycle before the frame signal is asserted
// are used to determine which master asserted the frame. This monitoring
// is used if there is multilevel priority as described in the PCI 
// specification (2.1, page 56). The last master to be granted the bus
// at each level (even if not currently granted at that level) must be 
// remembered in order to be fair for subsequent requests.
//
// When arb_lvl_en is true, priorities are assigned as follows:
//
// Host vs. level1 -----Level 0 (one bit of storage)
//	      |
//    slots 0 or 1 or level2 -----Level 1 (two bits of storage)
//			  |
//	          slots 2 or 3 -----Level 2 (one bit of storage)
//
// Every time a level is used, which position was used is saved so next
// time that level is accessed, then some other position is selected.
//
reg	[3:0]	grant_;		// Which master is granted this cycle.
reg		grant_host_;	// Which master is granted this cycle.
reg	[4:0]	grant_last_;	// Which master was granted last cycle.
reg	[4:0]	last_master_;	// Which master asserted frame last.
reg		l0_lst_;	// last level 0 granted bus 
reg	[1:0]	l1_lst_;	// last level 1 granted bus 
reg		l2_lst_;	// last level 2 granted bus 
wire		req_keep_bus_;	// request to keep the bus at the master
assign req_keep_bus_ = req_conf_ & ~req_quiescence & ~standby_park_req ;
wire	[4:0]	reqs_ ={asgn_map_func({(req_host_ & req_keep_bus_),req_},arb_asgn_reg[14:12]),
			asgn_map_func({(req_host_ & req_keep_bus_),req_},arb_asgn_reg[11:9]),
			asgn_map_func({(req_host_ & req_keep_bus_),req_},arb_asgn_reg[8:6]),
			asgn_map_func({(req_host_ & req_keep_bus_),req_},arb_asgn_reg[5:3]),
			asgn_map_func({(req_host_ & req_keep_bus_),req_},arb_asgn_reg[2:0])};

wire		grant_conf_ = req_keep_bus_ | granto_host_;
wire	[4:0]	nxt_grnt_ = nxt_grnt_gen_(arb_lvl_en,last_master_,reqs_,l0_lst_,l1_lst_,l2_lst_);

wire	[4:0]	remapd_grnt0_ = asgn_out_func(grant_[0],arb_asgn_reg[2:0]) ;
wire	[4:0]	remapd_grnt1_ = asgn_out_func(grant_[1],arb_asgn_reg[5:3]) ;
wire	[4:0]	remapd_grnt2_ = asgn_out_func(grant_[2],arb_asgn_reg[8:6]) ;
wire	[4:0]	remapd_grnt3_ = asgn_out_func(grant_[3],arb_asgn_reg[11:9]) ;
wire	[4:0]	remapd_grnth_ = asgn_out_func(grant_host_,arb_asgn_reg[14:12]) ;

wire	[4:0]	grants_	= (remapd_grnth_ & remapd_grnt3_ & remapd_grnt2_ & remapd_grnt1_ & remapd_grnt0_);
wire		granto_host_ = (arb_disable & req_[0] | 
				~arb_disable & grants_[4]);
wire	[3:0]	granto_	= arb_disable ? {2'b1, req_keep_bus_,(req_host_ & req_keep_bus_)}: grants_[3:0];

// add to support pci slave mode configuration operations
assign	pci_slave_idsel = req_[1] & pci_slave_mode;

function [4:0] nxt_grnt_gen_;
input		arb_lvl_en;
input	[4:0]	last_master_;
input	[4:0]	reqs_;
input		l0_lst_;	// Not used in this function (may not be 
				// needed in design at all! (since last_master
				// msb is if host used bus last.)
input	[1:0]	l1_lst_;
input		l2_lst_;	

reg	[4:0]	tmp_nxt_grnt_;

begin
casex(arb_lvl_en)
  1'b0:				// fixed rotating priorities
    begin
    casex(last_master_)
	5'b01111:
	   begin
	   casex(reqs_)
	     5'bxxxx0: tmp_nxt_grnt_ = 5'b11110; 
	     5'bxxx01: tmp_nxt_grnt_ = 5'b11101; 
	     5'bxx011: tmp_nxt_grnt_ = 5'b11011; 
	     5'bx0111: tmp_nxt_grnt_ = 5'b10111; 
	     5'b01111: tmp_nxt_grnt_ = 5'b01111; 
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	5'b11110:
	   begin
	   casex(reqs_)
	     5'bxxx0x: tmp_nxt_grnt_ = 5'b11101; 
	     5'bxx01x: tmp_nxt_grnt_ = 5'b11011; 
	     5'bx011x: tmp_nxt_grnt_ = 5'b10111; 
	     5'b0111x: tmp_nxt_grnt_ = 5'b01111; 
	     5'b11110: tmp_nxt_grnt_ = 5'b11110; 
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	5'b11101:
	   begin
	   casex(reqs_)
	     5'bxx0xx: tmp_nxt_grnt_ = 5'b11011; 
	     5'bx01xx: tmp_nxt_grnt_ = 5'b10111; 
	     5'b011xx: tmp_nxt_grnt_ = 5'b01111; 
	     5'b111x0: tmp_nxt_grnt_ = 5'b11110; 
	     5'b11101: tmp_nxt_grnt_ = 5'b11101; 
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	5'b11011:
	   begin
	   casex(reqs_)
	     5'bx0xxx: tmp_nxt_grnt_ = 5'b10111; 
	     5'b01xxx: tmp_nxt_grnt_ = 5'b01111; 
	     5'b11xx0: tmp_nxt_grnt_ = 5'b11110; 
	     5'b11x01: tmp_nxt_grnt_ = 5'b11101; 
	     5'b11011: tmp_nxt_grnt_ = 5'b11011; 
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	5'b10111:
	   begin
	   casex(reqs_)
	     5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; 
	     5'b1xxx0: tmp_nxt_grnt_ = 5'b11110; 
	     5'b1xx01: tmp_nxt_grnt_ = 5'b11101; 
	     5'b1x011: tmp_nxt_grnt_ = 5'b11011; 
	     5'b10111: tmp_nxt_grnt_ = 5'b10111; 
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	5'b11111:
	   begin
	   casex(reqs_)
	     5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; 
	     5'b1xxx0: tmp_nxt_grnt_ = 5'b11110; 
	     5'b1xx01: tmp_nxt_grnt_ = 5'b11101; 
	     5'b1x011: tmp_nxt_grnt_ = 5'b11011; 
	     5'b10111: tmp_nxt_grnt_ = 5'b10111; 
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	default: tmp_nxt_grnt_ = 5'b01111;	// assign host next grant if 
						// last_master is hosed!
    endcase
    end

// This is the three level priority area. Level 0 alternates
// between the host and all other slots. The host is granted
// access to the bus up to 50% of the accesses. Level 1 consists
// of slots 0 and 1. A third level 1 position is given to level 2
// slots, which are slots 2 and 3.
//
// Level 0 ---> Host vs level 1 (alternates every transaction)
// 			  |
// 			  v
// Level 1 ------> slot 0 vs 1 vs level 2 (rotates every Level 1 transaction)
// 				     |
// 				     v
// Level 2 ---------> 		slot 2 vs 3 (alternates every Level 2 transaction)

  1'b1:				// three levels of priority
    begin
    casex(last_master_)
	5'b01111:		// host (level 0) went last
	   begin	// check who was last user at each level (level 0 known to be host)
	   casex({l1_lst_[1:0],l2_lst_})
	     3'b1x1:		// last level 1 user was really a level 2 slot (3)
		begin		// therefore slot 0 will be next level 1 user
		casex(reqs_[4:0])
		  5'bxxxx0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  5'bxxx01: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// no level 1 requests so check level 2 below
		  5'bxx011: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		  5'bx0111: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		// no level 1 or 2 requests 
		  5'b01111: tmp_nxt_grnt_ = 5'b01111; // defaults back to host
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     3'b1x0:		// last level 1 user was really a level 2 slot (2)
		begin		
		casex(reqs_[4:0])
		  5'bxxxx0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  5'bxxx01: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// no level 1 requests so check level 2 below
		  5'bx0x11: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		  5'bx1011: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		// no level 1 or 2 requests 
		  5'b01111: tmp_nxt_grnt_ = 5'b01111; // defaults back to host
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     3'b000:		// last level 1 user was slot 0, last level 2 was slot 2
		begin	
		casex(reqs_[4:0])
		// go right to level 1 requests first (slot 1)
		// only check slot 1 at level 1, then go to level 2, slot 3 next
		  5'bxxx0x: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// no level 2 requests so check level 1 below
		  5'bx0x1x: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		  5'bx101x: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		// go back to level 1 requests now (slot 0)
		  5'bx1110: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		// no level 1 or 2 requests 
		  5'b01111: tmp_nxt_grnt_ = 5'b01111; // defaults back to host
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     3'b001:		// last level 1 user was slot 0, last level 2 was slot 3
		begin		
		casex(reqs_[4:0])
		// go right to level 1 requests first (slot 1)
		// only check slot 1 at level 1, then go to level 2, slot 2 next
		  5'bxxx0x: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// go right to level 2 requests first (slot 2 before slot 3)
		  5'bxx01x: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		  5'bx011x: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		// go back to level 1 requests now (slot 0)
		  5'bx1110: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		// no level 1 or 2 requests 
		  5'b01111: tmp_nxt_grnt_ = 5'b01111; // defaults back to host
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     3'b010:		// last level 1 user was slot 1, last level 2 was slot 2
		begin		
		casex(reqs_[4:0])
		// go right to level 2 requests first (slot 3 first)
		  5'bx0xxx: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		  5'bx10xx: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		// no level 2 requests so check level 1 below
		  5'bx11x0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  5'bx1101: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// no level 1 or 2 requests 
		  5'b01111: tmp_nxt_grnt_ = 5'b01111; // defaults back to host
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     3'b011:		// last level 1 user was slot 0, last level 2 was slot 3
		begin		
		casex(reqs_[4:0])
		// go right to level 2 requests first (slot 2 first)
		  5'bxx0xx: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		  5'bx01xx: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		// no level 2 requests so check level 1 below
		  5'bx11x0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  5'bx1101: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// no level 1 or 2 requests 
		  5'b01111: tmp_nxt_grnt_ = 5'b01111; // defaults back to host
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	5'b11110:		// level 1, slot 0 went last, slot 1 goes next
	   begin	// check who was last user level 2 (level 0 and 1 known)
	   casex(l2_lst_)
	     1'b0:		// last level 2 user was slot 2
		begin		
		casex(reqs_[4:0])
		  5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; // host request and grant
		  5'b1xx0x: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// no level 1 requests so check level 2 below
		  5'b10x1x: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		  5'b1101x: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		// then go back to level 1 again
		  5'b11110: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     1'b1:		// last level 2 user was slot 3
		begin		
		casex(reqs_[4:0])
		  5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; // host request and grant
		  5'b1xx0x: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// no level 1 requests so check level 2 below
		  5'b1x01x: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		  5'b1011x: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		// then go back to level 1 again
		  5'b11110: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     default: tmp_nxt_grnt_ = last_master_;
	   endcase
	   end
	5'b11101:		// level 1, slot 1 went last, level 2 goes next
	   begin
	   casex(l2_lst_)
	     1'b0:		// last level 2 user was slot 2
		begin		
		casex(reqs_[4:0])
		  5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; // host request and grant
		// now check level 2 below
		  5'b10xxx: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		  5'b110xx: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		// then go back to level 1 again
		  5'b111x0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  5'b11101: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	     1'b1:		// last level 2 user was slot 3
		begin		
		casex(reqs_[4:0])
		  5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; // host request and grant
		// now check level 2 below
		  5'b1x0xx: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
		  5'b101xx: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
		// then go back to level 1 again
		  5'b111x0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
		  5'b11101: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		  default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
		endcase
		end
	   endcase
	   end
	5'b11011:		// level 2, slot 2 went last, slot 3 goes next
	   begin
	     casex(reqs_[4:0])
	       5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; // host request and grant
		// now check level 1 below
	       5'b1xxx0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
	       5'b1xx01: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// then go back to level 2 again
	       5'b10x11: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
	       5'b11011: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
	       default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
	     endcase
	   end
	5'b10111:		// level 2, slot 3 went last, slot 2 goes next
	   begin
	     casex(reqs_[4:0])
	       5'b0xxxx: tmp_nxt_grnt_ = 5'b01111; // host request and grant
		// now check level 1 below
	       5'b1xxx0: tmp_nxt_grnt_ = 5'b11110; // slot 0 request and grant
	       5'b1xx01: tmp_nxt_grnt_ = 5'b11101; // slot 1 request and grant
		// then go back to level 2 again
	       5'b1x011: tmp_nxt_grnt_ = 5'b11011; // slot 2 request and grant
	       5'b10111: tmp_nxt_grnt_ = 5'b10111; // slot 3 request and grant
	       default: tmp_nxt_grnt_ = last_master_; // no level 1 or 2 requests
	     endcase
	   end
	default: tmp_nxt_grnt_ = 5'b01111;	// assign host next grant if 
    endcase					// last_master_ is hosed.
    end
  default: tmp_nxt_grnt_ = last_master_;
endcase

nxt_grnt_gen_ = tmp_nxt_grnt_;

end
endfunction


// Process requests in generating grants. 

reg	[3:0]	Wait4FrameCnt;
reg	[1:0]	arb_state;

// rev 2.0 does not use term req_new, instead uses term req_any
wire req_new = |( last_master_[4:0] & ~reqs_ );
wire req_current_grnt = |( ~{grant_host_,grant_} & ~reqs_ );
wire req_any =  ~&reqs_;
wire StopWait4Frame = &Wait4FrameCnt ;
wire clkLast = (new_frame | ((arb_state == `ARB_WAITF) & StopWait4Frame));  
wire l2Last = ~&grant_last_[1:0];	// any level 2 grants?

always @(posedge clock)
begin
if (arb_state == `ARB_WAITF)
  Wait4FrameCnt <= #1 (Wait4FrameCnt + 1'b1);
else
  Wait4FrameCnt <= #1 4'b0000;
end

wire	[4:0]	grant_last_in = (reset ? 5'b11111 : { grant_host_,grant_ }) ;

always @(posedge clock)
begin

grant_last_ <= #1 grant_last_in;

if (reset)
  begin
  last_master_ <= 5'b01111;
  l0_lst_ <= 1'b0;
  l1_lst_ <= 2'b00;
  l2_lst_ <= 1'b0;
  end
else if (clkLast && ~grant_last_[4])	// last master was host
  begin
  last_master_ <= #1 grant_last_;
  l0_lst_ <= #1 grant_last_[4];
  end
else if (clkLast && l2Last)		// last master was level 2 
  begin
  last_master_ <= #1 grant_last_;
  l0_lst_ <= #1 grant_last_[4];
  l1_lst_ <= #1 ({ ~&grant_last_[3:2],grant_last_[0] });
  end
else if (clkLast)			// last master was level 3
  begin
  last_master_ <= #1 grant_last_;
  l0_lst_ <= #1 grant_last_[4];
  l1_lst_ <= #1 ({ ~&grant_last_[3:2],grant_last_[0] });
  l2_lst_ <= #1 grant_last_[2];
  end
end


function [1:0] arb_sm;

input	[1:0]	arb_state;
input		new_frame;
input		bus_idle;
input		req_new;
input		req_any;
input		req_current_grnt;
input		StopWait4Frame;

// note: a input that compares the next grants (internal only)
// with the current requests is needed for ARB_WAITF testing.
// Also someting that counts on the 16 waits for a frame.

    reg [1:0] ns;		// next state

    begin
	case (arb_state)

// ARB_IDLE is used when the bus is parked on a position (last master).
// It is also used to ignore all other requests when the bus is locked.
// During idle the bus is granted to the last_master that used the bus,
// or if there is a new_request (not last_master), all grants are turned
// off for one cycle to prevent a parked master that has been doing
// address stepping from conflicting with the next master.

	    `ARB_IDLE:		// ARB_IDLE
		begin
		if (new_frame)
		   begin	// last master took bus
		   ns = `ARB_BUSY;
		   end
		else if (req_current_grnt) 
		   begin	// last master asks for bus
		   ns = `ARB_WAITF;
		   end
// rev 2.0 chng	else if (req_new) 
		else if (req_any) 
		   begin	// other master asks for bus
		   ns = `ARB_WAIT1;
		   end
		else ns = `ARB_IDLE;
		end

// ARB_WAIT1 is used to allow the bus to be idle one cycle where there is no
// grants since a master may use the bus just when it has a grant, even though
// it has no request, for address stepping. During ARB_WAIT1, the current set of
// requests are examined and a next grant made based on the highest priority
// request. If there are no requests (it dropped out?) the state machine returns
// back to ARB_IDLE and gives the grant to the last_master.

	    `ARB_WAIT1:		// ARB_WAIT1
		begin
		if (new_frame)
		   begin	// last granted took bus
		   ns = `ARB_BUSY;
		   end
// rev 2.0 chng	else if (req_new) 
		else if (req_any) 
		   begin	// any master wants bus; arbitrate!
		   ns = `ARB_WAITF;
		   end
		else ns = `ARB_IDLE;
		end

// ARB_WAITF is used to insure that a master that has been granted the bus and
// has kept it's request on, will respond by starting a transaction within
// 16 clocks. If it doesn't, it will be marked as the last_master, which will
// automatically give it the lowest priority. If it drops it's request during
// this wait time, the state machine will return to ARB_WAIT1 in order to 
// rearbitrate and either return to ARB_IDLE or ARB_WAITF if there is another 
// request. NOTE: WAITF is also used when a configuration cycle is needed.

	    `ARB_WAITF:
		begin
		if (new_frame)
		   begin	// last granted took bus
		   ns = `ARB_BUSY;
		   end
		else if (~req_current_grnt || StopWait4Frame )
		   begin	// no request anymore or timeout
		   ns = `ARB_WAIT1;
		   end
		else ns = `ARB_WAITF;
		end

// ARB_BUSY is used to monitor transactions. When a transaction starts, the
// busy state is entered. During this time, if the bus is not locked, all 
// input requests can be monitored and a grant supplied to the highest
// priority output. At the completion of a transaction, if the bus is locked
// or there are no other requests (req_new based on last_master) the state
// machine returns to idle. If there are other requests and the bus in not
// locked, the highest priority is granted and transitions to ARB_WAITF is made.

	    `ARB_BUSY:		// ARB_BUSY
		begin
		if (bus_idle && req_current_grnt )
		   begin	// current request also has grant
		   ns = `ARB_WAITF;
		   end
		else if (bus_idle && req_any)
		   begin	// request but not matching current grant
		   ns = `ARB_WAIT1;
		   end
		else if (bus_idle )
		   begin	// no requests, grant to last master to use bus 
		   ns = `ARB_IDLE;
		   end
		else ns = `ARB_BUSY;
		end
	     default:
		begin
		ns = `ARB_IDLE;		// ERROR; just for testing
		end
	endcase
    arb_sm[1:0] = ns;
    end
endfunction

wire [1:0] arb_state_in = arb_sm(arb_state, new_frame, bus_idle, req_new, req_any, req_current_grnt, StopWait4Frame );

always @(posedge clock)
begin
if (reset)
  begin
  arb_state <= `ARB_IDLE;
  end
else 
  begin
  arb_state <= #1 arb_state_in;
  end
end

// see notes in log for 3/5/97
always @(posedge clock)
begin
// in rev 2.0 change req_new to req_any
// if (reset || ((arb_state == `ARB_IDLE) && ~new_frame && ~req_current_grnt && req_new) || 
if (reset || ((arb_state == `ARB_IDLE) && ~new_frame && ~req_current_grnt && req_any) || 
	     ((arb_state == `ARB_WAITF)  && ~new_frame && ~req_current_grnt) ||
	     ((arb_state == `ARB_WAITF)  && ~new_frame && StopWait4Frame) || 
	     ((arb_state == `ARB_BUSY)  && bus_idle && req_any && ~req_current_grnt) ) 
  begin		// going to WAIT1: turn off all grants for one clock cycle
  grant_host_ <= #1 1'b1;
  grant_ <= #1 4'b1111;
  end
// following lines are added for rev 2.0
else if (((arb_state == `ARB_WAITF) & new_frame) |
	 ((arb_state == `ARB_WAITF) & req_current_grnt & ~StopWait4Frame) |
	 ((arb_state == `ARB_WAIT1) & new_frame) |	// this term could be deleted to allow 
							// arbitration this cycle (no grnt should
							// be true this cycle anyway!)
	 ((arb_state == `ARB_BUSY) & bus_idle & req_current_grnt) |
	 ((arb_state == `ARB_BUSY) & bus_idle & req_any & ~req_current_grnt ) |
	 ((arb_state == `ARB_BUSY) & bus_idle & ~req_any ) |
	 ((arb_state == `ARB_IDLE) & new_frame ) |
	 ((arb_state == `ARB_IDLE) & req_current_grnt ) |
	 ((arb_state == `ARB_IDLE) & ~req_any ) )
  begin		// going to hold current grant while waiting
  grant_host_ <= #1 grant_host_;
  grant_ <= #1 grant_[3:0];
  end
// The following else is redundant, since last_master is default as part of arbitration.
// else if (arb_state == `ARB_IDLE)
//  begin		// put out grant to last master that used bus
//  grant_host_ <= #1 last_master_[4];
//  grant_ <= #1 last_master_[3:0];
//  end
else 
  begin		// arbitrate! highest priority goes out (finally)
  grant_host_ <= #1 nxt_grnt_[4];
  grant_ <= #1 nxt_grnt_[3:0];
  end
end

function [4:0]	asgn_out_func;
input		grant_;
input	[2:0]	arb_asgn_reg;
reg	[4:0]	tmp_asgn_out_func;
  begin
   casex ({grant_,arb_asgn_reg})
	4'b1xxx: tmp_asgn_out_func = 5'b11111; // no grant out 
	4'b01xx: tmp_asgn_out_func = 5'b01111; // grant out to host 
	4'b0000: tmp_asgn_out_func = 5'b11110; // grant out to slot 0
	4'b0001: tmp_asgn_out_func = 5'b11101; // grant out to slot 1 
	4'b0010: tmp_asgn_out_func = 5'b11011; // grant out to slot 2 
	4'b0011: tmp_asgn_out_func = 5'b10111; // grant out to slot 3 
	default: tmp_asgn_out_func = 5'b11111; // no grant out 
  endcase
 asgn_out_func = tmp_asgn_out_func;
 end
endfunction

function	asgn_map_func;
input	[4:0]	req_in_;
input	[2:0]	arb_asgn_reg;
reg		tmp_asgn_map_func;
 begin
  casex ({arb_asgn_reg,req_in_})  
	8'bxxx11111: tmp_asgn_map_func = 1'b1;	// outputs off
	8'b000xxxx1: tmp_asgn_map_func = 1'b1;	// map postition 0 to output
	8'b000xxxx0: tmp_asgn_map_func = 1'b0;	// map postition 0 to output
	8'b001xxx1x: tmp_asgn_map_func = 1'b1;	// map postition 1 to output
	8'b001xxx0x: tmp_asgn_map_func = 1'b0;	// map postition 1 to output
	8'b010xx1xx: tmp_asgn_map_func = 1'b1;	// map postition 2 to output
	8'b010xx0xx: tmp_asgn_map_func = 1'b0;	// map postition 2 to output
	8'b011x1xxx: tmp_asgn_map_func = 1'b1;	// map postition 3 to output
	8'b011x0xxx: tmp_asgn_map_func = 1'b0;	// map postition 3 to output
	8'b1xx1xxxx: tmp_asgn_map_func = 1'b1;	// map postition 4 to output
	8'b1xx0xxxx: tmp_asgn_map_func = 1'b0;	// map postition 4 to output
	default:     tmp_asgn_map_func = 1'b1;	// output off
  endcase
 asgn_map_func = tmp_asgn_map_func;
 end
endfunction

endmodule
HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 12:02:43 1999
From: ../../../sparc_v8/ssparc/pcic/arbiter/rtl/arbiter.v

Verilog converted to html by v2html 5.0 (written by Costas Calamvokis).Help