OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [ambalib/] [axictrl.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
-----------------------------------------------------------------------------
2
--! @file
3
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
5
--! @details   Implementation of the axictrl device. 
6
------------------------------------------------------------------------------
7
 
8
library ieee;
9
use ieee.std_logic_1164.all;
10
library commonlib;
11
use commonlib.types_common.all;
12
library ambalib;
13
use ambalib.types_amba4.all;
14
 
15
--! @brief   AXI (NASTI) bus controller. 
16
--! @details Simplified version with the hardcoded priorities to bus access.
17
--!          Lower master index has a higher priority.
18
--! @todo    Round-robin algorithm for the master selection.
19
entity axictrl is
20
  generic (
21
    watchdog_memop : integer := 0
22
  );
23
  port (
24
    i_clk    : in std_logic;
25
    i_nrst   : in std_logic;
26
    i_slvcfg : in  nasti_slave_cfg_vector;
27
    i_slvo   : in  nasti_slaves_out_vector;
28
    i_msto   : in  nasti_master_out_vector;
29
    o_slvi   : out nasti_slave_in_vector;
30
    o_msti   : out nasti_master_in_vector;
31
    o_miss_irq  : out std_logic;
32
    o_miss_addr : out std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0);
33
    o_bus_util_w : out std_logic_vector(CFG_NASTI_MASTER_TOTAL-1 downto 0);
34
    o_bus_util_r : out std_logic_vector(CFG_NASTI_MASTER_TOTAL-1 downto 0)
35
  );
36
end;
37
 
38
architecture arch_axictrl of axictrl is
39
 
40
  constant MISS_ACCESS_SLAVE : nasti_slave_out_type := (
41
      '1', '1', '0', NASTI_RESP_EXOKAY,
42
      (others=>'0'), '0', '1', '0', NASTI_RESP_EXOKAY, (others=>'1'),
43
      '1', (others=>'0'), '0');
44
 
45
  type nasti_master_out_vector_miss is array (0 to CFG_NASTI_MASTER_TOTAL)
46
       of nasti_master_out_type;
47
 
48
  type nasti_master_in_vector_miss is array (0 to CFG_NASTI_MASTER_TOTAL)
49
       of nasti_master_in_type;
50
 
51
  type nasti_slave_out_vector_miss is array (0 to CFG_NASTI_SLAVES_TOTAL)
52
       of nasti_slave_out_type;
53
 
54
  type nasti_slave_in_vector_miss is array (0 to CFG_NASTI_SLAVES_TOTAL)
55
       of nasti_slave_in_type;
56
 
57
  type slave_selector_type is array (0 to CFG_NASTI_MASTER_TOTAL-1)
58
      of integer range 0 to CFG_NASTI_SLAVES_TOTAL;
59
 
60
  type reg_type is record
61
     w_busy : std_logic;
62
     w_mst_idx : integer range 0 to CFG_NASTI_MASTER_TOTAL;
63
     w_slv_idx : integer range 0 to CFG_NASTI_SLAVES_TOTAL; -- +1 miss access
64
     r_busy : std_logic;
65
     r_mst_idx : integer range 0 to CFG_NASTI_MASTER_TOTAL;
66
     r_slv_idx : integer range 0 to CFG_NASTI_SLAVES_TOTAL; -- +1 miss access
67
     b_busy : std_logic;
68
     b_mst_idx : integer range 0 to CFG_NASTI_MASTER_TOTAL;
69
     b_slv_idx : integer range 0 to CFG_NASTI_SLAVES_TOTAL; -- +1 miss access
70
 
71
     miss_addr : std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0);
72
  end record;
73
 
74
  signal rin, r : reg_type;
75
begin
76
 
77
  comblogic : process(i_nrst, i_slvcfg, i_msto, i_slvo, r)
78
    variable v : reg_type;
79
    variable missaccess : std_logic;
80
    variable ar_mst_idx : integer range 0 to CFG_NASTI_MASTER_TOTAL;
81
    variable aw_mst_idx : integer range 0 to CFG_NASTI_MASTER_TOTAL;
82
    variable ar_slv_idx : integer range 0 to CFG_NASTI_SLAVES_TOTAL; -- +1 miss access
83
    variable aw_slv_idx : integer range 0 to CFG_NASTI_SLAVES_TOTAL; -- +1 miss access
84
    variable vmsto : nasti_master_out_vector_miss;
85
    variable vmsti : nasti_master_in_vector_miss;
86
    variable vslvi : nasti_slave_in_vector_miss;
87
    variable vslvo : nasti_slave_out_vector_miss;
88
    variable aw_fire : std_logic;
89
    variable ar_fire : std_logic;
90
    variable w_fire : std_logic;
91
    variable w_available : std_logic;
92
    variable r_fire : std_logic;
93
    variable r_available : std_logic;
94
    variable b_fire : std_logic;
95
    variable b_available : std_logic;
96
    -- Bus statistic signals
97
    variable wb_bus_util_w : std_logic_vector(CFG_NASTI_MASTER_TOTAL downto 0);
98
    variable wb_bus_util_r : std_logic_vector(CFG_NASTI_MASTER_TOTAL downto 0);
99
 
100
  begin
101
 
102
    v := r;
103
 
104
    missaccess := '0';
105
    wb_bus_util_w := (others => '0');
106
    wb_bus_util_r := (others => '0');
107
    ar_mst_idx := CFG_NASTI_MASTER_TOTAL;   -- Default master is empty master
108
    aw_mst_idx := CFG_NASTI_MASTER_TOTAL;   -- Default master is empty master
109
    ar_slv_idx := CFG_NASTI_SLAVES_TOTAL;   -- miss access index
110
    aw_slv_idx := CFG_NASTI_SLAVES_TOTAL;   -- miss access index
111
 
112
    for n in 0 to CFG_NASTI_MASTER_TOTAL-1 loop
113
       vmsto(n) := i_msto(n);
114
       vmsti(n) := nasti_master_in_none;
115
    end loop;
116
    vmsto(CFG_NASTI_MASTER_TOTAL) := nasti_master_out_none;
117
    vmsti(CFG_NASTI_MASTER_TOTAL) := nasti_master_in_none;
118
    for k in 0 to CFG_NASTI_SLAVES_TOTAL-1 loop
119
       vslvo(k) := i_slvo(k);
120
       vslvi(k) := nasti_slave_in_none;
121
    end loop;
122
    vslvo(CFG_NASTI_SLAVES_TOTAL) := MISS_ACCESS_SLAVE;
123
    vslvi(CFG_NASTI_SLAVES_TOTAL) := nasti_slave_in_none;
124
 
125
    -- Select master bus:
126
    for n in 0 to CFG_NASTI_MASTER_TOTAL-1 loop
127
       if i_msto(n).ar_valid = '1' then
128
          ar_mst_idx := n;
129
       end if;
130
       if i_msto(n).aw_valid = '1' then
131
          aw_mst_idx := n;
132
       end if;
133
    end loop;
134
 
135
    -- Adress Read/Address Write channels
136
    for k in 0 to CFG_NASTI_SLAVES_TOTAL-1 loop
137
      if i_slvcfg(k).xmask /= X"00000" and
138
         (vmsto(ar_mst_idx).ar_bits.addr(CFG_NASTI_ADDR_BITS-1 downto 12)
139
          and i_slvcfg(k).xmask) = i_slvcfg(k).xaddr then
140
          ar_slv_idx := k;
141
      end if;
142
      if i_slvcfg(k).xmask /= X"00000" and
143
         (vmsto(aw_mst_idx).aw_bits.addr(CFG_NASTI_ADDR_BITS-1 downto 12)
144
          and i_slvcfg(k).xmask) = i_slvcfg(k).xaddr then
145
          aw_slv_idx := k;
146
      end if;
147
    end loop;
148
 
149
    -- Statistic
150
    wb_bus_util_w(r.w_mst_idx) := r.w_busy;
151
    wb_bus_util_r(r.r_mst_idx) := r.r_busy;
152
 
153
    -- Pipeline
154
    --! @todo It is possible to implement inpendent channels of same type for each
155
    --!       master slot and process transactions to separate slaves simultaneously.
156
    --!       I think it will be usefull feature but doesn't increase CPI of 
157
    --!       single core.
158
 
159
    -- Read Channel:
160
    r_fire := vmsto(r.r_mst_idx).r_ready and vslvo(r.r_slv_idx).r_valid and vslvo(r.r_slv_idx).r_last;
161
    r_available := not r.r_busy or (r.r_busy and r_fire);
162
    ar_fire := vmsto(ar_mst_idx).ar_valid and vslvo(ar_slv_idx).ar_ready and r_available;
163
    -- Write channel:
164
    w_fire := vmsto(r.w_mst_idx).w_valid and vslvo(r.w_slv_idx).w_ready and vmsto(r.w_mst_idx).w_last;
165
    w_available := not r.w_busy or (r.w_busy and w_fire);
166
    aw_fire := vmsto(aw_mst_idx).aw_valid and vslvo(aw_slv_idx).aw_ready and w_available;
167
 
168
    vmsti(ar_mst_idx).ar_ready := vslvo(ar_slv_idx).ar_ready and r_available;
169
    vslvi(ar_slv_idx).ar_valid := vmsto(ar_mst_idx).ar_valid and r_available;
170
    vslvi(ar_slv_idx).ar_bits  := vmsto(ar_mst_idx).ar_bits;
171
    vslvi(ar_slv_idx).ar_id    := vmsto(ar_mst_idx).ar_id;
172
    vslvi(ar_slv_idx).ar_user  := vmsto(ar_mst_idx).ar_user;
173
 
174
    vmsti(aw_mst_idx).aw_ready := vslvo(aw_slv_idx).aw_ready and w_available;
175
    vslvi(aw_slv_idx).aw_valid := vmsto(aw_mst_idx).aw_valid and w_available;
176
    vslvi(aw_slv_idx).aw_bits  := vmsto(aw_mst_idx).aw_bits;
177
    vslvi(aw_slv_idx).aw_id    := vmsto(aw_mst_idx).aw_id;
178
    vslvi(aw_slv_idx).aw_user  := vmsto(aw_mst_idx).aw_user;
179
 
180
    if (w_available and aw_fire) = '1' then
181
        v.w_busy := '1';
182
        v.w_slv_idx := aw_slv_idx;
183
        v.w_mst_idx := aw_mst_idx;
184
    end if;
185
 
186
    vmsti(r.w_mst_idx).w_ready := vslvo(r.w_slv_idx).w_ready;
187
    vslvi(r.w_slv_idx).w_valid := vmsto(r.w_mst_idx).w_valid;
188
    vslvi(r.w_slv_idx).w_data := vmsto(r.w_mst_idx).w_data;
189
    vslvi(r.w_slv_idx).w_last := vmsto(r.w_mst_idx).w_last;
190
    vslvi(r.w_slv_idx).w_strb := vmsto(r.w_mst_idx).w_strb;
191
    vslvi(r.w_slv_idx).w_user := vmsto(r.w_mst_idx).w_user;
192
 
193
    -- Write Handshake channel:
194
    b_fire := vmsto(r.b_mst_idx).b_ready and vslvo(r.b_slv_idx).b_valid;
195
    b_available := not r.b_busy or (r.b_busy and b_fire);
196
    if (b_available and w_fire) = '1' then
197
        v.w_busy := '0';
198
        v.b_busy := '1';
199
        v.b_slv_idx := r.w_slv_idx;
200
        v.b_mst_idx := r.w_mst_idx;
201
    end if;
202
    if b_fire = '1' then
203
        v.b_busy := w_fire;
204
    end if;
205
 
206
    vmsti(r.b_mst_idx).b_valid := vslvo(r.b_slv_idx).b_valid;
207
    vmsti(r.b_mst_idx).b_resp := vslvo(r.b_slv_idx).b_resp;
208
    vmsti(r.b_mst_idx).b_id := vslvo(r.b_slv_idx).b_id;
209
    vmsti(r.b_mst_idx).b_user := vslvo(r.b_slv_idx).b_user;
210
    vslvi(r.b_slv_idx).b_ready := vmsto(r.b_mst_idx).b_ready;
211
 
212
    if (r_available and ar_fire) = '1' then
213
        v.r_busy := '1';
214
        v.r_slv_idx := ar_slv_idx;
215
        v.r_mst_idx := ar_mst_idx;
216
    end if;
217
    if r_fire = '1' then
218
        v.r_busy := ar_fire;
219
    end if;
220
 
221
    vmsti(r.r_mst_idx).r_valid := vslvo(r.r_slv_idx).r_valid;
222
    vmsti(r.r_mst_idx).r_resp  := vslvo(r.r_slv_idx).r_resp;
223
    vmsti(r.r_mst_idx).r_data  := vslvo(r.r_slv_idx).r_data;
224
    vmsti(r.r_mst_idx).r_last  := vslvo(r.r_slv_idx).r_last;
225
    vmsti(r.r_mst_idx).r_id    := vslvo(r.r_slv_idx).r_id;
226
    vmsti(r.r_mst_idx).r_user  := vslvo(r.r_slv_idx).r_user;
227
    vslvi(r.r_slv_idx).r_ready := vmsto(r.r_mst_idx).r_ready;
228
 
229
    if aw_fire = '1' and aw_slv_idx = CFG_NASTI_SLAVES_TOTAL then
230
       missaccess := '1';
231
       v.miss_addr := vmsto(aw_mst_idx).aw_bits.addr;
232
    end if;
233
    if ar_fire = '1' and ar_slv_idx = CFG_NASTI_SLAVES_TOTAL then
234
       missaccess := '1';
235
       v.miss_addr := vmsto(ar_mst_idx).ar_bits.addr;
236
    end if;
237
 
238
    if i_nrst = '0' then
239
      v.w_busy := '0';
240
      v.w_mst_idx := CFG_NASTI_MASTER_TOTAL;
241
      v.w_slv_idx := CFG_NASTI_SLAVES_TOTAL;
242
      v.r_busy := '0';
243
      v.r_mst_idx := CFG_NASTI_MASTER_TOTAL;
244
      v.r_slv_idx := CFG_NASTI_SLAVES_TOTAL;
245
      v.b_busy := '0';
246
      v.b_mst_idx := CFG_NASTI_MASTER_TOTAL;
247
      v.b_slv_idx := CFG_NASTI_SLAVES_TOTAL;
248
      v.miss_addr := (others => '0');
249
    end if;
250
 
251
    rin <= v;
252
 
253
    for k in 0 to CFG_NASTI_MASTER_TOTAL-1 loop
254
       o_msti(k) <= vmsti(k);
255
    end loop;
256
    for k in 0 to CFG_NASTI_SLAVES_TOTAL-1 loop
257
       o_slvi(k) <= vslvi(k);
258
    end loop;
259
    o_miss_irq <= missaccess;
260
    o_miss_addr <= r.miss_addr;
261
    o_bus_util_w <= wb_bus_util_w(CFG_NASTI_MASTER_TOTAL-1 downto 0);
262
    o_bus_util_r <= wb_bus_util_r(CFG_NASTI_MASTER_TOTAL-1 downto 0);
263
  end process;
264
 
265
  reg0 : process(i_clk) begin
266
     if rising_edge(i_clk) then
267
        r <= rin;
268
     end if;
269
  end process;
270
end;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.