GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/axi/axi_lite_mux.vhd Lines: 89 89 100.0 %
Date: 2021-06-12 04:12:08 Branches: 255 371 68.7 %

Line Branch Exec Source
1
72
-- -------------------------------------------------------------------------------------------------
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
-- AXI-Lite mux, aka simple 1-to-N crossbar.
9
--
10
-- The slave_addrs generic is a list of base address configurations for the
11
-- N slaves. Eeach entry consists of a base address, along with a mask that
12
-- will be used to match the master address with a slave. Only the bits that
13
-- are asserted in the mask are taken into account when matching.
14
--
15
-- If the address requested by the master does not match any slave, this entity
16
-- will send AXI decode error on the response channel. There will still be
17
-- proper AXI handshaking done, so the master will not be stalled.
18
-- -------------------------------------------------------------------------------------------------
19
20
library ieee;
21
use ieee.std_logic_1164.all;
22
use ieee.numeric_std.all;
23
24
library math;
25
use math.math_pkg.all;
26
27
library common;
28
use common.addr_pkg.all;
29
30
use work.axi_lite_pkg.all;
31
use work.axi_pkg.all;
32
33
34










36405
entity axi_lite_mux is
35
  generic (
36
    slave_addrs : addr_and_mask_vec_t
37
  );
38
  port (
39
    clk : in std_logic;
40
41
    axi_lite_m2s : in axi_lite_m2s_t;
42
    axi_lite_s2m : out axi_lite_s2m_t := axi_lite_s2m_init;
43
44
    axi_lite_m2s_vec : out axi_lite_m2s_vec_t(slave_addrs'range) := (others => axi_lite_m2s_init);
45
    axi_lite_s2m_vec : in axi_lite_s2m_vec_t(slave_addrs'range)
46
  );
47
end entity;
48
49
architecture a of axi_lite_mux is
50
51
  -- Decode function will return upper index + 1 if no slave matched
52
12
  constant decode_failed : integer := axi_lite_m2s_vec'length;
53
54
12
  constant slave_decode_error_idx : integer := decode_failed;
55
12
  constant slave_not_selected_idx : integer := decode_failed + 1;
56
57
12
  signal read_slave_select, write_slave_select : integer range 0 to slave_not_selected_idx := slave_not_selected_idx;
58
59
804
  signal read_decode_error_s2m : axi_lite_read_s2m_t := axi_lite_read_s2m_init;
60
36
  signal write_decode_error_s2m : axi_lite_write_s2m_t := axi_lite_write_s2m_init;
61
62
begin
63
64
  ------------------------------------------------------------------------------
65
5976
  assign_s2m_read : process(all)
66
  begin
67
1797
    if read_slave_select = slave_not_selected_idx then
68
      -- Wait for the master to assert address valid so that we can select the correct slave
69
1074
      axi_lite_s2m.read.ar <= (ready => '0');
70
142842
      axi_lite_s2m.read.r <= (valid => '0', others => (others => '-'));
71
72
723
    elsif read_slave_select = slave_decode_error_idx then
73
      -- Master requested a slave address that does not exist. Return decode error.
74
      -- State machine will perform handshake on the different channels.
75
4
      axi_lite_s2m.read.ar <= (ready => read_decode_error_s2m.ar.ready);
76
524
      axi_lite_s2m.read.r <= (valid => read_decode_error_s2m.r.valid,
77
                          resp => axi_resp_decerr,
78
                          data => (others => '-'));
79
80
    else
81
      -- Connect the selected slave. State machine will un-select when all transactions are done.
82
49885
      axi_lite_s2m.read <= axi_lite_s2m_vec(read_slave_select).read;
83
    end if;
84
  end process;
85
86
87
  ------------------------------------------------------------------------------
88
3672
  assign_s2m_write : process(all)
89
  begin
90
1712
    if write_slave_select = slave_not_selected_idx then
91
      -- Wait for the master to assert address valid so that we can select the correct slave
92

1105
      axi_lite_s2m.write.aw <= (ready => '0');
93

1105
      axi_lite_s2m.write.w <= (ready => '0');
94



5525
      axi_lite_s2m.write.b <= (valid => '0', others => (others => '-'));
95
96
607
    elsif write_slave_select = slave_decode_error_idx then
97
      -- Master requested a slave address that does not exist. Return decode error.
98
      -- State machine will perform handshake on the different channels.
99

6
      axi_lite_s2m.write.aw <= (ready => write_decode_error_s2m.aw.ready);
100

6
      axi_lite_s2m.write.w <= (ready => write_decode_error_s2m.w.ready);
101


18
      axi_lite_s2m.write.b <= (valid => write_decode_error_s2m.b.valid,
102
                           resp => axi_resp_decerr);
103
104
    else
105
      -- Connect the selected slave. State machine will un-select when all transactions are done.
106





1803
      axi_lite_s2m.write <= axi_lite_s2m_vec(write_slave_select).write;
107
    end if;
108
  end process;
109
110
111
  ------------------------------------------------------------------------------
112
12864
  assign_m2s_vec : process(all)
113
  begin
114
2835
    for slave in axi_lite_m2s_vec'range loop
115











2795508
      axi_lite_m2s_vec(slave) <= axi_lite_m2s;
116
117
13908
      if write_slave_select /= slave then
118

13307
        axi_lite_m2s_vec(slave).write.aw.valid <= '0';
119

13307
        axi_lite_m2s_vec(slave).write.w.valid <= '0';
120

13307
        axi_lite_m2s_vec(slave).write.b.ready <= '0';
121
      end if;
122
123
13908
      if read_slave_select /= slave then
124

13342
        axi_lite_m2s_vec(slave).read.ar.valid <= '0';
125



30108
        axi_lite_m2s_vec(slave).read.r.ready <= '0';
126
      end if;
127
    end loop;
128
  end process;
129
130
131
  ------------------------------------------------------------------------------
132
  select_read : block
133
    type state_t is (waiting, decode_error, reading);
134
12
    signal state : state_t := waiting;
135
  begin
136
12
    select_read_slave : process
137
12
      variable decoded_idx : integer range 0 to decode_failed;
138
    begin
139

16200
      wait until rising_edge(clk);
140
141

4049
      case state is
142
        when waiting =>
143
2448
          if axi_lite_m2s.read.ar.valid then
144
285
            decoded_idx := decode(axi_lite_m2s.read.ar.addr, slave_addrs);
145
146
285
            if decoded_idx = decode_failed then
147
              -- If there is no AXI-Lite slave on the requested address, we have to complete the
148
              -- transaction via this state machine, as to not stall the AXI-Lite master.
149
              -- Should return error on the response channel.
150

2
              read_slave_select <= slave_decode_error_idx;
151
152
              -- Complete the AR transaction.
153
              -- Note that m2s valid is high, so transaction will occur straight away.
154
2
              assert not axi_lite_s2m.read.ar.ready;
155

2
              read_decode_error_s2m.ar.ready <= '1';
156
157
2
              assert not axi_lite_s2m.read.r.valid;
158

2
              read_decode_error_s2m.r.valid <= '1';
159
160

2
              state <= decode_error;
161
            else
162
              -- If the requested address has a corresponding slave, select that and
163
              -- wait until transaction is finished.
164

283
              read_slave_select <= decoded_idx;
165

2448
              state <= reading;
166
            end if;
167
          end if;
168
169
        when decode_error =>
170

4
          read_decode_error_s2m.ar.ready <= '0';
171
172
4
          if axi_lite_m2s.read.r.ready and axi_lite_s2m.read.r.valid then
173

2
            read_decode_error_s2m.r.valid <= '0';
174
175

2
            read_slave_select <= slave_not_selected_idx;
176

4
            state <= waiting;
177
          end if;
178
179
        when reading =>
180
1597
          if axi_lite_m2s.read.r.ready and axi_lite_s2m.read.r.valid then
181

283
            read_slave_select <= slave_not_selected_idx;
182


24298
            state <= waiting;
183
          end if;
184
      end case;
185
    end process;
186
  end block;
187
188
189
  ------------------------------------------------------------------------------
190
  select_write : block
191
    type state_t is (waiting, decode_error_w, decode_error_b, writing);
192
24
    signal state : state_t := waiting;
193
  begin
194
12
    select_write_slave : process
195
12
      variable decoded_idx : integer range 0 to decode_failed;
196
    begin
197

16200
      wait until rising_edge(clk);
198
199

4049
      case state is
200
        when waiting =>
201
2837
          if axi_lite_m2s.write.aw.valid then
202
223
            decoded_idx := decode(axi_lite_m2s.write.aw.addr, slave_addrs);
203
204
223
            if decoded_idx = decode_failed then
205
              -- If there is no AXI-Lite slave on the requested address, we have to complete the
206
              -- transaction via this state machine, as to not stall the AXI-Lite master.
207
              -- Should return error on the response channel.
208

2
              write_slave_select <= slave_decode_error_idx;
209
210
              -- Complete the AW transaction.
211
              -- Note that m2s valid is high, so transaction will occur straight away.
212
2
              assert not axi_lite_s2m.write.aw.ready;
213

2
              write_decode_error_s2m.aw.ready <= '1';
214
215
2
              assert not axi_lite_s2m.write.w.ready;
216

2
              write_decode_error_s2m.w.ready <= '1';
217
218

2
              state <= decode_error_w;
219
            else
220
              -- If the requested address has a corresponding slave, select that and
221
              -- wait until transaction is finished.
222

221
              write_slave_select <= decoded_idx;
223

2837
              state <= writing;
224
            end if;
225
          end if;
226
227
        when decode_error_w =>
228

4
          write_decode_error_s2m.aw.ready <= '0';
229
230
4
          if axi_lite_s2m.write.w.ready and axi_lite_m2s.write.w.valid then
231

2
            write_decode_error_s2m.w.ready <= '0';
232
233
2
            assert not axi_lite_s2m.write.b.valid;
234

2
            write_decode_error_s2m.b.valid <= '1';
235
236

4
            state <= decode_error_b;
237
          end if;
238
239
        when decode_error_b =>
240
2
          if axi_lite_m2s.write.b.ready and axi_lite_s2m.write.b.valid then
241

2
            write_decode_error_s2m.b.valid <= '0';
242
243

2
            write_slave_select <= slave_not_selected_idx;
244

2
            state <= waiting;
245
          end if;
246
247
        when writing =>
248
1206
          if axi_lite_m2s.write.b.ready and axi_lite_s2m.write.b.valid then
249

221
            write_slave_select <= slave_not_selected_idx;
250

8110
            state <= waiting;
251
          end if;
252
      end case;
253
    end process;
254
  end block;
255
256
end architecture;