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

Subversion Repositories simpcon

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 21 martin
--
2 29 martin
--
3
--  This file is a part of JOP, the Java Optimized Processor
4
--
5
--  Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
6
--
7
--  This program is free software: you can redistribute it and/or modify
8
--  it under the terms of the GNU General Public License as published by
9
--  the Free Software Foundation, either version 3 of the License, or
10
--  (at your option) any later version.
11
--
12
--  This program is distributed in the hope that it will be useful,
13
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
--  GNU General Public License for more details.
16
--
17
--  You should have received a copy of the GNU General Public License
18
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
--
20
 
21
 
22
--
23 21 martin
--      sc_sys.vhd
24
--
25
--      counter, interrrupt handling and watchdog bit
26
--
27 29 martin
--      Author: Martin Schoeberl        martin@jopdesign.com
28 21 martin
--
29
--              address map:
30
--
31
--                      0        read clk counter, write irq ena
32 29 martin
--                      1       read 1 MHz counter, write timer val (us)
33 21 martin
--                      2       write generates sw-int (for yield())
34
--                      3       write wd port
35
--                      4       write generates SW exception, read exception reason
36
--
37
--      todo:
38
--
39
--
40
--      2003-07-05      new IO standard
41
--      2003-08-15      us counter, irq added
42
--      2005-11-30      change interface to SimpCon
43
--      2006-01-11      added exception
44
--      2007-03-17      changed interrupts to records
45
--  2007-06-01  changed name from sc_cnt to sc_sys
46 29 martin
--  2007-11-22  added global lock and bootup of CMP
47
--      2007-12-03      prioritized interrupt processing
48
--  2007-12-07  global lock redesign
49
 
50
 
51 21 martin
--
52 29 martin
--      state for a single interrupt
53
--
54
library ieee;
55
use ieee.std_logic_1164.all;
56
use ieee.numeric_std.all;
57 21 martin
 
58 29 martin
entity intstate is
59
 
60
port (
61
        clk             : in std_logic;
62
        reset   : in std_logic;
63
 
64
        irq             : in std_logic;         -- external request
65
        ena             : in std_logic;         -- local enable
66
        ack             : in std_logic;         -- is served
67
        clear   : in std_logic;         -- reset pending interrupt
68
        pending : out std_logic         -- the output request
69
);
70
end intstate;
71
 
72
architecture rtl of intstate is
73
 
74
        signal flag             : std_logic;
75
 
76
begin
77
 
78
--      TODO: add minimum interarrival time
79
 
80
process(clk, reset) begin
81
 
82
        if reset='1' then
83
                flag <= '0';
84
        elsif rising_edge(clk) then
85
                if ack='1' or clear='1' then
86
                        flag <= '0';
87
                elsif irq='1' then
88
                        flag <= '1';
89
                end if;
90
        end if;
91
 
92
end process;
93
 
94
        pending <= flag and ena;
95
 
96
end rtl;
97
 
98
--
99
--      the sc_sys component
100
--
101 21 martin
library ieee;
102
use ieee.std_logic_1164.all;
103
use ieee.numeric_std.all;
104
 
105
use work.jop_types.all;
106
 
107
entity sc_sys is
108
 
109
generic (addr_bits : integer;
110
        clk_freq : integer;
111 29 martin
        cpu_id   : integer;
112
        cpu_cnt  : integer;
113
        num_io_int : integer := 2);             -- a default value to play with SW interrupts
114 21 martin
port (
115
        clk             : in std_logic;
116
        reset   : in std_logic;
117
 
118
-- SimpCon interface
119
 
120
        address         : in std_logic_vector(addr_bits-1 downto 0);
121
        wr_data         : in std_logic_vector(31 downto 0);
122
        rd, wr          : in std_logic;
123
        rd_data         : out std_logic_vector(31 downto 0);
124
        rdy_cnt         : out unsigned(1 downto 0);
125
 
126
--
127
--      Interrupts from IO devices
128
--
129 29 martin
        irq_in          : out irq_bcf_type;
130
        irq_out         : in irq_ack_type;
131 21 martin
        exc_req         : in exception_type;
132 29 martin
 
133
        io_int          : in std_logic_vector(num_io_int-1 downto 0) := "00";
134 21 martin
 
135 29 martin
        sync_out : in sync_out_type := NO_SYNC;
136 21 martin
        sync_in  : out sync_in_type;
137
 
138 29 martin
        wd                              : out std_logic;
139
 
140
        -- remove the comment for RAM access counting
141
        -- ram_count    : in std_logic;
142 21 martin
 
143 29 martin
        inval           : out std_logic
144
 
145 21 martin
);
146
end sc_sys ;
147
 
148
architecture rtl of sc_sys is
149
 
150
        signal clock_cnt                : std_logic_vector(31 downto 0);
151
        signal pre_scale                : std_logic_vector(7 downto 0);
152
        signal us_cnt                   : std_logic_vector(31 downto 0);
153
 
154
        constant div_val        : integer := clk_freq/1000000-1;
155
 
156
        signal timer_int                : std_logic;
157
 
158 29 martin
        signal timer_cnt                : std_logic_vector(31 downto 0);
159 21 martin
        signal timer_equ                : std_logic;
160
        signal timer_dly                : std_logic;
161
 
162
        signal exc_type                 : std_logic_vector(7 downto 0);
163
 
164 29 martin
        signal cpu_identity             : std_logic_vector(31 downto 0);
165
        signal lock_reqest              : std_logic;
166 21 martin
 
167 29 martin
        -- remove the comment for RAM access counting
168
        -- signal ram_counter   : std_logic_vector(31 downto 0);
169
 
170
 
171
        signal cnt_ena                  : unsigned(31 downto 0);
172 21 martin
 
173 29 martin
--
174
--      signals for interrupt handling
175
--
176
        signal int_pend         : std_logic;
177
        signal int_ena          : std_logic;
178
        signal exc_pend         : std_logic;
179
        signal irq_gate         : std_logic;
180
        signal irq_dly          : std_logic;
181
        signal exc_dly          : std_logic;
182
 
183
--
184
--      signals for interrupt source state machines
185
--
186
        constant NUM_INT        : integer := num_io_int+1;              -- plus timer interrupt
187
        signal hwreq            : std_logic_vector(NUM_INT-1 downto 0);
188
        signal swreq            : std_logic_vector(NUM_INT-1 downto 0);
189
        signal intreq           : std_logic_vector(NUM_INT-1 downto 0);
190
        signal mask                     : std_logic_vector(NUM_INT-1 downto 0);
191
        signal ack                      : std_logic_vector(NUM_INT-1 downto 0);
192
        signal pending          : std_logic_vector(NUM_INT-1 downto 0);
193
        signal prioint          : std_logic_vector(4 downto 0);
194
        signal intnr            : std_logic_vector(4 downto 0);          -- processing int number
195
        signal clearall         : std_logic;
196
 
197 21 martin
begin
198
 
199
        cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32));
200 29 martin
        rdy_cnt <= "11" when (sync_out.halted='1' and lock_reqest='1') else "00";
201
 
202 21 martin
--
203
--      read cnt values
204
--
205
process(clk, reset)
206
begin
207
 
208 29 martin
        if reset='1' then
209 21 martin
                rd_data <= (others => '0');
210
        elsif rising_edge(clk) then
211
 
212
                if rd='1' then
213 29 martin
                        case address(3 downto 0) is
214
                                when "0000" =>
215 21 martin
                                        rd_data <= clock_cnt;
216 29 martin
                                when "0001" =>
217 21 martin
                                        rd_data <= us_cnt;
218 29 martin
                                when "0010" =>
219
                                        rd_data(4 downto 0) <= intnr;
220
                                        rd_data(31 downto 5) <= (others => '0');
221
                                when "0100" =>
222 21 martin
                                        rd_data(7 downto 0) <= exc_type;
223
                                        rd_data(31 downto 8) <= (others => '0');
224 29 martin
                                when "0101" =>
225
                                        rd_data(0) <= lock_reqest;
226
                                        rd_data(31 downto 1) <= (others => '0');
227
                                when "0110" =>
228 21 martin
                                        rd_data <= cpu_identity;
229 29 martin
                                when "0111" =>
230 21 martin
                                        rd_data(0) <= sync_out.s_out;
231
                                        rd_data(31 downto 1) <= (others => '0');
232 29 martin
                                -- remove the comment for RAM access counting
233
                                -- when "1010" =>
234
                                --      rd_data(31 downto 0) <= ram_counter;
235
                                when "1011" =>
236
                                        rd_data <= std_logic_vector(to_unsigned(cpu_cnt, 32));
237
                                when "1111" =>
238
                                        -- nothing, cache inval is write only
239
                                when others =>
240
                                        -- nothing
241 21 martin
                        end case;
242
                end if;
243
        end if;
244
 
245
end process;
246
 
247
--
248
--      compare timer value and us counter
249
--      and generate single shot
250
--
251 29 martin
process(us_cnt, timer_cnt) begin
252 21 martin
        timer_equ <= '0';
253 29 martin
        if us_cnt = timer_cnt then
254 21 martin
                timer_equ <= '1';
255
        end if;
256
end process;
257
 
258 29 martin
process(clk, reset) begin
259
        if reset='1' then
260 21 martin
                timer_dly <= '0';
261
        elsif rising_edge(clk) then
262
                timer_dly <= timer_equ;
263
        end if;
264
end process;
265
 
266
        timer_int <= timer_equ and not timer_dly;
267
 
268
--
269
--      int processing from timer and yield request
270
--
271
 
272 29 martin
        hwreq(0) <= timer_int;
273
        hwreq(NUM_INT-1 downto 1) <= io_int;
274
 
275
process(prioint, irq_out.ack_irq) begin
276
        ack <= (others => '0');
277
        ack(to_integer(unsigned(prioint))) <= irq_out.ack_irq;
278
end process;
279
 
280
        gen_int: for i in 0 to NUM_INT-1 generate
281
                intreq(i) <= hwreq(i) or swreq(i);
282
                cis: entity work.intstate
283
                        port map(clk, reset,
284
                                irq => intreq(i),
285
                                ena => mask(i),
286
                                ack => ack(i),
287
                                clear => clearall,
288
                                pending => pending(i)
289
                        );
290
 
291
 
292
        end generate;
293
 
294
-- find highest priority pending interrupt
295
process(pending) begin
296
 
297
        int_pend <= '0';
298
        prioint <= (others => '0');
299
        for i in NUM_INT-1 downto 0 loop
300
                if pending(i)='1' then
301
                        int_pend <= '1';
302
                        prioint <= std_logic_vector(to_unsigned(i, 5));
303
                        exit;
304
                end if;
305
        end loop;
306
end process;
307
 
308
--
309
--      interrupt processing
310
--
311
process(clk, reset) begin
312
 
313
        if reset='1' then
314
                irq_dly <= '0';
315
                exc_dly <= '0';
316
                intnr <= (others => '0');
317
 
318 21 martin
        elsif rising_edge(clk) then
319 29 martin
 
320
                irq_dly <= irq_gate;
321
                exc_dly <= exc_pend;
322
                -- save processing interrupt number
323
                if irq_out.ack_irq='1' then
324
                        intnr <= prioint;
325 21 martin
                end if;
326 29 martin
 
327 21 martin
        end if;
328
 
329
end process;
330
 
331 29 martin
        irq_gate <= int_pend and int_ena;
332
        irq_in.irq <= irq_gate and not irq_dly;
333
        irq_in.exc <= exc_pend and not exc_dly;
334
        irq_in.ena <= int_ena;
335 21 martin
 
336
 
337 29 martin
 
338 21 martin
--
339
--      counters
340
--              pre_scale is 8 bit => fmax = 255 MHz
341
--
342
process(clk, reset) begin
343
 
344
        if (reset='1') then
345
 
346
                clock_cnt <= (others => '0');
347
                us_cnt <= (others => '0');
348
                pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length));
349
 
350
        elsif rising_edge(clk) then
351
 
352
                clock_cnt <= std_logic_vector(unsigned(clock_cnt) + 1);
353
                pre_scale <= std_logic_vector(unsigned(pre_scale) - 1);
354
                if pre_scale = "00000000" then
355
                        pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length));
356
                        us_cnt <= std_logic_vector(unsigned(us_cnt) + 1);
357
                end if;
358
 
359
        end if;
360
end process;
361
 
362
--
363
--      io write processing and exception processing
364
--
365
process(clk, reset)
366
 
367
begin
368
        if (reset='1') then
369
 
370 29 martin
                int_ena <= '0';
371
                timer_cnt <= (others => '0');
372 21 martin
                wd <= '0';
373
                sync_in.s_in <= '0';
374 29 martin
                sync_in.lock_req <= '0';
375
                lock_reqest <= '0';
376 21 martin
 
377
                exc_type <= (others => '0');
378 29 martin
                exc_pend <= '0';
379 21 martin
 
380 29 martin
                swreq <= (others => '0');
381
                mask <= (others => '0');
382
                clearall <= '0';
383
 
384 21 martin
        elsif rising_edge(clk) then
385
 
386 29 martin
                exc_pend <= '0';
387
                swreq <= (others => '0');
388
                clearall <= '0';
389
                inval <= '0';
390 21 martin
 
391 29 martin
                -- disable interrupts on a taken interrupt or excption
392
                if irq_out.ack_irq='1' or irq_out.ack_exc='1' then
393
                        int_ena <= '0';
394
                end if;
395 21 martin
 
396 29 martin
                -- exceptions from core or memory
397 21 martin
                if exc_req.spov='1' then
398
                        exc_type(2 downto 0) <= EXC_SPOV;
399 29 martin
                        exc_pend <= '1';
400 21 martin
                end if;
401
                if exc_req.np='1' then
402
                        exc_type(2 downto 0) <= EXC_NP;
403 29 martin
                        exc_pend <= '1';
404 21 martin
                end if;
405
                if exc_req.ab='1' then
406
                        exc_type(2 downto 0) <= EXC_AB;
407 29 martin
                        exc_pend <= '1';
408 21 martin
                end if;
409
 
410
                if wr='1' then
411 29 martin
                        case address(3 downto 0) is
412
                                when "0000" =>
413
                                        int_ena <= wr_data(0);
414
                                when "0001" =>
415
                                        timer_cnt <= wr_data;
416
                                when "0010" =>
417
                                        swreq(to_integer(unsigned(wr_data))) <= '1';
418
                                when "0011" =>
419 21 martin
                                        wd <= wr_data(0);
420 29 martin
                                when "0100" =>
421 21 martin
                                        exc_type <= wr_data(7 downto 0);
422 29 martin
                                        exc_pend <= '1';
423
                                when "0101" =>
424
                                        sync_in.lock_req <= wr_data(0);
425
                                        lock_reqest <= wr_data(0);
426
                                        -- implicit cache invalidation on monitorenter
427
                                        inval <= wr_data(0);
428
                                when "0110" =>
429 21 martin
                                        -- nothing, processor id is read only
430 29 martin
                                when "0111" =>
431
                                        sync_in.s_in <= wr_data(0);
432
                                when "1000" =>
433
                                        mask <= wr_data(NUM_INT-1 downto 0);
434
                                when "1001" =>
435
                                        clearall <= '1';
436
                                when "1010" =>
437
                                        -- nothing, ram_counter is read only
438
                                when "1111" =>
439
                                        -- explicit cache invalidation
440
                                        inval <= '1';
441 21 martin
                                when others =>
442
                        end case;
443
                end if;
444
 
445
        end if;
446
end process;
447
 
448 29 martin
-- remove the comment for RAM access counting
449
-- process(clk, reset)
450
-- begin
451
--      if reset = '1' then
452
--              ram_counter <= (others => '0');
453
--      elsif rising_edge(clk) then
454
--              if (ram_count='0') then
455
--                      ram_counter <= std_logic_vector(unsigned(ram_counter) + 1);
456
--              end if;
457
--      end if;
458
-- end process;
459
 
460 21 martin
end rtl;

powered by: WebSVN 2.1.0

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