| 1 | 36 | dgisselq | ///////////////////////////////////////////////////////////////////////////
 | 
      
         | 2 |  |  | //
 | 
      
         | 3 |  |  | // Filename:    wbpriarbiter.v
 | 
      
         | 4 |  |  | //
 | 
      
         | 5 |  |  | // Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
 | 
      
         | 6 |  |  | //
 | 
      
         | 7 |  |  | // Purpose:     This is a priority bus arbiter.  It allows two separate wishbone
 | 
      
         | 8 |  |  | //              masters to connect to the same bus, while also guaranteeing
 | 
      
         | 9 |  |  | //              that one master can have the bus with no delay any time the
 | 
      
         | 10 |  |  | //              other master is not using the bus.  The goal is to eliminate
 | 
      
         | 11 |  |  | //              the combinatorial logic required in the other wishbone
 | 
      
         | 12 |  |  | //              arbiter, while still guarateeing access time for the priority
 | 
      
         | 13 |  |  | //              channel.
 | 
      
         | 14 |  |  | //
 | 
      
         | 15 |  |  | //              The core logic works like this:
 | 
      
         | 16 |  |  | //
 | 
      
         | 17 |  |  | //              1. When no one requests the bus, 'A' is granted the bus and
 | 
      
         | 18 |  |  | //                      guaranteed that any access will go right through.
 | 
      
         | 19 |  |  | //              2. If 'B' requests the bus (asserts cyc), and the bus is idle,
 | 
      
         | 20 |  |  | //                      then 'B' will be granted the bus.
 | 
      
         | 21 |  |  | //              3. Bus grants last as long as the 'cyc' line is high.
 | 
      
         | 22 |  |  | //              4. Once 'cyc' is dropped, the bus returns to 'A' as the owner.
 | 
      
         | 23 |  |  | //
 | 
      
         | 24 |  |  | //
 | 
      
         | 25 |  |  | // Creator:     Dan Gisselquist, Ph.D.
 | 
      
         | 26 |  |  | //              Gisselquist Tecnology, LLC
 | 
      
         | 27 |  |  | //
 | 
      
         | 28 |  |  | ///////////////////////////////////////////////////////////////////////////
 | 
      
         | 29 |  |  | //
 | 
      
         | 30 |  |  | // Copyright (C) 2015, Gisselquist Technology, LLC
 | 
      
         | 31 |  |  | //
 | 
      
         | 32 |  |  | // This program is free software (firmware): you can redistribute it and/or
 | 
      
         | 33 |  |  | // modify it under the terms of  the GNU General Public License as published
 | 
      
         | 34 |  |  | // by the Free Software Foundation, either version 3 of the License, or (at
 | 
      
         | 35 |  |  | // your option) any later version.
 | 
      
         | 36 |  |  | //
 | 
      
         | 37 |  |  | // This program is distributed in the hope that it will be useful, but WITHOUT
 | 
      
         | 38 |  |  | // ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
 | 
      
         | 39 |  |  | // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 | 
      
         | 40 |  |  | // for more details.
 | 
      
         | 41 |  |  | //
 | 
      
         | 42 |  |  | // License:     GPL, v3, as defined and found on www.gnu.org,
 | 
      
         | 43 |  |  | //              http://www.gnu.org/licenses/gpl.html
 | 
      
         | 44 |  |  | //
 | 
      
         | 45 |  |  | //
 | 
      
         | 46 |  |  | ///////////////////////////////////////////////////////////////////////////
 | 
      
         | 47 |  |  | //
 | 
      
         | 48 | 56 | dgisselq | module  wbpriarbiter(i_clk,
 | 
      
         | 49 | 36 | dgisselq |         // Bus A
 | 
      
         | 50 |  |  |         i_a_cyc, i_a_stb, i_a_we, i_a_adr, i_a_dat, o_a_ack, o_a_stall, o_a_err,
 | 
      
         | 51 |  |  |         // Bus B
 | 
      
         | 52 |  |  |         i_b_cyc, i_b_stb, i_b_we, i_b_adr, i_b_dat, o_b_ack, o_b_stall, o_b_err,
 | 
      
         | 53 |  |  |         // Both buses
 | 
      
         | 54 |  |  |         o_cyc, o_stb, o_we, o_adr, o_dat, i_ack, i_stall, i_err);
 | 
      
         | 55 |  |  |         parameter                       DW=32, AW=32;
 | 
      
         | 56 | 56 | dgisselq |         //
 | 
      
         | 57 |  |  |         input                           i_clk;
 | 
      
         | 58 | 36 | dgisselq |         // Bus A
 | 
      
         | 59 |  |  |         input                           i_a_cyc, i_a_stb, i_a_we;
 | 
      
         | 60 |  |  |         input           [(AW-1):0]       i_a_adr;
 | 
      
         | 61 |  |  |         input           [(DW-1):0]       i_a_dat;
 | 
      
         | 62 |  |  |         output  wire                    o_a_ack, o_a_stall, o_a_err;
 | 
      
         | 63 |  |  |         // Bus B
 | 
      
         | 64 |  |  |         input                           i_b_cyc, i_b_stb, i_b_we;
 | 
      
         | 65 |  |  |         input           [(AW-1):0]       i_b_adr;
 | 
      
         | 66 |  |  |         input           [(DW-1):0]       i_b_dat;
 | 
      
         | 67 |  |  |         output  wire                    o_b_ack, o_b_stall, o_b_err;
 | 
      
         | 68 |  |  |         // 
 | 
      
         | 69 |  |  |         output  wire                    o_cyc, o_stb, o_we;
 | 
      
         | 70 |  |  |         output  wire    [(AW-1):0]       o_adr;
 | 
      
         | 71 |  |  |         output  wire    [(DW-1):0]       o_dat;
 | 
      
         | 72 |  |  |         input                           i_ack, i_stall, i_err;
 | 
      
         | 73 |  |  |  
 | 
      
         | 74 |  |  |         // Go high immediately (new cycle) if ...
 | 
      
         | 75 |  |  |         //      Previous cycle was low and *someone* is requesting a bus cycle
 | 
      
         | 76 |  |  |         // Go low immadiately if ...
 | 
      
         | 77 |  |  |         //      We were just high and the owner no longer wants the bus
 | 
      
         | 78 |  |  |         // WISHBONE Spec recommends no logic between a FF and the o_cyc
 | 
      
         | 79 |  |  |         //      This violates that spec.  (Rec 3.15, p35)
 | 
      
         | 80 |  |  |         assign o_cyc = (r_a_owner) ? i_a_cyc : i_b_cyc;
 | 
      
         | 81 |  |  |         reg     r_a_owner;
 | 
      
         | 82 |  |  |         initial r_a_owner = 1'b1;
 | 
      
         | 83 |  |  |         always @(posedge i_clk)
 | 
      
         | 84 |  |  |                 if (~i_b_cyc)
 | 
      
         | 85 |  |  |                         r_a_owner <= 1'b1;
 | 
      
         | 86 |  |  |                 else if ((i_b_cyc)&&(~i_a_cyc))
 | 
      
         | 87 |  |  |                         r_a_owner <= 1'b0;
 | 
      
         | 88 |  |  |  
 | 
      
         | 89 |  |  |  
 | 
      
         | 90 |  |  |         // Realistically, if neither master owns the bus, the output is a
 | 
      
         | 91 |  |  |         // don't care.  Thus we trigger off whether or not 'A' owns the bus.
 | 
      
         | 92 |  |  |         // If 'B' owns it all we care is that 'A' does not.  Likewise, if 
 | 
      
         | 93 |  |  |         // neither owns the bus than the values on the various lines are
 | 
      
         | 94 |  |  |         // irrelevant.
 | 
      
         | 95 |  |  |         assign o_stb = (r_a_owner) ? i_a_stb : i_b_stb;
 | 
      
         | 96 |  |  |         assign o_we  = (r_a_owner) ? i_a_we  : i_b_we;
 | 
      
         | 97 |  |  |         assign o_adr = (r_a_owner) ? i_a_adr : i_b_adr;
 | 
      
         | 98 |  |  |         assign o_dat = (r_a_owner) ? i_a_dat : i_b_dat;
 | 
      
         | 99 |  |  |  
 | 
      
         | 100 |  |  |         // We cannot allow the return acknowledgement to ever go high if
 | 
      
         | 101 |  |  |         // the master in question does not own the bus.  Hence we force it
 | 
      
         | 102 |  |  |         // low if the particular master doesn't own the bus.
 | 
      
         | 103 |  |  |         assign  o_a_ack   = ( r_a_owner) ? i_ack   : 1'b0;
 | 
      
         | 104 |  |  |         assign  o_b_ack   = (~r_a_owner) ? i_ack   : 1'b0;
 | 
      
         | 105 |  |  |  
 | 
      
         | 106 |  |  |         // Stall must be asserted on the same cycle the input master asserts
 | 
      
         | 107 |  |  |         // the bus, if the bus isn't granted to him.
 | 
      
         | 108 |  |  |         assign  o_a_stall = ( r_a_owner) ? i_stall : 1'b1;
 | 
      
         | 109 |  |  |         assign  o_b_stall = (~r_a_owner) ? i_stall : 1'b1;
 | 
      
         | 110 |  |  |  
 | 
      
         | 111 |  |  |         // 
 | 
      
         | 112 |  |  |         // 
 | 
      
         | 113 |  |  |         assign  o_a_err = ( r_a_owner) ? i_err : 1'b0;
 | 
      
         | 114 |  |  |         assign  o_b_err = (~r_a_owner) ? i_err : 1'b0;
 | 
      
         | 115 |  |  |  
 | 
      
         | 116 |  |  | endmodule
 | 
      
         | 117 |  |  |  
 |