diff options
Diffstat (limited to 'src/arb.sv')
| -rw-r--r-- | src/arb.sv | 99 |
1 files changed, 21 insertions, 78 deletions
@@ -1,99 +1,42 @@ -module first_set #( - parameter WIDTH = 32 -)( - input reg[WIDTH-1 :0] cand, - output reg[WIDTH-1 :0] selected -); - -/* base case */ -if (WIDTH == 1) begin :base - assign selected = cand; -end - -/* recursive case */ -else begin :recursive - localparam SLICE_WIDTH = WIDTH / 2; - logic[SLICE_WIDTH-1:0] left, right; - logic pref_left, pref_right; - logic empty_left, empty_right; - - first_set #( - .WIDTH(SLICE_WIDTH) - ) first_set_left ( - .cand(cand[SLICE_WIDTH +: SLICE_WIDTH]), - .selected (left) - ); - - first_set #( - .WIDTH(SLICE_WIDTH) - ) first_set_right ( - .cand(cand[0 +: SLICE_WIDTH]), - .selected (right) - ); - - assign selected = right != '0 - ? {{SLICE_WIDTH{1'b0}}, right} - : {left, {SLICE_WIDTH{1'b0}}} - ; -end - -always_comb begin - assert ($onehot0(selected)); -end - -`ifdef NOSUCHDEF -/* assertions that verilator don't support, apparently */ -assert property (WIDTH >= 1) -else $error("input width too narrow"); - -assert property (1 << $clog2(WIDTH) == WIDTH) -else $error("width not pow2"); - -`endif - -endmodule // arb_recursive - module arb #( parameter WIDTH = 32 )( input clk, input rstx, - input [WIDTH-1:0] cand, + input [WIDTH-1:0] valid, output[WIDTH-1:0] selected ); -localparam W2 = 1 << $clog2(WIDTH); -localparam DEPTH = W2 == 1 ? 1 : $clog2(W2); +logic found0, found1; +logic [WIDTH-1:0] mask, next_mask0, next_mask1, cand0, cand1; -logic[W2-1:0] w2_cand, w2_selected, mask, next_mask, rot_selected; +always_comb begin + found0 = 0; + found1 = 0; + for (int i = 0; i < WIDTH; ++i) begin + cand0[i] = !found0 & valid[i] & mask[i]; + cand1[i] = !found1 & valid[i]; -/* if there are candidates within the mask of 'above preferred index', use them, - * otherwise invert the mask and use candidates 'below' preferred index. */ -assign w2_cand = ((cand & mask) == '0) ? cand & ~mask : cand & mask; + next_mask0[i] = found0; + next_mask1[i] = found1; -first_set #( - .WIDTH(W2) -) first_set_i ( - .cand (w2_cand), - .selected(w2_selected) -); + if (valid[i] & mask[i]) + found0 = 1; -assign selected = w2_selected; - -assign rot_selected = { - w2_selected[0 +: W2-1], - w2_selected[W2-1] -}; + if (valid[i]) + found1 = 1; + end +end -assign next_mask = ~(rot_selected - 1) | rot_selected; +assign selected = found0 ? cand0 : cand1; always_ff @(posedge clk or negedge rstx) if (!rstx) begin - mask <= ~0; + mask <= '0; end else begin - if (selected != 0 && mask != next_mask) - mask <= next_mask; + if (|valid) + mask <= found0 ? next_mask0 : next_mask1; else mask <= mask; end |
