summaryrefslogtreecommitdiff
path: root/arbiter.v
diff options
context:
space:
mode:
Diffstat (limited to 'arbiter.v')
-rw-r--r--arbiter.v67
1 files changed, 67 insertions, 0 deletions
diff --git a/arbiter.v b/arbiter.v
new file mode 100644
index 0000000..0e83403
--- /dev/null
+++ b/arbiter.v
@@ -0,0 +1,67 @@
+/* Arbiter
+ * A module that grants access to a shared ressource (e.g a bus)
+ * to an arbitrary amount of drivers. A driver of the shared resource
+ * has a bit on the `request` line and fires it up when it wants to use
+ * the resource. The arbiter fires the corresponding `grant` bit when
+ * the driver is allowed to use the resource */
+module arbiter #(
+ parameter NUM_CLIENTS = 4
+) (
+ input clk,
+
+ // Request bits, each driver has its request line
+ input[NUM_CLIENTS-1:0] request,
+
+ // Grant bits, each driver has its grant line
+ output[NUM_CLIENTS-1:0] grant
+);
+ // The current round of the arbiter
+ reg[NUM_CLIENTS-1:0] round = 1;
+
+ // A circle of wires used by the arbiter to
+ // indicate that a driver that has the priority
+ // to use the resource yields it to the next driver
+ // because it doesn't need to use the resource
+ wire pass_on_rollover;
+ /* verilator lint_off UNOPTFLAT */
+ logic pass_on;
+ assign pass_on_rollover = pass_on; // NOTE: assign is applied on last assignment to wire
+
+ // Logic bitfield used to generate the grant bus
+ logic[NUM_CLIENTS-1:0] grant_gen;
+ assign grant = grant_gen;
+
+ always @(posedge clk) begin
+ // Keep current grant as round, allowing a selected driver
+ // to freeze the arbiter during the entire duration of its
+ // resource utilization
+ round <= |grant ?
+ grant : { round[NUM_CLIENTS-2:0], round[NUM_CLIENTS-1] };
+ end
+
+ always_comb begin
+ pass_on = pass_on_rollover;
+
+ for (integer i = 0; i < NUM_CLIENTS; i++) begin
+ logic has_priority;
+
+ // Current driver has priority if it's its round
+ // or previous driver has passed on its
+ has_priority = round[i] || pass_on;
+
+ // By default, do not grant to driver
+ grant_gen[i] = 0;
+
+ // By default, do not pass on priority
+ // to next driver (current may not have it)
+ pass_on = 0;
+
+ if (has_priority) begin
+ if (request[i])
+ grant_gen[i] = 1;
+ else
+ pass_on = 1;
+ end
+ end
+ end
+endmodule \ No newline at end of file