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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [ex/] [wbpriarbiter.v] - Blame information for rev 209

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 209 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 other
10
//      master is not using the bus.  The goal is to eliminate the combinatorial
11
//      logic required in the other wishbone arbiter, while still guarateeing
12
//      access time for the priority channel.
13
//
14
//      The core logic works like this:
15
//
16
//      1. When no one requests the bus, 'A' is granted the bus and guaranteed
17
//              that any access will go right through.
18
//      2. If 'B' requests the bus (asserts cyc), and the bus is idle, then
19
//              'B' will be granted the bus.
20
//      3. Bus grants last as long as the 'cyc' line is high.
21
//      4. Once 'cyc' is dropped, the bus returns to 'A' as the owner.
22
//
23
//
24
// Creator:     Dan Gisselquist, Ph.D.
25
//              Gisselquist Technology, LLC
26
//
27
////////////////////////////////////////////////////////////////////////////////
28
//
29
// Copyright (C) 2015,2018-2019, Gisselquist Technology, LLC
30
//
31
// This program is free software (firmware): you can redistribute it and/or
32
// modify it under the terms of the GNU General Public License as published
33
// by the Free Software Foundation, either version 3 of the License, or (at
34
// your option) any later version.
35
//
36
// This program is distributed in the hope that it will be useful, but WITHOUT
37
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
38
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
39
// for more details.
40
//
41
// You should have received a copy of the GNU General Public License along
42
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
43
// target there if the PDF file isn't present.)  If not, see
44
// <http://www.gnu.org/licenses/> for a copy.
45
//
46
// License:     GPL, v3, as defined and found on www.gnu.org,
47
//              http://www.gnu.org/licenses/gpl.html
48
//
49
//
50
////////////////////////////////////////////////////////////////////////////////
51
//
52
//
53
`default_nettype        none
54
//
55
module  wbpriarbiter(i_clk,
56
        // Bus A
57
        i_a_cyc, i_a_stb, i_a_we, i_a_adr, i_a_dat, i_a_sel, o_a_ack, o_a_stall, o_a_err,
58
        // Bus B
59
        i_b_cyc, i_b_stb, i_b_we, i_b_adr, i_b_dat, i_b_sel, o_b_ack, o_b_stall, o_b_err,
60
        // Both buses
61
        o_cyc, o_stb, o_we, o_adr, o_dat, o_sel, i_ack, i_stall, i_err);
62
        parameter                       DW=32, AW=32;
63
        //
64
        // ZERO_ON_IDLE uses more logic than the alternative.  It should be
65
        // useful for reducing power, as these circuits tend to drive wires
66
        // all the way across the design, but it may also slow down the master
67
        // clock.  I've used it as an option when using VERILATOR, 'cause
68
        // zeroing things on idle can make them stand out all the more when
69
        // staring at wires and dumps and such.
70
        parameter       [0:0]             OPT_ZERO_ON_IDLE = 1'b0;
71
        //
72
        input   wire                    i_clk;
73
        // Bus A
74
        input   wire                    i_a_cyc, i_a_stb, i_a_we;
75
        input   wire    [(AW-1):0]       i_a_adr;
76
        input   wire    [(DW-1):0]       i_a_dat;
77
        input   wire    [(DW/8-1):0]     i_a_sel;
78
        output  wire                    o_a_ack, o_a_stall, o_a_err;
79
        // Bus B
80
        input   wire                    i_b_cyc, i_b_stb, i_b_we;
81
        input   wire    [(AW-1):0]       i_b_adr;
82
        input   wire    [(DW-1):0]       i_b_dat;
83
        input   wire    [(DW/8-1):0]     i_b_sel;
84
        output  wire                    o_b_ack, o_b_stall, o_b_err;
85
        //
86
        output  wire                    o_cyc, o_stb, o_we;
87
        output  wire    [(AW-1):0]       o_adr;
88
        output  wire    [(DW-1):0]       o_dat;
89
        output  wire    [(DW/8-1):0]     o_sel;
90
        input   wire                    i_ack, i_stall, i_err;
91
 
92
        // Go high immediately (new cycle) if ...
93
        //      Previous cycle was low and *someone* is requesting a bus cycle
94
        // Go low immadiately if ...
95
        //      We were just high and the owner no longer wants the bus
96
        // WISHBONE Spec recommends no logic between a FF and the o_cyc
97
        //      This violates that spec.  (Rec 3.15, p35)
98
        reg     r_a_owner;
99
 
100
        initial r_a_owner = 1'b1;
101
        always @(posedge i_clk)
102
                if (!i_b_cyc)
103
                        r_a_owner <= 1'b1;
104
                // Allow B to set its CYC line w/o activating this interface
105
                else if ((i_b_cyc)&&(i_b_stb)&&(!i_a_cyc))
106
                        r_a_owner <= 1'b0;
107
 
108
        // Realistically, if neither master owns the bus, the output is a
109
        // don't care.  Thus we trigger off whether or not 'A' owns the bus.
110
        // If 'B' owns it all we care is that 'A' does not.  Likewise, if
111
        // neither owns the bus than the values on these various lines are
112
        // irrelevant.
113
 
114
        assign o_cyc = (r_a_owner) ? i_a_cyc : i_b_cyc;
115
        assign o_we  = (r_a_owner) ? i_a_we  : i_b_we;
116
        assign o_stb   = (r_a_owner) ? i_a_stb   : i_b_stb;
117
        generate if (OPT_ZERO_ON_IDLE)
118
        begin
119
                assign  o_adr     = (o_stb)?((r_a_owner) ? i_a_adr  : i_b_adr):0;
120
                assign  o_dat     = (o_stb)?((r_a_owner) ? i_a_dat  : i_b_dat):0;
121
                assign  o_sel     = (o_stb)?((r_a_owner) ? i_a_sel  : i_b_sel):0;
122
                assign  o_a_ack   = (o_cyc)&&( r_a_owner) ? i_ack   : 1'b0;
123
                assign  o_b_ack   = (o_cyc)&&(!r_a_owner) ? i_ack   : 1'b0;
124
                assign  o_a_stall = (o_cyc)&&( r_a_owner) ? i_stall : 1'b1;
125
                assign  o_b_stall = (o_cyc)&&(!r_a_owner) ? i_stall : 1'b1;
126
                assign  o_a_err   = (o_cyc)&&( r_a_owner) ? i_err : 1'b0;
127
                assign  o_b_err   = (o_cyc)&&(!r_a_owner) ? i_err : 1'b0;
128
        end else begin
129
                assign o_adr   = (r_a_owner) ? i_a_adr   : i_b_adr;
130
                assign o_dat   = (r_a_owner) ? i_a_dat   : i_b_dat;
131
                assign o_sel   = (r_a_owner) ? i_a_sel   : i_b_sel;
132
 
133
                // We cannot allow the return acknowledgement to ever go high if
134
                // the master in question does not own the bus.  Hence we force it
135
                // low if the particular master doesn't own the bus.
136
                assign  o_a_ack   = ( r_a_owner) ? i_ack   : 1'b0;
137
                assign  o_b_ack   = (!r_a_owner) ? i_ack   : 1'b0;
138
 
139
                // Stall must be asserted on the same cycle the input master asserts
140
                // the bus, if the bus isn't granted to him.
141
                assign  o_a_stall = ( r_a_owner) ? i_stall : 1'b1;
142
                assign  o_b_stall = (!r_a_owner) ? i_stall : 1'b1;
143
 
144
                //
145
                //
146
                assign  o_a_err = ( r_a_owner) ? i_err : 1'b0;
147
                assign  o_b_err = (!r_a_owner) ? i_err : 1'b0;
148
        end endgenerate
149
 
150
`ifdef  FORMAL
151
`ifdef  WBPRIARBITER
152
`define ASSUME  assume
153
`else
154
`define ASSUME  assert
155
`endif
156
 
157
        reg     f_past_valid;
158
        initial f_past_valid = 1'b0;
159
        always @(posedge i_clk)
160
                f_past_valid <= 1'b1;
161
 
162
        initial assume(!i_a_cyc);
163
        initial assume(!i_a_stb);
164
 
165
        initial assume(!i_b_cyc);
166
        initial assume(!i_b_stb);
167
 
168
        initial assume(!i_ack);
169
        initial assume(!i_err);
170
 
171
        always @(posedge i_clk)
172
        begin
173
                if (o_cyc)
174
                        assert((i_a_cyc)||(i_b_cyc));
175
                if ((f_past_valid)&&($past(o_cyc))&&(o_cyc))
176
                        assert($past(r_a_owner) == r_a_owner);
177
                if ((f_past_valid)&&($past(!o_cyc))&&($past(i_a_stb)))
178
                        assert(r_a_owner);
179
                if ((f_past_valid)&&($past(!o_cyc))&&($past(i_b_stb)))
180
                        assert(!r_a_owner);
181
        end
182
 
183
        reg     f_reset;
184
        initial f_reset = 1'b1;
185
        always @(posedge i_clk)
186
                f_reset <= 1'b0;
187
        always @(*)
188
                if (!f_past_valid)
189
                        assert(f_reset);
190
 
191
        parameter       F_LGDEPTH=3;
192
 
193
        wire    [(F_LGDEPTH-1):0]        f_nreqs, f_nacks, f_outstanding,
194
                        f_a_nreqs, f_a_nacks, f_a_outstanding,
195
                        f_b_nreqs, f_b_nacks, f_b_outstanding;
196
 
197
        fwb_master #(.F_MAX_STALL(0),
198
                        .F_LGDEPTH(F_LGDEPTH),
199
                        .F_MAX_ACK_DELAY(0),
200
                        .F_OPT_RMW_BUS_OPTION(1),
201
                        .F_OPT_DISCONTINUOUS(1))
202
                f_wbm(i_clk, f_reset,
203
                        o_cyc, o_stb, o_we, o_adr, o_dat, o_sel,
204
                        i_ack, i_stall, 32'h0, i_err,
205
                        f_nreqs, f_nacks, f_outstanding);
206
        fwb_slave  #(.F_MAX_STALL(0),
207
                        .F_LGDEPTH(F_LGDEPTH),
208
                        .F_MAX_ACK_DELAY(0),
209
                        .F_OPT_RMW_BUS_OPTION(1),
210
                        .F_OPT_DISCONTINUOUS(1))
211
                f_wba(i_clk, f_reset,
212
                        i_a_cyc, i_a_stb, i_a_we, i_a_adr, i_a_dat, i_a_sel,
213
                        o_a_ack, o_a_stall, 32'h0, o_a_err,
214
                        f_a_nreqs, f_a_nacks, f_a_outstanding);
215
        fwb_slave  #(.F_MAX_STALL(0),
216
                        .F_LGDEPTH(F_LGDEPTH),
217
                        .F_MAX_ACK_DELAY(0),
218
                        .F_OPT_RMW_BUS_OPTION(1),
219
                        .F_OPT_DISCONTINUOUS(1))
220
                f_wbb(i_clk, f_reset,
221
                        i_b_cyc, i_b_stb, i_b_we, i_b_adr, i_b_dat, i_b_sel,
222
                        o_b_ack, o_b_stall, 32'h0, o_b_err,
223
                        f_b_nreqs, f_b_nacks, f_b_outstanding);
224
 
225
        always @(posedge i_clk)
226
                if (r_a_owner)
227
                begin
228
                        assert(f_b_nreqs == 0);
229
                        assert(f_b_nacks == 0);
230
                        assert(f_a_outstanding == f_outstanding);
231
                end else begin
232
                        assert(f_a_nreqs == 0);
233
                        assert(f_a_nacks == 0);
234
                        assert(f_b_outstanding == f_outstanding);
235
                end
236
 
237
        always @(posedge i_clk)
238
                if ((r_a_owner)&&(i_b_cyc))
239
                        assume(i_b_stb);
240
 
241
        always @(posedge i_clk)
242
                if ((r_a_owner)&&(i_a_cyc))
243
                        assume(i_a_stb);
244
 
245
`endif
246
endmodule

powered by: WebSVN 2.1.0

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