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

Subversion Repositories wb2axip

[/] [wb2axip/] [trunk/] [rtl/] [wbarbiter.v] - Blame information for rev 10

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

Line No. Rev Author Line
1 8 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    wbarbiter.v
4
//
5
// Project:     Pipelined Wishbone to AXI converter
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 as much
11
//      combinatorial logic as possible, while still guarateeing minimum access
12
//      time for the priority (last, or alternate) channel.
13
//
14
// Creator:     Dan Gisselquist, Ph.D.
15
//              Gisselquist Technology, LLC
16
//
17
////////////////////////////////////////////////////////////////////////////////
18
//
19
// Copyright (C) 2015,2017, Gisselquist Technology, LLC
20
//
21
// This program is free software (firmware): you can redistribute it and/or
22
// modify it under the terms of  the GNU General Public License as published
23
// by the Free Software Foundation, either version 3 of the License, or (at
24
// your option) any later version.
25
//
26
// This program is distributed in the hope that it will be useful, but WITHOUT
27
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
28
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29
// for more details.
30
//
31
// You should have received a copy of the GNU General Public License along
32
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
33
// target there if the PDF file isn't present.)  If not, see
34
// <http://www.gnu.org/licenses/> for a copy.
35
//
36
// License:     GPL, v3, as defined and found on www.gnu.org,
37
//              http://www.gnu.org/licenses/gpl.html
38
//
39
//
40
////////////////////////////////////////////////////////////////////////////////
41
//
42
//
43
`default_nettype        none
44
//
45
`define WBA_ALTERNATING
46
//
47
module  wbarbiter(i_clk, i_reset,
48
        // Bus A -- the priority bus
49
        i_a_cyc, i_a_stb, i_a_we, i_a_adr, i_a_dat, i_a_sel,
50
                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, i_b_sel,
53
                o_b_ack, o_b_stall, o_b_err,
54
        // Combined/arbitrated bus
55
        o_cyc, o_stb, o_we, o_adr, o_dat, o_sel, i_ack, i_stall, i_err);
56
        parameter                       DW=32, AW=32;
57
        parameter                       SCHEME="ALTERNATING";
58
        parameter       [0:0]             OPT_ZERO_ON_IDLE = 1'b0;
59
`ifdef  FORMAL
60
        parameter                       F_LGDEPTH=3;
61
`endif
62
 
63
        //
64
        input   wire                    i_clk, i_reset;
65
        // Bus A
66
        input   wire                    i_a_cyc, i_a_stb, i_a_we;
67
        input   wire    [(AW-1):0]       i_a_adr;
68
        input   wire    [(DW-1):0]       i_a_dat;
69
        input   wire    [(DW/8-1):0]     i_a_sel;
70
        output  wire                    o_a_ack, o_a_stall, o_a_err;
71
        // Bus B
72
        input   wire                    i_b_cyc, i_b_stb, i_b_we;
73
        input   wire    [(AW-1):0]       i_b_adr;
74
        input   wire    [(DW-1):0]       i_b_dat;
75
        input   wire    [(DW/8-1):0]     i_b_sel;
76
        output  wire                    o_b_ack, o_b_stall, o_b_err;
77
        //
78
        output  wire                    o_cyc, o_stb, o_we;
79
        output  wire    [(AW-1):0]       o_adr;
80
        output  wire    [(DW-1):0]       o_dat;
81
        output  wire    [(DW/8-1):0]     o_sel;
82
        input   wire                    i_ack, i_stall, i_err;
83
 
84
        // Go high immediately (new cycle) if ...
85
        //      Previous cycle was low and *someone* is requesting a bus cycle
86
        // Go low immadiately if ...
87
        //      We were just high and the owner no longer wants the bus
88
        // WISHBONE Spec recommends no logic between a FF and the o_cyc
89
        //      This violates that spec.  (Rec 3.15, p35)
90
        reg     r_a_owner;
91
 
92
        assign o_cyc = (r_a_owner) ? i_a_cyc : i_b_cyc;
93
        initial r_a_owner = 1'b1;
94
 
95
        generate if (SCHEME == "PRIORITY")
96
        begin : PRI
97
 
98
                always @(posedge i_clk)
99
                        if (!i_b_cyc)
100
                                r_a_owner <= 1'b1;
101
                        // Allow B to set its CYC line w/o activating this
102
                        // interface
103
                        else if ((i_b_stb)&&(!i_a_cyc))
104
                                r_a_owner <= 1'b0;
105
 
106
        end else if (SCHEME == "ALTERNATING")
107
        begin : ALT
108
 
109
                reg     last_owner;
110
                initial last_owner = 1'b0;
111
                always @(posedge i_clk)
112
                        if ((i_a_cyc)&&(r_a_owner))
113
                                last_owner <= 1'b1;
114
                        else if ((i_b_cyc)&&(!r_a_owner))
115
                                last_owner <= 1'b0;
116
 
117
                always @(posedge i_clk)
118
                        if ((!i_a_cyc)&&(!i_b_cyc))
119
                                r_a_owner <= !last_owner;
120
                        else if ((r_a_owner)&&(!i_a_cyc))
121
                        begin
122
 
123
                                if (i_b_stb)
124
                                        r_a_owner <= 1'b0;
125
 
126
                        end else if ((!r_a_owner)&&(!i_b_cyc))
127
                        begin
128
 
129
                                if (i_a_stb)
130
                                        r_a_owner <= 1'b1;
131
 
132
                        end
133
 
134
        end else // if (SCHEME == "LAST")
135
        begin : LST
136
                always @(posedge i_clk)
137
                        if ((!i_a_cyc)&&(i_b_stb))
138
                                r_a_owner <= 1'b0;
139
                        else if ((!i_b_cyc)&&(i_a_stb))
140
                                r_a_owner <= 1'b1;
141
        end endgenerate
142
 
143
 
144
        // Realistically, if neither master owns the bus, the output is a
145
        // don't care.  Thus we trigger off whether or not 'A' owns the bus.
146
        // If 'B' owns it all we care is that 'A' does not.  Likewise, if
147
        // neither owns the bus than the values on the various lines are
148
        // irrelevant.
149
        assign o_we  = (r_a_owner) ? i_a_we  : i_b_we;
150
 
151
        generate if (OPT_ZERO_ON_IDLE)
152
        begin
153
                //
154
                // OPT_ZERO_ON_IDLE will use up more logic and may even slow
155
                // down the master clock if set.  However, it may also reduce
156
                // the power used by the FPGA by preventing things from toggling
157
                // when the bus isn't in use.  The option is here because it
158
                // also makes it a lot easier to look for when things happen
159
                // on the bus via VERILATOR when timing and logic counts
160
                // don't matter.
161
                //
162
                assign o_stb     = (o_cyc)? ((r_a_owner) ? i_a_stb : i_b_stb):0;
163
                assign o_adr     = (o_stb)? ((r_a_owner) ? i_a_adr : i_b_adr):0;
164
                assign o_dat     = (o_stb)? ((r_a_owner) ? i_a_dat : i_b_dat):0;
165
                assign o_sel     = (o_stb)? ((r_a_owner) ? i_a_sel : i_b_sel):0;
166
                assign o_a_ack   = (o_cyc)&&( r_a_owner) ? i_ack   : 1'b0;
167
                assign o_b_ack   = (o_cyc)&&(!r_a_owner) ? i_ack   : 1'b0;
168
                assign o_a_stall = (o_cyc)&&( r_a_owner) ? i_stall : 1'b1;
169
                assign o_b_stall = (o_cyc)&&(!r_a_owner) ? i_stall : 1'b1;
170
                assign o_a_err   = (o_cyc)&&( r_a_owner) ? i_err : 1'b0;
171
                assign o_b_err   = (o_cyc)&&(!r_a_owner) ? i_err : 1'b0;
172
        end else begin
173
 
174
                assign o_stb = (r_a_owner) ? i_a_stb : i_b_stb;
175
                assign o_adr = (r_a_owner) ? i_a_adr : i_b_adr;
176
                assign o_dat = (r_a_owner) ? i_a_dat : i_b_dat;
177
                assign o_sel = (r_a_owner) ? i_a_sel : i_b_sel;
178
 
179
                // We cannot allow the return acknowledgement to ever go high if
180
                // the master in question does not own the bus.  Hence we force
181
                // it low if the particular master doesn't own the bus.
182
                assign  o_a_ack   = ( r_a_owner) ? i_ack   : 1'b0;
183
                assign  o_b_ack   = (!r_a_owner) ? i_ack   : 1'b0;
184
 
185
                // Stall must be asserted on the same cycle the input master
186
                // asserts the bus, if the bus isn't granted to him.
187
                assign  o_a_stall = ( r_a_owner) ? i_stall : 1'b1;
188
                assign  o_b_stall = (!r_a_owner) ? i_stall : 1'b1;
189
 
190
                //
191
                //
192
                assign  o_a_err = ( r_a_owner) ? i_err : 1'b0;
193
                assign  o_b_err = (!r_a_owner) ? i_err : 1'b0;
194
        end endgenerate
195
 
196
        // Make Verilator happy
197
        // verilator lint_off UNUSED
198
        wire    unused;
199
        assign  unused = i_reset;
200
        // verilator lint_on  UNUSED
201
 
202
`ifdef  FORMAL
203
 
204
`ifdef  WBARBITER
205
        reg     f_last_clk;
206
        initial assume(!i_clk);
207
        always @($global_clock)
208
        begin
209
                assume(i_clk != f_last_clk);
210
                f_last_clk <= i_clk;
211
        end
212
`define ASSUME  assume
213
`else
214
`define ASSUME  assert
215
`endif
216
 
217
        reg     f_past_valid;
218
        initial f_past_valid = 1'b0;
219
        always @($global_clock)
220
                f_past_valid <= 1'b1;
221
 
222
        initial `ASSUME(!i_a_cyc);
223
        initial `ASSUME(!i_a_stb);
224
 
225
        initial `ASSUME(!i_b_cyc);
226
        initial `ASSUME(!i_b_stb);
227
 
228
        initial `ASSUME(!i_ack);
229
        initial `ASSUME(!i_err);
230
 
231
        always @(posedge i_clk)
232
        begin
233
                if (o_cyc)
234
                        assert((i_a_cyc)||(i_b_cyc));
235
                if ((f_past_valid)&&($past(o_cyc))&&(o_cyc))
236
                        assert($past(r_a_owner) == r_a_owner);
237
        end
238
 
239
        wire    [(F_LGDEPTH-1):0]        f_nreqs, f_nacks, f_outstanding,
240
                        f_a_nreqs, f_a_nacks, f_a_outstanding,
241
                        f_b_nreqs, f_b_nacks, f_b_outstanding;
242
 
243
        fwb_master #(.DW(DW), .AW(AW),
244
                        .F_MAX_STALL(0),
245
                        .F_LGDEPTH(F_LGDEPTH),
246
                        .F_MAX_ACK_DELAY(0),
247
                        .F_OPT_RMW_BUS_OPTION(1),
248
                        .F_OPT_DISCONTINUOUS(1))
249
                f_wbm(i_clk, i_reset,
250
                        o_cyc, o_stb, o_we, o_adr, o_dat, o_sel,
251
                        i_ack, i_stall, 32'h0, i_err,
252
                        f_nreqs, f_nacks, f_outstanding);
253
 
254
        fwb_slave  #(.DW(DW), .AW(AW),
255
                        .F_MAX_STALL(0),
256
                        .F_LGDEPTH(F_LGDEPTH),
257
                        .F_MAX_ACK_DELAY(0),
258
                        .F_OPT_RMW_BUS_OPTION(1),
259
                        .F_OPT_DISCONTINUOUS(1))
260
                f_wba(i_clk, i_reset,
261
                        i_a_cyc, i_a_stb, i_a_we, i_a_adr, i_a_dat, i_a_sel,
262
                        o_a_ack, o_a_stall, 32'h0, o_a_err,
263
                        f_a_nreqs, f_a_nacks, f_a_outstanding);
264
 
265
        fwb_slave  #(.DW(DW), .AW(AW),
266
                        .F_MAX_STALL(0),
267
                        .F_LGDEPTH(F_LGDEPTH),
268
                        .F_MAX_ACK_DELAY(0),
269
                        .F_OPT_RMW_BUS_OPTION(1),
270
                        .F_OPT_DISCONTINUOUS(1))
271
                f_wbb(i_clk, i_reset,
272
                        i_b_cyc, i_b_stb, i_b_we, i_b_adr, i_b_dat, i_b_sel,
273
                        o_b_ack, o_b_stall, 32'h0, o_b_err,
274
                        f_b_nreqs, f_b_nacks, f_b_outstanding);
275
 
276
        always @(posedge i_clk)
277
                if (r_a_owner)
278
                begin
279
                        assert(f_b_nreqs == 0);
280
                        assert(f_b_nacks == 0);
281
                        assert(f_a_outstanding == f_outstanding);
282
                end else begin
283
                        assert(f_a_nreqs == 0);
284
                        assert(f_a_nacks == 0);
285
                        assert(f_b_outstanding == f_outstanding);
286
                end
287
 
288
        always @(posedge i_clk)
289
        if ((f_past_valid)&&(!$past(i_reset))
290
                        &&($past(i_a_stb))&&(!$past(i_b_cyc)))
291
                assert(r_a_owner);
292
        always @(posedge i_clk)
293
        if ((f_past_valid)&&(!$past(i_reset))
294
                        &&(!$past(i_a_cyc))&&($past(i_b_stb)))
295
                assert(!r_a_owner);
296
 
297
        always @(posedge i_clk)
298
                if ((f_past_valid)&&(r_a_owner != $past(r_a_owner)))
299
                        assert(!$past(o_cyc));
300
 
301
`endif
302
endmodule
303
 

powered by: WebSVN 2.1.0

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