Skip to content

Instantly share code, notes, and snippets.

@pervognsen
Last active June 17, 2020 11:05
Show Gist options
  • Save pervognsen/4825c531363f0ddce20a8881f90e775b to your computer and use it in GitHub Desktop.
Save pervognsen/4825c531363f0ddce20a8881f90e775b to your computer and use it in GitHub Desktop.
// A round-robin priority arbiter for valid/ready signaling using carry chain logic.
module arbiter#(parameter N = 2)
(
input wire clk,
input wire [N-1:0] s_valid,
output wire [N-1:0] s_ready,
output wire m_valid,
input wire m_ready
);
// This mask has a bit set when the corresponding lane is deprioritized this cycle.
reg [N-1:0] mask = 0;
// Isolate the highest priority valid lane (lower bits are higher priority).
wire [N-1:0] valid_isolated = s_valid & -s_valid;
// Mask out any deprioritized lanes.
wire [N-1:0] valid_prioritized = s_valid & ~mask;
// Isolate the highest priority prioritized valid lane.
wire [N-1:0] valid_prioritized_isolated = valid_prioritized & -valid_prioritized;
// Pick the highest priority prioritized lane. If none exists, include deprioritized lanes as well.
wire [N-1:0] valid = |valid_prioritized_isolated ? valid_prioritized_isolated : valid_isolated;
// You'd probably want to register these outputs since there's a lot of logic hanging off of them.
assign m_valid = |s_valid;
assign s_ready = {N{m_ready}} & valid;
always @(posedge clk)
// Deprioritize the chosen lane and all higher priority lanes in the next cycle.
// If s_ready is zero then all lanes will be deprioritized, which is a no-op.
mask <= (s_ready << 1) - 1;
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment