forked from SJTU-YONGFU-RESEARCH-GRP/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharbiter.v
More file actions
executable file
·153 lines (142 loc) · 7.51 KB
/
arbiter.v
File metadata and controls
executable file
·153 lines (142 loc) · 7.51 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
/**
* Configurable Arbiter Module
*
* This module implements an arbiter that resolves conflicts when multiple ports
* request access to a shared resource simultaneously. It supports two priority schemes:
* fixed priority and round-robin (fair) arbitration.
*
* Use Cases:
* - Bus arbitration in multi-master systems
* - Resource sharing in NoC (Network-on-Chip) designs
* - Memory controller arbitration
* - I/O port multiplexing
*
* Priority Schemes:
* 1. Fixed Priority (PRIORITY_SCHEME = 0):
* - Higher port indices have higher priority
* - Simple and fast, but can starve lower-priority ports
* - Suitable when port priorities are well-defined
*
* 2. Round-Robin (PRIORITY_SCHEME = 1):
* - Fair arbitration: each port gets equal opportunity
* - Priority rotates after each grant
* - Prevents starvation of any port
* - Slightly more complex but provides fairness
*
* Operation:
* - On each clock cycle, if any port requests, one port is granted
* - Only one port can be granted at a time (mutual exclusion)
* - The 'active' signal indicates when arbitration is occurring
*
* @param NUM_PORTS Number of ports competing for access (default: 4)
* @param PRIORITY_SCHEME Priority scheme: 0 = Fixed, 1 = Round-robin (default: 0)
*
* @input clk Clock signal
* @input rst_n Active-low reset signal
* @input request[NUM_PORTS-1:0] Request signals from each port (1 = requesting)
* @output grant[NUM_PORTS-1:0] Grant signals to each port (1 = granted, one-hot)
* @output active High when any port is requesting (OR of all request signals)
*/
module arbiter #(
parameter NUM_PORTS = 4,
parameter PRIORITY_SCHEME = 0 // 0: Fixed priority, 1: Round-robin
) (
input wire clk,
input wire rst_n,
input wire [NUM_PORTS-1:0] request,
output reg [NUM_PORTS-1:0] grant,
output wire active // Indicates if any request is being serviced
);
// ============================================================================
// Internal State Registers
// ============================================================================
// Priority pointer for round-robin scheme: tracks which port has highest priority
// Size is log2(NUM_PORTS) to index into the port array
reg [$clog2(NUM_PORTS)-1:0] priority_ptr;
// Temporary variables for round-robin computation (integers for modulo arithmetic)
integer i; // Loop counter
integer check_idx; // Current port index being checked
integer ptr; // Copy of priority_ptr for computation
integer granted; // Flag indicating if a grant has been issued
// ============================================================================
// Active Signal Generation
// ============================================================================
// The active signal is high when any port is currently granted access.
// This is useful for indicating when the shared resource is in use.
// Using OR reduction operator (|) to check if any grant bit is set.
assign active = |grant;
// ============================================================================
// Main Arbitration Logic
// ============================================================================
// This always block implements the core arbitration algorithm.
// It runs on every positive clock edge and handles both priority schemes.
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// ====================================================================
// Reset State
// ====================================================================
// Clear all grants (no port has access)
grant <= {NUM_PORTS{1'b0}};
// Initialize priority pointer to port 0 (for round-robin)
priority_ptr <= 0;
end
else begin
// ====================================================================
// Default State: No Grants
// ====================================================================
// Start with no grants. We'll set a grant only if there's a request.
grant <= {NUM_PORTS{1'b0}};
// Only perform arbitration if at least one port is requesting
if (|request) begin
if (PRIORITY_SCHEME == 0) begin
// ============================================================
// Fixed Priority Scheme
// ============================================================
// Higher port indices have higher priority.
// This is a simple priority encoder: check ports from highest to lowest.
// Note: This implementation is hardcoded for 4 ports. For parameterized
// designs, a generate loop or priority encoder module would be better.
if (request[3]) begin
grant <= 4'b1000; // Port 3 has highest priority
end else if (request[2]) begin
grant <= 4'b0100; // Port 2 has second priority
end else if (request[1]) begin
grant <= 4'b0010; // Port 1 has third priority
end else if (request[0]) begin
grant <= 4'b0001; // Port 0 has lowest priority
end else begin
grant <= 4'b0000; // No requests (shouldn't happen due to outer if)
end
end else begin
// ============================================================
// Round-Robin Priority Scheme
// ============================================================
// This scheme provides fair access by rotating priority.
// After granting to a port, priority moves to the next port.
// This prevents any port from being starved.
granted = 0; // Initialize: no grant issued yet
/* verilator lint_off WIDTHEXPAND */
// Convert priority pointer to integer for modulo arithmetic
ptr = priority_ptr;
/* verilator lint_on WIDTHEXPAND */
// Check all ports starting from the priority pointer
// This ensures we check ports in round-robin order
for (i = 0; i < NUM_PORTS; i = i + 1) begin
// Calculate which port to check: wrap around using modulo
check_idx = (ptr + i) % NUM_PORTS;
// If this port is requesting and we haven't granted yet, grant it
if (request[check_idx] && !granted) begin
grant[check_idx] <= 1'b1; // Grant this port
granted = 1; // Mark that we've granted
/* verilator lint_off WIDTHTRUNC */
// Update priority pointer for next cycle
// Next cycle will start checking from the port after this one
priority_ptr <= (check_idx + 1) % NUM_PORTS;
/* verilator lint_on WIDTHTRUNC */
end
end
end
end
end
end
endmodule