Files
OpenExSys_NoC/rtl/util/commoncell/src/Queue/hw/AgeMatrixSelector.v
2023-11-26 14:59:34 +01:00

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