Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [aux/] [wbarbiter.v] - Rev 36

Go to most recent revision | Compare with Previous | Blame | View Log

// Filename: 	wbarbiter.v
// Project:	Zip CPU -- a small, lightweight, RISC CPU soft core
// Purpose:	At some point in time, I might wish to have two masters connect
//		to the same wishbone bus.  As an example, I might wish to have
//		both the instruction fetch and the load/store operators
//		of my Zip CPU access the the same bus.  How shall they both
//		get access to the same resource?  This module allows the
//		wishbone interfaces from two sources to drive the bus, while
//		guaranteeing that only one drives the bus at a time.
//		The core logic works like this:
//		1. If 'A' or 'B' asserts the o_cyc line, a bus cycle will begin,
//			with acccess granted to whomever requested it.
//		2. If both 'A' and 'B' assert o_cyc at the same time, only 'A'
//			will be granted the bus.  (If the alternating parameter 
//			is set, A and B will alternate who gets the bus in
//			this case.)
//		3. The bus will remain owned by whomever the bus was granted to
//			until they deassert the o_cyc line.
//		4. At the end of a bus cycle, o_cyc is guaranteed to be
//			deasserted (low) for one clock.
//		5. On the next clock, bus arbitration takes place again.  If
//			'A' requests the bus, no matter how long 'B' was
//			waiting, 'A' will then be granted the bus.  (Unless
//			again the alternating parameter is set, then the
//			access is guaranteed to switch to B.)
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Tecnology, LLC
// Copyright (C) 2015, Gisselquist Technology, LLC
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// License:	GPL, v3, as defined and found on,
module	wbarbiter(i_clk, i_rst, 
	// Bus A
	i_a_adr, i_a_dat, i_a_we, i_a_stb, i_a_cyc, o_a_ack, o_a_stall, o_a_err,
	// Bus B
	i_b_adr, i_b_dat, i_b_we, i_b_stb, i_b_cyc, o_b_ack, o_b_stall, o_b_err,
	// Both buses
	o_adr, o_dat, o_we, o_stb, o_cyc, i_ack, i_stall, i_err);
	// 18 bits will address one GB, 4 bytes at a time.
	// 19 bits will allow the ability to address things other than just
	// the 1GB of memory we are expecting.
	parameter			DW=32, AW=19;
	// Wishbone doesn't use an i_ce signal.  While it could, they dislike
	// what it would (might) do to the synchronous reset signal, i_rst.
	input				i_clk, i_rst;
	input		[(AW-1):0]	i_a_adr, i_b_adr;
	input		[(DW-1):0]	i_a_dat, i_b_dat;
	input				i_a_we, i_a_stb, i_a_cyc;
	input				i_b_we, i_b_stb, i_b_cyc;
	output	wire			o_a_ack, o_b_ack, o_a_stall, o_b_stall,
					o_a_err, o_b_err;
	output	wire	[(AW-1):0]	o_adr;
	output	wire	[(DW-1):0]	o_dat;
	output	wire			o_we, o_stb, o_cyc;
	input				i_ack, i_stall, i_err;
	// All the fancy stuff here is done with the three primary signals:
	//	o_cyc
	//	w_a_owner
	//	w_b_owner
	// These signals are helped by r_cyc, r_a_owner, and r_b_owner.
	// If you understand these signals, all else will fall into place.
	// r_cyc just keeps track of the last o_cyc value.  That way, on
	// the next clock we can tell if we've had one non-cycle before
	// starting another cycle.  Specifically, no new cycles will be
	// allowed to begin unless r_cyc=0.
	reg	r_cyc;
	always @(posedge i_clk)
		if (i_rst)
			r_cyc <= 1'b0;
			r_cyc <= o_cyc;
	// Go high immediately (new cycle) if ...
	//	Previous cycle was low and *someone* is requesting a bus cycle
	// Go low immadiately if ...
	//	We were just high and the owner no longer wants the bus
	// WISHBONE Spec recommends no logic between a FF and the o_cyc
	//	This violates that spec.  (Rec 3.15, p35)
	assign o_cyc = ((~r_cyc)&&((i_a_cyc)||(i_b_cyc))) || ((r_cyc)&&((w_a_owner)||(w_b_owner)));
	// Register keeping track of the last owner, wire keeping track of the
	// current owner allowing us to not lose a clock in arbitrating the
	// first clock of the bus cycle
	reg	r_a_owner, r_b_owner;
	wire	w_a_owner, w_b_owner;
	reg	r_a_last_owner;
	// Stall must be asserted on the same cycle the input master asserts
	// the bus, if the bus isn't granted to him.
	assign	o_a_stall = (w_a_owner) ? i_stall : 1'b1;
	assign	o_b_stall = (w_b_owner) ? i_stall : 1'b1;
	always @(posedge i_clk)
		if (i_rst)
			r_a_owner <= 1'b0;
			r_b_owner <= 1'b0;
		end else begin
			r_a_owner <= w_a_owner;
			r_b_owner <= w_b_owner;
			if (w_a_owner)
				r_a_last_owner <= 1'b1;
			else if (w_b_owner)
				r_a_last_owner <= 1'b0;
	// If you are the owner, retain ownership until i_x_cyc is no
	// longer asserted.  Likewise, you cannot become owner until o_cyc
	// is de-asserted for one cycle.
	// 'A' is given arbitrary priority over 'B'
	// 'A' may own the bus only if he wants it.  When 'A' drops i_a_cyc,
	// o_cyc must drop and so must w_a_owner on the same cycle.
	// However, when 'A' asserts i_a_cyc, he can only capture the bus if
	// it's had an idle cycle.
	// The same is true for 'B' with one exception: if both contend for the
	// bus on the same cycle, 'A' arbitrarily wins.
	assign w_a_owner = (i_a_cyc)	// if A requests ownership, and either
			&& ((r_a_owner) // A has already been recognized or
			|| ((~r_cyc) // the bus is free and
				&&((~i_b_cyc) // B has not requested, or if he 
				||(~r_a_last_owner)) )); // has, it's A's turn
	assign w_b_owner = (i_b_cyc)&& ((r_b_owner) || ((~r_cyc)&&((~i_a_cyc)||(r_a_last_owner)) ));
	assign w_a_owner = (i_a_cyc)&& ((r_a_owner) ||  (~r_cyc) );
	assign w_b_owner = (i_b_cyc)&& ((r_b_owner) || ((~r_cyc)&&(~i_a_cyc)) );
	// Realistically, if neither master owns the bus, the output is a
	// don't care.  Thus we trigger off whether or not 'A' owns the bus.
	// If 'B' owns it all we care is that 'A' does not.  Likewise, if 
	// neither owns the bus than the values on the various lines are
	// irrelevant.
	assign o_adr = (w_a_owner) ? i_a_adr : i_b_adr;
	assign o_dat = (w_a_owner) ? i_a_dat : i_b_dat;
	assign o_we  = (w_a_owner) ? i_a_we  : i_b_we;
	assign o_stb = (o_cyc) && ((w_a_owner) ? i_a_stb : i_b_stb);
	// We cannot allow the return acknowledgement to ever go high if
	// the master in question does not own the bus.  Hence we force it
	// low if the particular master doesn't own the bus.
	assign	o_a_ack   = (w_a_owner) ? i_ack   : 1'b0;
	assign	o_b_ack   = (w_b_owner) ? i_ack   : 1'b0;
	assign	o_a_err = (w_a_owner) ? i_err : 1'b0;
	assign	o_b_err = (w_b_owner) ? i_err : 1'b0;

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.