OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [aux/] [wbarbiter.v] - Diff between revs 2 and 36

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

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