forked from SJTU-YONGFU-RESEARCH-GRP/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmatrix_arbiter.v
More file actions
executable file
·243 lines (228 loc) · 11.7 KB
/
matrix_arbiter.v
File metadata and controls
executable file
·243 lines (228 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/**
* Matrix-Based Arbiter with Programmable Priorities
*
* This module implements a sophisticated arbiter that uses a matrix-based priority
* scheme. Unlike simple priority arbiters, this design allows each requestor to
* have a programmable priority relative to every other requestor, providing
* fine-grained control over arbitration behavior.
*
* Key Features:
* - Matrix-based priority: Each pair (i,j) has a priority value
* - Fairness support: Round-robin fallback when priorities are equal
* - Configurable reset polarity: Supports both active-high and active-low reset
* - Mutual exclusion: Only one requestor granted per cycle
*
* Priority Matrix:
* The priority_matrix input is a packed array of size:
* NUM_REQUESTORS * NUM_REQUESTORS * PRIORITY_WIDTH
*
* For requestor i vs requestor j:
* - Priority value is at index: (i*NUM_REQUESTORS + j)*PRIORITY_WIDTH
* - Higher value means higher priority
* - If priority[i,j] > priority[j,i], then i wins over j
*
* Algorithm:
* 1. Compare each active requestor with all other active requestors
* 2. A requestor wins only if it has higher priority than all competitors
* 3. If no clear winner (ties), use round-robin based on previous grant
* 4. Update previous grant for next cycle fairness
*
* Use Cases:
* - Complex priority schemes where priorities depend on requestor pairs
* - Quality-of-service (QoS) arbitration
* - Weighted fair queuing
* - Custom arbitration policies
*
* @param NUM_REQUESTORS Number of requestors competing for access (default: 4)
* @param PRIORITY_WIDTH Width of priority values in matrix (default: 2 bits)
* @param RESET_HIGH Reset polarity: 1 = active high, 0 = active low (default: 1)
*
* @input clk Clock signal
* @input rst Reset signal (polarity depends on RESET_HIGH)
* @input req[NUM_REQUESTORS-1:0] Request signals from each requestor
* @input priority_matrix[NUM_REQUESTORS*NUM_REQUESTORS*PRIORITY_WIDTH-1:0]
* Priority matrix: priority[i,j] at index (i*NUM_REQUESTORS + j)*PRIORITY_WIDTH
* @output grant[NUM_REQUESTORS-1:0] Grant signals (one-hot)
* @output grant_valid High when any requestor is granted
*/
module matrix_arbiter #(
parameter NUM_REQUESTORS = 4, // Number of requestors
parameter PRIORITY_WIDTH = 2, // Width of priority values
parameter RESET_HIGH = 1 // Active high (1) or low (0) reset
)(
input wire clk,
input wire rst,
input wire [NUM_REQUESTORS-1:0] req, // Request inputs
input wire [NUM_REQUESTORS*NUM_REQUESTORS*PRIORITY_WIDTH-1:0] priority_matrix, // Priority matrix entries
output reg [NUM_REQUESTORS-1:0] grant, // Grant output vector
output wire grant_valid // Indicates if any request was granted
);
// ============================================================================
// Reset Signal Polarity Handling
// ============================================================================
// Convert reset signal to internal polarity based on RESET_HIGH parameter
// This allows the module to work with either active-high or active-low reset
wire reset = (RESET_HIGH != 0) ? rst : ~rst;
// ============================================================================
// Internal State Registers
// ============================================================================
// Previous grant register: used for round-robin fallback when priorities are equal
// This ensures fairness when multiple requestors have equal priority
reg [NUM_REQUESTORS-1:0] prev_grant;
// ============================================================================
// Status Signal Generation
// ============================================================================
// Grant valid signal: high when at least one requestor is granted
assign grant_valid = |grant;
// ============================================================================
// Priority Matrix Access Function
// ============================================================================
// This function extracts the priority value for requestor i relative to requestor j
// from the packed priority_matrix input.
//
// Priority Matrix Layout:
// The matrix is stored in row-major order:
// [req0_vs_req0, req0_vs_req1, ..., req0_vs_reqN-1,
// req1_vs_req0, req1_vs_req1, ..., req1_vs_reqN-1,
// ...
// reqN-1_vs_req0, reqN-1_vs_req1, ..., reqN-1_vs_reqN-1]
//
// Each entry is PRIORITY_WIDTH bits wide.
function [PRIORITY_WIDTH-1:0] get_priority;
input integer i, j; // Requestor indices (i = row, j = column)
integer base;
begin
// Calculate base index: row i, column j
// Formula: (i * NUM_REQUESTORS + j) * PRIORITY_WIDTH
base = (i*NUM_REQUESTORS + j)*PRIORITY_WIDTH;
// Extract PRIORITY_WIDTH bits starting from base index
get_priority = priority_matrix[base +: PRIORITY_WIDTH];
end
endfunction
// ============================================================================
// Arbitration Logic Variables
// ============================================================================
// Temporary variables for combinational arbitration computation
integer i, j; // Loop counters
reg [NUM_REQUESTORS-1:0] winner; // Winner vector (one-hot)
reg [31:0] start_idx; // Starting index for round-robin
reg found; // Flag: winner found in round-robin
reg found_prev_grant; // Flag: previous grant found
// ============================================================================
// Combinational Arbitration Logic
// ============================================================================
// This always block implements the core arbitration algorithm.
// It's combinational (always @(*)) to minimize latency.
always @(*) begin
// ========================================================================
// Initialize Variables (Prevent Latches)
// ========================================================================
// Initialize all variables to prevent unwanted latches in synthesis
winner = {NUM_REQUESTORS{1'b0}};
start_idx = 0;
found = 1'b0;
found_prev_grant = 1'b0;
// Only perform arbitration if at least one requestor is active
if (req != {NUM_REQUESTORS{1'b0}}) begin
// ====================================================================
// Phase 1: Priority-Based Comparison
// ====================================================================
// Start by assuming all active requestors are winners
// Then eliminate losers through pairwise comparison
winner = req;
// Compare each active requestor with all other active requestors
for (i = 0; i < NUM_REQUESTORS; i = i + 1) begin
if (req[i]) begin
// Requestor i is active - compare it with all others
for (j = 0; j < NUM_REQUESTORS; j = j + 1) begin
if (i != j && req[j]) begin
// Both i and j are active - compare their priorities
// If j has higher priority than i, then i loses
if (get_priority(j, i) > get_priority(i, j)) begin
// j wins over i, so eliminate i from winners
winner[i] = 1'b0;
end
end
end
end
else begin
// Requestor i is not active, so it can't win
winner[i] = 1'b0;
end
end
// ====================================================================
// Phase 2: Round-Robin Fallback for Ties
// ====================================================================
// If no clear winner (all priorities equal or conflicts),
// use round-robin based on previous grant for fairness
if (winner == {NUM_REQUESTORS{1'b0}}) begin
// Find the index of the last granted requestor
// Start searching from highest index (most recent)
start_idx = 0; // Default: start from 0 if no previous grant
found_prev_grant = 1'b0;
// Search backwards to find last granted requestor
for (i = NUM_REQUESTORS-1; i >= 0; i = i - 1) begin
if (!found_prev_grant && prev_grant[i]) begin
// Found last granted requestor - start from next one
start_idx = (i + 1) % NUM_REQUESTORS;
found_prev_grant = 1'b1;
end
end
// ================================================================
// Round-Robin Search
// ================================================================
// Search for next active requestor starting from start_idx
found = 1'b0;
for (i = 0; i < NUM_REQUESTORS; i = i + 1) begin
// Calculate index with wrap-around
j = (start_idx + i) % NUM_REQUESTORS;
// Grant to first active requestor found
if (!found && req[j]) begin
winner[j] = 1'b1;
found = 1'b1;
end
end
// ================================================================
// Fallback (Should Never Execute)
// ================================================================
// This should never happen since we know req != 0,
// but included for safety and completeness
if (!found) begin
// Grant to first active requestor found
for (i = 0; i < NUM_REQUESTORS; i = i + 1) begin
if (req[i]) begin
winner[i] = 1'b1;
// Note: No break needed - only first match matters
end
end
end
end
end
end
// ============================================================================
// Registered Output and State Update
// ============================================================================
// Register the grant outputs for timing closure and update previous grant
// for next cycle's round-robin fairness calculation.
always @(posedge clk or posedge reset) begin
if (reset) begin
// ====================================================================
// Reset State
// ====================================================================
grant <= {NUM_REQUESTORS{1'b0}};
prev_grant <= {NUM_REQUESTORS{1'b0}};
end
else begin
// ====================================================================
// Normal Operation
// ====================================================================
// Register the winner from combinational logic
grant <= winner;
// Update previous grant only if a grant was issued
// This is used for round-robin fairness in next cycle
if (|winner) begin
prev_grant <= winner;
end
end
end
endmodule