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

Subversion Repositories simpcon

[/] [simpcon/] [trunk/] [vhdl/] [sc_arbiter.vhd] - Blame information for rev 29

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 21 martin
 
2
 
3
-- 150407: first working version with records
4
-- 170407: produce number of registers depending on the cpu_cnt
5
-- 110507: * arbiter that can be used with prefered number of masters
6
--                               * full functional arbiter with two masters
7
--                               * short modelsim test with 3 masters carried out
8
-- 190607: Problem found: Both CPU1 and CPU2 start to read cache line!!!
9
-- 030707: Several bugs are fixed now. CMP with 3 running masters functions!
10
 
11
 
12
library ieee;
13
use ieee.std_logic_1164.all;
14
use ieee.numeric_std.all;
15
 
16
use work.sc_pack.all;
17
use work.sc_arbiter_pack.all;
18
 
19
entity arbiter is
20
generic(
21
                        addr_bits : integer;
22
                        cpu_cnt : integer);             -- number of masters for the arbiter
23
port (
24
                        clk, reset      : in std_logic;
25
                        arb_out                 : in arb_out_type(0 to cpu_cnt-1);
26
                        arb_in                  : out arb_in_type(0 to cpu_cnt-1);
27
                        mem_out                 : out sc_mem_out_type;
28
                        mem_in                  : in sc_in_type
29
);
30
end arbiter;
31
 
32
 
33
architecture rtl of arbiter is
34
 
35
-- signals for the input register of each master
36
 
37
        type reg_type is record
38
                rd : std_logic;
39
                wr : std_logic;
40
                wr_data : std_logic_vector(31 downto 0);
41
                address : std_logic_vector(addr_bits-1 downto 0);
42
        end record;
43
 
44
        type reg_array_type is array (0 to cpu_cnt-1) of reg_type;
45
        signal reg_in : reg_array_type;
46
 
47
-- one fsm for each CPU
48
 
49
        type state_type is (idle, read, write, waitingR, sendR,
50
        waitingW, sendW);
51
        type state_array is array (0 to cpu_cnt-1) of state_type;
52
        signal state : state_array;
53
        signal next_state : state_array;
54
 
55
-- one fsm for each serve
56
 
57
        type serve_type is (idl, serv);
58
        type serve_array is array (0 to cpu_cnt-1) of serve_type;
59
        signal this_state : serve_array;
60
        signal follow_state : serve_array;
61
 
62
-- arbiter
63
 
64
        type set_type is array (0 to cpu_cnt-1) of std_logic;
65
        signal set : set_type;
66
        signal waiting : set_type;
67
        signal masterWaiting : std_logic;
68
 
69
 
70
begin
71
 
72
 
73
-- Generates the input register and saves incoming data for each master
74
gen_register: for i in 0 to cpu_cnt-1 generate
75
        process(clk, reset)
76
        begin
77
                if reset = '1' then
78
                        reg_in(i).rd <= '0';
79
                        reg_in(i).wr <= '0';
80
                        reg_in(i).wr_data <= (others => '0');
81
                        reg_in(i).address <= (others => '0');
82
                elsif rising_edge(clk) then
83
                        if arb_out(i).rd = '1' or arb_out(i).wr = '1' then
84
                        reg_in(i).rd <= arb_out(i).rd;
85
                                reg_in(i).wr <= arb_out(i).wr;
86
                                reg_in(i).address <= arb_out(i).address;
87
                                reg_in(i).wr_data <= arb_out(i).wr_data;
88
                        end if;
89
                end if;
90
        end process;
91
end generate;
92
 
93
-- Register for masterWaiting
94
process(clk, reset)
95
        begin
96
                if reset = '1' then
97
                        masterWaiting <= '0';
98
                elsif rising_edge(clk) then
99
                        for i in 0 to cpu_cnt-1 loop
100
                                if waiting(i) = '1' then
101
                                        masterWaiting <= '1';
102
                                        exit;
103
                                else
104
                                        masterWaiting <= '0';
105
                                end if;
106
                        end loop;
107
                end if;
108
        end process;
109
 
110
-- Generates next state of the FSM for each master
111
gen_next_state: for i in 0 to cpu_cnt-1 generate
112
        process(reset, state, arb_out, mem_in, this_state, reg_in, masterWaiting)
113
        begin
114
 
115
                next_state(i) <= state(i);
116
                waiting(i) <= '0';
117
 
118
                case state(i) is
119
                        when idle =>
120
 
121
                                -- checks if this CPU is on turn (pipelined access)
122
                                if this_state(i) = serv then
123
                                        -- pipelined access
124
                                        if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then
125
                                                next_state(i) <= read;
126
 
127
                                        elsif (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then
128
 
129
                                                -- check if some master is waiting
130
                                                if masterWaiting = '1' then
131
                                                        if arb_out(i).rd = '1' then
132
                                                                next_state(i) <= waitingR;
133
                                                                waiting(i) <= '1';
134
                                                        elsif arb_out(i).wr = '1' then
135
                                                                next_state(i) <= waitingW;
136
                                                                waiting(i) <= '1';
137
                                                        end if;
138
 
139
                                                -- check if parallel access             
140
                                                else
141
                                                        for j in 0 to cpu_cnt-1 loop
142
                                                                if arb_out(j).rd = '1' or arb_out(j).wr = '1' then
143
                                                                        if i<=j then
144
                                                                                if arb_out(i).rd = '1' then
145
                                                                                        next_state(i) <= read;
146
                                                                                        exit;
147
                                                                                elsif arb_out(i).wr = '1' then
148
                                                                                        next_state(i) <= write;
149
                                                                                        exit;
150
                                                                                end if;
151
                                                                        else
152
                                                                                if arb_out(i).rd = '1' then
153
                                                                                        next_state(i) <= waitingR;
154
                                                                                        waiting(i) <= '1';
155
                                                                                        exit;
156
                                                                                elsif arb_out(i).wr = '1' then
157
                                                                                        next_state(i) <= waitingW;
158
                                                                                        waiting(i) <= '1';
159
                                                                                        exit;
160
                                                                                end if;
161
                                                                        end if;
162
                                                                end if;
163
                                                        end loop;
164
                                                end if;
165
 
166
                                        -- all other kinds of rdy_cnt
167
                                        else
168
                                                if arb_out(i).rd = '1' then
169
                                                        next_state(i) <= waitingR;
170
                                                        waiting(i) <= '1';
171
                                                elsif arb_out(i).wr = '1' then
172
                                                        next_state(i) <= waitingW;
173
                                                        waiting(i) <= '1';
174
                                                end if;
175
                                        end if;
176
 
177
                                -- CPU is not on turn (no pipelined access possible)
178
                                else
179
                                        if (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then
180
                                                -- check if some master is waiting
181
                                                if masterWaiting = '1' then
182
                                                        if arb_out(i).rd = '1' then
183
                                                                next_state(i) <= waitingR;
184
                                                                waiting(i) <= '1';
185
                                                        elsif arb_out(i).wr = '1' then
186
                                                                next_state(i) <= waitingW;
187
                                                                waiting(i) <= '1';
188
                                                        end if;
189
 
190
                                                -- check if parallel access             
191
                                                else
192
                                                        for j in 0 to cpu_cnt-1 loop
193
                                                                if arb_out(j).rd = '1' or arb_out(j).wr = '1' then
194
                                                                        if i<=j then
195
                                                                                if arb_out(i).rd = '1' then
196
                                                                                        next_state(i) <= read;
197
                                                                                        exit;
198
                                                                                elsif arb_out(i).wr = '1' then
199
                                                                                        next_state(i) <= write;
200
                                                                                        exit;
201
                                                                                end if;
202
                                                                        else
203
                                                                                if arb_out(i).rd = '1' then
204
                                                                                        next_state(i) <= waitingR;
205
                                                                                        waiting(i) <= '1';
206
                                                                                        exit;
207
                                                                                elsif arb_out(i).wr = '1' then
208
                                                                                        next_state(i) <= waitingW;
209
                                                                                        waiting(i) <= '1';
210
                                                                                        exit;
211
                                                                                end if;
212
                                                                        end if;
213
                                                                -- if no parallel access, master can access
214
                                                                else
215
                                                                        if arb_out(i).rd = '1' then
216
                                                                                next_state(i) <= read;
217
                                                                        elsif arb_out(i).wr = '1' then
218
                                                                                next_state(i) <= write;
219
                                                                        end if;
220
                                                                end if;
221
                                                        end loop;
222
                                                end if;
223
 
224
                                        -- rdy_cnt != 0 
225
                                        else
226
                                                if arb_out(i).rd = '1' then
227
                                                        next_state(i) <= waitingR;
228
                                                        waiting(i) <= '1';
229
                                                elsif arb_out(i).wr = '1' then
230
                                                        next_state(i) <= waitingW;
231
                                                        waiting(i) <= '1';
232
                                                end if;
233
                                        end if;
234
                                end if;
235
 
236
 
237
                        when read =>
238
                                next_state(i) <= idle;
239
 
240
                        when write =>
241
                                next_state(i) <= idle;
242
 
243
                        when waitingR =>
244
                                if mem_in.rdy_cnt = 0 then
245
                                -- checks which CPU in waitingR has highest priority
246
                                        for j in 0 to cpu_cnt-1 loop
247
                                                if (state(j) = waitingR) or (state(j) = waitingW) then
248
                                                        if j<i then
249
                                                                next_state(i) <= waitingR;
250
                                                                waiting(i) <= '1';
251
                                                                exit;
252
                                                        elsif j=i then
253
                                                                next_state(i) <= sendR;
254
                                                                exit;
255
                                                        else
256
                                                                next_state(i) <= sendR;
257
                                                                exit;
258
                                                        end if;
259
                                                else
260
                                                        next_state(i) <= sendR;
261
                                                end if;
262
                                        end loop;
263
                                else
264
                                        next_state(i) <= waitingR;
265
                                        waiting(i) <= '1';
266
                                end if;
267
 
268
                        when sendR =>
269
                                next_state(i) <= idle;
270
 
271
                        when waitingW =>
272
 
273
                                if mem_in.rdy_cnt = 0 then
274
                                        for j in 0 to cpu_cnt-1 loop
275
                                                if (state(j) = waitingR) or (state(j) = waitingW) then
276
                                                        if j<i then
277
                                                                next_state(i) <= waitingW;
278
                                                                waiting(i) <= '1';
279
                                                                exit;
280
                                                        elsif j=i then
281
                                                                next_state(i) <= sendW;
282
                                                                exit;
283
                                                        else
284
                                                                next_state(i) <= sendW;
285
                                                                exit;
286
                                                        end if;
287
                                                else
288
                                                        next_state(i) <= sendW;
289
                                                end if;
290
                                        end loop;
291
                                else
292
                                        next_state(i) <= waitingW;
293
                                        waiting(i) <= '1';
294
                                end if;
295
 
296
                        when sendW =>
297
                                next_state(i) <= idle;
298
 
299
                end case;
300
        end process;
301
end generate;
302
 
303
 
304
-- Generates the FSM state for each master
305
gen_state: for i in 0 to cpu_cnt-1 generate
306
        process (clk, reset)
307
        begin
308
                if (reset = '1') then
309
                        state(i) <= idle;
310
        elsif (rising_edge(clk)) then
311
                        state(i) <= next_state(i);
312
                end if;
313
        end process;
314
end generate;
315
 
316
 
317
-- The arbiter output
318
process (arb_out, reg_in, next_state)
319
begin
320
 
321
        mem_out.rd <= '0';
322
        mem_out.wr <= '0';
323
        mem_out.address <= (others => '0');
324
        mem_out.wr_data <= (others => '0');
325
 
326
        for i in 0 to cpu_cnt-1 loop
327
                set(i) <= '0';
328
 
329
                case next_state(i) is
330
                        when idle =>
331
 
332
                        when read =>
333
                                set(i) <= '1';
334
                                mem_out.rd <= arb_out(i).rd;
335
                                mem_out.address <= arb_out(i).address;
336
 
337
                        when write =>
338
                                set(i) <= '1';
339
                                mem_out.wr <= arb_out(i).wr;
340
                                mem_out.address <= arb_out(i).address;
341
                                mem_out.wr_data <= arb_out(i).wr_data;
342
 
343
                        when waitingR =>
344
 
345
                        when sendR =>
346
                                set(i) <= '1';
347
                                mem_out.rd <= reg_in(i).rd;
348
                                mem_out.address <= reg_in(i).address;
349
 
350
                        when waitingW =>
351
 
352
                        when sendW =>
353
                                set(i) <= '1';
354
                                mem_out.wr <= reg_in(i).wr;
355
                                mem_out.address <= reg_in(i).address;
356
                                mem_out.wr_data <= reg_in(i).wr_data;
357
 
358
                end case;
359
        end loop;
360
end process;
361
 
362
-- generation of follow_state
363
gen_serve: for i in 0 to cpu_cnt-1 generate
364
        process(mem_in, set, this_state)
365
        begin
366
                case this_state(i) is
367
                        when idl =>
368
                                follow_state(i) <= idl;
369
                                if set(i) = '1' then
370
                                        follow_state(i) <= serv;
371
                                end if;
372
                        when serv =>
373
                                follow_state(i) <= serv;
374
                                if mem_in.rdy_cnt = 0 and set(i) = '0' then
375
                                        follow_state(i) <= idl;
376
                                end if;
377
                end case;
378
        end process;
379
end generate;
380
 
381
gen_serve2: for i in 0 to cpu_cnt-1 generate
382
        process (clk, reset)
383
        begin
384
                if (reset = '1') then
385
                        this_state(i) <= idl;
386
        elsif (rising_edge(clk)) then
387
                        this_state(i) <= follow_state(i);
388
                end if;
389
        end process;
390
end generate;
391
 
392
gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate
393
        process (mem_in, state, this_state)
394
        begin
395
                arb_in(i).rdy_cnt <= mem_in.rdy_cnt;
396
                arb_in(i).rd_data <= mem_in.rd_data;
397
 
398
                case state(i) is
399
                        when idle =>
400
                                case this_state(i) is
401
                                        when idl =>
402
                                                arb_in(i).rdy_cnt <= "00";
403
                                        when serv =>
404
                                end case;
405
 
406
                        when read =>
407
 
408
                        when write =>
409
 
410
                        when waitingR =>
411
                                arb_in(i).rdy_cnt <= "11";
412
 
413
                        when sendR =>
414
 
415
                        when waitingW =>
416
                                arb_in(i).rdy_cnt <= "11";
417
 
418
                        when sendW =>
419
 
420
                end case;
421
        end process;
422
end generate;
423
 
424
end rtl;

powered by: WebSVN 2.1.0

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