Skip to content

Commit a534f04

Browse files
committed
axi_demux_id_counters: Split to own module and add any_outstanding_trx_o port
1 parent 814b000 commit a534f04

File tree

3 files changed

+147
-123
lines changed

3 files changed

+147
-123
lines changed

Bender.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ sources:
3333
# Level 0
3434
- src/axi_pkg.sv
3535
# Level 1
36+
- src/axi_demux_id_counters.sv
3637
- src/axi_intf.sv
3738
# Level 2
3839
- src/axi_atop_filter.sv

src/axi_demux_id_counters.sv

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright (c) 2019 ETH Zurich and University of Bologna.
2+
// Copyright and related rights are licensed under the Solderpad Hardware
3+
// License, Version 0.51 (the "License"); you may not use this file except in
4+
// compliance with the License. You may obtain a copy of the License at
5+
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6+
// or agreed to in writing, software, hardware and materials distributed under
7+
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
// specific language governing permissions and limitations under the License.
10+
//
11+
// Authors:
12+
// - Wolfgang Roenninger <wroennin@iis.ee.ethz.ch>
13+
// - Michael Rogenmoser <michaero@iis.ee.ethz.ch>
14+
// - Thomas Benz <tbenz@iis.ee.ethz.ch>
15+
// - Andreas Kurth <akurth@iis.ee.ethz.ch>
16+
17+
`include "common_cells/registers.svh"
18+
19+
module axi_demux_id_counters #(
20+
// the lower bits of the AXI ID that should be considered, results in 2**AXI_ID_BITS counters
21+
parameter int unsigned AxiIdBits = 2,
22+
parameter int unsigned CounterWidth = 4,
23+
parameter type mst_port_select_t = logic
24+
) (
25+
input logic clk_i, // Clock
26+
input logic rst_ni, // Asynchronous reset active low
27+
// lookup
28+
input logic [AxiIdBits-1:0] lookup_axi_id_i,
29+
output mst_port_select_t lookup_mst_select_o,
30+
output logic lookup_mst_select_occupied_o,
31+
// push
32+
output logic full_o,
33+
input logic [AxiIdBits-1:0] push_axi_id_i,
34+
input mst_port_select_t push_mst_select_i,
35+
input logic push_i,
36+
// inject ATOPs in AR channel
37+
input logic [AxiIdBits-1:0] inject_axi_id_i,
38+
input logic inject_i,
39+
// pop
40+
input logic [AxiIdBits-1:0] pop_axi_id_i,
41+
input logic pop_i,
42+
// outstanding transactions
43+
output logic any_outstanding_trx_o
44+
);
45+
localparam int unsigned NoCounters = 2**AxiIdBits;
46+
typedef logic [CounterWidth-1:0] cnt_t;
47+
48+
// registers, each gets loaded when push_en[i]
49+
mst_port_select_t [NoCounters-1:0] mst_select_q;
50+
51+
// counter signals
52+
logic [NoCounters-1:0] push_en, inject_en, pop_en, occupied, cnt_full;
53+
54+
//-----------------------------------
55+
// Lookup
56+
//-----------------------------------
57+
assign lookup_mst_select_o = mst_select_q[lookup_axi_id_i];
58+
assign lookup_mst_select_occupied_o = occupied[lookup_axi_id_i];
59+
//-----------------------------------
60+
// Push and Pop
61+
//-----------------------------------
62+
assign push_en = (push_i) ? (1 << push_axi_id_i) : '0;
63+
assign inject_en = (inject_i) ? (1 << inject_axi_id_i) : '0;
64+
assign pop_en = (pop_i) ? (1 << pop_axi_id_i) : '0;
65+
assign full_o = |cnt_full;
66+
//-----------------------------------
67+
// Status
68+
//-----------------------------------
69+
assign any_outstanding_trx_o = |occupied;
70+
71+
// counters
72+
for (genvar i = 0; i < NoCounters; i++) begin : gen_counters
73+
logic cnt_en, cnt_down, overflow;
74+
cnt_t cnt_delta, in_flight;
75+
always_comb begin
76+
unique case ({push_en[i], inject_en[i], pop_en[i]})
77+
3'b001 : begin // pop_i = -1
78+
cnt_en = 1'b1;
79+
cnt_down = 1'b1;
80+
cnt_delta = cnt_t'(1);
81+
end
82+
3'b010 : begin // inject_i = +1
83+
cnt_en = 1'b1;
84+
cnt_down = 1'b0;
85+
cnt_delta = cnt_t'(1);
86+
end
87+
// 3'b011, inject_i & pop_i = 0 --> use default
88+
3'b100 : begin // push_i = +1
89+
cnt_en = 1'b1;
90+
cnt_down = 1'b0;
91+
cnt_delta = cnt_t'(1);
92+
end
93+
// 3'b101, push_i & pop_i = 0 --> use default
94+
3'b110 : begin // push_i & inject_i = +2
95+
cnt_en = 1'b1;
96+
cnt_down = 1'b0;
97+
cnt_delta = cnt_t'(2);
98+
end
99+
3'b111 : begin // push_i & inject_i & pop_i = +1
100+
cnt_en = 1'b1;
101+
cnt_down = 1'b0;
102+
cnt_delta = cnt_t'(1);
103+
end
104+
default : begin // do nothing to the counters
105+
cnt_en = 1'b0;
106+
cnt_down = 1'b0;
107+
cnt_delta = cnt_t'(0);
108+
end
109+
endcase
110+
end
111+
112+
delta_counter #(
113+
.WIDTH ( CounterWidth ),
114+
.STICKY_OVERFLOW ( 1'b0 )
115+
) i_in_flight_cnt (
116+
.clk_i ( clk_i ),
117+
.rst_ni ( rst_ni ),
118+
.clear_i ( 1'b0 ),
119+
.en_i ( cnt_en ),
120+
.load_i ( 1'b0 ),
121+
.down_i ( cnt_down ),
122+
.delta_i ( cnt_delta ),
123+
.d_i ( '0 ),
124+
.q_o ( in_flight ),
125+
.overflow_o ( overflow )
126+
);
127+
assign occupied[i] = |in_flight;
128+
assign cnt_full[i] = overflow | (&in_flight);
129+
130+
// holds the selection signal for this id
131+
`FFLARN(mst_select_q[i], push_mst_select_i, push_en[i], '0, clk_i, rst_ni)
132+
133+
// pragma translate_off
134+
`ifndef VERILATOR
135+
`ifndef XSIM
136+
// Validate parameters.
137+
cnt_underflow: assert property(
138+
@(posedge clk_i) disable iff (~rst_ni) (pop_en[i] |=> !overflow)) else
139+
$fatal(1, "axi_demux_id_counters > Counter: %0d underflowed.\
140+
The reason is probably a faulty AXI response.", i);
141+
`endif
142+
`endif
143+
// pragma translate_on
144+
end
145+
endmodule
146+

src/axi_demux_simple.sv

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -508,126 +508,3 @@ module axi_demux_simple #(
508508
// pragma translate_on
509509
end
510510
endmodule
511-
512-
513-
module axi_demux_id_counters #(
514-
// the lower bits of the AXI ID that should be considered, results in 2**AXI_ID_BITS counters
515-
parameter int unsigned AxiIdBits = 2,
516-
parameter int unsigned CounterWidth = 4,
517-
parameter type mst_port_select_t = logic
518-
) (
519-
input logic clk_i, // Clock
520-
input logic rst_ni, // Asynchronous reset active low
521-
// lookup
522-
input logic [AxiIdBits-1:0] lookup_axi_id_i,
523-
output mst_port_select_t lookup_mst_select_o,
524-
output logic lookup_mst_select_occupied_o,
525-
// push
526-
output logic full_o,
527-
input logic [AxiIdBits-1:0] push_axi_id_i,
528-
input mst_port_select_t push_mst_select_i,
529-
input logic push_i,
530-
// inject ATOPs in AR channel
531-
input logic [AxiIdBits-1:0] inject_axi_id_i,
532-
input logic inject_i,
533-
// pop
534-
input logic [AxiIdBits-1:0] pop_axi_id_i,
535-
input logic pop_i
536-
);
537-
localparam int unsigned NoCounters = 2**AxiIdBits;
538-
typedef logic [CounterWidth-1:0] cnt_t;
539-
540-
// registers, each gets loaded when push_en[i]
541-
mst_port_select_t [NoCounters-1:0] mst_select_q;
542-
543-
// counter signals
544-
logic [NoCounters-1:0] push_en, inject_en, pop_en, occupied, cnt_full;
545-
546-
//-----------------------------------
547-
// Lookup
548-
//-----------------------------------
549-
assign lookup_mst_select_o = mst_select_q[lookup_axi_id_i];
550-
assign lookup_mst_select_occupied_o = occupied[lookup_axi_id_i];
551-
//-----------------------------------
552-
// Push and Pop
553-
//-----------------------------------
554-
assign push_en = (push_i) ? (1 << push_axi_id_i) : '0;
555-
assign inject_en = (inject_i) ? (1 << inject_axi_id_i) : '0;
556-
assign pop_en = (pop_i) ? (1 << pop_axi_id_i) : '0;
557-
assign full_o = |cnt_full;
558-
// counters
559-
for (genvar i = 0; i < NoCounters; i++) begin : gen_counters
560-
logic cnt_en, cnt_down, overflow;
561-
cnt_t cnt_delta, in_flight;
562-
always_comb begin
563-
unique case ({push_en[i], inject_en[i], pop_en[i]})
564-
3'b001 : begin // pop_i = -1
565-
cnt_en = 1'b1;
566-
cnt_down = 1'b1;
567-
cnt_delta = cnt_t'(1);
568-
end
569-
3'b010 : begin // inject_i = +1
570-
cnt_en = 1'b1;
571-
cnt_down = 1'b0;
572-
cnt_delta = cnt_t'(1);
573-
end
574-
// 3'b011, inject_i & pop_i = 0 --> use default
575-
3'b100 : begin // push_i = +1
576-
cnt_en = 1'b1;
577-
cnt_down = 1'b0;
578-
cnt_delta = cnt_t'(1);
579-
end
580-
// 3'b101, push_i & pop_i = 0 --> use default
581-
3'b110 : begin // push_i & inject_i = +2
582-
cnt_en = 1'b1;
583-
cnt_down = 1'b0;
584-
cnt_delta = cnt_t'(2);
585-
end
586-
3'b111 : begin // push_i & inject_i & pop_i = +1
587-
cnt_en = 1'b1;
588-
cnt_down = 1'b0;
589-
cnt_delta = cnt_t'(1);
590-
end
591-
default : begin // do nothing to the counters
592-
cnt_en = 1'b0;
593-
cnt_down = 1'b0;
594-
cnt_delta = cnt_t'(0);
595-
end
596-
endcase
597-
end
598-
599-
delta_counter #(
600-
.WIDTH ( CounterWidth ),
601-
.STICKY_OVERFLOW ( 1'b0 )
602-
) i_in_flight_cnt (
603-
.clk_i ( clk_i ),
604-
.rst_ni ( rst_ni ),
605-
.clear_i ( 1'b0 ),
606-
.en_i ( cnt_en ),
607-
.load_i ( 1'b0 ),
608-
.down_i ( cnt_down ),
609-
.delta_i ( cnt_delta ),
610-
.d_i ( '0 ),
611-
.q_o ( in_flight ),
612-
.overflow_o ( overflow )
613-
);
614-
assign occupied[i] = |in_flight;
615-
assign cnt_full[i] = overflow | (&in_flight);
616-
617-
// holds the selection signal for this id
618-
`FFLARN(mst_select_q[i], push_mst_select_i, push_en[i], '0, clk_i, rst_ni)
619-
620-
// pragma translate_off
621-
`ifndef VERILATOR
622-
`ifndef XSIM
623-
// Validate parameters.
624-
cnt_underflow: assert property(
625-
@(posedge clk_i) disable iff (~rst_ni) (pop_en[i] |=> !overflow)) else
626-
$fatal(1, "axi_demux_id_counters > Counter: %0d underflowed.\
627-
The reason is probably a faulty AXI response.", i);
628-
`endif
629-
`endif
630-
// pragma translate_on
631-
end
632-
endmodule
633-

0 commit comments

Comments
 (0)