blob: e924eeeda1d02505fc9a505f16370c8fd3feb865 [file] [log] [blame]
Sylvain Munaut21b03ba2020-09-14 10:01:45 +02001/*
2 * wb_arbiter.v
3 *
4 * vim: ts=4 sw=4
5 *
6 * Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
7 * SPDX-License-Identifier: CERN-OHL-P-2.0
8 */
9
10`default_nettype none
11
12module wb_arbiter #(
13 parameter integer N = 3,
14 parameter integer DW = 32,
15 parameter integer AW = 16,
16 parameter integer MW = DW / 8
17)(
18 /* Slave buses */
19 input wire [(N*AW)-1:0] s_addr,
20 output wire [(N*DW)-1:0] s_rdata,
21 input wire [(N*DW)-1:0] s_wdata,
22 input wire [(N*MW)-1:0] s_wmsk,
23 input wire [ N -1:0] s_we,
24 input wire [ N -1:0] s_cyc,
25 output wire [ N -1:0] s_ack,
26
27 /* Master bus */
28 output reg [AW-1:0] m_addr,
29 input wire [DW-1:0] m_rdata,
30 output reg [DW-1:0] m_wdata,
31 output reg [MW-1:0] m_wmsk,
32 output reg m_we,
33 output wire m_cyc,
34 input wire m_ack,
35
36 /* Clock / Reset */
37 input wire clk,
38 input wire rst
39);
40
41 // Signals
42 // -------
43
44 genvar i;
45
46 reg [AW-1:0] mux_addr;
47 reg [DW-1:0] mux_wdata;
48 reg [MW-1:0] mux_wmsk;
49
50 reg [N-1:0] sel_nxt;
51 reg [N-1:0] sel;
52 reg busy;
53 wire reselect;
54
55
56 // Muxing
57 // ------
58
59 for (i=0; i<N; i=i+1)
60 begin
61 assign s_rdata[DW*i+:DW] = sel[i] ? m_rdata : { DW{1'b0} };
62 assign s_ack[i] = sel[i] ? m_ack : 1'b0;
63 end
64
65 always @(*)
66 begin : mux
67 integer i;
68
69 mux_addr = { AW{1'b0} };
70 mux_wdata = { DW{1'b0} };
71 mux_wmsk = { MW{1'b0} };
72
73 for (i=N-1; i>=0; i=i-1) begin
74 mux_addr = mux_addr | (sel_nxt[i] ? s_addr[AW*i+:AW] : { AW{1'b0} });
75 mux_wdata = mux_wdata | (sel_nxt[i] ? s_wdata[DW*i+:DW] : { DW{1'b0} });
76 mux_wmsk = mux_wmsk | (sel_nxt[i] ? s_wmsk[MW*i+:MW] : { MW{1'b0} });
77 end
78 end
79
80 always @(posedge clk or posedge rst)
81 begin
82 if (rst) begin
83 m_addr <= { AW{1'b0} };
84 m_wdata <= { DW{1'b0} };
85 m_wmsk <= { MW{1'b0} };
86 m_we <= 1'b0;
87 end else if (reselect) begin
88 m_addr <= mux_addr;
89 m_wdata <= mux_wdata;
90 m_wmsk <= mux_wmsk;
91 m_we <= |(s_we & sel_nxt);
92 end
93 end
94
95
96 // Arbitration
97 // -----------
98
99 // Priority encoder for the next master
100 always @(*)
101 begin : prio
102 integer i;
103
104 sel_nxt <= 0;
105 for (i=N-1; i>=0; i=i-1)
106 if (s_cyc[i] & ~sel[i]) begin
107 sel_nxt <= 0;
108 sel_nxt[i] <= 1'b1;
109 end
110 end
111
112 // When to reselect
113 assign reselect = m_ack | ~busy;
114
115 // Register current master (if any)
116 always @(posedge clk or posedge rst)
117 if (rst) begin
118 busy <= 1'b0;
119 sel <= 0;
120 end else if (reselect) begin
121 busy <= |(s_cyc & ~sel);
122 sel <= sel_nxt;
123 end
124
125 assign m_cyc = busy;
126
127endmodule // wb_arbiter