forked from SJTU-YONGFU-RESEARCH-GRP/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharbiter_rr.v
More file actions
executable file
·125 lines (117 loc) · 5.95 KB
/
arbiter_rr.v
File metadata and controls
executable file
·125 lines (117 loc) · 5.95 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
/**
* Round-Robin Arbiter Module
*
* This module implements an arbiter with configurable priority schemes,
* optimized for round-robin (fair) arbitration. It provides fair access
* to a shared resource by rotating priority after each grant.
*
* Priority Schemes:
* 1. Fixed Priority (PRIORITY_SCHEME = 0):
* - Higher port indices have higher priority
* - Simple but can starve lower-priority ports
*
* 2. Round-Robin (PRIORITY_SCHEME = 1):
* - Priority rotates after each grant
* - Provides fairness and prevents starvation
* - Cycles through ports starting from last granted port
*
* Design Notes:
* - Default is round-robin (PRIORITY_SCHEME = 1)
* - Priority pointer cycles downward (wraps around)
* - Only one port can be granted per cycle (mutual exclusion)
*
* @param NUM_PORTS Number of ports competing for access (default: 4)
* @param PRIORITY_SCHEME 0 = Fixed, 1 = Round-robin (default: 1)
*
* @input clk Clock signal
* @input rst_n Active-low reset signal
* @input request[NUM_PORTS-1:0] Request signals from each port
* @output grant[NUM_PORTS-1:0] Grant signals (one-hot)
* @output active High when any port is granted
*/
module arbiter_rr #(
parameter NUM_PORTS = 4,
parameter PRIORITY_SCHEME = 1 // 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: tracks which port has highest priority
reg [$clog2(NUM_PORTS)-1:0] priority_ptr;
// ============================================================================
// Active Signal Generation
// ============================================================================
// Active signal indicates when any port is currently granted access
assign active = |grant;
// ============================================================================
// Main Arbitration Logic
// ============================================================================
// Temporary variables for arbitration computation
reg [1:0] found; // Flag for fixed priority scheme
reg [1:0] granted; // Flag for round-robin scheme
reg [1:0] ptr; // Temporary pointer copy
reg [1:0] check_idx; // Current port index being checked
integer i; // Loop counter
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// ====================================================================
// Reset State
// ====================================================================
grant <= {NUM_PORTS{1'b0}};
// Initialize priority pointer to highest port (for round-robin)
priority_ptr <= NUM_PORTS-1;
end else begin
// ====================================================================
// Default: No Grants
// ====================================================================
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
// Check ports from highest to lowest index
/* verilator lint_off BLKSEQ */
found = 0;
// Check ports in priority order (3, 2, 1, 0)
if (request[3] && !found) begin grant[3] <= 1'b1; found = 1; end
if (request[2] && !found) begin grant[2] <= 1'b1; found = 1; end
if (request[1] && !found) begin grant[1] <= 1'b1; found = 1; end
if (request[0] && !found) begin grant[0] <= 1'b1; found = 1; end
/* verilator lint_on BLKSEQ */
end else begin
// ============================================================
// Round-Robin Priority Scheme
// ============================================================
// Start checking from priority_ptr and cycle downward
// This ensures fair rotation of priority
/* verilator lint_off BLKSEQ */
granted = 0; // No grant issued yet
// Check all ports starting from priority_ptr, cycling downward
for (i = 0; i < NUM_PORTS; i = i + 1) begin
// Calculate port index: start from priority_ptr and go down
// Modulo arithmetic handles wrap-around
check_idx = (priority_ptr - i + NUM_PORTS) % 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
// Update priority pointer: next cycle starts from port before this one
// This implements the round-robin rotation
priority_ptr <= (check_idx - 1 + NUM_PORTS) % NUM_PORTS;
end
end
/* verilator lint_on BLKSEQ */
end
end
end
end
endmodule