initial commit for open source NoC IP
This commit is contained in:
58
rtl/util/commoncell/src/Queue/Queue.yaml
Normal file
58
rtl/util/commoncell/src/Queue/Queue.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
Name: Queue
|
||||
Dependency:
|
||||
- ../StdDFF/StdDFF.yaml
|
||||
- ../Basic/Basic.yaml
|
||||
Module:
|
||||
- name: QueueManager
|
||||
description: Queue Ptr Manager
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/QueueManager.v
|
||||
dependency:
|
||||
- CountOne
|
||||
- StdDFF
|
||||
|
||||
- name: StaticPrioritySelector
|
||||
description: Static Priority Selector
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/StaticPrioritySelector.v
|
||||
sim:
|
||||
- dv/StaticPrioritySelector_tb.v
|
||||
|
||||
- name: AgeMatrixSelector
|
||||
description: Age Matrix selector to select in age order
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/AgeMatrixSelector.v
|
||||
# sim:
|
||||
# - dv/AgeMatrixSelector_tb.v
|
||||
dependency:
|
||||
- MuxOH
|
||||
|
||||
- name: MultiPortStreamFIFO
|
||||
description: MultiPortStream FIFO
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/FIFO/MultiPortStreamFIFO.v
|
||||
sim:
|
||||
- dv/FIFO/MultiPortStreamFIFO_tb.v
|
||||
dependency:
|
||||
- QueueManager
|
||||
|
||||
- name: FIAOWithQueueManager
|
||||
description: FIAOWithQueueManager
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/FIAO/FIAOWithQueueManager.v
|
||||
dependency:
|
||||
- QueueManager
|
||||
|
||||
# - name: FIAOWithAgeMatrix
|
||||
# description: FIAOWithAgeMatrix
|
||||
# language: SystemVerilog
|
||||
# rtl:
|
||||
# - hw/FIAO/FIAOWithAgeMatrix.v
|
||||
# dependency:
|
||||
# - OH2UInt
|
||||
# - AgeMatrixSelector
|
||||
168
rtl/util/commoncell/src/Queue/dv/AgeMatrixSelector_tb.v
Normal file
168
rtl/util/commoncell/src/Queue/dv/AgeMatrixSelector_tb.v
Normal file
@@ -0,0 +1,168 @@
|
||||
// module AgeMatrixSelector_tb;
|
||||
|
||||
// // Parameters
|
||||
// localparam int unsigned EntryCount = 4;
|
||||
// localparam int unsigned EnqWidth = 2;
|
||||
// localparam int unsigned SelWidth = 2;
|
||||
|
||||
// // Ports
|
||||
// reg [EnqWidth-1:0] enq_fire_i;
|
||||
// reg [EntryCount-1:0] enq_mask_i[EnqWidth];
|
||||
// reg [EntryCount-1:0] sel_mask_i;
|
||||
// wire [EntryCount-1:0] result_mask_o[SelWidth];
|
||||
// reg [EntryCount-1:0] entry_vld_i;
|
||||
// reg clk = 0;
|
||||
// reg rstn = 0;
|
||||
|
||||
// bit [EntryCount-1:0][EntryCount-1:0] golden_age_matrix_d, golden_age_matrix_q;
|
||||
// bit [EntryCount-1:0][EntryCount-1:0] golden_masked_age_matrix[SelWidth];
|
||||
// bit [EntryCount-1:0] golden_selected_mask[SelWidth];
|
||||
// bit [EntryCount-1:0] golden_sel_result[SelWidth];
|
||||
|
||||
// always @(posedge clk) begin
|
||||
// if (~rstn) begin
|
||||
// golden_age_matrix_q <= 0;
|
||||
// end else begin
|
||||
// for (int row = 0; row < EntryCount; row++) begin
|
||||
// for (int col = 0; col < EntryCount; col++) begin
|
||||
// if (row != col) begin
|
||||
// golden_age_matrix_q[row][col] <= golden_age_matrix_d[row][col];
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// always @(*) begin
|
||||
// for (int row = 0; row < EntryCount; row++) begin
|
||||
// golden_age_matrix_q[row][row] <= entry_vld_i[row];
|
||||
// end
|
||||
// end
|
||||
// always @(*) begin
|
||||
// golden_age_matrix_d = golden_age_matrix_q;
|
||||
// for (int i = 0; i < EnqWidth; i++) begin
|
||||
// if (enq_fire_i[i]) begin
|
||||
// for (int row = 0; row < EntryCount; row++) begin
|
||||
// if (enq_mask_i[i][row]) begin
|
||||
// for (int col = 0; col < EntryCount; col++) begin
|
||||
// golden_age_matrix_d[row][col] = ~golden_age_matrix_d[col][col];
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
|
||||
// always @(*) begin
|
||||
// for (int i = 0; i < EntryCount; i++) begin
|
||||
// if (i == 0) begin
|
||||
// golden_selected_mask[i] = 0;
|
||||
// end else begin
|
||||
// golden_selected_mask[i] = golden_selected_mask[i-1] | golden_sel_result[i-1];
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
|
||||
// always @(*) begin
|
||||
// for (int i = 0; i < SelWidth; i++) begin
|
||||
// golden_masked_age_matrix[i] = golden_age_matrix_q;
|
||||
// for (int col = 0; col < EntryCount; col++) begin
|
||||
// if (golden_selected_mask[i][col] | ~sel_mask_i[col]) begin
|
||||
// for (int row = 0; row < EntryCount; row++) begin
|
||||
// golden_masked_age_matrix[i][row][col] = col != row;
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
|
||||
// always @(*) begin
|
||||
// for (int i = 0; i < SelWidth; i++) begin
|
||||
// for (int row = 0; row < EntryCount; row++) begin
|
||||
// golden_sel_result[i][row] = &golden_masked_age_matrix[i][row];
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
|
||||
// default disable iff (~rstn);
|
||||
|
||||
// int iter = 10000;
|
||||
|
||||
// int random_ptr;
|
||||
|
||||
// CHECK_EQULATION :
|
||||
// assert property (@(negedge clk) golden_age_matrix_q == AgeMatrixSelector_dut.age_matrix_q)
|
||||
// else begin
|
||||
// $fatal("\n Error : Age matrix is not equal to golden one \n");
|
||||
// end
|
||||
|
||||
// initial begin
|
||||
// #100 rstn = 1'b1;
|
||||
// entry_vld_i = 0;
|
||||
// enq_fire_i = 0;
|
||||
// sel_mask_i = 0;
|
||||
|
||||
// repeat (iter) begin
|
||||
// @(posedge clk);
|
||||
// entry_vld_i = entry_vld_i & ~(entry_vld_i & $urandom_range(0, (1 << EntryCount) - 1));
|
||||
// for (int i = 0; i < EnqWidth; i++) begin
|
||||
// if (enq_fire_i[i]) begin
|
||||
// entry_vld_i = entry_vld_i | enq_mask_i[i];
|
||||
// end
|
||||
// end
|
||||
// sel_mask_i = $urandom_range(0, (1 << EntryCount) - 1) & entry_vld_i;
|
||||
|
||||
// @(negedge clk);
|
||||
// for (int i = 0; i < EnqWidth; i++) begin
|
||||
// enq_fire_i[i] = 0;
|
||||
// enq_mask_i[i] = 0;
|
||||
// random_ptr = $urandom_range(0, EntryCount - 1);
|
||||
// if (~entry_vld_i[random_ptr]) begin
|
||||
// enq_fire_i[i] = 1;
|
||||
// enq_mask_i[i][random_ptr] = 1;
|
||||
// end
|
||||
// for(int j = 0 ; j < i; j++) begin
|
||||
// if(enq_fire_i[j] && (enq_mask_i[j] == enq_mask_i[i])) begin
|
||||
// enq_fire_i[i] = 0;
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// for (int i = 0; i < SelWidth; i++) begin
|
||||
// assert (result_mask_o[i] == golden_sel_result[i])
|
||||
// else begin
|
||||
// $fatal("\n Error : Selection is not equal, golden[%b] our[%b] \n", golden_sel_result[i],
|
||||
// result_mask_o[i]);
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
// $info("\n PASS after %d iter \n",iter);
|
||||
// $finish();
|
||||
// end
|
||||
|
||||
|
||||
// AgeMatrixSelector #(
|
||||
// .EntryCount(EntryCount),
|
||||
// .EnqWidth (EnqWidth),
|
||||
// .SelWidth (SelWidth)
|
||||
// ) AgeMatrixSelector_dut (
|
||||
// .enq_fire_i(enq_fire_i),
|
||||
// .enq_mask_i(enq_mask_i),
|
||||
// .sel_mask_i(sel_mask_i),
|
||||
// .result_mask_o(result_mask_o),
|
||||
// .entry_vld_i(entry_vld_i),
|
||||
// .clk(clk),
|
||||
// .rstn(rstn)
|
||||
// );
|
||||
|
||||
// `ifdef DUMPON
|
||||
// initial begin : GEN_WAVEFORM
|
||||
// $fsdbDumpfile("AgeMatrixSelector_tb.fsdb");
|
||||
// $fsdbDumpvars(0, AgeMatrixSelector_tb);
|
||||
// $fsdbDumpvars("+mda");
|
||||
// $fsdbDumpvars("+all");
|
||||
// $fsdbDumpon();
|
||||
// end
|
||||
// `endif
|
||||
|
||||
// always #20 clk = !clk;
|
||||
|
||||
// endmodule
|
||||
111
rtl/util/commoncell/src/Queue/dv/FIFO/MultiPortStreamFIFO_tb.v
Normal file
111
rtl/util/commoncell/src/Queue/dv/FIFO/MultiPortStreamFIFO_tb.v
Normal file
@@ -0,0 +1,111 @@
|
||||
module MultiPortStreamFIFO_tb;
|
||||
|
||||
// Parameters
|
||||
localparam int unsigned Depth = 8;
|
||||
localparam int unsigned DataWidth = 32;
|
||||
localparam int unsigned EnqWidth = 2;
|
||||
localparam int unsigned DeqWidth = 2;
|
||||
localparam int unsigned TakenAll = 0;
|
||||
|
||||
// Ports
|
||||
reg [EnqWidth-1:0] enq_vld_i;
|
||||
reg [EnqWidth-1:0][DataWidth-1:0] enq_payload_i;
|
||||
wire [EnqWidth-1:0] enq_rdy_o;
|
||||
wire [DeqWidth-1:0] deq_vld_o;
|
||||
wire [DeqWidth-1:0][DataWidth-1:0] deq_payload_o;
|
||||
reg [DeqWidth-1:0] deq_rdy_i;
|
||||
reg flush_i = 0;
|
||||
reg clk = 0;
|
||||
reg rstn = 0;
|
||||
|
||||
bit [DataWidth-1:0] golden_fifo[$];
|
||||
bit [DataWidth-1:0] golden_fifo_front;
|
||||
int usage = 0;
|
||||
|
||||
int iter = 1000000;
|
||||
|
||||
always @(posedge clk) begin
|
||||
for (int i = 0; i < DeqWidth; i++) begin : test_deq
|
||||
if (deq_vld_o[i] & deq_rdy_i[i]) begin
|
||||
usage = usage - 1;
|
||||
golden_fifo_front = golden_fifo.pop_front();
|
||||
assert (deq_payload_o[i] == golden_fifo_front)
|
||||
else begin
|
||||
$fatal("\n Error: Fail when check equalation, ours[%x] -- gloden[%x]", deq_payload_o[i],
|
||||
golden_fifo_front);
|
||||
end
|
||||
end
|
||||
end
|
||||
for (int i = 0; i < EnqWidth; i++) begin : enq_test
|
||||
if (enq_vld_i[i] & enq_rdy_o[i]) begin
|
||||
usage = usage + 1;
|
||||
golden_fifo.push_back(enq_payload_i[i]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initial begin
|
||||
#10 rstn = 1'b1;
|
||||
repeat (iter) begin : random_test
|
||||
@(negedge clk);
|
||||
deq_rdy_i = {DeqWidth{1'b0}};
|
||||
enq_vld_i = {EnqWidth{1'b0}};
|
||||
for (int i = 0; i < DeqWidth; i++) begin : gen_deq_rdy
|
||||
if ($urandom_range(0, 1)) begin
|
||||
deq_rdy_i[i] = 1'b1;
|
||||
end else begin
|
||||
break;
|
||||
end
|
||||
end
|
||||
for (int i = 0; i < EnqWidth; i++) begin : gen_enq_vld
|
||||
if ($urandom_range(0, 1)) begin
|
||||
enq_vld_i[i] = 1'b1;
|
||||
enq_payload_i[i] = $urandom();
|
||||
end else begin
|
||||
break;
|
||||
end
|
||||
end
|
||||
CHECK_USAGE :
|
||||
assert (usage == MultiPortStreamFIFO_dut.u_QueueManager.usage)
|
||||
else begin
|
||||
$fatal("\n Error : Usage is not equal, which should never happen! ours[%d] gloden[%d] \n",
|
||||
MultiPortStreamFIFO_dut.u_QueueManager.usage, usage);
|
||||
end
|
||||
end
|
||||
$info("\n PASS after %d iter \n", iter);
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
MultiPortStreamFIFO #(
|
||||
.Depth(Depth),
|
||||
.DataWidth(DataWidth),
|
||||
.EnqWidth(EnqWidth),
|
||||
.DeqWidth(DeqWidth),
|
||||
.TakenAll(TakenAll)
|
||||
) MultiPortStreamFIFO_dut (
|
||||
.enq_vld_i(enq_vld_i),
|
||||
.enq_payload_i(enq_payload_i),
|
||||
.enq_rdy_o(enq_rdy_o),
|
||||
.deq_vld_o(deq_vld_o),
|
||||
.deq_payload_o(deq_payload_o),
|
||||
.deq_rdy_i(deq_rdy_i),
|
||||
.flush_i(flush_i),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
|
||||
`ifdef DUMPON
|
||||
initial begin : GEN_WAVEFORM
|
||||
$fsdbDumpfile("MultiPortStreamFIFO_tb.fsdb");
|
||||
$fsdbDumpvars(0, MultiPortStreamFIFO_tb);
|
||||
$fsdbDumpvars("+mda");
|
||||
$fsdbDumpvars("+all");
|
||||
$fsdbDumpon();
|
||||
end
|
||||
`endif
|
||||
|
||||
always #20 clk = !clk;
|
||||
|
||||
|
||||
endmodule
|
||||
99
rtl/util/commoncell/src/Queue/dv/StaticPrioritySelector_tb.v
Normal file
99
rtl/util/commoncell/src/Queue/dv/StaticPrioritySelector_tb.v
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
module StaticPrioritySelector_tb;
|
||||
|
||||
// Parameters
|
||||
localparam int unsigned Depth = 8;
|
||||
localparam int unsigned EnqWidth = 2;
|
||||
localparam int unsigned SelWidth = 2;
|
||||
localparam int unsigned PtrWidth = $clog2(Depth);
|
||||
|
||||
// Ports
|
||||
wire [EnqWidth-1:0][Depth-1:0] enq_mask_o;
|
||||
reg [Depth-1:0] sel_mask_i;
|
||||
wire [SelWidth-1:0][Depth-1:0] result_mask_o;
|
||||
reg [Depth-1:0] entry_vld_i;
|
||||
|
||||
int iter = 100000;
|
||||
|
||||
bit [EnqWidth-1:0][Depth-1:0] golden_enq_mask;
|
||||
bit [SelWidth-1:0][Depth-1:0] golden_result_mask;
|
||||
|
||||
int cnt;
|
||||
|
||||
initial begin
|
||||
repeat (iter) begin
|
||||
entry_vld_i = $urandom_range(0, ((1 << Depth) - 1));
|
||||
sel_mask_i = $urandom_range(0, ((1 << Depth) - 1)) & entry_vld_i;
|
||||
#100;
|
||||
for (int i = 0; i < EnqWidth; i++) begin : init_golden_enq_mask
|
||||
golden_enq_mask[i] = 0;
|
||||
end
|
||||
cnt = 0;
|
||||
for (int i = 0; i < Depth; i++) begin : gen_golden_enq_mask
|
||||
if (~entry_vld_i[i]) begin
|
||||
golden_enq_mask[cnt][i] = 1'b1;
|
||||
cnt = cnt + 1;
|
||||
if (cnt == EnqWidth) begin
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
for (int i = 0; i < SelWidth; i++) begin : init_golden_result_mask
|
||||
golden_result_mask[i] = 0;
|
||||
end
|
||||
cnt = 0;
|
||||
for (int i = 0; i < Depth; i++) begin : gen_golden_result_mask
|
||||
if (sel_mask_i[i]) begin
|
||||
golden_result_mask[cnt][i] = 1'b1;
|
||||
cnt = cnt + 1;
|
||||
if (cnt == SelWidth) begin
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
CheckEnqEqual :
|
||||
for (int i = 0; i < EnqWidth; i++) begin
|
||||
assert (golden_enq_mask[i] == enq_mask_o[i])
|
||||
else begin
|
||||
$fatal("\n Masks are not equal, ours[%b] - golden[%b] \n", enq_mask_o[i],
|
||||
golden_enq_mask[i]);
|
||||
end
|
||||
end
|
||||
for (int i = 0; i < SelWidth; i++) begin
|
||||
CheckSelEqual :
|
||||
assert (golden_result_mask[i] == result_mask_o[i])
|
||||
else begin
|
||||
$fatal("\n Masks are not equal, ours[%b] - golden[%b] \n", result_mask_o[i],
|
||||
golden_result_mask[i]);
|
||||
end
|
||||
end
|
||||
end
|
||||
#100;
|
||||
$info("PASS\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
StaticPrioritySelector #(
|
||||
.Depth(Depth),
|
||||
.EnqWidth(EnqWidth),
|
||||
.SelWidth(SelWidth)
|
||||
) StaticPrioritySelector_dut (
|
||||
.enq_mask_o(enq_mask_o),
|
||||
.sel_mask_i(sel_mask_i),
|
||||
.result_mask_o(result_mask_o),
|
||||
.entry_vld_i(entry_vld_i)
|
||||
);
|
||||
|
||||
|
||||
`ifdef DUMPON
|
||||
initial begin : GEN_WAVEFORM
|
||||
$fsdbDumpfile("StaticPrioritySelector_tb.fsdb");
|
||||
$fsdbDumpvars(0, StaticPrioritySelector_tb);
|
||||
$fsdbDumpvars("+mda");
|
||||
$fsdbDumpvars("+all");
|
||||
$fsdbDumpon();
|
||||
end
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
187
rtl/util/commoncell/src/Queue/hw/AgeMatrixSelector.v
Normal file
187
rtl/util/commoncell/src/Queue/hw/AgeMatrixSelector.v
Normal file
@@ -0,0 +1,187 @@
|
||||
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
|
||||
|
||||
|
||||
61
rtl/util/commoncell/src/Queue/hw/FIAO/FIAOWithAgeMatrix.v
Normal file
61
rtl/util/commoncell/src/Queue/hw/FIAO/FIAOWithAgeMatrix.v
Normal file
@@ -0,0 +1,61 @@
|
||||
// module FIAOWithAgeMatrix #(
|
||||
// parameter int unsigned Depth = 8,
|
||||
// parameter int unsigned EnqWidth = 2,
|
||||
// parameter int unsigned SelWidth = 2,
|
||||
// localparam int unsigned PtrWidth = $clog2(Depth)
|
||||
// ) (
|
||||
// // Enqueue Port
|
||||
// input wire [EnqWidth-1:0] enq_fire_i,
|
||||
// input wire [EnqWidth-1:0] enq_eval_i,
|
||||
// output wire [Depth-1:0] enq_mask_o[EnqWidth],
|
||||
// output wire [PtrWidth-1:0] enq_ptr_o[EnqWidth],
|
||||
// // Select Port
|
||||
// input wire [Depth-1:0] sel_mask_i,
|
||||
// output wire [Depth-1:0] result_mask_o[SelWidth],
|
||||
// // Status
|
||||
// input wire [Depth-1:0] entry_vld_i,
|
||||
|
||||
// input wire clk,
|
||||
// input wire rstn
|
||||
// );
|
||||
|
||||
// wire [Depth-1:0] enq_rdy_mask[EnqWidth];
|
||||
|
||||
// generate
|
||||
// for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_rdy_mask
|
||||
// if (i == 0) begin : gen_initial_one
|
||||
// assign enq_rdy_mask[i] = ~entry_vld_i;
|
||||
// end else begin : gen_others
|
||||
// assign enq_rdy_mask[i] = enq_eval_i[i-1] ?
|
||||
// enq_rdy_mask[i-1] : (enq_rdy_mask[i-1] & ~enq_mask_o[i-1]);
|
||||
// end
|
||||
// end
|
||||
// for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_mask
|
||||
// assign enq_mask_o[i] = enq_rdy_mask[i] & ~(enq_rdy_mask[i] - 1'b1);
|
||||
// OH2UInt #(
|
||||
// .InputWidth(Depth)
|
||||
// ) u_OH2UInt (
|
||||
// .oh_i(enq_mask_o[i]),
|
||||
// .result_o(enq_ptr_o[i])
|
||||
// );
|
||||
|
||||
// end
|
||||
// endgenerate
|
||||
|
||||
// AgeMatrixSelector #(
|
||||
// .EntryCount(Depth),
|
||||
// .EnqWidth (EnqWidth),
|
||||
// .SelWidth (SelWidth)
|
||||
// ) u_AgeMatrixSelector (
|
||||
// .enq_fire_i(enq_fire_i),
|
||||
// .enq_mask_i(enq_mask_o),
|
||||
// .sel_mask_i(sel_mask_i),
|
||||
// .result_mask_o(result_mask_o),
|
||||
// .entry_vld_i(entry_vld_i),
|
||||
// .clk(clk),
|
||||
// .rstn(rstn)
|
||||
// );
|
||||
|
||||
|
||||
|
||||
// endmodule
|
||||
126
rtl/util/commoncell/src/Queue/hw/FIAO/FIAOWithQueueManager.v
Normal file
126
rtl/util/commoncell/src/Queue/hw/FIAO/FIAOWithQueueManager.v
Normal file
@@ -0,0 +1,126 @@
|
||||
module FIAOWithQueueManager #(
|
||||
parameter int unsigned Depth = 8,
|
||||
parameter int unsigned EnqWidth = 2,
|
||||
parameter int unsigned DeqWidth = 2,
|
||||
parameter int unsigned SelWidth = 2,
|
||||
localparam int unsigned PtrWidth = $clog2(Depth)
|
||||
) (
|
||||
// Enqueue Port
|
||||
input wire [EnqWidth-1:0] enq_fire_i,
|
||||
input wire [EnqWidth-1:0] enq_eval_i,
|
||||
output wire [EnqWidth-1:0][Depth-1:0] enq_mask_o,
|
||||
output wire [EnqWidth-1:0][PtrWidth-1:0] enq_ptr_o,
|
||||
// Select Port
|
||||
input wire [Depth-1:0] sel_mask_i,
|
||||
output wire [SelWidth-1:0][Depth-1:0] result_mask_o,
|
||||
// Status
|
||||
input wire [Depth-1:0] entry_vld_i,
|
||||
|
||||
input wire clk,
|
||||
input wire rstn
|
||||
);
|
||||
|
||||
localparam int unsigned TagWidth = PtrWidth + 1;
|
||||
|
||||
wire [EnqWidth-1:0][PtrWidth-1:0] enq_ptr;
|
||||
wire [EnqWidth-1:0] enq_flag;
|
||||
wire [EnqWidth-1:0][TagWidth-1:0] enq_tag;
|
||||
wire [DeqWidth-1:0] enq_eval;
|
||||
wire [DeqWidth-1:0] enq_fire;
|
||||
|
||||
wire [DeqWidth-1:0][PtrWidth-1:0] deq_ptr;
|
||||
wire [DeqWidth-1:0] deq_flag;
|
||||
wire [DeqWidth-1:0][TagWidth-1:0] deq_tag;
|
||||
wire [DeqWidth-1:0] deq_eval;
|
||||
wire [DeqWidth-1:0] deq_fire;
|
||||
|
||||
wire first_enq_flag;
|
||||
wire [PtrWidth-1:0] first_enq_ptr;
|
||||
wire first_deq_flag;
|
||||
wire [PtrWidth-1:0] first_deq_ptr;
|
||||
wire flag_equal;
|
||||
wire [Depth-1:0] head_inv_mask;
|
||||
wire [Depth-1:0] tail_inv_mask;
|
||||
wire [Depth-1:0] head_side_sel_mask[SelWidth-1:0];
|
||||
wire [Depth-1:0] tail_side_sel_mask[SelWidth-1:0];
|
||||
wire [Depth-1:0] head_side_sel_result[SelWidth-1:0];
|
||||
wire [Depth-1:0] tail_side_sel_result[SelWidth-1:0];
|
||||
wire [Depth-1:0] selected_mask[SelWidth-1:0];
|
||||
|
||||
// Enqueue Logic
|
||||
assign enq_eval = enq_eval_i;
|
||||
assign enq_fire = enq_fire_i;
|
||||
assign enq_ptr_o = enq_ptr;
|
||||
generate
|
||||
for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_logic
|
||||
assign enq_ptr[i] = enq_tag[i][PtrWidth-1:0];
|
||||
assign enq_flag[i] = enq_tag[i][TagWidth-1];
|
||||
assign enq_mask_o[i] = {{Depth - 1{1'b0}}, 1'b1} << enq_ptr[i];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
// Select Logic
|
||||
assign first_enq_flag = enq_flag[0];
|
||||
assign first_enq_ptr = enq_ptr[0];
|
||||
assign first_deq_flag = deq_flag[0];
|
||||
assign first_deq_ptr = deq_ptr[0];
|
||||
assign flag_equal = ~(first_enq_flag ^ first_deq_flag);
|
||||
|
||||
assign head_inv_mask = (({{PtrWidth - 1{1'b0}}, {1'b1}} << first_deq_ptr) - 1'b1);
|
||||
assign tail_inv_mask = ~(({{PtrWidth - 1{1'b0}}, {1'b1}} << first_enq_ptr) - 1'b1);
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < SelWidth; i++) begin : gen_selected_mask
|
||||
if (i == 0) begin : gen_initial_one
|
||||
assign selected_mask[i] = {Depth{1'b0}};
|
||||
end else begin : gen_others
|
||||
assign selected_mask[i] = selected_mask[i-1] | result_mask_o[i-1];
|
||||
end
|
||||
end
|
||||
for (genvar i = 0; i < SelWidth; i++) begin : gen_side_sel_mask
|
||||
assign head_side_sel_mask[i] = sel_mask_i & ~selected_mask[i] & ~head_inv_mask;
|
||||
assign tail_side_sel_mask[i] = sel_mask_i & ~selected_mask[i] & ~tail_inv_mask;
|
||||
end
|
||||
for (genvar i = 0; i < SelWidth; i++) begin : gen_priority_select_result
|
||||
assign head_side_sel_result[i] = head_side_sel_mask[i] & ~(head_side_sel_mask[i] - 1'b1);
|
||||
assign tail_side_sel_result[i] = tail_side_sel_mask[i] & ~(tail_side_sel_mask[i] - 1'b1);
|
||||
assign result_mask_o[i] = flag_equal ? head_side_sel_result[i] :
|
||||
(|head_side_sel_result[i] ? head_side_sel_result[i] : tail_side_sel_result[i]);
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Dequeue Logic
|
||||
generate
|
||||
for (genvar i = 0; i < DeqWidth; i++) begin : gen_deq_logic
|
||||
assign deq_ptr[i] = deq_tag[i][PtrWidth-1:0];
|
||||
assign deq_flag[i] = deq_tag[i][TagWidth-1];
|
||||
assign deq_eval[i] = 1'b1;
|
||||
assign deq_fire[i] = ~entry_vld_i[deq_tag[i]];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
QueueManager #(
|
||||
.Depth(Depth),
|
||||
.EnqWidth(EnqWidth),
|
||||
.DeqWidth(DeqWidth),
|
||||
.FlagEnable(1),
|
||||
.EnqCollapse(1),
|
||||
.DeqCollapse(0),
|
||||
.InitFull(0)
|
||||
) u_QueueManager (
|
||||
.enq_fire_i(enq_fire),
|
||||
.enq_eval_i(enq_eval),
|
||||
.enq_tag_o(enq_tag),
|
||||
.deq_fire_i(deq_fire),
|
||||
.deq_eval_i(deq_eval),
|
||||
.deq_tag_o(deq_tag),
|
||||
.flush_i(1'b0),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
124
rtl/util/commoncell/src/Queue/hw/FIFO/MultiPortStreamFIFO.v
Normal file
124
rtl/util/commoncell/src/Queue/hw/FIFO/MultiPortStreamFIFO.v
Normal file
@@ -0,0 +1,124 @@
|
||||
module MultiPortStreamFIFO #(
|
||||
parameter int unsigned Depth = 8,
|
||||
parameter int unsigned DataWidth = 32,
|
||||
parameter int unsigned EnqWidth = 2,
|
||||
parameter int unsigned DeqWidth = 2,
|
||||
parameter int unsigned TakenAll = 0
|
||||
) (
|
||||
input wire [EnqWidth-1:0] enq_vld_i,
|
||||
input wire [EnqWidth-1:0][DataWidth-1:0] enq_payload_i,
|
||||
output wire [EnqWidth-1:0] enq_rdy_o,
|
||||
output wire [DeqWidth-1:0] deq_vld_o,
|
||||
output wire [DeqWidth-1:0][DataWidth-1:0] deq_payload_o,
|
||||
input wire [DeqWidth-1:0] deq_rdy_i,
|
||||
input wire flush_i,
|
||||
input wire clk,
|
||||
input wire rstn
|
||||
);
|
||||
|
||||
localparam int unsigned PtrWidth = $clog2(Depth);
|
||||
|
||||
reg [Depth-1:0] payload_clk_en;
|
||||
reg [Depth-1:0] vld_dff_d, vld_dff_q;
|
||||
reg [Depth-1:0][DataWidth-1:0] payload_dff_d, payload_dff_q;
|
||||
|
||||
wire [EnqWidth-1:0][PtrWidth-1:0] enq_ptr;
|
||||
wire [DeqWidth-1:0][PtrWidth-1:0] deq_ptr;
|
||||
|
||||
wire [EnqWidth-1:0] enq_rdy;
|
||||
wire [EnqWidth-1:0] enq_fire;
|
||||
wire [DeqWidth-1:0] deq_fire;
|
||||
|
||||
assign enq_fire = enq_vld_i & enq_rdy_o;
|
||||
assign deq_fire = deq_vld_o & deq_rdy_i;
|
||||
|
||||
always @(*) begin : vld_dff_update_logic
|
||||
vld_dff_d = vld_dff_q;
|
||||
for (int i = 0; i < EnqWidth; i++) begin
|
||||
if (enq_fire[i]) begin
|
||||
vld_dff_d[enq_ptr[i]] = 1'b1;
|
||||
end
|
||||
end
|
||||
for (int i = 0; i < DeqWidth; i++) begin
|
||||
if (deq_fire[i]) begin
|
||||
vld_dff_d[deq_ptr[i]] = 1'b0;
|
||||
end
|
||||
end
|
||||
if (flush_i) begin
|
||||
vld_dff_d = {Depth{1'b0}};
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin : payload_update_logic
|
||||
for (int i = 0; i < Depth; i++) begin : payload_init
|
||||
payload_clk_en[i] = 1'b0;
|
||||
payload_dff_d[i] = payload_dff_q[i];
|
||||
end
|
||||
for (int i = 0; i < EnqWidth; i++) begin : enq_update
|
||||
if (enq_fire[i] & ~flush_i) begin
|
||||
payload_clk_en[enq_ptr[i]] = 1'b1;
|
||||
payload_dff_d[enq_ptr[i]] = enq_payload_i[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
if (TakenAll) begin : gen_rdy_if_need_taken_all
|
||||
assign enq_rdy_o = {EnqWidth{&enq_rdy}};
|
||||
end else begin : gen_normal_rdy
|
||||
assign enq_rdy_o = enq_rdy;
|
||||
end
|
||||
for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_rdy_logic
|
||||
assign enq_rdy[i] = ~vld_dff_q[enq_ptr[i]];
|
||||
end
|
||||
for (genvar i = 0; i < DeqWidth; i++) begin : gen_deq_logic
|
||||
assign deq_vld_o[i] = vld_dff_q[deq_ptr[i]];
|
||||
assign deq_payload_o[i] = payload_dff_q[deq_ptr[i]];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
DFFR #(
|
||||
.Width(Depth)
|
||||
) u_vld_dff (
|
||||
.CLK(clk),
|
||||
.RSTN(rstn),
|
||||
.DRST({Depth{1'b0}}),
|
||||
.D(vld_dff_d),
|
||||
.Q(vld_dff_q)
|
||||
);
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < Depth; i++) begin : gen_payload_dff
|
||||
DFFE #(
|
||||
.Width(DataWidth)
|
||||
) u_payload_dff (
|
||||
.CLK(clk),
|
||||
.EN (payload_clk_en[i]),
|
||||
.D (payload_dff_d[i]),
|
||||
.Q (payload_dff_q[i])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
QueueManager #(
|
||||
.Depth(Depth),
|
||||
.EnqWidth(EnqWidth),
|
||||
.DeqWidth(DeqWidth),
|
||||
.FlagEnable(0),
|
||||
.EnqCollapse(1),
|
||||
.DeqCollapse(0),
|
||||
.InitFull(0)
|
||||
) u_QueueManager (
|
||||
.enq_fire_i(enq_fire),
|
||||
.enq_eval_i(enq_vld_i),
|
||||
.enq_tag_o(enq_ptr),
|
||||
.deq_fire_i(deq_fire),
|
||||
.deq_eval_i(deq_vld_o),
|
||||
.deq_tag_o(deq_ptr),
|
||||
.flush_i(flush_i),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
|
||||
endmodule
|
||||
206
rtl/util/commoncell/src/Queue/hw/QueueManager.v
Normal file
206
rtl/util/commoncell/src/Queue/hw/QueueManager.v
Normal file
@@ -0,0 +1,206 @@
|
||||
module QueueManager #(
|
||||
parameter int unsigned Depth = 8,
|
||||
parameter int unsigned EnqWidth = 2,
|
||||
parameter int unsigned DeqWidth = 2,
|
||||
parameter bit FlagEnable = 0,
|
||||
parameter bit EnqCollapse = 0,
|
||||
parameter bit DeqCollapse = 0,
|
||||
parameter bit InitFull = 0,
|
||||
localparam int unsigned PtrWidth = $clog2(Depth),
|
||||
localparam int unsigned CntWidth = $clog2(Depth + 1),
|
||||
localparam int unsigned TagWidth = PtrWidth + FlagEnable
|
||||
) (
|
||||
input wire [EnqWidth-1:0] enq_fire_i,
|
||||
input wire [EnqWidth-1:0] enq_eval_i,
|
||||
output wire [EnqWidth-1:0][TagWidth-1:0] enq_tag_o,
|
||||
input wire [DeqWidth-1:0] deq_fire_i,
|
||||
input wire [DeqWidth-1:0] deq_eval_i,
|
||||
output wire [DeqWidth-1:0][TagWidth-1:0] deq_tag_o,
|
||||
input wire flush_i,
|
||||
input wire clk,
|
||||
input wire rstn
|
||||
);
|
||||
|
||||
localparam int unsigned EnqCountWidth = $clog2(EnqWidth + 1);
|
||||
localparam int unsigned DeqCountWidth = $clog2(DeqWidth + 1);
|
||||
|
||||
function automatic [TagWidth-1:0] tagPlusOne;
|
||||
input [TagWidth-1:0] originalTag;
|
||||
begin
|
||||
if (FlagEnable) begin
|
||||
if (originalTag[PtrWidth-1:0] == Depth - 1) begin
|
||||
tagPlusOne = {~originalTag[TagWidth-1], {PtrWidth{1'b0}}};
|
||||
end else begin
|
||||
tagPlusOne = originalTag + 1'b1;
|
||||
end
|
||||
end else begin
|
||||
if (originalTag[PtrWidth-1:0] == Depth - 1) begin
|
||||
tagPlusOne = {PtrWidth{1'b0}};
|
||||
end else begin
|
||||
tagPlusOne = originalTag + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function automatic [TagWidth-1:0] tagPlus;
|
||||
input [TagWidth-1:0] originalTag;
|
||||
input [PtrWidth-1:0] delta;
|
||||
reg [PtrWidth:0] sum;
|
||||
reg [PtrWidth:0] reverse_sum;
|
||||
begin
|
||||
if (2 ** $clog2(Depth) == Depth) begin
|
||||
tagPlus = originalTag + delta;
|
||||
end else begin
|
||||
sum = $unsigned({1'b0, originalTag[PtrWidth-1:0]}) + $unsigned({{1'b0}, delta});
|
||||
reverse_sum = $signed(sum) - $unsigned(Depth);
|
||||
if ($signed(reverse_sum) >= 0) begin
|
||||
if (FlagEnable) begin
|
||||
tagPlus = {~originalTag[TagWidth-1], reverse_sum[PtrWidth-1:0]};
|
||||
end else begin
|
||||
tagPlus = reverse_sum[PtrWidth-1:0];
|
||||
end
|
||||
end else begin
|
||||
if (FlagEnable) begin
|
||||
tagPlus = {originalTag[TagWidth-1], sum[PtrWidth-1:0]};
|
||||
end else begin
|
||||
tagPlus = sum[PtrWidth-1:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
wire enq_tag_clk_en;
|
||||
wire [EnqWidth-1:0] enq_rdy_mask, enq_collapse_rdy_mask;
|
||||
wire [EnqCountWidth-1:0] enq_cnt;
|
||||
wire [PtrWidth-1:0] enq_delta;
|
||||
reg [TagWidth-1:0] enq_tag_d, enq_tag_q;
|
||||
|
||||
wire deq_tag_clk_en;
|
||||
wire [DeqCountWidth-1:0] deq_cnt;
|
||||
wire [PtrWidth-1:0] deq_delta;
|
||||
reg [TagWidth-1:0] deq_tag_d, deq_tag_q;
|
||||
|
||||
assign enq_tag_clk_en = (|enq_fire_i);
|
||||
assign deq_tag_clk_en = (|deq_fire_i);
|
||||
|
||||
assign enq_delta = {{PtrWidth - EnqCountWidth{1'b0}}, enq_cnt};
|
||||
assign deq_delta = {{PtrWidth - DeqCountWidth{1'b0}}, deq_cnt};
|
||||
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_ptr
|
||||
if (i == 0) begin : gen_first_enq_ptr
|
||||
assign enq_tag_o[i] = enq_tag_q;
|
||||
end else begin : gen_next_enq_ptr
|
||||
assign enq_tag_o[i] = (EnqCollapse & ~enq_eval_i[i-1]) ? enq_tag_o[i-1] : tagPlusOne(
|
||||
enq_tag_o[i-1]
|
||||
);
|
||||
end
|
||||
end
|
||||
for (genvar i = 0; i < DeqWidth; i++) begin : gen_deq_ptr
|
||||
if (i == 0) begin : gen_first_deq_ptr
|
||||
assign deq_tag_o[i] = deq_tag_q;
|
||||
end else begin : gen_next_deq_ptr
|
||||
assign deq_tag_o[i] = (DeqCollapse & ~deq_eval_i[i-1]) ? deq_tag_o[i-1] : tagPlusOne(
|
||||
deq_tag_o[i-1]
|
||||
);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @(*) begin : enq_tag_update_logic
|
||||
enq_tag_d = enq_tag_q;
|
||||
if (enq_tag_clk_en) begin
|
||||
enq_tag_d = tagPlus(enq_tag_q, enq_delta);
|
||||
end
|
||||
if (flush_i) begin
|
||||
if (InitFull & FlagEnable) begin
|
||||
enq_tag_d = {~deq_tag_q[TagWidth-1], deq_tag_q[PtrWidth-1:0]};
|
||||
end else begin
|
||||
enq_tag_d = deq_tag_q;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin : deq_tag_update_logic
|
||||
deq_tag_d = deq_tag_q;
|
||||
if (deq_tag_clk_en) begin
|
||||
deq_tag_d = tagPlus(deq_tag_q, deq_delta);
|
||||
end
|
||||
if (flush_i) begin
|
||||
deq_tag_d = deq_tag_q;
|
||||
end
|
||||
end
|
||||
|
||||
CountOne #(
|
||||
.InputWidth(EnqWidth)
|
||||
) u_enqCounter (
|
||||
.bits_i(enq_fire_i),
|
||||
.cnt_o (enq_cnt)
|
||||
);
|
||||
CountOne #(
|
||||
.InputWidth(DeqWidth)
|
||||
) u_deqCounter (
|
||||
.bits_i(deq_fire_i),
|
||||
.cnt_o (deq_cnt)
|
||||
);
|
||||
|
||||
DFFRE #(
|
||||
.Width(TagWidth)
|
||||
) u_enq_tag_dff (
|
||||
.CLK(clk),
|
||||
.RSTN(rstn),
|
||||
.EN(enq_tag_clk_en | flush_i),
|
||||
.DRST({(InitFull & FlagEnable), {TagWidth - 1{1'b0}}}),
|
||||
.D(enq_tag_d),
|
||||
.Q(enq_tag_q)
|
||||
);
|
||||
|
||||
DFFRE #(
|
||||
.Width(TagWidth)
|
||||
) u_deq_tag_dff (
|
||||
.CLK(clk),
|
||||
.RSTN(rstn),
|
||||
.EN(deq_tag_clk_en | flush_i),
|
||||
.DRST({TagWidth{1'b0}}),
|
||||
.D(deq_tag_d),
|
||||
.Q(deq_tag_q)
|
||||
);
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
default disable iff (~rstn);
|
||||
|
||||
int unsigned usage = 0;
|
||||
always @(posedge clk) begin : gen_usage
|
||||
if (~rstn) begin
|
||||
usage = 0;
|
||||
end else begin
|
||||
if (flush_i) begin
|
||||
usage = 0;
|
||||
end else if (enq_tag_clk_en & deq_tag_clk_en) begin
|
||||
usage = usage + enq_cnt - deq_cnt;
|
||||
end else if (enq_tag_clk_en) begin
|
||||
usage = usage + enq_cnt;
|
||||
end else if (deq_tag_clk_en) begin
|
||||
usage = usage - deq_cnt;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CHECK_ENQ_WHEN_FULL :
|
||||
assert property (@(posedge clk) enq_tag_clk_en |-> (Depth - usage >= enq_cnt))
|
||||
else begin
|
||||
$fatal("\n Error : Enqueue count[%d] > Availible count[%d]\n", enq_cnt, Depth - usage);
|
||||
end
|
||||
|
||||
CHECK_DEQ_WHEN_EMPTY :
|
||||
assert property (@(posedge clk) deq_tag_clk_en |-> (usage >= deq_cnt))
|
||||
else begin
|
||||
$fatal("\n Error : Dequeue count[%d] > Availible count[%d]\n", deq_cnt, usage);
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
52
rtl/util/commoncell/src/Queue/hw/StaticPrioritySelector.v
Normal file
52
rtl/util/commoncell/src/Queue/hw/StaticPrioritySelector.v
Normal file
@@ -0,0 +1,52 @@
|
||||
module StaticPrioritySelector #(
|
||||
parameter int unsigned Depth = 8,
|
||||
parameter int unsigned EnqWidth = 2,
|
||||
parameter int unsigned SelWidth = 2
|
||||
) (
|
||||
// Enqueue Port
|
||||
output wire [EnqWidth-1:0][Depth-1:0] enq_mask_o,
|
||||
// Select Port
|
||||
input wire [Depth-1:0] sel_mask_i,
|
||||
output wire [SelWidth-1:0][Depth-1:0] result_mask_o,
|
||||
// Status
|
||||
input wire [Depth-1:0] entry_vld_i
|
||||
);
|
||||
|
||||
|
||||
wire [EnqWidth-1:0][Depth-1:0] enq_allocated_mask;
|
||||
wire [EnqWidth-1:0][Depth-1:0] masked_enq_rdy;
|
||||
|
||||
wire [SelWidth-1:0][Depth-1:0] selected_mask;
|
||||
wire [SelWidth-1:0][Depth-1:0] masked_sel_mask;
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_allocated_mask
|
||||
if (i == 0) begin : gen_initial_one
|
||||
assign enq_allocated_mask[i] = {Depth{1'b0}};
|
||||
end else begin : gen_others
|
||||
assign enq_allocated_mask[i] = enq_allocated_mask[i-1] | enq_mask_o[i-1];
|
||||
end
|
||||
assign masked_enq_rdy[i] = ~enq_allocated_mask[i] & ~entry_vld_i;
|
||||
end
|
||||
for (genvar i = 0; i < EnqWidth; i++) begin : gen_enq_mask
|
||||
assign enq_mask_o[i] = masked_enq_rdy[i] & ~(masked_enq_rdy[i] - 1);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < SelWidth; i++) begin : gen_masked_sel_mask
|
||||
if (i == 0) begin : gen_initial_one
|
||||
assign selected_mask[i] = {Depth{1'b0}};
|
||||
end else begin : gen_others
|
||||
assign selected_mask[i] = selected_mask[i-1] | result_mask_o[i-1];
|
||||
end
|
||||
assign masked_sel_mask[i] = ~selected_mask[i] & sel_mask_i;
|
||||
end
|
||||
for (genvar i = 0; i < SelWidth; i++) begin : gen_sel_result
|
||||
assign result_mask_o[i] = masked_sel_mask[i] & ~(masked_sel_mask[i] - 1);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user