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