188 lines
6.0 KiB
Verilog
188 lines
6.0 KiB
Verilog
module AgeMatrixSelector #(
|
|
parameter int unsigned EntryCount = 4,
|
|
parameter int unsigned EnqWidth = 2,
|
|
parameter int unsigned SelWidth = 2
|
|
) (
|
|
input wire [EnqWidth-1:0] enq_fire_i,
|
|
input wire [EnqWidth-1:0][EntryCount-1:0] enq_mask_i,
|
|
input wire deq_fire_i,
|
|
input wire [EntryCount-1:0] deq_mask_i,
|
|
input wire [EntryCount-1:0] sel_mask_i,
|
|
output wire [SelWidth-1:0][EntryCount-1:0] result_mask_o,
|
|
input wire [EntryCount-1:0] entry_vld_i,
|
|
input wire clk,
|
|
input wire rstn
|
|
);
|
|
|
|
wire [EntryCount-1:0] age_matrix_clk_en;
|
|
wire [EntryCount-1:0] enq_age_matrix_en;
|
|
wire [EntryCount-1:0] deq_age_matrix_en;
|
|
wire [EnqWidth-1:0][EntryCount-1:0] enq_dependency_vec;
|
|
wire [EntryCount-1:0][EnqWidth-1:0] enq_entry_sel_mask;
|
|
wire [EntryCount-1:0][EntryCount-1:0] enq_age_matrix;
|
|
wire [EntryCount-1:0][EntryCount-1:0] deq_age_matrix;
|
|
reg [EntryCount-1:0][EntryCount-1:0] age_matrix_d, age_matrix_q;
|
|
|
|
wire [SelWidth-1:0][EntryCount-1:0] selected_vec;
|
|
wire [SelWidth-1:0][EntryCount-1:0][EntryCount-1:0] masked_age_matrix;
|
|
|
|
// In age order select
|
|
generate
|
|
for (genvar i = 0; i < SelWidth; i++) begin : gen_selected_vec
|
|
if (i == 0) begin : gen_initial_one
|
|
assign selected_vec[i] = {EntryCount{1'b0}};
|
|
end else begin : gen_others
|
|
assign selected_vec[i] = selected_vec[i-1] | result_mask_o[i-1];
|
|
end
|
|
end
|
|
for (genvar i = 0; i < SelWidth; i++) begin : gen_sel_matrix
|
|
for (genvar col = 0; col < EntryCount; col++) begin : gen_col
|
|
for (genvar row = 0; row < EntryCount; row++) begin : gen_row
|
|
if (col == row) begin : gen_masked_vld
|
|
assign masked_age_matrix[i][row][col] = sel_mask_i[col] & ~selected_vec[i][col];
|
|
end else begin : gen_masked_dependency
|
|
assign masked_age_matrix[i][row][col] = (sel_mask_i[col] & ~selected_vec[i][col]) ?
|
|
age_matrix_q[row][col] : 1'b1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for (genvar i = 0; i < SelWidth; i++) begin : gen_multi_result
|
|
for (genvar row = 0; row < EntryCount; row++) begin : gen_one
|
|
assign result_mask_o[i][row] = &masked_age_matrix[i][row];
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
|
|
// Enq -> Set dependency bits
|
|
generate
|
|
for (genvar i = 0; i < EntryCount; i++) begin : gen_enq_entry_en
|
|
assign enq_age_matrix_en[i] = |enq_entry_sel_mask[i];
|
|
end
|
|
endgenerate
|
|
|
|
generate
|
|
for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_dependency_vec
|
|
if (i == 0) begin : gen_init_vec
|
|
assign enq_dependency_vec[i] = deq_fire_i ? (~entry_vld_i | deq_mask_i) : ~entry_vld_i;
|
|
end else begin : gen_vec_with_inter_check
|
|
assign enq_dependency_vec[i] = enq_fire_i[i-1] ?
|
|
(enq_dependency_vec[i-1] & ~enq_mask_i[i-1]) : enq_dependency_vec[i-1];
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
generate
|
|
for (genvar i = 0; i < EntryCount; i++) begin : gen_enq_entry_sel_mask
|
|
for (genvar j = 0; j < EnqWidth; j++) begin : gen_sel
|
|
assign enq_entry_sel_mask[i][j] = enq_fire_i[j] & enq_mask_i[j][i];
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
// Deq -> Clear dependency bits
|
|
generate
|
|
for (genvar i = 0; i < EntryCount; i++) begin : gen_deq_entry_clk_en
|
|
assign deq_age_matrix[i] = age_matrix_q[i] | deq_mask_i;
|
|
end
|
|
endgenerate
|
|
|
|
generate
|
|
for (genvar i = 0; i < EntryCount; i++) begin : gen_deq_entry_en
|
|
assign deq_age_matrix_en[i] = deq_fire_i & entry_vld_i[i];
|
|
end
|
|
endgenerate
|
|
|
|
assign age_matrix_clk_en = enq_age_matrix_en | deq_age_matrix_en;
|
|
|
|
// Age matrix update
|
|
|
|
always @(*) begin : age_matrix_vld_dff
|
|
for (int i = 0; i < EntryCount; i++) begin
|
|
age_matrix_q[i][i] = entry_vld_i[i];
|
|
end
|
|
end
|
|
|
|
generate
|
|
for (genvar i = 0; i < EntryCount; i++) begin : gen_age_matrix_update_logic
|
|
MuxOH #(
|
|
.InputWidth(2),
|
|
.DataWidth (EntryCount)
|
|
) u_age_matrix_update_MuxOH (
|
|
.sel_i ({enq_age_matrix_en[i], deq_age_matrix_en[i]}),
|
|
.data_i({enq_age_matrix[i], deq_age_matrix[i]}),
|
|
.data_o(age_matrix_d[i])
|
|
);
|
|
end
|
|
endgenerate
|
|
|
|
|
|
generate
|
|
for (genvar i = 0; i < EntryCount; i++) begin : gen_entry_update_dependency_vec
|
|
MuxOH #(
|
|
.InputWidth(EnqWidth),
|
|
.DataWidth (EntryCount)
|
|
) u_depend_vec_MuxOH (
|
|
.sel_i (enq_entry_sel_mask[i]),
|
|
.data_i(enq_dependency_vec),
|
|
.data_o(enq_age_matrix[i])
|
|
);
|
|
end
|
|
endgenerate
|
|
|
|
always @(posedge clk or negedge rstn) begin : age_matrix_dependency_dff
|
|
if (~rstn) begin
|
|
for (int row = 0; row < EntryCount; row++) begin
|
|
for (int col = 0; col < EntryCount; col++) begin
|
|
if (row != col) begin
|
|
age_matrix_q[row][col] <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
end else begin
|
|
for (int row = 0; row < EntryCount; row++) begin
|
|
if (age_matrix_clk_en[row]) begin
|
|
for (int col = 0; col < EntryCount; col++) begin
|
|
if (row != col) begin
|
|
age_matrix_q[row][col] <= age_matrix_d[row][col];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
`ifndef SYNTHESIS
|
|
default disable iff (~rstn);
|
|
generate
|
|
for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_checker
|
|
ENQ_VLD_ENTRY :
|
|
assert property (@(posedge clk) enq_fire_i[i] |-> ((enq_mask_i[i] & entry_vld_i) == 0))
|
|
else begin
|
|
$fatal("\n Error : Enqueueing a valid entry! enq_mask[%b]\n", enq_mask_i[i]);
|
|
end
|
|
end
|
|
for (genvar i = 0; i < SelWidth; i++) begin : gen_sel_checker
|
|
SEL_INVLD_ENTRY :
|
|
assert property (@(negedge clk) |sel_mask_i |-> ((result_mask_o[i] & ~entry_vld_i) == 0))
|
|
else begin
|
|
$fatal("\n Error : Selecting a invalid entry! sel_mask[%b]\n",
|
|
(result_mask_o[i] & ~entry_vld_i));
|
|
end
|
|
|
|
RESULT_MASK_IS_ONEHOT :
|
|
assert property (@(negedge clk) |sel_mask_i |-> $onehot0(result_mask_o[i]))
|
|
else begin
|
|
$fatal("\n Error : Got multi-choice which should never happend! result_mask[%b]\n",
|
|
result_mask_o[i]);
|
|
end
|
|
end
|
|
endgenerate
|
|
`endif
|
|
|
|
|
|
endmodule
|
|
|
|
|