tsfpga VHDL coverage


Directory: generated/vunit_out/preprocessed/
File: generated/vunit_out/preprocessed/common/handshake_pipeline.vhd
Date: 2021-07-26 04:08:16
Exec Total Coverage
Lines: 54 54 100.0%
Branches: 147 210 70.0%

Line Branch Exec Source
1 168 -- -------------------------------------------------------------------------------------------------
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 -- Handshake pipeline. Is used to ease the timing of a streaming data interface by inserting
9 -- register stages on the data and, in some modes, the control signals.
10 --
11 -- There are many modes available, with different characteristics.
12 -- See the descriptions within the code.
13 -- -------------------------------------------------------------------------------------------------
14
15 library ieee;
16 use ieee.std_logic_1164.all;
17
18
19
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✓ Branch 4 taken 822 times.
✓ Branch 5 taken 28 times.
✓ Branch 10 taken 822 times.
✓ Branch 11 taken 28 times.
14772 entity handshake_pipeline is
20 generic (
21 data_width : integer;
22 -- Setting to false can save logic footprint, at the cost of lower throughput
23 full_throughput : boolean := true;
24 -- Can result in smaller logic footprint and higher througphput, at the cost of worse timing
25 -- on the input_ready signal.
26 allow_poor_input_ready_timing : boolean := false
27 );
28 port (
29 clk : in std_logic;
30 --
31 input_ready : out std_logic := '0';
32 input_valid : in std_logic;
33 input_last : in std_logic := '-';
34 input_data : in std_logic_vector(data_width - 1 downto 0);
35 --
36 output_ready : in std_logic;
37 output_valid : out std_logic := '0';
38 output_last : out std_logic := '0';
39 output_data : out std_logic_vector(data_width - 1 downto 0) := (others => '0')
40 );
41 end entity;
42
43 56 architecture a of handshake_pipeline is
44
45 begin
46
47 ------------------------------------------------------------------------------
48 choose_mode : if full_throughput and allow_poor_input_ready_timing generate
49
50 -- In this mode, the data and control signals are driven by registers, except for input_ready
51 -- which will have an increased critical path. It still maintaints full throughput,
52 -- and has a much smaller footprint than the full skid-aside buffer.
53 --
54 -- It is suitable in situtations where there is a complex net driving the data, which needs to
55 -- be pipelined in order to achieve timing closure, but the timing of the control signals is
56 -- not critical.
57
58
3/4
✓ Branch 0 taken 8727 times.
✓ Branch 1 taken 17448 times.
✓ Branch 2 taken 8725 times.
✗ Branch 3 not taken.
46190 input_ready <= output_ready or not output_valid;
59
60
61 ------------------------------------------------------------------------------
62 34 main : process
63 begin
64
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 17448 times.
✓ Branch 6 taken 8725 times.
✓ Branch 7 taken 8723 times.
34900 wait until rising_edge(clk);
65
66
2/2
✓ Branch 1 taken 6904 times.
✓ Branch 2 taken 1821 times.
8725 if input_ready then
67
2/4
✓ Branch 0 taken 6904 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6904 times.
✗ Branch 3 not taken.
6904 output_valid <= input_valid;
68
6/10
✓ Branch 0 taken 6904 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6904 times.
✓ Branch 6 taken 110464 times.
✓ Branch 7 taken 6904 times.
✓ Branch 8 taken 110464 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 110464 times.
✗ Branch 11 not taken.
117368 output_data <= input_data;
69
2/4
✓ Branch 0 taken 6904 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6904 times.
✗ Branch 3 not taken.
17450 output_last <= input_last;
70 end if;
71 end process;
72
73
74 ------------------------------------------------------------------------------
75 elsif full_throughput and not allow_poor_input_ready_timing generate
76
77 -- This mode is a full skid-aside buffer, aka skid buffer.
78 --
79 -- It makes sure that all output signals (data as well as control signals) are driven by
80 -- a register. It does so while sustaining full throughput. It has the best timing
81 -- characteristics but also the largest logic footprint.
82
83 12 signal input_ready_int : std_logic := '1';
84
85 type state_t is (wait_for_input_valid, full_handshake_throughput, wait_for_output_ready);
86 12 signal state : state_t := wait_for_input_valid;
87
88 266 signal input_data_skid : std_logic_vector(input_data'range);
89 26 signal input_last_skid : std_logic;
90
91 begin
92
93
6/8
✓ Branch 0 taken 404398 times.
✓ Branch 1 taken 808760 times.
✓ Branch 2 taken 404386 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2362 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 2372 times.
✗ Branch 7 not taken.
1619928 input_ready <= input_ready_int;
94
95
96 ------------------------------------------------------------------------------
97 520 main : process
98 begin
99
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 808760 times.
✓ Branch 6 taken 404386 times.
✓ Branch 7 taken 404374 times.
1617544 wait until rising_edge(clk);
100
101
3/4
✓ Branch 0 taken 381002 times.
✓ Branch 1 taken 21942 times.
✓ Branch 2 taken 1442 times.
✗ Branch 3 not taken.
404386 case state is
102 when wait_for_input_valid =>
103
2/2
✓ Branch 1 taken 11615 times.
✓ Branch 2 taken 369387 times.
381002 if input_valid then
104 -- input_ready is '1', so if we get here an input transaction has occured
105
3/4
✓ Branch 0 taken 1105 times.
✓ Branch 1 taken 10510 times.
✓ Branch 2 taken 11615 times.
✗ Branch 3 not taken.
11615 output_valid <= '1';
106
8/10
✓ Branch 0 taken 11615 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11615 times.
✓ Branch 6 taken 269194 times.
✓ Branch 7 taken 11615 times.
✓ Branch 8 taken 17680 times.
✓ Branch 9 taken 251514 times.
✓ Branch 10 taken 92062 times.
✓ Branch 11 taken 177132 times.
280809 output_data <= input_data;
107
4/4
✓ Branch 0 taken 1105 times.
✓ Branch 1 taken 10510 times.
✓ Branch 2 taken 1115 times.
✓ Branch 3 taken 10500 times.
11615 output_last <= input_last;
108
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11615 times.
✓ Branch 2 taken 11615 times.
✗ Branch 3 not taken.
381002 state <= full_handshake_throughput;
109 end if;
110
111 when full_handshake_throughput =>
112 -- input_ready and output_valid are always '1' in this state
113
114
2/2
✓ Branch 2 taken 2835 times.
✓ Branch 3 taken 19107 times.
21942 if input_valid and output_ready then
115 -- Input and output transactions have occured. Update data register.
116
6/10
✓ Branch 0 taken 2835 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2835 times.
✓ Branch 6 taken 45360 times.
✓ Branch 7 taken 2835 times.
✓ Branch 8 taken 45360 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 45360 times.
✗ Branch 11 not taken.
48195 output_data <= input_data;
117
2/4
✓ Branch 0 taken 2835 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2835 times.
✗ Branch 3 not taken.
2835 output_last <= input_last;
118
2/2
✓ Branch 1 taken 11615 times.
✓ Branch 2 taken 7492 times.
19107 elsif output_ready then
119 -- Output transaction has occured, but no input transaction
120
3/4
✓ Branch 0 taken 1105 times.
✓ Branch 1 taken 10510 times.
✓ Branch 2 taken 11615 times.
✗ Branch 3 not taken.
11615 output_valid <= '0';
121
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11615 times.
✓ Branch 2 taken 11615 times.
✗ Branch 3 not taken.
11615 state <= wait_for_input_valid;
122
2/2
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 6312 times.
7492 elsif input_valid then
123 -- Input transaction has occured, but no output transaction
124 -- Values from input transaction will be saved in the skid-aside buffer while we wait for output_ready.
125
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 1180 times.
✗ Branch 3 not taken.
1180 input_ready_int <= '0';
126
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 1180 times.
✗ Branch 3 not taken.
21942 state <= wait_for_output_ready;
127 end if;
128
129 when wait_for_output_ready =>
130
2/2
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 262 times.
1442 if output_ready then
131 -- output_valid is '1', so if we get here an output transaction has occured
132
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 1180 times.
✗ Branch 3 not taken.
1180 input_ready_int <= '1';
133
6/10
✓ Branch 0 taken 1180 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1180 times.
✓ Branch 6 taken 18880 times.
✓ Branch 7 taken 1180 times.
✓ Branch 8 taken 18880 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18880 times.
✗ Branch 11 not taken.
20060 output_data <= input_data_skid;
134
2/4
✓ Branch 0 taken 1180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1180 times.
✗ Branch 3 not taken.
1180 output_last <= input_last_skid;
135
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 1180 times.
✗ Branch 3 not taken.
1180 state <= full_handshake_throughput;
136 end if;
137 end case;
138
139
2/2
✓ Branch 2 taken 15630 times.
✓ Branch 3 taken 388756 times.
404386 if input_ready and input_valid then
140
7/10
✓ Branch 0 taken 15630 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15630 times.
✓ Branch 6 taken 333434 times.
✓ Branch 7 taken 15630 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 333434 times.
✓ Branch 10 taken 115358 times.
✓ Branch 11 taken 218076 times.
349064 input_data_skid <= input_data;
141
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15630 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 15610 times.
808772 input_last_skid <= input_last;
142 end if;
143 end process;
144
145
146 ------------------------------------------------------------------------------
147 elsif (not full_throughput) and allow_poor_input_ready_timing generate
148
149 -- All signals are driven by registers, except input_ready which will have an increased
150 -- critical path. This mode will be able to maintain a one half throughput.
151 --
152 -- Compared to the first mode in this file, this one has a lower load on the input_ready.
153 -- This results in somewhat better timing on the input_ready signal, at the cost of
154 -- lower throughput.
155
156 14 begin
157
158
5/8
✓ Branch 0 taken 10997 times.
✓ Branch 1 taken 21991 times.
✓ Branch 2 taken 10996 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 11313 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11313 times.
✗ Branch 8 not taken.
55298 input_ready <= output_ready and output_valid;
159
160
161 ------------------------------------------------------------------------------
162 17 main : process
163 begin
164
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 21991 times.
✓ Branch 6 taken 10996 times.
✓ Branch 7 taken 10995 times.
43984 wait until rising_edge(clk);
165
166
2/4
✓ Branch 3 taken 10996 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10996 times.
✗ Branch 6 not taken.
10996 output_valid <= input_valid and not (output_valid and output_ready);
167
6/10
✓ Branch 0 taken 10996 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10996 times.
✓ Branch 6 taken 175936 times.
✓ Branch 7 taken 10996 times.
✓ Branch 8 taken 175936 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 175936 times.
✗ Branch 11 not taken.
186932 output_data <= input_data;
168
5/8
✓ Branch 0 taken 387808 times.
✓ Branch 1 taken 775581 times.
✓ Branch 2 taken 387795 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10996 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10996 times.
✗ Branch 7 not taken.
1573176 output_last <= input_last;
169 end process;
170
171
172 ------------------------------------------------------------------------------
173 elsif (not full_throughput) and (not allow_poor_input_ready_timing) generate
174
175 -- All signals are driven by registers, which results in the best timing but also the lowest
176 -- throughput. This mode will be able to maintain a one third throughput.
177
178 41 begin
179
180
181 ------------------------------------------------------------------------------
182 533 main : process
183 begin
184
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 775581 times.
✓ Branch 6 taken 387795 times.
✓ Branch 7 taken 387786 times.
1551184 wait until rising_edge(clk);
185
186
4/4
✓ Branch 1 taken 14825 times.
✓ Branch 2 taken 372970 times.
✓ Branch 3 taken 26825 times.
✓ Branch 4 taken 360970 times.
387795 input_ready <= output_ready and output_valid;
187 -- Since there is a one cycle latency on output_valid, and a one cycle latency on input_ready,
188 -- we have to stall for two cycles after a transaction, to allow the "input" master to update
189 -- data and valid.
190
4/4
✓ Branch 5 taken 14825 times.
✓ Branch 6 taken 372970 times.
✓ Branch 7 taken 26825 times.
✓ Branch 8 taken 360970 times.
387795 output_valid <= input_valid and not (output_valid and output_ready) and not input_ready;
191
8/10
✓ Branch 0 taken 387795 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 387795 times.
✓ Branch 6 taken 15901940 times.
✓ Branch 7 taken 387795 times.
✓ Branch 8 taken 237200 times.
✓ Branch 9 taken 15664740 times.
✓ Branch 10 taken 272438 times.
✓ Branch 11 taken 15629502 times.
16289735 output_data <= input_data;
192
4/4
✓ Branch 1 taken 14825 times.
✓ Branch 2 taken 372970 times.
✓ Branch 3 taken 14837 times.
✓ Branch 4 taken 372958 times.
775618 output_last <= input_last;
193 end process;
194
195 end generate;
196
197 end architecture;
198