1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Rewrite priority encoder to remove recusive construction

This commit is contained in:
Alex Forencich 2020-08-17 18:29:05 -07:00
parent 71bd4a1811
commit ae10935a93

View File

@ -42,57 +42,43 @@ module priority_encoder #
output wire [WIDTH-1:0] output_unencoded
);
// power-of-two width
parameter W1 = 2**$clog2(WIDTH);
parameter W2 = W1/2;
parameter LEVELS = WIDTH > 2 ? $clog2(WIDTH) : 1;
parameter W = 2**LEVELS;
// pad input to even power of two
wire [W-1:0] input_padded = {{W-WIDTH{1'b0}}, input_unencoded};
wire [W/2-1:0] stage_valid[LEVELS-1:0];
wire [W/2-1:0] stage_enc[LEVELS-1:0];
generate
if (WIDTH == 1) begin
// one input
assign output_valid = input_unencoded;
assign output_encoded = 0;
end else if (WIDTH == 2) begin
// two inputs - just an OR gate
assign output_valid = |input_unencoded;
genvar l, n;
// process input bits; generate valid bit and encoded bit for each pair
for (n = 0; n < W/2; n = n + 1) begin : loop_in
assign stage_valid[0][n] = |input_padded[n*2+1:n*2];
if (LSB_PRIORITY == "LOW") begin
assign output_encoded = input_unencoded[1];
assign stage_enc[0][n] = input_padded[n*2+1];
end else begin
assign output_encoded = ~input_unencoded[0];
assign stage_enc[0][n] = !input_padded[n*2+0];
end
end else begin
// more than two inputs - split into two parts and recurse
// also pad input to correct power-of-two width
wire [$clog2(W2)-1:0] out1, out2;
wire valid1, valid2;
priority_encoder #(
.WIDTH(W2),
.LSB_PRIORITY(LSB_PRIORITY)
)
priority_encoder_inst1 (
.input_unencoded(input_unencoded[W2-1:0]),
.output_valid(valid1),
.output_encoded(out1)
);
priority_encoder #(
.WIDTH(W2),
.LSB_PRIORITY(LSB_PRIORITY)
)
priority_encoder_inst2 (
.input_unencoded({{W1-WIDTH{1'b0}}, input_unencoded[WIDTH-1:W2]}),
.output_valid(valid2),
.output_encoded(out2)
);
// multiplexer to select part
assign output_valid = valid1 | valid2;
end
// compress down to single valid bit and encoded bus
for (l = 1; l < LEVELS; l = l + 1) begin : loop_levels
for (n = 0; n < W/(2*2**l); n = n + 1) begin : loop_compress
assign stage_valid[l][n] = |stage_valid[l-1][n*2+1:n*2];
if (LSB_PRIORITY == "LOW") begin
assign output_encoded = valid2 ? {1'b1, out2} : {1'b0, out1};
assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+1] ? {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]} : {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]};
end else begin
assign output_encoded = valid1 ? {1'b0, out1} : {1'b1, out2};
assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+0] ? {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]} : {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]};
end
end
end
endgenerate
// unencoded output
assign output_valid = stage_valid[LEVELS-1];
assign output_encoded = stage_enc[LEVELS-1];
assign output_unencoded = 1 << output_encoded;
endmodule