initial commit for open source NoC IP
This commit is contained in:
67
rtl/util/commoncell/src/Basic/Basic.yaml
Normal file
67
rtl/util/commoncell/src/Basic/Basic.yaml
Normal file
@@ -0,0 +1,67 @@
|
||||
Name: Basic
|
||||
Dependency:
|
||||
- ../StdDFF/StdDFF.yaml
|
||||
Module:
|
||||
- name: CountOne
|
||||
description: CountOne
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/CountOne.v
|
||||
sim:
|
||||
- dv/CountOne_tb.v
|
||||
|
||||
- name: MuxOH
|
||||
description: One-hot Mux
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/MuxOH.v
|
||||
sim:
|
||||
- dv/MuxOH_tb.v
|
||||
|
||||
- name: OH2UInt
|
||||
description: One-hot to UInt
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/OH2UInt.v
|
||||
dependency:
|
||||
- CountOne
|
||||
|
||||
- name: PriorityMux
|
||||
description: Priority Mux
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/PriorityMux.v
|
||||
dependency:
|
||||
- MuxOH
|
||||
|
||||
- name: SyncFIFO
|
||||
description: Sync FIFO
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/SyncFIFO.v
|
||||
sim:
|
||||
- dv/SyncFIFO_tb.v
|
||||
dependency:
|
||||
- StdDFF
|
||||
|
||||
- name: StreamFIFO
|
||||
description: StreamFIFO
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/StreamFIFO.v
|
||||
sim:
|
||||
- dv/StreamFIFO_tb.v
|
||||
dependency:
|
||||
- SyncFIFO
|
||||
|
||||
- name: PLRU
|
||||
description: PLRU
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/PLRUTree.v
|
||||
- hw/PLRU.v
|
||||
sim:
|
||||
- dv/PLRU_tb.v
|
||||
dependency:
|
||||
- StdDFF
|
||||
|
||||
59
rtl/util/commoncell/src/Basic/dv/CountOne_tb.v
Normal file
59
rtl/util/commoncell/src/Basic/dv/CountOne_tb.v
Normal file
@@ -0,0 +1,59 @@
|
||||
module CountOne_tb;
|
||||
|
||||
// Parameters
|
||||
localparam int unsigned InputWidth = 8;
|
||||
localparam int unsigned CountWidth = $clog2(InputWidth + 1);
|
||||
|
||||
// Ports
|
||||
reg [InputWidth-1:0] bits_i;
|
||||
wire [CountWidth-1:0] cnt_o;
|
||||
|
||||
CountOne #(
|
||||
.InputWidth(InputWidth)
|
||||
) u_CountOne (
|
||||
.bits_i(bits_i),
|
||||
.cnt_o (cnt_o)
|
||||
);
|
||||
|
||||
function automatic [CountWidth-1:0] GlodenModel;
|
||||
input bit [InputWidth-1:0] in;
|
||||
bit [CountWidth-1:0] sum;
|
||||
begin
|
||||
sum = 0;
|
||||
for (int i = 0; i < InputWidth; i++) begin
|
||||
sum = sum + in[i];
|
||||
end
|
||||
GlodenModel = sum;
|
||||
end
|
||||
endfunction
|
||||
|
||||
`ifdef DUMPON
|
||||
initial begin : GEN_WAVEFORM
|
||||
$fsdbDumpfile("CountOne_tb.fsdb");
|
||||
$fsdbDumpvars(0, CountOne_tb);
|
||||
$fsdbDumpvars("+mda");
|
||||
$fsdbDumpvars("+all");
|
||||
$fsdbDumpon();
|
||||
end
|
||||
`endif
|
||||
|
||||
initial begin : RANDOM_TEST
|
||||
begin
|
||||
repeat (10000) begin : GEN_CASE
|
||||
bits_i = $urandom_range(0, InputWidth - 1);
|
||||
#100;
|
||||
NOT_EQUAL :
|
||||
assert (cnt_o == GlodenModel(bits_i))
|
||||
else begin
|
||||
$error("Input[%b], Output[%d], Gloden[%d]\n", bits_i, cnt_o, GlodenModel(bits_i));
|
||||
break;
|
||||
end
|
||||
end
|
||||
#100;
|
||||
$fatal("PASS\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
66
rtl/util/commoncell/src/Basic/dv/MuxOH_tb.v
Normal file
66
rtl/util/commoncell/src/Basic/dv/MuxOH_tb.v
Normal file
@@ -0,0 +1,66 @@
|
||||
module MuxOH_tb;
|
||||
|
||||
// Parameters
|
||||
localparam int unsigned InputWidth = 8;
|
||||
localparam int unsigned DataWidth = 8;
|
||||
|
||||
// Ports
|
||||
reg [InputWidth-1:0] sel_i;
|
||||
reg [InputWidth-1:0][DataWidth-1:0] data_i;
|
||||
wire [DataWidth-1:0] data_o;
|
||||
|
||||
MuxOH #(
|
||||
.InputWidth(InputWidth),
|
||||
.DataWidth (DataWidth)
|
||||
) u_MuxOH (
|
||||
.sel_i (sel_i),
|
||||
.data_i(data_i),
|
||||
.data_o(data_o)
|
||||
);
|
||||
|
||||
function automatic [DataWidth-1:0] GlodenModel;
|
||||
input bit [InputWidth-1:0] sel;
|
||||
input bit [InputWidth-1:0][DataWidth-1:0] data;
|
||||
bit [DataWidth-1:0] result;
|
||||
begin
|
||||
for (int i = 0; i < InputWidth; i++) begin
|
||||
if (sel[i]) begin
|
||||
result = data[i];
|
||||
end
|
||||
end
|
||||
GlodenModel = result;
|
||||
end
|
||||
endfunction
|
||||
|
||||
`ifdef DUMPON
|
||||
initial begin : GEN_WAVEFORM
|
||||
$fsdbDumpfile("MuxOH_tb.fsdb");
|
||||
$fsdbDumpvars(0, MuxOH_tb);
|
||||
$fsdbDumpvars("+mda");
|
||||
$fsdbDumpvars("+all");
|
||||
$fsdbDumpon();
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
initial begin
|
||||
repeat (10000) begin : GEN_CASE
|
||||
sel_i = 1 << $urandom_range(0, InputWidth - 1);
|
||||
for (int i = 0; i < InputWidth; i++) begin
|
||||
data_i[i] = $urandom();
|
||||
end
|
||||
#100;
|
||||
NOT_EQUAL :
|
||||
assert (data_o == GlodenModel(sel_i, data_i))
|
||||
else begin
|
||||
$fatal("Input[%b], Output[%d], Gloden[%d]\n", sel_i, data_o, GlodenModel(sel_i, data_i));
|
||||
break;
|
||||
end
|
||||
end
|
||||
#100;
|
||||
$info("PASS\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
49
rtl/util/commoncell/src/Basic/dv/PLRU_tb.v
Normal file
49
rtl/util/commoncell/src/Basic/dv/PLRU_tb.v
Normal file
@@ -0,0 +1,49 @@
|
||||
module PLRU_tb;
|
||||
|
||||
// Parameters
|
||||
localparam ENTRY_COUNT = 4;
|
||||
|
||||
// Ports
|
||||
reg [ENTRY_COUNT-1:0] access_mask_i;
|
||||
wire [ENTRY_COUNT-1:0] least_used_mask_o;
|
||||
reg clk = 0;
|
||||
reg rstn = 0;
|
||||
|
||||
PLRU #(
|
||||
.ENTRY_COUNT(ENTRY_COUNT)
|
||||
) PLRU_dut (
|
||||
.access_mask_i(access_mask_i),
|
||||
.least_used_mask_o(least_used_mask_o),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
|
||||
initial begin
|
||||
begin
|
||||
#10 rstn = 1'b1;
|
||||
repeat (10000) begin
|
||||
@(negedge clk);
|
||||
if (|access_mask_i) begin
|
||||
$info("\n Access Entry[%d], PLRU Change to [%d]\n", $countones(access_mask_i-1), $countones(
|
||||
least_used_mask_o - 1));
|
||||
end
|
||||
access_mask_i = 1 << $urandom_range(0, ENTRY_COUNT - 1);
|
||||
@(posedge clk);
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef DUMPON
|
||||
initial begin : GEN_WAVEFORM
|
||||
$fsdbDumpfile("PLRU_tb.fsdb");
|
||||
$fsdbDumpvars(0, PLRU_tb);
|
||||
$fsdbDumpvars("+mda");
|
||||
$fsdbDumpvars("+all");
|
||||
$fsdbDumpon();
|
||||
end
|
||||
`endif
|
||||
|
||||
always #20 clk = !clk;
|
||||
|
||||
endmodule
|
||||
83
rtl/util/commoncell/src/Basic/dv/StreamFIFO_tb.v
Normal file
83
rtl/util/commoncell/src/Basic/dv/StreamFIFO_tb.v
Normal file
@@ -0,0 +1,83 @@
|
||||
module StreamFIFO_tb;
|
||||
|
||||
// Parameters
|
||||
localparam int unsigned Depth = 8;
|
||||
localparam int unsigned WordWidth = 64;
|
||||
|
||||
// Ports
|
||||
reg enq_vld_i = 0;
|
||||
reg [WordWidth-1:0] enq_payload_i;
|
||||
wire enq_rdy_o;
|
||||
wire deq_vld_o;
|
||||
wire [WordWidth-1:0] deq_payload_o;
|
||||
reg deq_rdy_i = 0;
|
||||
reg flush_i = 0;
|
||||
reg clk = 0;
|
||||
reg rstn = 0;
|
||||
|
||||
bit [WordWidth-1:0] golden_fifo[$];
|
||||
bit [WordWidth-1:0] random_payload;
|
||||
bit [WordWidth-1:0] golden_fifo_front;
|
||||
|
||||
int iter = 1000000;
|
||||
|
||||
|
||||
initial begin
|
||||
begin
|
||||
#10 rstn = 1'b1;
|
||||
repeat (iter) begin : random_test
|
||||
@(negedge clk);
|
||||
enq_vld_i = 1'b0;
|
||||
deq_rdy_i = 1'b0;
|
||||
if ($urandom_range(0, 1) && deq_vld_o) begin : test_deq
|
||||
deq_rdy_i = 1'b1;
|
||||
golden_fifo_front = golden_fifo.pop_front();
|
||||
CHECK_EQUALATION :
|
||||
assert (deq_payload_o == golden_fifo_front)
|
||||
else begin
|
||||
$fatal("\n Error: Fail when check equalation, ours[%x] -- gloden[%x]", deq_payload_o,
|
||||
golden_fifo_front);
|
||||
end
|
||||
;
|
||||
end
|
||||
if ($urandom_range(0, 1) && enq_rdy_o) begin : test_push
|
||||
random_payload = $urandom();
|
||||
enq_vld_i = 1'b1;
|
||||
enq_payload_i = random_payload;
|
||||
golden_fifo.push_back(random_payload);
|
||||
end
|
||||
end
|
||||
$info("\n PASS after %d iter \n", iter);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
StreamFIFO #(
|
||||
.Depth(Depth),
|
||||
.WordWidth(WordWidth)
|
||||
) StreamFIFO_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("StreamFIFO_tb.fsdb");
|
||||
$fsdbDumpvars(0, StreamFIFO_tb);
|
||||
$fsdbDumpvars("+mda");
|
||||
$fsdbDumpvars("+all");
|
||||
$fsdbDumpon();
|
||||
end
|
||||
`endif
|
||||
|
||||
always #20 clk = !clk;
|
||||
|
||||
endmodule
|
||||
83
rtl/util/commoncell/src/Basic/dv/SyncFIFO_tb.v
Normal file
83
rtl/util/commoncell/src/Basic/dv/SyncFIFO_tb.v
Normal file
@@ -0,0 +1,83 @@
|
||||
module SyncFIFO_tb;
|
||||
|
||||
// Parameters
|
||||
localparam int unsigned Depth = 8;
|
||||
localparam int unsigned WordWidth = 32;
|
||||
|
||||
// Ports
|
||||
reg push_i = 0;
|
||||
reg [WordWidth-1:0] push_payload_i;
|
||||
reg pop_i = 0;
|
||||
wire [WordWidth-1:0] pop_payload_o;
|
||||
wire full_o;
|
||||
wire empty_o;
|
||||
reg flush_i = 0;
|
||||
reg clk = 0;
|
||||
reg rstn = 0;
|
||||
|
||||
bit [WordWidth-1:0] golden_fifo[$];
|
||||
bit [WordWidth-1:0] random_payload;
|
||||
bit [WordWidth-1:0] golden_fifo_front;
|
||||
|
||||
int iter = 1000000;
|
||||
|
||||
initial begin
|
||||
begin
|
||||
#10 rstn = 1'b1;
|
||||
repeat (iter) begin : random_test
|
||||
@(negedge clk);
|
||||
pop_i = 1'b0;
|
||||
push_i = 1'b0;
|
||||
if ($urandom_range(0, 1) && ~empty_o) begin : test_pop
|
||||
pop_i = 1'b1;
|
||||
golden_fifo_front = golden_fifo.pop_front();
|
||||
CHECK_EQUALATION :
|
||||
assert (pop_payload_o == golden_fifo_front)
|
||||
else begin
|
||||
$fatal("\n Error: Fail when check equalation, ours[%x] -- gloden[%x]", pop_payload_o,
|
||||
golden_fifo_front);
|
||||
end
|
||||
;
|
||||
end
|
||||
if ($urandom_range(0, 1) && ~full_o) begin : test_push
|
||||
random_payload = $urandom();
|
||||
push_i = 1'b1;
|
||||
push_payload_i = random_payload;
|
||||
golden_fifo.push_back(random_payload);
|
||||
end
|
||||
end
|
||||
$info("\n PASS after %d iter \n", iter);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
SyncFIFO #(
|
||||
.Depth(Depth),
|
||||
.WordWidth(WordWidth)
|
||||
) SyncFIFO_dut (
|
||||
.push_i(push_i),
|
||||
.push_payload_i(push_payload_i),
|
||||
.pop_i(pop_i),
|
||||
.pop_payload_o(pop_payload_o),
|
||||
.full_o(full_o),
|
||||
.empty_o(empty_o),
|
||||
.flush_i(flush_i),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
|
||||
`ifdef DUMPON
|
||||
initial begin : GEN_WAVEFORM
|
||||
$fsdbDumpfile("SyncFIFO_tb.fsdb");
|
||||
$fsdbDumpvars(0, SyncFIFO_tb);
|
||||
$fsdbDumpvars("+mda");
|
||||
$fsdbDumpvars("+all");
|
||||
$fsdbDumpon();
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
|
||||
always #20 clk = !clk;
|
||||
|
||||
endmodule
|
||||
42
rtl/util/commoncell/src/Basic/hw/CountOne.v
Normal file
42
rtl/util/commoncell/src/Basic/hw/CountOne.v
Normal file
@@ -0,0 +1,42 @@
|
||||
module CountOne #(
|
||||
parameter int unsigned InputWidth = 8,
|
||||
localparam int unsigned CountWidth = $clog2(InputWidth + 1)
|
||||
) (
|
||||
input wire [InputWidth-1:0] bits_i,
|
||||
output wire [CountWidth-1:0] cnt_o
|
||||
);
|
||||
localparam int unsigned PaddedWidth = 1 << $clog2(InputWidth);
|
||||
localparam int unsigned ChildCountWidth = PaddedWidth == 1 ? 1 : $clog2(PaddedWidth);
|
||||
|
||||
wire [ChildCountWidth-1:0] leftChildCount, rightChildCount;
|
||||
|
||||
|
||||
generate
|
||||
if (InputWidth == 1) begin : gen_single_node
|
||||
assign leftChildCount = 1'b0;
|
||||
assign rightChildCount = bits_i;
|
||||
end else if (InputWidth == 2) begin : gen_leaf_node
|
||||
assign leftChildCount = bits_i[0];
|
||||
assign rightChildCount = bits_i[1];
|
||||
end else begin : gen_non_leaf_node
|
||||
wire [PaddedWidth-1:0] paddedBits;
|
||||
// Zero pad the input bits to next power of two
|
||||
assign paddedBits = {{PaddedWidth - InputWidth{1'b0}}, bits_i};
|
||||
CountOne #(
|
||||
.InputWidth(PaddedWidth / 2)
|
||||
) u_leftChild (
|
||||
.bits_i(paddedBits[PaddedWidth-1:PaddedWidth/2]),
|
||||
.cnt_o (leftChildCount)
|
||||
);
|
||||
CountOne #(
|
||||
.InputWidth(PaddedWidth / 2)
|
||||
) u_rightChild (
|
||||
.bits_i(paddedBits[PaddedWidth/2-1:0]),
|
||||
.cnt_o (rightChildCount)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign cnt_o = leftChildCount + rightChildCount;
|
||||
|
||||
endmodule
|
||||
21
rtl/util/commoncell/src/Basic/hw/MuxOH.v
Normal file
21
rtl/util/commoncell/src/Basic/hw/MuxOH.v
Normal file
@@ -0,0 +1,21 @@
|
||||
module MuxOH #(
|
||||
parameter int unsigned InputWidth = 8,
|
||||
parameter int unsigned DataWidth = 8
|
||||
) (
|
||||
input wire [InputWidth-1:0] sel_i,
|
||||
input wire [InputWidth-1:0][DataWidth-1:0] data_i,
|
||||
output wire [DataWidth-1:0] data_o
|
||||
);
|
||||
|
||||
wire [DataWidth-1:0][InputWidth-1:0] dataT;
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < DataWidth; i++) begin : gen_row
|
||||
for (genvar j = 0; j < InputWidth; j++) begin : gen_col
|
||||
assign dataT[i][j] = data_i[j][i];
|
||||
end
|
||||
assign data_o[i] = |(dataT[i] & sel_i);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
25
rtl/util/commoncell/src/Basic/hw/OH2UInt.v
Normal file
25
rtl/util/commoncell/src/Basic/hw/OH2UInt.v
Normal file
@@ -0,0 +1,25 @@
|
||||
module OH2UInt #(
|
||||
parameter int unsigned InputWidth = 8,
|
||||
localparam int unsigned OutputWidth = InputWidth > 1 ? $clog2(InputWidth) : 1
|
||||
) (
|
||||
input wire [ InputWidth-1:0] oh_i,
|
||||
output wire [OutputWidth-1:0] result_o
|
||||
);
|
||||
|
||||
localparam int unsigned CountWidth = $clog2(InputWidth + 1);
|
||||
|
||||
wire [InputWidth-1:0] maskLow;
|
||||
wire [CountWidth-1:0] count;
|
||||
|
||||
|
||||
assign maskLow = oh_i - 1'b1;
|
||||
assign result_o = count[OutputWidth-1:0];
|
||||
|
||||
CountOne #(
|
||||
.InputWidth(InputWidth)
|
||||
) CountOne_dut (
|
||||
.bits_i(maskLow),
|
||||
.cnt_o (count)
|
||||
);
|
||||
|
||||
endmodule
|
||||
48
rtl/util/commoncell/src/Basic/hw/PLRU.v
Normal file
48
rtl/util/commoncell/src/Basic/hw/PLRU.v
Normal file
@@ -0,0 +1,48 @@
|
||||
module PLRU #(
|
||||
parameter ENTRY_COUNT = 4
|
||||
) (
|
||||
input [ENTRY_COUNT-1:0] access_mask_i,
|
||||
output [ENTRY_COUNT-1:0] least_used_mask_o,
|
||||
input clk,
|
||||
input rstn
|
||||
);
|
||||
|
||||
localparam PLRUTreeLvl = $clog2(ENTRY_COUNT);
|
||||
localparam NodeCount = ENTRY_COUNT - 1;
|
||||
|
||||
generate
|
||||
if (ENTRY_COUNT == 1) begin : gen_one_entry_case
|
||||
assign least_used_mask_o = 1'b1;
|
||||
end else begin : gen_normal_case
|
||||
|
||||
wire plru_nodes_clk_en;
|
||||
wire [NodeCount-1:0] plru_nodes_d;
|
||||
reg [NodeCount-1:0] plru_nodes_q;
|
||||
|
||||
assign plru_nodes_clk_en = |access_mask_i;
|
||||
|
||||
DFFRE #(
|
||||
.Width(NodeCount)
|
||||
) u_plru_nodes_DFFRE (
|
||||
.CLK(clk),
|
||||
.RSTN(rstn),
|
||||
.DRST({NodeCount{1'b0}}),
|
||||
.EN(plru_nodes_clk_en),
|
||||
.D(plru_nodes_d),
|
||||
.Q(plru_nodes_q)
|
||||
);
|
||||
PLRUTree #(
|
||||
.TREE_LVL_COUNT(PLRUTreeLvl)
|
||||
) u_PLRUTree (
|
||||
.access_mask_i(access_mask_i),
|
||||
.plru_old_node_i(plru_nodes_q),
|
||||
.plru_new_node_o(plru_nodes_d),
|
||||
.node_en_i(1'b1),
|
||||
.least_used_mask_o(least_used_mask_o),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
64
rtl/util/commoncell/src/Basic/hw/PLRUTree.v
Normal file
64
rtl/util/commoncell/src/Basic/hw/PLRUTree.v
Normal file
@@ -0,0 +1,64 @@
|
||||
module PLRUTree #(
|
||||
parameter TREE_LVL_COUNT = 3,
|
||||
localparam ENTRY_COUNT = (1 << TREE_LVL_COUNT),
|
||||
localparam NODE_COUNT = ENTRY_COUNT - 1
|
||||
) (
|
||||
input [ENTRY_COUNT-1:0] access_mask_i,
|
||||
input [NODE_COUNT-1:0] plru_old_node_i,
|
||||
output [NODE_COUNT-1:0] plru_new_node_o,
|
||||
input node_en_i,
|
||||
output [ENTRY_COUNT-1:0] least_used_mask_o,
|
||||
input clk,
|
||||
input rstn
|
||||
);
|
||||
|
||||
wire node_toggle_en;
|
||||
wire node;
|
||||
|
||||
wire left_child_node_en;
|
||||
wire right_child_node_en;
|
||||
|
||||
wire access_left;
|
||||
wire access_right;
|
||||
|
||||
assign node = plru_old_node_i[0];
|
||||
assign node_toggle_en = (~node & access_left) | (node & access_right);
|
||||
assign plru_new_node_o[0] = node_toggle_en ? ~node : node;
|
||||
|
||||
assign access_left = |access_mask_i[ENTRY_COUNT/2-1:0];
|
||||
assign access_right = |access_mask_i[ENTRY_COUNT-1:ENTRY_COUNT/2];
|
||||
|
||||
assign left_child_node_en = node_en_i & ~node;
|
||||
assign right_child_node_en = node_en_i & node;
|
||||
|
||||
generate
|
||||
if (TREE_LVL_COUNT > 1) begin : gen_child_tree
|
||||
PLRUTree #(
|
||||
.TREE_LVL_COUNT(TREE_LVL_COUNT - 1)
|
||||
) u_left_child_PLRUTree (
|
||||
.access_mask_i(access_mask_i[ENTRY_COUNT/2-1:0]),
|
||||
.plru_old_node_i(plru_old_node_i[(NODE_COUNT-1)/2:1]),
|
||||
.plru_new_node_o(plru_new_node_o[(NODE_COUNT-1)/2:1]),
|
||||
.node_en_i(left_child_node_en),
|
||||
.least_used_mask_o(least_used_mask_o[ENTRY_COUNT/2-1:0]),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
PLRUTree #(
|
||||
.TREE_LVL_COUNT(TREE_LVL_COUNT - 1)
|
||||
) u_right_child_PLRUTree (
|
||||
.access_mask_i(access_mask_i[ENTRY_COUNT-1:ENTRY_COUNT/2]),
|
||||
.plru_old_node_i(plru_old_node_i[NODE_COUNT-1:(NODE_COUNT+1)/2]),
|
||||
.plru_new_node_o(plru_new_node_o[NODE_COUNT-1:(NODE_COUNT+1)/2]),
|
||||
.node_en_i(right_child_node_en),
|
||||
.least_used_mask_o(least_used_mask_o[ENTRY_COUNT-1:ENTRY_COUNT/2]),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
end else begin : gen_leaf
|
||||
assign least_used_mask_o[0] = left_child_node_en;
|
||||
assign least_used_mask_o[1] = right_child_node_en;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
24
rtl/util/commoncell/src/Basic/hw/PriorityMux.v
Normal file
24
rtl/util/commoncell/src/Basic/hw/PriorityMux.v
Normal file
@@ -0,0 +1,24 @@
|
||||
module PriorityMux #(
|
||||
parameter int unsigned InputWidth = 8,
|
||||
parameter int unsigned DataWidth = 8
|
||||
) (
|
||||
input wire [InputWidth-1:0] sel_i,
|
||||
input wire [InputWidth-1:0][DataWidth-1:0] data_i,
|
||||
output wire [DataWidth-1:0] data_o
|
||||
);
|
||||
|
||||
wire [InputWidth-1:0] sel_oh;
|
||||
|
||||
assign sel_oh = sel_i & (~(sel_i - 1));
|
||||
|
||||
MuxOH #(
|
||||
.InputWidth(InputWidth),
|
||||
.DataWidth (DataWidth)
|
||||
) u_MuxOH (
|
||||
.sel_i (sel_oh),
|
||||
.data_i(data_i),
|
||||
.data_o(data_o)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
52
rtl/util/commoncell/src/Basic/hw/StreamFIFO.v
Normal file
52
rtl/util/commoncell/src/Basic/hw/StreamFIFO.v
Normal file
@@ -0,0 +1,52 @@
|
||||
module StreamFIFO #(
|
||||
parameter int unsigned Depth = 8,
|
||||
parameter int unsigned WordWidth = 64
|
||||
) (
|
||||
input wire enq_vld_i,
|
||||
input wire [WordWidth-1:0] enq_payload_i,
|
||||
output wire enq_rdy_o,
|
||||
output wire deq_vld_o,
|
||||
output wire [WordWidth-1:0] deq_payload_o,
|
||||
input wire deq_rdy_i,
|
||||
input wire flush_i,
|
||||
input wire clk,
|
||||
input wire rstn
|
||||
);
|
||||
|
||||
wire push;
|
||||
wire [WordWidth-1:0] push_payload;
|
||||
wire pop;
|
||||
wire [WordWidth-1:0] pop_payload;
|
||||
wire full;
|
||||
wire empty;
|
||||
|
||||
wire enq_fire;
|
||||
wire deq_fire;
|
||||
|
||||
assign enq_rdy_o = ~full;
|
||||
assign enq_fire = enq_vld_i & enq_rdy_o;
|
||||
assign push = enq_fire;
|
||||
assign push_payload = enq_payload_i;
|
||||
|
||||
assign pop = deq_fire;
|
||||
assign deq_vld_o = ~empty;
|
||||
assign deq_fire = deq_vld_o & deq_rdy_i;
|
||||
assign deq_payload_o = pop_payload;
|
||||
|
||||
SyncFIFO #(
|
||||
.Depth(Depth),
|
||||
.WordWidth(WordWidth)
|
||||
) u_SyncFIFO (
|
||||
.push_i(push),
|
||||
.push_payload_i(push_payload),
|
||||
.pop_i(pop),
|
||||
.pop_payload_o(pop_payload),
|
||||
.full_o(full),
|
||||
.empty_o(empty),
|
||||
.flush_i(flush_i),
|
||||
.clk(clk),
|
||||
.rstn(rstn)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
129
rtl/util/commoncell/src/Basic/hw/SyncFIFO.v
Normal file
129
rtl/util/commoncell/src/Basic/hw/SyncFIFO.v
Normal file
@@ -0,0 +1,129 @@
|
||||
module SyncFIFO #(
|
||||
parameter int unsigned Depth = 8,
|
||||
parameter int unsigned WordWidth = 64
|
||||
) (
|
||||
input wire push_i,
|
||||
input wire [WordWidth-1:0] push_payload_i,
|
||||
input wire pop_i,
|
||||
output wire [WordWidth-1:0] pop_payload_o,
|
||||
output wire full_o,
|
||||
output wire empty_o,
|
||||
input wire flush_i,
|
||||
input wire clk,
|
||||
input wire rstn
|
||||
);
|
||||
|
||||
localparam int unsigned PtrWidth = $clog2(Depth);
|
||||
|
||||
wire [Depth-1:0] payload_ram_clk_en;
|
||||
wire [Depth-1:0][WordWidth-1:0] payload_ram_d, payload_ram_q;
|
||||
|
||||
wire head_clk_en;
|
||||
reg head_flag_d, head_flag_q;
|
||||
reg [PtrWidth-1:0] head_ptr_d, head_ptr_q;
|
||||
|
||||
wire tail_clk_en;
|
||||
reg tail_flag_d, tail_flag_q;
|
||||
reg [PtrWidth-1:0] tail_ptr_d, tail_ptr_q;
|
||||
|
||||
wire ptr_equal;
|
||||
wire flag_equal;
|
||||
|
||||
assign head_clk_en = pop_i | flush_i;
|
||||
assign tail_clk_en = push_i | flush_i;
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < Depth; i++) begin : gen_payload_update_logic
|
||||
assign payload_ram_clk_en[i] = (push_i & ~flush_i) & (tail_ptr_q == i);
|
||||
assign payload_ram_d[i] = payload_ram_clk_en[i] ? push_payload_i : payload_ram_q[i];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @(*) begin : tail_update_logic
|
||||
{tail_flag_d, tail_ptr_d} = {tail_flag_q, tail_ptr_q};
|
||||
if (push_i) begin
|
||||
if (tail_ptr_q == Depth - 1) begin
|
||||
{tail_flag_d, tail_ptr_d} = {~tail_flag_q, {PtrWidth{1'b0}}};
|
||||
end else begin
|
||||
tail_ptr_d = tail_ptr_q + 1'b1;
|
||||
end
|
||||
end
|
||||
if (flush_i) begin
|
||||
{tail_flag_d, tail_ptr_d} = {PtrWidth + 1{1'b0}};
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin : head_update_logic
|
||||
{head_flag_d, head_ptr_d} = {head_flag_q, head_ptr_q};
|
||||
if (pop_i) begin
|
||||
if (head_ptr_q == Depth - 1) begin
|
||||
{head_flag_d, head_ptr_d} = {~head_flag_q, {PtrWidth{1'b0}}};
|
||||
end else begin
|
||||
head_ptr_d = head_ptr_q + 1'b1;
|
||||
end
|
||||
end
|
||||
if (flush_i) begin
|
||||
{head_flag_d, head_ptr_d} = {PtrWidth + 1{1'b0}};
|
||||
end
|
||||
end
|
||||
|
||||
assign flag_equal = head_flag_q == tail_flag_q;
|
||||
assign ptr_equal = head_ptr_q == tail_ptr_q;
|
||||
|
||||
assign full_o = (~flag_equal & ptr_equal & ~pop_i);
|
||||
assign empty_o = flag_equal & ptr_equal;
|
||||
assign pop_payload_o = payload_ram_q[head_ptr_q];
|
||||
|
||||
DFFRE #(
|
||||
.Width(PtrWidth + 1)
|
||||
) u_head_dff (
|
||||
.CLK(clk),
|
||||
.RSTN(rstn),
|
||||
.EN(head_clk_en),
|
||||
.DRST({PtrWidth + 1{1'b0}}),
|
||||
.D({head_flag_d, head_ptr_d}),
|
||||
.Q({head_flag_q, head_ptr_q})
|
||||
);
|
||||
|
||||
DFFRE #(
|
||||
.Width(PtrWidth + 1)
|
||||
) u_tail_dff (
|
||||
.CLK(clk),
|
||||
.RSTN(rstn),
|
||||
.EN(tail_clk_en),
|
||||
.DRST({PtrWidth + 1{1'b0}}),
|
||||
.D({tail_flag_d, tail_ptr_d}),
|
||||
.Q({tail_flag_q, tail_ptr_q})
|
||||
);
|
||||
|
||||
generate
|
||||
for (genvar i = 0; i < Depth; i++) begin : gen_payload_dff
|
||||
DFFE #(
|
||||
.Width(WordWidth)
|
||||
) u_payload_dff (
|
||||
.CLK(clk),
|
||||
.EN (payload_ram_clk_en[i]),
|
||||
.D (payload_ram_d[i]),
|
||||
.Q (payload_ram_q[i])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
|
||||
default disable iff (~rstn); CHECK_POP_WHEN_EMPTY :
|
||||
assert property (@(posedge clk) pop_i |-> ~empty_o)
|
||||
else begin
|
||||
$error("Pop when empty\n");
|
||||
end
|
||||
|
||||
CHECK_PUSH_WHEN_FULL :
|
||||
assert property (@(posedge clk) push_i |-> ~full_o)
|
||||
else begin
|
||||
$error("Push when full\n");
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
||||
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
|
||||
39
rtl/util/commoncell/src/StdDFF/StdDFF.yaml
Normal file
39
rtl/util/commoncell/src/StdDFF/StdDFF.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
Name : StdDFF
|
||||
Module:
|
||||
- name: DFFUncertainChecker
|
||||
description: DFF uncertain checker
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- dv/DFFUncertainChecker.v
|
||||
|
||||
- name: DFF
|
||||
description: Standard DFF
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/DFF.v
|
||||
dependency:
|
||||
- DFFUncertainChecker
|
||||
|
||||
- name: DFFE
|
||||
description: Standard DFF with EN port
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/DFFE.v
|
||||
dependency:
|
||||
- DFFUncertainChecker
|
||||
|
||||
- name: DFFR
|
||||
description: Standard DFF with RST port
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/DFFR.v
|
||||
dependency:
|
||||
- DFFUncertainChecker
|
||||
|
||||
- name: DFFRE
|
||||
description: Standard DFF with EN and RST port
|
||||
language: SystemVerilog
|
||||
rtl:
|
||||
- hw/DFFRE.v
|
||||
dependency:
|
||||
- DFFUncertainChecker
|
||||
17
rtl/util/commoncell/src/StdDFF/dv/DFFUncertainChecker.v
Normal file
17
rtl/util/commoncell/src/StdDFF/dv/DFFUncertainChecker.v
Normal file
@@ -0,0 +1,17 @@
|
||||
module DFFUncertainChecker #(
|
||||
parameter int unsigned Width = 8
|
||||
) (
|
||||
input wire CLK,
|
||||
input wire EN,
|
||||
input reg [Width-1:0] Q
|
||||
);
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
CHECK_UNCERTAIN :
|
||||
assert property (@(posedge CLK) EN |=> (|Q !== 1'bx))
|
||||
else begin
|
||||
$fatal("\n Error : detected a X value which should never happen!\n");
|
||||
end
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
25
rtl/util/commoncell/src/StdDFF/hw/DFF.v
Normal file
25
rtl/util/commoncell/src/StdDFF/hw/DFF.v
Normal file
@@ -0,0 +1,25 @@
|
||||
module DFF #(
|
||||
parameter int unsigned Width = 8
|
||||
) (
|
||||
input wire CLK,
|
||||
input wire [Width-1:0] D,
|
||||
output reg [Width-1:0] Q
|
||||
);
|
||||
|
||||
always @(posedge CLK) begin : dff
|
||||
Q <= D;
|
||||
end
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
|
||||
DFFUncertainChecker #(
|
||||
.Width(Width)
|
||||
) u_DFFUncertainChecker (
|
||||
.CLK(CLK),
|
||||
.EN (1'b1),
|
||||
.Q (Q)
|
||||
);
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
28
rtl/util/commoncell/src/StdDFF/hw/DFFE.v
Normal file
28
rtl/util/commoncell/src/StdDFF/hw/DFFE.v
Normal file
@@ -0,0 +1,28 @@
|
||||
module DFFE #(
|
||||
parameter int unsigned Width = 8
|
||||
) (
|
||||
input wire CLK,
|
||||
input wire EN,
|
||||
input wire [Width-1:0] D,
|
||||
output reg [Width-1:0] Q
|
||||
);
|
||||
|
||||
always @(posedge CLK) begin : dff
|
||||
if (EN) begin
|
||||
Q <= D;
|
||||
end
|
||||
end
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
|
||||
DFFUncertainChecker #(
|
||||
.Width(Width)
|
||||
) u_DFFUncertainChecker (
|
||||
.CLK(CLK),
|
||||
.EN (EN),
|
||||
.Q (Q)
|
||||
);
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
31
rtl/util/commoncell/src/StdDFF/hw/DFFR.v
Normal file
31
rtl/util/commoncell/src/StdDFF/hw/DFFR.v
Normal file
@@ -0,0 +1,31 @@
|
||||
module DFFR #(
|
||||
parameter int unsigned Width = 8
|
||||
) (
|
||||
input wire CLK,
|
||||
input wire RSTN,
|
||||
input wire [Width-1:0] DRST,
|
||||
input wire [Width-1:0] D,
|
||||
output reg [Width-1:0] Q
|
||||
);
|
||||
|
||||
always @(posedge CLK or negedge RSTN) begin : dff
|
||||
if (~RSTN) begin
|
||||
Q <= DRST;
|
||||
end else begin
|
||||
Q <= D;
|
||||
end
|
||||
end
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
|
||||
DFFUncertainChecker #(
|
||||
.Width(Width)
|
||||
) u_DFFUncertainChecker (
|
||||
.CLK(CLK),
|
||||
.EN (1'b1),
|
||||
.Q (Q)
|
||||
);
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
35
rtl/util/commoncell/src/StdDFF/hw/DFFRE.v
Normal file
35
rtl/util/commoncell/src/StdDFF/hw/DFFRE.v
Normal file
@@ -0,0 +1,35 @@
|
||||
module DFFRE #(
|
||||
parameter int unsigned Width = 8
|
||||
) (
|
||||
input wire CLK,
|
||||
input wire RSTN,
|
||||
input wire EN,
|
||||
input wire [Width-1:0] DRST,
|
||||
input wire [Width-1:0] D,
|
||||
output reg [Width-1:0] Q
|
||||
);
|
||||
|
||||
always @(posedge CLK or negedge RSTN) begin : dff
|
||||
if (~RSTN) begin
|
||||
Q <= DRST;
|
||||
end else begin
|
||||
if (EN) begin
|
||||
Q <= D;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
|
||||
DFFUncertainChecker #(
|
||||
.Width(Width)
|
||||
) u_DFFUncertainChecker (
|
||||
.CLK(CLK),
|
||||
.EN (EN),
|
||||
.Q (Q)
|
||||
);
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user