tsfpga VHDL coverage


Directory: generated/vunit_out/preprocessed/
File: generated/vunit_out/preprocessed/axi/axi_write_throttle.vhd
Date: 2021-07-25 04:08:32
Exec Total Coverage
Lines: 47 47 100.0%
Branches: 197 246 80.1%

Line Branch Exec Source
1 36 -- -------------------------------------------------------------------------------------------------
2 -- Copyright (c) Lukas Vik. All rights reserved.
3 --
4 -- This file is part of the tsfpga project.
5 -- https://tsfpga.com
6 -- https://gitlab.com/tsfpga/tsfpga
7 -- -------------------------------------------------------------------------------------------------
8 -- Performs throttling of an AXI bus by limiting the number of outstanding
9 -- transactions.
10 --
11 -- This entity is to be used in conjuction with a data FIFO on the input.w side.
12 -- Using the level from that FIFO, the throttling will make sure that an address
13 -- transactio is not done until all data for that transaction is available in
14 -- the FIFO. This avoids stalling on the throttled_m2s.w channel.
15 --
16 -- To achieve this it keeps track of the number of outstanding beats
17 -- that have been negotiated but not yet sent.
18 -- -------------------------------------------------------------------------------------------------
19
20 library ieee;
21 use ieee.numeric_std.all;
22 use ieee.std_logic_1164.all;
23
24 library axi;
25 use axi.axi_pkg.all;
26
27 library common;
28 use common.types_pkg.all;
29
30 library math;
31 6 use math.math_pkg.all;
32
33
34
42/44
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 390 times.
✓ Branch 7 taken 12 times.
✓ Branch 8 taken 252 times.
✓ Branch 9 taken 54 times.
✓ Branch 10 taken 12 times.
✓ Branch 12 taken 18 times.
✓ Branch 13 taken 12 times.
✓ Branch 15 taken 12 times.
✓ Branch 16 taken 6 times.
✓ Branch 19 taken 768 times.
✓ Branch 20 taken 6 times.
✓ Branch 22 taken 96 times.
✓ Branch 23 taken 6 times.
✓ Branch 26 taken 144 times.
✓ Branch 27 taken 6 times.
✓ Branch 33 taken 144 times.
✓ Branch 34 taken 6 times.
✓ Branch 36 taken 12 times.
✓ Branch 37 taken 6 times.
✓ Branch 40 taken 144 times.
✓ Branch 41 taken 6 times.
✓ Branch 43 taken 384 times.
✓ Branch 44 taken 6 times.
✓ Branch 46 taken 48 times.
✓ Branch 47 taken 6 times.
✓ Branch 49 taken 18 times.
✓ Branch 50 taken 6 times.
✓ Branch 52 taken 12 times.
✓ Branch 53 taken 6 times.
✓ Branch 56 taken 768 times.
✓ Branch 57 taken 6 times.
✓ Branch 59 taken 96 times.
✓ Branch 60 taken 6 times.
✓ Branch 63 taken 144 times.
✓ Branch 64 taken 6 times.
✓ Branch 70 taken 144 times.
✓ Branch 71 taken 6 times.
✓ Branch 73 taken 12 times.
✓ Branch 74 taken 6 times.
19404 entity axi_write_throttle is
35 generic(
36 6 data_fifo_depth : positive;
37 6 max_burst_length_beats : positive;
38 6 id_width : natural;
39
8/10
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 6 taken 252 times.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✓ Branch 11 taken 252 times.
✓ Branch 12 taken 6 times.
✓ Branch 13 taken 252 times.
✓ Branch 14 taken 6 times.
762 addr_width : positive;
40 -- The AW channel is pipelined one step to improve poor timing, mainly on AWVALID.
41 -- If this generic is set to false, the pipelining will be of a simpler model that has lower
42 -- logic footprint, but only allow a transaction every third clock cycle. If it is set to true,
43 -- the pipeline will support a transaction every clock cycle, at the cost of a greater
44 -- logic footprint.
45 full_aw_throughput : boolean
46 );
47 port(
48 clk : in std_logic;
49 --
50 data_fifo_level : in integer range 0 to data_fifo_depth;
51 --
52 input_m2s : in axi_write_m2s_t := axi_write_m2s_init;
53 input_s2m : out axi_write_s2m_t := axi_write_s2m_init;
54 --
55 throttled_m2s : out axi_write_m2s_t := axi_write_m2s_init;
56 throttled_s2m : in axi_write_s2m_t := axi_write_s2m_init
57 );
58 end entity;
59
60 architecture a of axi_write_throttle is
61
62 612 signal pipelined_m2s_aw : axi_m2s_a_t := axi_m2s_a_init;
63 6 signal pipelined_s2m_aw : axi_s2m_a_t := axi_s2m_a_init;
64
65 6 signal address_transaction, data_transaction : std_logic := '0';
66
67 -- The bits of the AWLEN field that shall be taken into account
68 6 constant len_width : positive := num_bits_needed(max_burst_length_beats - 1);
69 subtype len_range is integer range len_width - 1 downto 0;
70
71 -- +1 in range for sign bit
72 82 signal minus_burst_length_beats : signed(len_width + 1 - 1 downto 0) :=
73 (others => '0');
74
75 -- Since W transactions can happen before AW transaction,
76 -- the counters can become negative as well as positive.
77 subtype data_counter_t is integer range -data_fifo_depth to data_fifo_depth;
78
79 -- Negation of:
80 -- Data beats that are available in the FIFO, but have not yet been claimed by
81 -- an address transaction.
82 6 signal minus_num_beats_available_but_not_negotiated : data_counter_t := 0;
83
84 -- Number of data beats that have been negotiated through an address transaction,
85 -- but have not yet been sent via data transactions. Aka outstanding beats.
86 6 signal num_beats_negotiated_but_not_sent : data_counter_t := 0;
87
88 begin
89
90 ------------------------------------------------------------------------------
91 pipeline : block
92 6 constant m2s_length : positive := axi_m2s_a_sz(id_width=>id_width, addr_width=>addr_width);
93 1014 signal input_m2s_aw_slv, pipelined_m2s_aw_slv :
94 std_logic_vector(m2s_length - 1 downto 0) := (others => '0');
95 12 signal pipelined_valid : std_logic := '0';
96 begin
97
98 517638 input_m2s_aw_slv <= to_slv(data=>input_m2s.aw, id_width=>id_width, addr_width=>addr_width);
99
100
101 ------------------------------------------------------------------------------
102 24048 handshake_pipeline_inst : entity common.handshake_pipeline
103 generic map (
104 data_width => input_m2s_aw_slv'length,
105 -- Choosable by user, since it affects footprint.
106 full_throughput => full_aw_throughput,
107 -- The goal of this pipeline is to improve timing of the control bits, so this one must
108 -- be false, even though it will increase footprint.
109 allow_poor_input_ready_timing => false
110 )
111 port map (
112 clk => clk,
113 --
114 input_ready => input_s2m.aw.ready,
115 input_valid => input_m2s.aw.valid,
116 input_data => input_m2s_aw_slv,
117 --
118 output_ready => pipelined_s2m_aw.ready,
119 output_valid => pipelined_valid,
120 output_data => pipelined_m2s_aw_slv
121 );
122
123
124 ------------------------------------------------------------------------------
125 864 assign_aw : process(all)
126 begin
127
28/34
✗ Branch 1 not taken.
✓ Branch 2 taken 12018 times.
✓ Branch 3 taken 3000 times.
✓ Branch 4 taken 9018 times.
✓ Branch 6 taken 288432 times.
✓ Branch 7 taken 12018 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 288432 times.
✓ Branch 10 taken 60 times.
✓ Branch 11 taken 288372 times.
✓ Branch 13 taken 769152 times.
✓ Branch 14 taken 12018 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 769152 times.
✓ Branch 17 taken 17025 times.
✓ Branch 18 taken 752127 times.
✓ Branch 20 taken 96144 times.
✓ Branch 21 taken 12018 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 96144 times.
✓ Branch 24 taken 96 times.
✓ Branch 25 taken 96048 times.
✓ Branch 27 taken 36054 times.
✓ Branch 28 taken 12018 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 36054 times.
✓ Branch 31 taken 225 times.
✓ Branch 32 taken 35829 times.
✓ Branch 34 taken 24036 times.
✓ Branch 35 taken 12018 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 24036 times.
✓ Branch 38 taken 213 times.
✓ Branch 39 taken 23823 times.
2451672 pipelined_m2s_aw <= to_axi_m2s_a(
128 data=>pipelined_m2s_aw_slv,
129 id_width=>id_width,
130 addr_width=>addr_width
131 );
132
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12018 times.
✓ Branch 2 taken 6000 times.
✓ Branch 3 taken 6018 times.
24054 pipelined_m2s_aw.valid <= pipelined_valid;
133 end process;
134
135 end block;
136
137
138 -- Two complement inversion: inv(len) = - len - 1 = - (len + 1) = - burst_length_beats
139
13/22
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 18 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 18 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 18 times.
✓ Branch 21 taken 18 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 18 times.
✓ Branch 27 taken 114 times.
✓ Branch 28 taken 18 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 114 times.
✓ Branch 31 taken 102 times.
✓ Branch 32 taken 12 times.
208 minus_burst_length_beats <= not signed('0' & pipelined_m2s_aw.len(len_range));
140
141 ------------------------------------------------------------------------------
142 6 assign_throttled_bus : process(all)
143 3584 variable block_address_transactions : boolean;
144 begin
145
28/34
✗ Branch 0 not taken.
✓ Branch 1 taken 112010 times.
✓ Branch 2 taken 3000 times.
✓ Branch 3 taken 109010 times.
✓ Branch 5 taken 2688240 times.
✓ Branch 6 taken 112010 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2688240 times.
✓ Branch 9 taken 60 times.
✓ Branch 10 taken 2688180 times.
✓ Branch 12 taken 7168640 times.
✓ Branch 13 taken 112010 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 7168640 times.
✓ Branch 16 taken 17025 times.
✓ Branch 17 taken 7151615 times.
✓ Branch 19 taken 896080 times.
✓ Branch 20 taken 112010 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 896080 times.
✓ Branch 23 taken 96 times.
✓ Branch 24 taken 895984 times.
✓ Branch 26 taken 336030 times.
✓ Branch 27 taken 112010 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 336030 times.
✓ Branch 30 taken 225 times.
✓ Branch 31 taken 335805 times.
✓ Branch 33 taken 224020 times.
✓ Branch 34 taken 112010 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 224020 times.
✓ Branch 37 taken 213 times.
✓ Branch 38 taken 223807 times.
11425020 throttled_m2s.aw <= pipelined_m2s_aw;
146
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112010 times.
✓ Branch 2 taken 56671 times.
✓ Branch 3 taken 55339 times.
112010 pipelined_s2m_aw <= throttled_s2m.aw;
147
148
20/26
✗ Branch 0 not taken.
✓ Branch 1 taken 112010 times.
✓ Branch 2 taken 6000 times.
✓ Branch 3 taken 106010 times.
✓ Branch 5 taken 14337280 times.
✓ Branch 6 taken 112010 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14337280 times.
✓ Branch 9 taken 95964 times.
✓ Branch 10 taken 14241316 times.
✓ Branch 12 taken 1792160 times.
✓ Branch 13 taken 112010 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1792160 times.
✓ Branch 16 taken 24048 times.
✓ Branch 17 taken 1768112 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 112010 times.
✓ Branch 21 taken 6012 times.
✓ Branch 22 taken 105998 times.
✓ Branch 24 taken 2688240 times.
✓ Branch 25 taken 112010 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 2688240 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 2688240 times.
18929690 throttled_m2s.w <= input_m2s.w;
149
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112010 times.
✓ Branch 2 taken 6000 times.
✓ Branch 3 taken 106010 times.
112010 input_s2m.w <= throttled_s2m.w;
150
151
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 112010 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 112004 times.
112010 throttled_m2s.b <= input_m2s.b;
152
13/16
✗ Branch 0 not taken.
✓ Branch 1 taken 112010 times.
✓ Branch 2 taken 6000 times.
✓ Branch 3 taken 106010 times.
✓ Branch 5 taken 2688240 times.
✓ Branch 6 taken 112010 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2688240 times.
✓ Branch 9 taken 60 times.
✓ Branch 10 taken 2688180 times.
✓ Branch 12 taken 224020 times.
✓ Branch 13 taken 112010 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 224020 times.
✓ Branch 16 taken 24 times.
✓ Branch 17 taken 223996 times.
3024270 input_s2m.b <= throttled_s2m.b;
153
154 -- The original condition would have been
155 --
156 -- block_address_transactions =
157 -- burst_length_beats > num_beats_available_but_not_negotiated
158 --
159 -- where num_beats_available_but_not_negotiated =
160 -- data_fifo_level - num_beats_negotiated_but_not_sent
161 --
162 -- where num_beats_negotiated_but_not_sent was given by accumulating
163 -- to_int(address_transaction) * burst_length_beats - to_int(data_transaction)
164 --
165 -- However this created a very long critical path from AWLEN to AWVALID. The
166 -- bytes_per_beat = AWLEN + 1 term, used in two places was replaced with -inv(AWLEN).
167 -- The minus sign was moved to the right side of the expression, which changed the subtraction
168 -- order. This makes the signals and their ranges a bit harder to understand, but it improves
169 -- the critical path a lot.
170 112010 block_address_transactions :=
171 minus_burst_length_beats < minus_num_beats_available_but_not_negotiated;
172
2/2
✓ Branch 0 taken 96087 times.
✓ Branch 1 taken 15923 times.
112010 if block_address_transactions then
173
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96087 times.
✓ Branch 2 taken 3000 times.
✓ Branch 3 taken 93087 times.
96087 throttled_m2s.aw.valid <= '0';
174
6/8
✓ Branch 0 taken 186491 times.
✓ Branch 1 taken 372966 times.
✓ Branch 2 taken 186485 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 96087 times.
✓ Branch 6 taken 5161 times.
✓ Branch 7 taken 90926 times.
842029 pipelined_s2m_aw.ready <= '0';
175 end if;
176 end process;
177
178
179 ------------------------------------------------------------------------------
180 6 count : process
181 6 variable num_beats_negotiated_but_not_sent_int : data_counter_t := 0;
182 44 variable aw_term : signed(minus_burst_length_beats'range) := (others => '0');
183 begin
184
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 372966 times.
✓ Branch 6 taken 186485 times.
✓ Branch 7 taken 186481 times.
745942 wait until rising_edge(clk);
185
186 -- This muxing results in a shorter critical path than doing
187 -- e.g. minus_burst_length_beats * to_int(address_transaction).
188 -- LUT usage stayed the same.
189
2/2
✓ Branch 1 taken 3000 times.
✓ Branch 2 taken 183485 times.
186485 if address_transaction then
190
1/2
✓ Branch 0 taken 3000 times.
✗ Branch 1 not taken.
3000 aw_term := minus_burst_length_beats;
191 else
192
2/2
✓ Branch 0 taken 1285469 times.
✓ Branch 1 taken 183485 times.
1468954 aw_term := (others => '0');
193 end if;
194
195
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 186485 times.
186485 num_beats_negotiated_but_not_sent_int := num_beats_negotiated_but_not_sent
196 - to_integer(aw_term)
197 - to_int(data_transaction);
198
199
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 186485 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 186485 times.
✓ Branch 5 taken 12000 times.
✓ Branch 6 taken 174485 times.
186485 minus_num_beats_available_but_not_negotiated <=
200 num_beats_negotiated_but_not_sent_int - data_fifo_level;
201
202
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 186485 times.
✓ Branch 2 taken 6000 times.
✓ Branch 3 taken 180485 times.
372970 num_beats_negotiated_but_not_sent <= num_beats_negotiated_but_not_sent_int;
203 end process;
204
205
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 82953 times.
✓ Branch 3 taken 6000 times.
✓ Branch 4 taken 76953 times.
82959 address_transaction <= throttled_s2m.aw.ready and throttled_m2s.aw.valid;
206
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 12006 times.
✓ Branch 4 taken 6000 times.
✓ Branch 5 taken 6006 times.
12018 data_transaction <= throttled_s2m.w.ready and throttled_m2s.w.valid;
207
208 end architecture;
209