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