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

Subversion Repositories simpcon

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 29 martin
--
2
--  This file is part of JOP, the Java Optimized Processor
3
--
4
--  Copyright (C) 2007,2008, Christof Pitter
5
--
6
--  This program is free software: you can redistribute it and/or modify
7
--  it under the terms of the GNU General Public License as published by
8
--  the Free Software Foundation, either version 3 of the License, or
9
--  (at your option) any later version.
10
--
11
--  This program is distributed in the hope that it will be useful,
12
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
--  GNU General Public License for more details.
15
--
16
--  You should have received a copy of the GNU General Public License
17
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
--
19
 
20
 
21
 
22
 
23
-- 150407: first working version with records
24
-- 170407: produce number of registers depending on the cpu_cnt
25
-- 110507: * arbiter that can be used with prefered number of masters
26
--                               * full functional arbiter with two masters
27
--                               * short modelsim test with 3 masters carried out
28
-- 190607: Problem found: Both CPU1 and CPU2 start to read cache line!!!
29
-- 030707: Several bugs are fixed now. CMP with 3 running masters functions!
30
-- 150108: Quasi Round Robin Arbiter -- added sync signal to arbiter
31
-- 160108: First tests running with new Round Robin Arbiter
32
-- 190208: Development of TDMA Arbiter
33
-- 130308: * Renaming of this_state to mode, follow_state to next_mode
34
--                               * counter dependencies moved from FSM to slot generation
35
--                               * changed set to 2 bits
36
--                               * changed serv to servR and servW
37
--                               * added signal pipelined
38
--                               * added rd_data register for each CPU
39
-- 140308: Working version
40
-- 070808: removed combinatorial loop (pipelined bug)
41
-- 210808: - reg_in_rd_data(i) also gets loaded when rdy_cnt = 3 using pipelined access
42
--                               - arb_in(i).rd_data gets mem_in.rd_data when rdy_cnt 3 using pipelined access
43
 
44
-- TODO:  - Add atomic for Wolfgang
45
--                              - full pipelined version
46
--                              - add period and time slots from software using RAM
47
 
48
 
49
 
50
library ieee;
51
use ieee.std_logic_1164.all;
52
use ieee.numeric_std.all;
53
 
54
use work.sc_pack.all;
55
use work.sc_arbiter_pack.all;
56
use work.jop_types.all;
57
 
58
entity arbiter is
59
generic(
60
                        addr_bits : integer;
61
                        cpu_cnt : integer);             -- number of masters for the arbiter
62
port (
63
                        clk, reset      : in std_logic;
64
                        arb_out                 : in arb_out_type(0 to cpu_cnt-1);
65
                        arb_in                  : out arb_in_type(0 to cpu_cnt-1);
66
                        mem_out                 : out sc_out_type;
67
                        mem_in                  : in sc_in_type
68
);
69
end arbiter;
70
 
71
 
72
architecture rtl of arbiter is
73
 
74
-- stores the signals in a register of each master
75
 
76
        type reg_type is record
77
                rd : std_logic;
78
                wr : std_logic;
79
                wr_data : std_logic_vector(31 downto 0);
80
                address : std_logic_vector(addr_bits-1 downto 0);
81
        end record;
82
 
83
        type reg_out_type is array (0 to cpu_cnt-1) of reg_type;
84
        signal reg_out : reg_out_type;
85
 
86
-- register to CPU for rd_data
87
 
88
        type reg_in_type is array (0 to cpu_cnt-1) of std_logic_vector(31 downto 0);
89
        signal reg_in_rd_data : reg_in_type;
90
 
91
-- one fsm for each CPU
92
 
93
        type state_type is (idle, read, write, waitingR, sendR,
94
        waitingW, sendW);
95
        type state_array is array (0 to cpu_cnt-1) of state_type;
96
        signal state : state_array;
97
        signal next_state : state_array;
98
 
99
-- one fsm for each serve
100
 
101
        type serve_type is (idl, servR, servW);
102
        type serve_array is array (0 to cpu_cnt-1) of serve_type;
103
        signal mode : serve_array;
104
        signal next_mode : serve_array;
105
 
106
-- arbiter 
107
 
108
        type set_type is array (0 to cpu_cnt-1) of std_logic_vector(1 downto 0);
109
        signal set : set_type;
110
        type pipelined_type is array (0 to cpu_cnt-1) of std_logic;
111
        signal pipelined : pipelined_type;
112
        signal next_pipelined : pipelined_type;
113
 
114
-- counter
115
        signal counter : integer;
116
        signal period   : integer;
117
        signal slot_length : integer;
118
        type time_type is array (0 to cpu_cnt-1) of integer;
119
        signal cpu_time : time_type; -- how much clock cycles each CPU
120
        type slot_type is array (0 to cpu_cnt-1) of std_logic;
121
        signal slot : slot_type; -- defines which CPU is on turn
122
 
123
-- read and write gaps
124
 
125
        signal read_gap : integer;
126
        signal write_gap : integer;
127
 
128
 
129
begin
130
 
131
-- Constants for read_gap, write_gap, slot_length:
132
-- DE2 board:   6 cycle memory write, 4 cycle memory read
133
--              write_gap <= 5; read_gap <= 3;
134
--              minimal slot_length <= 6;
135
-- cyc12 board: 3 cycle memory write, 2 cycle memory read
136
--              write_gap <= 2; read_gap <= 1;
137
--              minimal slot_length <= 3;
138
 
139
write_gap <= 2;
140
read_gap <= 1;
141
slot_length <=7;
142
period <= cpu_cnt*slot_length;
143
 
144
-- generate slot information
145
slots: for i in 0 to cpu_cnt-1 generate
146
        cpu_time(i) <= (i+1)*slot_length;
147
end generate;
148
 
149
-- TODO: should really be configrable with: number of CPUs, slot length,
150
-- and memory access time. Should use assert to check that the slot length
151
-- is longer than the memory access time.
152
 
153
 
154
-- Generates the input register and saves incoming data for each master
155
gen_register: for i in 0 to cpu_cnt-1 generate
156
        process(clk, reset)
157
        begin
158
                if reset = '1' then
159
                        reg_out(i).rd <= '0';
160
                        reg_out(i).wr <= '0';
161
                        reg_out(i).wr_data <= (others => '0');
162
                        reg_out(i).address <= (others => '0');
163
                elsif rising_edge(clk) then
164
                        if arb_out(i).rd = '1' or arb_out(i).wr = '1' then
165
                                reg_out(i).rd <= arb_out(i).rd;
166
                                reg_out(i).wr <= arb_out(i).wr;
167
                                reg_out(i).address <= arb_out(i).address;
168
                                reg_out(i).wr_data <= arb_out(i).wr_data;
169
                        end if;
170
                end if;
171
        end process;
172
end generate;
173
 
174
-- Generate Counter
175
process(clk, reset)
176
        begin
177
                if reset = '1' then
178
                        counter <= 0;
179
                elsif rising_edge(clk) then
180
                        counter <= counter + 1;
181
                        if counter = period-1 then
182
                                counter <= 0;
183
                        end if;
184
                end if;
185
end process;
186
 
187
-- A time slot is assigned to each CPU 
188
process(counter, cpu_time, read_gap, write_gap, arb_out)
189
        begin
190
                for j in 0 to cpu_cnt-1 loop
191
                        slot(j) <= '0';
192
                end loop;
193
 
194
                if (counter > -1) and (counter < cpu_time(0)-write_gap) then
195
                        slot(0) <= '1';
196
                elsif (counter > -1) and (counter < cpu_time(0)-read_gap) and (arb_out(0).rd = '1') then -- rd is 2 cycles longer allowed
197
                        slot(0) <= '1';
198
 
199
                elsif (counter > cpu_time(0)-1) and (counter < cpu_time(1)-write_gap) then
200
                        slot(1) <= '1';
201
                elsif (counter > cpu_time(0)-1) and (counter < cpu_time(1)-read_gap) and (arb_out(1).rd = '1') then -- rd is 2 cycles longer allowed
202
                        slot(1) <= '1';
203
 
204
                elsif (counter > cpu_time(1)-1) and (counter < cpu_time(2)-write_gap) then
205
                        slot(2) <= '1';
206
                elsif (counter > cpu_time(1)-1) and (counter < cpu_time(2)-read_gap) and (arb_out(2).rd = '1') then -- rd is 2 cycles longer allowed
207
                        slot(2) <= '1';
208
--                      
209
--              elsif (counter > cpu_time(2)-1) and (counter < cpu_time(3)-write_gap) then
210
--                      slot(3) <= '1';
211
--              elsif (counter > cpu_time(2)-1) and (counter < cpu_time(3)-read_gap) and (arb_out(3).rd = '1') then -- rd is 2 cycles longer allowed
212
--                      slot(3) <= '1';
213
--                      
214
--              elsif (counter > cpu_time(3)-1) and (counter < cpu_time(4)-write_gap) then
215
--                      slot(4) <= '1';
216
--              elsif (counter > cpu_time(3)-1) and (counter < cpu_time(4)-read_gap) and (arb_out(4).rd = '1') then -- rd is 2 cycles longer allowed
217
--                      slot(4) <= '1';
218
--                      
219
--              elsif (counter > cpu_time(4)-1) and (counter < cpu_time(5)-write_gap) then
220
--                      slot(5) <= '1';
221
--              elsif (counter > cpu_time(4)-1) and (counter < cpu_time(5)-read_gap) and (arb_out(5).rd = '1') then -- rd is 2 cycles longer allowed
222
--                      slot(5) <= '1';
223
--                      
224
--              elsif (counter > cpu_time(5)-1) and (counter < cpu_time(6)-write_gap) then
225
--                      slot(6) <= '1';
226
--              elsif (counter > cpu_time(5)-1) and (counter < cpu_time(6)-read_gap) and (arb_out(6).rd = '1') then -- rd is 2 cycles longer allowed
227
--                      slot(6) <= '1';
228
--                      
229
--              elsif (counter > cpu_time(6)-1) and (counter < cpu_time(7)-write_gap) then
230
--                      slot(7) <= '1';
231
--              elsif (counter > cpu_time(6)-1) and (counter < cpu_time(7)-read_gap) and (arb_out(7).rd = '1') then -- rd is 2 cycles longer allowed
232
--                      slot(7) <= '1';
233
                end if;
234
end process;
235
 
236
 
237
-- Generates next state of the FSM for each master
238
gen_next_state: for i in 0 to cpu_cnt-1 generate
239
        process(state, mode, slot, counter, mem_in, arb_out, pipelined)
240
        begin
241
 
242
                next_state(i) <= state(i);
243
 
244
                case state(i) is
245
                        when idle =>
246
                                next_pipelined(i) <= '0';
247
 
248
                                -- is CPU allowed to access
249
                                if (slot(i) = '1') then
250
 
251
                                        -- pipelined read access
252
                                        if (mode(i) = servR) and (mem_in.rdy_cnt = 1) and (arb_out(i).rd = '1') then
253
                                                next_state(i) <= read;
254
                                                next_pipelined(i) <= '1';
255
 
256
                                        elsif (mode(i) = servR) and (mem_in.rdy_cnt = 0) then
257
                                                if arb_out(i).rd = '1' then
258
                                                        next_state(i) <= read;
259
                                                elsif arb_out(i).wr = '1' then
260
                                                        next_state(i) <= write;
261
                                                end if;
262
 
263
                                        elsif (mode(i) = servW) and (mem_in.rdy_cnt = 0) then
264
                                                if arb_out(i).rd = '1' then
265
                                                        next_state(i) <= read;
266
                                                elsif arb_out(i).wr = '1' then
267
                                                        next_state(i) <= write;
268
                                                end if;
269
 
270
                                        elsif (mode(i) = idl) and (mem_in.rdy_cnt = 0) then
271
                                                if arb_out(i).rd = '1' then
272
                                                        next_state(i) <= read;
273
                                                elsif arb_out(i).wr = '1' then
274
                                                        next_state(i) <= write;
275
                                                end if;
276
 
277
                                        -- all other kinds (can that happen at all?)
278
                                        else
279
                                                if arb_out(i).rd = '1' then
280
                                                        next_state(i) <= waitingR;
281
                                                elsif arb_out(i).wr = '1' then
282
                                                        next_state(i) <= waitingW;
283
                                                end if;
284
                                        end if;
285
 
286
                                -- CPU is not allowed to access
287
                                else
288
                                        if arb_out(i).rd = '1' then
289
                                                next_state(i) <= waitingR;
290
                                        elsif arb_out(i).wr = '1' then
291
                                                next_state(i) <= waitingW;
292
                                        end if;
293
                                end if;
294
 
295
                        when read =>
296
                                next_state(i) <= idle;
297
                                next_pipelined(i) <= '0';
298
 
299
                                if pipelined(i) = '1' then
300
                                        next_pipelined(i) <= '1';
301
                                end if;
302
 
303
                        when write =>
304
                                next_state(i) <= idle;
305
                                next_pipelined(i) <= '0';
306
 
307
                        when waitingR =>
308
                                next_pipelined(i) <= '0';
309
                                if ((mem_in.rdy_cnt = 0) and (slot(i) = '1')) then
310
                                        next_state(i) <= sendR;
311
                                else
312
                                        next_state(i) <= waitingR;
313
                                end if;
314
 
315
                        when sendR =>
316
                                next_state(i) <= idle;
317
                                next_pipelined(i) <= '0';
318
 
319
                        when waitingW =>
320
                                next_pipelined(i) <= '0';
321
                                if ((mem_in.rdy_cnt = 0) and (slot(i) = '1')) then
322
                                        next_state(i) <= sendW;
323
                                else
324
                                        next_state(i) <= waitingW;
325
                                end if;
326
 
327
                        when sendW =>
328
                                next_state(i) <= idle;
329
                                next_pipelined(i) <= '0';
330
 
331
                end case;
332
        end process;
333
end generate;
334
 
335
 
336
-- Generates the FSM state for each master
337
gen_state: for i in 0 to cpu_cnt-1 generate
338
        process (clk, reset)
339
        begin
340
                if (reset = '1') then
341
                        state(i) <= idle;
342
                        pipelined(i) <= '0';
343
        elsif (rising_edge(clk)) then
344
                        state(i) <= next_state(i);
345
                        pipelined(i) <= next_pipelined(i);
346
                end if;
347
        end process;
348
end generate;
349
 
350
 
351
-- The arbiter output
352
process (arb_out, reg_out, next_state)
353
begin
354
 
355
        mem_out.rd <= '0';
356
        mem_out.wr <= '0';
357
        mem_out.address <= (others => '0');
358
        mem_out.wr_data <= (others => '0');
359
        mem_out.atomic <= '0';
360
 
361
        for i in 0 to cpu_cnt-1 loop
362
                set(i) <= "00";
363
 
364
                case next_state(i) is
365
                        when idle =>
366
 
367
                        when read =>
368
                                set(i) <= "01";
369
                                mem_out.rd <= arb_out(i).rd;
370
                                mem_out.address <= arb_out(i).address;
371
 
372
                        when write =>
373
                                set(i) <= "10";
374
                                mem_out.wr <= arb_out(i).wr;
375
                                mem_out.address <= arb_out(i).address;
376
                                mem_out.wr_data <= arb_out(i).wr_data;
377
 
378
                        when waitingR =>
379
 
380
                        when sendR =>
381
                                set(i) <= "01";
382
                                mem_out.rd <= reg_out(i).rd;
383
                                mem_out.address <= reg_out(i).address;
384
 
385
                        when waitingW =>
386
 
387
                        when sendW =>
388
                                set(i) <= "10";
389
                                mem_out.wr <= reg_out(i).wr;
390
                                mem_out.address <= reg_out(i).address;
391
                                mem_out.wr_data <= reg_out(i).wr_data;
392
 
393
                end case;
394
        end loop;
395
end process;
396
 
397
-- generation of next_mode
398
gen_serve: for i in 0 to cpu_cnt-1 generate
399
        process(mem_in, set, mode)
400
        begin
401
                case mode(i) is
402
                        when idl =>
403
                                next_mode(i) <= idl;
404
                                if set(i) = "01" then
405
                                        next_mode(i) <= servR;
406
                                elsif set(i) = "10" then
407
                                        next_mode(i) <= servW;
408
                                end if;
409
                        when servR =>
410
                                next_mode(i) <= servR;
411
                                if mem_in.rdy_cnt = 0 and set(i) = "00" then
412
                                        next_mode(i) <= idl;
413
                                end if;
414
                        when servW =>
415
                                next_mode(i) <= servW;
416
                                if mem_in.rdy_cnt = 0 and set(i) = "00" then
417
                                        next_mode(i) <= idl;
418
                                end if;
419
                end case;
420
        end process;
421
end generate;
422
 
423
gen_serve2: for i in 0 to cpu_cnt-1 generate
424
        process (clk, reset)
425
        begin
426
                if (reset = '1') then
427
                        mode(i) <= idl;
428
        elsif (rising_edge(clk)) then
429
                        mode(i) <= next_mode(i);
430
                end if;
431
        end process;
432
end generate;
433
 
434
 
435
 
436
-- Registers rd_data for each CPU
437
gen_reg_in: for i in 0 to cpu_cnt-1 generate
438
        process(clk, reset)
439
        begin
440
                if reset = '1' then
441
                        reg_in_rd_data(i) <= (others => '0');
442
                elsif rising_edge(clk) then
443
                        if mode(i) = servR then
444
                                if mem_in.rdy_cnt = 0 then
445
                                        reg_in_rd_data(i) <= mem_in.rd_data;
446
                                -- added mem_in.rdy_cnt = 3. 
447
                                -- More correct would be: ((mem_in.rdy_cnt = ram_cnt) or (mem_in.rdy_cnt = 3))
448
                                elsif ((( mem_in.rdy_cnt = 2 ) or ( mem_in.rdy_cnt = 3 ))  and next_pipelined(i) = '1') then
449
                                        reg_in_rd_data(i) <= mem_in.rd_data;
450
                                end if;
451
                        end if;
452
                end if;
453
        end process;
454
end generate;
455
 
456
 
457
 
458
-- Generates rdy_cnt and rd_data for all CPUs
459
gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate
460
        process (mem_in, state, mode, next_pipelined, reg_in_rd_data)
461
        begin
462
 
463
                arb_in(i).rd_data <= reg_in_rd_data(i);
464
                arb_in(i).rdy_cnt <= mem_in.rdy_cnt;
465
 
466
                case state(i) is
467
                        when idle =>
468
                                if (mode(i) = idl) then
469
                                        arb_in(i).rdy_cnt <= "00";
470
                                elsif (mode(i) = servR) and (mem_in.rdy_cnt = 0) then
471
                                        arb_in(i).rd_data <= mem_in.rd_data;
472
                                end if;
473
 
474
                        when read =>
475
                                if (mode(i) = servR) then
476
                                        if (mem_in.rdy_cnt = 0) then
477
                                                arb_in(i).rd_data <= mem_in.rd_data;
478
                                        -- added mem_in.rdy_cnt = 3. 
479
                                        -- More correct would be: ((mem_in.rdy_cnt = ram_cnt) or (mem_in.rdy_cnt = 3))
480
                                        elsif ((( mem_in.rdy_cnt = 2 ) or ( mem_in.rdy_cnt = 3 ))  and next_pipelined(i) = '1') then
481
                                                arb_in(i).rd_data <= mem_in.rd_data;
482
                                        end if;
483
                                end if;
484
 
485
                        when write =>
486
 
487
                        when waitingR =>
488
                                arb_in(i).rdy_cnt <= "11";
489
                                if mode(i) = servR then
490
                                        arb_in(i).rd_data <= mem_in.rd_data;
491
                                end if;
492
 
493
                        when sendR =>
494
 
495
                        when waitingW =>
496
                                arb_in(i).rdy_cnt <= "11";
497
 
498
                        when sendW =>
499
 
500
                end case;
501
        end process;
502
end generate;
503
 
504
end rtl;

powered by: WebSVN 2.1.0

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