// Copyright © 2019-2023 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. `include "VX_platform.vh" `TRACING_OFF module VX_rr_arbiter #( parameter NUM_REQS = 1, parameter LOCK_ENABLE = 0, parameter MODEL = 1, parameter LOG_NUM_REQS = `LOG2UP(NUM_REQS) ) ( input wire clk, input wire reset, input wire [NUM_REQS-1:0] requests, output wire [LOG_NUM_REQS-1:0] grant_index, output wire [NUM_REQS-1:0] grant_onehot, output wire grant_valid, input wire grant_unlock ); if (NUM_REQS == 1) begin `UNUSED_VAR (clk) `UNUSED_VAR (reset) `UNUSED_VAR (grant_unlock) assign grant_index = '0; assign grant_onehot = requests; assign grant_valid = requests[0]; end else if (NUM_REQS == 2) begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [LOG_NUM_REQS-1:0] state; always @(*) begin casez ({state, requests}) 3'b0_01, 3'b1_?1: begin grant_onehot_r = 2'b01; grant_index_r = LOG_NUM_REQS'(0); end default: begin grant_onehot_r = 2'b10; grant_index_r = LOG_NUM_REQS'(1); end endcase end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end /*else if (NUM_REQS == 3) begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [LOG_NUM_REQS-1:0] state; always @(*) begin casez ({state, requests}) 5'b00_001, 5'b01_0?1, 5'b10_??1: begin grant_onehot_r = 3'b001; grant_index_r = LOG_NUM_REQS'(0); end 5'b00_?1?, 5'b01_010, 5'b10_?10: begin grant_onehot_r = 3'b010; grant_index_r = LOG_NUM_REQS'(1); end default: begin grant_onehot_r = 3'b100; grant_index_r = LOG_NUM_REQS'(2); end endcase end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end */else if (NUM_REQS == 4) begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [LOG_NUM_REQS-1:0] state; always @(*) begin casez ({state, requests}) 6'b00_0001, 6'b01_00?1, 6'b10_0??1, 6'b11_???1: begin grant_onehot_r = 4'b0001; grant_index_r = LOG_NUM_REQS'(0); end 6'b00_??1?, 6'b01_0010, 6'b10_0?10, 6'b11_??10: begin grant_onehot_r = 4'b0010; grant_index_r = LOG_NUM_REQS'(1); end 6'b00_?10?, 6'b01_?1??, 6'b10_0100, 6'b11_?100: begin grant_onehot_r = 4'b0100; grant_index_r = LOG_NUM_REQS'(2); end default: begin grant_onehot_r = 4'b1000; grant_index_r = LOG_NUM_REQS'(3); end endcase end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end /*else if (NUM_REQS == 5) begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [LOG_NUM_REQS-1:0] state; always @(*) begin casez ({state, requests}) 8'b000_00001, 8'b001_000?1, 8'b010_00??1, 8'b011_0???1, 8'b100_????1: begin grant_onehot_r = 5'b00001; grant_index_r = LOG_NUM_REQS'(0); end 8'b000_???1?, 8'b001_00010, 8'b010_00?10, 8'b011_0??10, 8'b100_???10: begin grant_onehot_r = 5'b00010; grant_index_r = LOG_NUM_REQS'(1); end 8'b000_??10?, 8'b001_??1??, 8'b010_00100, 8'b011_0?100, 8'b100_??100: begin grant_onehot_r = 5'b00100; grant_index_r = LOG_NUM_REQS'(2); end 8'b000_?100?, 8'b001_?10??, 8'b010_?1???, 8'b011_01000, 8'b100_?1000: begin grant_onehot_r = 5'b01000; grant_index_r = LOG_NUM_REQS'(3); end default: begin grant_onehot_r = 5'b10000; grant_index_r = LOG_NUM_REQS'(4); end endcase end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end else if (NUM_REQS == 6) begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [LOG_NUM_REQS-1:0] state; always @(*) begin casez ({state, requests}) 9'b000_000001, 9'b001_0000?1, 9'b010_000??1, 9'b011_00???1, 9'b100_0????1, 9'b101_?????1: begin grant_onehot_r = 6'b000001; grant_index_r = LOG_NUM_REQS'(0); end 9'b000_????1?, 9'b001_000010, 9'b010_000?10, 9'b011_00??10, 9'b100_0???10, 9'b101_????10: begin grant_onehot_r = 6'b000010; grant_index_r = LOG_NUM_REQS'(1); end 9'b000_???10?, 9'b001_???1??, 9'b010_000100, 9'b011_00?100, 9'b100_0??100, 9'b101_???100: begin grant_onehot_r = 6'b000100; grant_index_r = LOG_NUM_REQS'(2); end 9'b000_??100?, 9'b001_??10??, 9'b010_??1???, 9'b011_001000, 9'b100_0?1000, 9'b101_??1000: begin grant_onehot_r = 6'b001000; grant_index_r = LOG_NUM_REQS'(3); end 9'b000_?1000?, 9'b001_?100??, 9'b010_?10???, 9'b011_?1????, 9'b100_010000, 9'b101_?10000: begin grant_onehot_r = 6'b010000; grant_index_r = LOG_NUM_REQS'(4); end default: begin grant_onehot_r = 6'b100000; grant_index_r = LOG_NUM_REQS'(5); end endcase end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end else if (NUM_REQS == 7) begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [LOG_NUM_REQS-1:0] state; always @(*) begin casez ({state, requests}) 10'b000_000001, 10'b001_0000?1, 10'b010_000??1, 10'b011_00???1, 10'b100_00???1, 10'b101_0????1, 10'b110_?????1: begin grant_onehot_r = 7'b0000001; grant_index_r = LOG_NUM_REQS'(0); end 10'b000_?????1?, 10'b001_0000010, 10'b010_0000?10, 10'b011_000??10, 10'b100_00???10, 10'b101_0????10, 10'b110_?????10: begin grant_onehot_r = 7'b0000010; grant_index_r = LOG_NUM_REQS'(1); end 10'b000_????10?, 10'b001_????1??, 10'b010_0000100, 10'b011_000?100, 10'b100_00??100, 10'b101_0???100, 10'b110_????100: begin grant_onehot_r = 7'b0000100; grant_index_r = LOG_NUM_REQS'(2); end 10'b000_???100?, 10'b001_???10??, 10'b010_???1???, 10'b011_0001000, 10'b100_00?1000, 10'b101_0??1000, 10'b110_???1000: begin grant_onehot_r = 7'b0001000; grant_index_r = LOG_NUM_REQS'(3); end 10'b000_??1000?, 10'b001_??100??, 10'b010_??10???, 10'b011_??1????, 10'b100_0010000, 10'b101_0?10000, 10'b110_??10000: begin grant_onehot_r = 7'b0010000; grant_index_r = LOG_NUM_REQS'(4); end 10'b000_?10000?, 10'b001_?1000??, 10'b010_?100???, 10'b011_?10????, 10'b100_?1?????, 10'b101_0100000, 10'b110_?100000: begin grant_onehot_r = 7'b0100000; grant_index_r = LOG_NUM_REQS'(5); end default: begin grant_onehot_r = 7'b1000000; grant_index_r = LOG_NUM_REQS'(6); end endcase end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end */else if (NUM_REQS == 8) begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [LOG_NUM_REQS-1:0] state; always @(*) begin casez ({state, requests}) 11'b000_00000001, 11'b001_000000?1, 11'b010_00000??1, 11'b011_0000???1, 11'b100_000????1, 11'b101_00?????1, 11'b110_0??????1, 11'b111_???????1: begin grant_onehot_r = 8'b00000001; grant_index_r = LOG_NUM_REQS'(0); end 11'b000_??????1?, 11'b001_00000010, 11'b010_00000?10, 11'b011_0000??10, 11'b100_000???10, 11'b101_00????10, 11'b110_0?????10, 11'b111_??????10: begin grant_onehot_r = 8'b00000010; grant_index_r = LOG_NUM_REQS'(1); end 11'b000_?????10?, 11'b001_?????1??, 11'b010_00000100, 11'b011_0000?100, 11'b100_000??100, 11'b101_00???100, 11'b110_0????100, 11'b111_?????100: begin grant_onehot_r = 8'b00000100; grant_index_r = LOG_NUM_REQS'(2); end 11'b000_????100?, 11'b001_????10??, 11'b010_????1???, 11'b011_00001000, 11'b100_000?1000, 11'b101_00??1000, 11'b110_0???1000, 11'b111_????1000: begin grant_onehot_r = 8'b00001000; grant_index_r = LOG_NUM_REQS'(3); end 11'b000_???1000?, 11'b001_???100??, 11'b010_???10???, 11'b011_???1????, 11'b100_00010000, 11'b101_00?10000, 11'b110_0??10000, 11'b111_???10000: begin grant_onehot_r = 8'b00010000; grant_index_r = LOG_NUM_REQS'(4); end 11'b000_??10000?, 11'b001_??1000??, 11'b010_??100???, 11'b011_??10????, 11'b100_??1?????, 11'b101_00100000, 11'b110_0?100000, 11'b111_??100000: begin grant_onehot_r = 8'b00100000; grant_index_r = LOG_NUM_REQS'(5); end 11'b000_?100000?, 11'b001_?10000??, 11'b010_?1000???, 11'b011_?100????, 11'b100_?10?????, 11'b101_?1??????, 11'b110_01000000, 11'b111_?1000000: begin grant_onehot_r = 8'b01000000; grant_index_r = LOG_NUM_REQS'(6); end default: begin grant_onehot_r = 8'b10000000; grant_index_r = LOG_NUM_REQS'(7); end endcase end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end else if (MODEL == 1) begin `IGNORE_UNOPTFLAT_BEGIN wire [NUM_REQS-1:0] mask_higher_pri_regs, unmask_higher_pri_regs; `IGNORE_UNOPTFLAT_END wire [NUM_REQS-1:0] grant_masked, grant_unmasked; reg [NUM_REQS-1:0] pointer_reg; wire [NUM_REQS-1:0] req_masked = requests & pointer_reg; assign mask_higher_pri_regs[NUM_REQS-1:1] = mask_higher_pri_regs[NUM_REQS-2:0] | req_masked[NUM_REQS-2:0]; assign mask_higher_pri_regs[0] = 1'b0; assign grant_masked[NUM_REQS-1:0] = req_masked[NUM_REQS-1:0] & ~mask_higher_pri_regs[NUM_REQS-1:0]; assign unmask_higher_pri_regs[NUM_REQS-1:1] = unmask_higher_pri_regs[NUM_REQS-2:0] | requests[NUM_REQS-2:0]; assign unmask_higher_pri_regs[0] = 1'b0; assign grant_unmasked[NUM_REQS-1:0] = requests[NUM_REQS-1:0] & ~unmask_higher_pri_regs[NUM_REQS-1:0]; wire no_req_masked = ~(|req_masked); assign grant_onehot = ({NUM_REQS{no_req_masked}} & grant_unmasked) | grant_masked; always @(posedge clk) begin if (reset) begin pointer_reg <= {NUM_REQS{1'b1}}; end else if (!LOCK_ENABLE || grant_unlock) begin if (|req_masked) begin pointer_reg <= mask_higher_pri_regs; end else if (|requests) begin pointer_reg <= unmask_higher_pri_regs; end else begin pointer_reg <= pointer_reg; end end end assign grant_valid = (| requests); VX_onehot_encoder #( .N (NUM_REQS) ) onehot_encoder ( .data_in (grant_onehot), .data_out (grant_index), `UNUSED_PIN (valid_out) ); end else begin reg [LOG_NUM_REQS-1:0] grant_index_r; reg [NUM_REQS-1:0] grant_onehot_r; reg [NUM_REQS-1:0] state; always @(*) begin grant_index_r = 'x; grant_onehot_r = 'x; for (integer i = 0; i < NUM_REQS; ++i) begin for (integer j = 0; j < NUM_REQS; ++j) begin if (state[i] && requests[(j + 1) % NUM_REQS]) begin grant_index_r = LOG_NUM_REQS'((j + 1) % NUM_REQS); grant_onehot_r = '0; grant_onehot_r[(j + 1) % NUM_REQS] = 1; end end end end always @(posedge clk) begin if (reset) begin state <= '0; end else if (!LOCK_ENABLE || grant_unlock) begin state <= grant_index_r; end end assign grant_index = grant_index_r; assign grant_onehot = grant_onehot_r; assign grant_valid = (| requests); end endmodule `TRACING_ON