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

Subversion Repositories marca

[/] [marca/] [tags/] [INITIAL/] [vhdl/] [alu.vhd] - Blame information for rev 8

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jeunes2
--  This file is part of the marca processor.
2
--  Copyright (C) 2007 Wolfgang Puffitsch
3
 
4
--  This program is free software; you can redistribute it and/or modify it
5
--  under the terms of the GNU Library General Public License as published
6
--  by the Free Software Foundation; either version 2, or (at your option)
7
--  any later version.
8
 
9
--  This program is distributed in the hope that it will be useful,
10
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
--  Library General Public License for more details.
13
 
14
--  You should have received a copy of the GNU Library General Public
15
--  License along with this program; if not, write to the Free Software
16
--  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
17
 
18
-------------------------------------------------------------------------------
19
-- MARCA ALU
20
-------------------------------------------------------------------------------
21
-- architecture for the ALU
22
-------------------------------------------------------------------------------
23
 
24
-------------------------------------------------------------------------------
25
-- Wolfgang Puffitsch
26
-- Computer Architecture Lab, Group 3
27
-------------------------------------------------------------------------------
28
 
29
library IEEE;
30
use IEEE.std_logic_1164.all;
31
use IEEE.numeric_std.all;
32
 
33
use work.marca_pkg.all;
34
 
35
architecture behaviour of alu is
36
 
37
  type WAIT_STATE is (WAIT_NONE, WAIT_MULT, WAIT_DIV, WAIT_UDIV, WAIT_MOD, WAIT_UMOD);
38
  signal state      : WAIT_STATE;
39
  signal next_state : WAIT_STATE;
40
 
41
  signal flags      : std_logic_vector(REG_WIDTH-1 downto 0);
42
  signal next_flags : std_logic_vector(REG_WIDTH-1 downto 0);
43
 
44
  signal shflags      : std_logic_vector(REG_WIDTH-1 downto 0);
45
  signal next_shflags : std_logic_vector(REG_WIDTH-1 downto 0);
46
 
47
  signal old_sgna, old_sgnb : std_logic;
48
  signal sgna, sgnb         : std_logic;
49
 
50
  component multiplier is
51
                         generic (
52
                           width : integer := REG_WIDTH);
53
                       port (
54
                         clock    : in std_logic;
55
                         reset    : in std_logic;
56
                         trigger  : in std_logic;
57
                         operand1 : in std_logic_vector(width-1 downto 0);
58
                         operand2 : in std_logic_vector(width-1 downto 0);
59
                         busy     : out std_logic;
60
                         product  : out std_logic_vector(width downto 0));
61
  end component;
62
 
63
  signal mult_op1     : std_logic_vector(REG_WIDTH-1 downto 0);
64
  signal mult_op2     : std_logic_vector(REG_WIDTH-1 downto 0);
65
  signal mult_trigger : std_logic;
66
  signal mult_busy    : std_logic;
67
  signal mult_result  : std_logic_vector(REG_WIDTH downto 0);
68
 
69
 
70
  component divider is
71
                      generic (
72
                        width : integer := REG_WIDTH);
73
                    port (
74
                      clock    : in std_logic;
75
                      reset    : in std_logic;
76
                      trigger  : in std_logic;
77
                      denom    : in std_logic_vector(width-1 downto 0);
78
                      numer    : in std_logic_vector(width-1 downto 0);
79
                      exc      : out std_logic;
80
                      busy     : out std_logic;
81
                      quotient : out std_logic_vector(width-1 downto 0);
82
                      remain   : out std_logic_vector(width-1 downto 0));
83
  end component;
84
 
85
  signal udiv_op1     : std_logic_vector(REG_WIDTH-1 downto 0);
86
  signal udiv_op2     : std_logic_vector(REG_WIDTH-1 downto 0);
87
  signal udiv_trigger : std_logic;
88
  signal udiv_exc     : std_logic;
89
  signal udiv_busy    : std_logic;
90
  signal udiv_result  : std_logic_vector(REG_WIDTH-1 downto 0);
91
  signal umod_result  : std_logic_vector(REG_WIDTH-1 downto 0);
92
 
93
 
94
  signal adder_op1    : std_logic_vector(REG_WIDTH downto 0);
95
  signal adder_op2    : std_logic_vector(REG_WIDTH downto 0);
96
  signal adder_op3    : std_logic;
97
  signal adder_result : std_logic_vector(REG_WIDTH downto 0);
98
 
99
 
100
  function shift_left (a : std_logic_vector;
101
                       b : std_logic_vector)
102
    return std_logic_vector is
103
    variable result : std_logic_vector(a'length-1 downto 0);
104
    variable i : integer;
105
  begin
106
    for i in 0 to a'length-1 loop
107
      if i < to_integer(unsigned(b)) then
108
        result(i) := '0';
109
      else
110
        result(i) := a(i - to_integer(unsigned(b)));
111
      end if;
112
    end loop;
113
    return result;
114
  end;
115
 
116
  function shift_right (a : std_logic_vector;
117
                        b : std_logic_vector)
118
    return std_logic_vector is
119
    variable result : std_logic_vector(a'length-1 downto 0);
120
    variable i : integer;
121
  begin
122
    for i in 0 to a'length-1 loop
123
      if i < to_integer(unsigned(b)) then
124
        result(i) := a(i + to_integer(unsigned(b)));
125
      elsif i < a'length-1 then
126
        result(i) := '0';
127
      else
128
        result(i) := a(to_integer(unsigned(b)) - 1);
129
      end if;
130
    end loop;
131
    return result;
132
  end;
133
 
134
  function shift_aright (a : std_logic_vector;
135
                         b : std_logic_vector)
136
    return std_logic_vector is
137
    variable result : std_logic_vector(a'length-1 downto 0);
138
    variable i : integer;
139
  begin
140
    for i in 0 to a'length-1 loop
141
      if i < to_integer(unsigned(b)) then
142
        result(i) := a(i + to_integer(unsigned(b)));
143
      elsif i < a'length-1 then
144
        result(i) := a(a'length-1);
145
      else
146
        result(i) := a(to_integer(unsigned(b)) - 1);
147
      end if;
148
    end loop;
149
    return result;
150
  end;
151
 
152
  function rotate_left (a : std_logic_vector;
153
                        b : std_logic_vector;
154
                        c : std_logic)
155
    return std_logic_vector is
156
    variable result : std_logic_vector(a'length-1 downto 0);
157
    variable i : integer;
158
  begin
159
    for i in 0 to a'length-1 loop
160
      if i < to_integer(unsigned(b)) - 1 then
161
        result(i) := a(a'length - to_integer(unsigned(b)) + i);
162
      elsif i = to_integer(unsigned(b)) - 1 then
163
        result(i) := c;
164
      else
165
        result(i) := a(i - to_integer(unsigned(b)));
166
      end if;
167
    end loop;
168
    return result;
169
  end;
170
 
171
  function rotate_right(a : std_logic_vector;
172
                        b : std_logic_vector;
173
                        c : std_logic)
174
    return std_logic_vector is
175
    variable result : std_logic_vector(a'length-1 downto 0);
176
    variable i : integer;
177
  begin
178
    for i in 0 to a'length-1 loop
179
      if i < a'length - to_integer(unsigned(b)) then
180
        result(i) := a(to_integer(unsigned(b)) + i);
181
      elsif i = a'length - to_integer(unsigned(b)) - 1 then
182
        result(i) := c;
183
      else
184
        result(i) := a(i - a'length - to_integer(unsigned(b)));
185
      end if;
186
    end loop;
187
    return result;
188
  end;
189
 
190
  function to_unsigned(a : std_logic)
191
    return unsigned is
192
    variable result : unsigned(0 downto 0);
193
  begin  -- to_unsigned
194
    if a = '1' then
195
      result := "1";
196
    else
197
      result := "0";
198
    end if;
199
    return result;
200
  end to_unsigned;
201
 
202
  function parity(a : std_logic_vector)
203
    return std_logic is
204
    variable result : std_logic;
205
    variable i : integer;
206
  begin
207
    result := '1';
208
    for i in a'low to a'high loop
209
      result := result xor a(i);
210
    end loop;
211
    return result;
212
  end;
213
 
214
begin  -- behaviour
215
 
216
  -- hardwire the interrupt enable flag
217
  iena <= flags(FLAG_I);
218
  -- and the exception signal to the divider
219
  exc <= udiv_exc;
220
 
221
  mult_unit : multiplier
222
    port map (
223
      clock    => clock,
224
      reset    => reset,
225
      trigger  => mult_trigger,
226
      operand1 => mult_op1,
227
      operand2 => mult_op2,
228
      busy     => mult_busy,
229
      product  => mult_result);
230
 
231
  udiv_unit : divider
232
    port map (
233
      clock    => clock,
234
      reset    => reset,
235
      trigger  => udiv_trigger,
236
      numer    => udiv_op1,
237
      denom    => udiv_op2,
238
      exc      => udiv_exc,
239
      busy     => udiv_busy,
240
      quotient => udiv_result,
241
      remain   => umod_result);
242
 
243
  syn_proc: process (clock, reset)
244
  begin  -- process syn_proc
245
    if reset = RESET_ACTIVE then                 -- asynchronous reset (active low)
246
      flags <= (others => '0');
247
      shflags <= (others => '0');
248
      state <= WAIT_NONE;
249
      old_sgna <= '0';
250
      old_sgnb <= '0';
251
    elsif clock'event and clock = '1' then  -- rising clock edge
252
      flags <= next_flags;
253
      shflags <= next_shflags;
254
      state <= next_state;
255
      old_sgna <= sgna;
256
      old_sgnb <= sgnb;
257
    end if;
258
  end process syn_proc;
259
 
260
  business: process(next_state)
261
  begin  -- process business
262
    if next_state /= WAIT_NONE then
263
      busy <= '1';
264
    else
265
      busy <= '0';
266
    end if;
267
  end process business;
268
 
269
  adder: process (adder_op1, adder_op2, adder_op3)
270
  begin  -- process adder
271
    adder_result <= std_logic_vector(unsigned(adder_op1) + unsigned(adder_op2)
272
                                     + to_unsigned(adder_op3));
273
  end process adder;
274
 
275
  compute: process (state, op, a, b, i, pc, flags, shflags,
276
                    intr,
277
                    sgna, sgnb, old_sgna, old_sgnb,
278
                    mult_busy, mult_result,
279
                    udiv_busy, udiv_result, umod_result,
280
                    adder_result)
281
 
282
    variable wr_flags : std_logic;
283
    variable tmp : std_logic_vector(REG_WIDTH downto 0);
284
 
285
  begin
286
    wr_flags := '1';
287
    tmp := (others => '0');
288
 
289
    next_flags <= flags;
290
    next_shflags <= shflags;
291
    next_state <= state;
292
 
293
    sgna <= a(REG_WIDTH-1);
294
    sgnb <= b(REG_WIDTH-1);
295
 
296
    mult_op1 <= (others => '0');
297
    mult_op2 <= (others => '0');
298
    mult_trigger <= '0';
299
 
300
    udiv_op1 <= (others => '0');
301
    udiv_op2 <= (others => '0');
302
    udiv_trigger <= '0';
303
 
304
    adder_op1 <= (others => '0');
305
    adder_op2 <= (others => '0');
306
    adder_op3 <= '0';
307
 
308
    pcchg <= '0';
309
 
310
    case state is
311
      when WAIT_MULT =>
312
        sgna <= old_sgna;
313
        sgnb <= old_sgnb;
314
        tmp := mult_result;
315
        if mult_busy = '0' then
316
          next_state <= WAIT_NONE;
317
        end if;
318
      when WAIT_DIV =>
319
        sgna <= old_sgna;
320
        sgnb <= old_sgnb;
321
        if sgna = sgnb then
322
          tmp(REG_WIDTH-1 downto 0) := udiv_result;
323
        else
324
          tmp(REG_WIDTH-1 downto 0) := std_logic_vector(-signed(udiv_result));
325
        end if;
326
        if udiv_busy = '0' then
327
          next_state <= WAIT_NONE;
328
        end if;
329
      when WAIT_UDIV =>
330
        sgna <= old_sgna;
331
        sgnb <= old_sgnb;
332
        tmp(REG_WIDTH-1 downto 0) := udiv_result;
333
        if udiv_busy = '0' then
334
          next_state <= WAIT_NONE;
335
        end if;
336
      when WAIT_MOD =>
337
        sgna <= old_sgna;
338
        sgnb <= old_sgnb;
339
        if sgna = sgnb then
340
          tmp(REG_WIDTH-1 downto 0) := umod_result;
341
        else
342
          tmp(REG_WIDTH-1 downto 0) := std_logic_vector(-signed(umod_result));
343
        end if;
344
        if udiv_busy = '0' then
345
          next_state <= WAIT_NONE;
346
        end if;
347
      when WAIT_UMOD =>
348
        sgna <= old_sgna;
349
        sgnb <= old_sgnb;
350
        tmp(REG_WIDTH-1 downto 0) := umod_result;
351
        if udiv_busy = '0' then
352
          next_state <= WAIT_NONE;
353
        end if;
354
      when WAIT_NONE =>
355
        case op is
356
          when ALU_ADD  => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
357
                           adder_op2 <= std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
358
                           tmp := adder_result;
359
          when ALU_SUB  => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
360
                           adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
361
                           adder_op3 <= '1';
362
                           tmp := adder_result;
363
          when ALU_ADDC => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
364
                           adder_op2 <= std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
365
                           adder_op3 <= flags(FLAG_C);
366
                           tmp := adder_result;
367
          when ALU_SUBC => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
368
                           adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
369
                           adder_op3 <= not flags(FLAG_C);
370
                           tmp := adder_result;
371
          when ALU_AND  => tmp(REG_WIDTH-1 downto 0) := a and b;
372
          when ALU_OR   => tmp(REG_WIDTH-1 downto 0) := a or b;
373
          when ALU_XOR  => tmp(REG_WIDTH-1 downto 0) := a xor b;
374
-------------------------------------------------------------------------------                       
375
          when ALU_MUL  => mult_trigger <= '1';
376
                           mult_op1 <= a;
377
                           mult_op2 <= b;
378
                           next_state <= WAIT_MULT;
379
          when ALU_DIV  => udiv_trigger <= '1';
380
                           udiv_op1 <= std_logic_vector(abs(signed(a)));
381
                           udiv_op2 <= std_logic_vector(abs(signed(b)));
382
                           next_state <= WAIT_DIV;
383
          when ALU_UDIV => udiv_trigger <= '1';
384
                           udiv_op1 <= a;
385
                           udiv_op2 <= b;
386
                           next_state <= WAIT_UDIV;
387
          when ALU_MOD  => udiv_trigger <= '1';
388
                           udiv_op1 <= std_logic_vector(abs(signed(a)));
389
                           udiv_op2 <= std_logic_vector(abs(signed(b)));
390
                           next_state <= WAIT_MOD;
391
          when ALU_UMOD => udiv_trigger <= '1';
392
                           udiv_op1 <= a;
393
                           udiv_op2 <= b;
394
                           next_state <= WAIT_UMOD;
395
-------------------------------------------------------------------------------                       
396
          when ALU_LDIL => tmp(REG_WIDTH-1 downto 0) := a(REG_WIDTH-1 downto REG_WIDTH/2) & i(REG_WIDTH/2-1 downto 0);
397
          when ALU_LDIH => tmp(REG_WIDTH-1 downto 0) := i(REG_WIDTH/2-1 downto 0) & a(REG_WIDTH/2-1 downto 0);
398
          when ALU_LDIB => tmp(REG_WIDTH-1 downto 0) := i;
399
-------------------------------------------------------------------------------                       
400
          when ALU_MOV  => tmp(REG_WIDTH-1 downto 0) := b;
401
          when ALU_NOT  => tmp(REG_WIDTH-1 downto 0) := not b;
402
          when ALU_NEG  => adder_op1 <= (others => '0');
403
                           adder_op2 <= not std_logic_vector(resize(unsigned(b), REG_WIDTH+1));
404
                           adder_op3 <= '1';
405
                           tmp := adder_result;
406
          when ALU_ADDI => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
407
                           adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
408
                           tmp := adder_result;
409
                           sgnb <= i(REG_WIDTH-1);
410
          when ALU_CMPI => adder_op1 <= std_logic_vector(resize(unsigned(a), REG_WIDTH+1));
411
                           adder_op2 <= not std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
412
                           adder_op3 <= '1';
413
                           tmp := adder_result;
414
                           sgnb <= i(REG_WIDTH-1);
415
          when ALU_SHL  => tmp := shift_left   (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b);
416
          when ALU_SHR  => tmp := shift_right  (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b);
417
          when ALU_SAR  => tmp := shift_aright (std_logic_vector(resize(  signed(a), REG_WIDTH+1)), b);
418
          when ALU_ROLC => tmp := rotate_left  (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b(REG_WIDTH_LOG-1 downto 0), flags(FLAG_C));
419
          when ALU_RORC => tmp := rotate_right (std_logic_vector(resize(unsigned(a), REG_WIDTH+1)), b(REG_WIDTH_LOG-1 downto 0), flags(FLAG_C));
420
          when ALU_BSET => tmp(REG_WIDTH-1 downto 0) := a; tmp(to_integer(unsigned(i))) := '1';
421
          when ALU_BCLR => tmp(REG_WIDTH-1 downto 0) := a; tmp(to_integer(unsigned(i))) := '0';
422
          when ALU_BTEST => tmp := (others => '0'); tmp(0) := a(to_integer(unsigned(i)));
423
          when ALU_SEXT => tmp(REG_WIDTH-1 downto 0) := std_logic_vector(resize(signed(a(REG_WIDTH/2-1 downto 0)), REG_WIDTH));
424
-------------------------------------------------------------------------------
425
          when ALU_BRZ  => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
426
                           if flags(FLAG_Z) = '1' then
427
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
428
                             pcchg <= '1';
429
                           end if;
430
                           tmp := adder_result;
431
                           wr_flags := '0';
432
          when ALU_BRNZ => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
433
                           if flags(FLAG_Z) = '0' then
434
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
435
                             pcchg <= '1';
436
                           end if;
437
                           tmp := adder_result;
438
                           wr_flags := '0';
439
          when ALU_BRLE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
440
                           if flags(FLAG_Z) = '1' or flags(FLAG_N) /= flags(FLAG_V) then
441
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
442
                             pcchg <= '1';
443
                           end if;
444
                           tmp := adder_result;
445
                           wr_flags := '0';
446
          when ALU_BRLT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
447
                           if flags(FLAG_Z) = '0' and flags(FLAG_N) /= flags(FLAG_V) then
448
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
449
                             pcchg <= '1';
450
                           end if;
451
                           tmp := adder_result;
452
                           wr_flags := '0';
453
          when ALU_BRGE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
454
                           if flags(FLAG_Z) = '1' or flags(FLAG_N) = flags(FLAG_V) then
455
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
456
                             pcchg <= '1';
457
                           end if;
458
                           tmp := adder_result;
459
                           wr_flags := '0';
460
          when ALU_BRGT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
461
                           if flags(FLAG_Z) = '0' and flags(FLAG_N) = flags(FLAG_V) then
462
                             adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
463
                             pcchg <= '1';
464
                           end if;
465
                           tmp := adder_result;
466
                           wr_flags := '0';
467
          when ALU_BRULE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
468
                            if flags(FLAG_Z) = '1' or flags(FLAG_C) = '1' then
469
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
470
                              pcchg <= '1';
471
                            end if;
472
                            tmp := adder_result;
473
                            wr_flags := '0';
474
          when ALU_BRULT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
475
                            if flags(FLAG_Z) = '0' and flags(FLAG_C) = '1' then
476
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
477
                              pcchg <= '1';
478
                            end if;
479
                            tmp := adder_result;
480
                            wr_flags := '0';
481
          when ALU_BRUGE => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
482
                            if flags(FLAG_Z) = '1' or flags(FLAG_C) = '0' then
483
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
484
                              pcchg <= '1';
485
                            end if;
486
                            tmp := adder_result;
487
                            wr_flags := '0';
488
          when ALU_BRUGT => adder_op1 <= std_logic_vector(resize(unsigned(pc), REG_WIDTH+1));
489
                            if flags(FLAG_Z) = '0' and flags(FLAG_C) = '0' then
490
                              adder_op2 <= std_logic_vector(resize(unsigned(i), REG_WIDTH+1));
491
                              pcchg <= '1';
492
                            end if;
493
                            tmp := adder_result;
494
                            wr_flags := '0';
495
-------------------------------------------------------------------------------
496
          when ALU_JMP   => tmp(REG_WIDTH-1 downto 0) := a;
497
                            pcchg <= '1';
498
                            wr_flags := '0';
499
          when ALU_JMPZ  => if flags(FLAG_Z) = '1' then
500
                              tmp(REG_WIDTH-1 downto 0) := a;
501
                              pcchg <= '1';
502
                            else
503
                              tmp(REG_WIDTH-1 downto 0) := pc;
504
                            end if;
505
                            wr_flags := '0';
506
          when ALU_JMPNZ => if flags(FLAG_Z) = '0' then
507
                              tmp(REG_WIDTH-1 downto 0) := a;
508
                              pcchg <= '1';
509
                            else
510
                              tmp(REG_WIDTH-1 downto 0) := pc;
511
                            end if;
512
                            wr_flags := '0';
513
          when ALU_JMPLE => if flags(FLAG_Z) = '1' or flags(FLAG_N) /= flags(FLAG_V) then
514
                              tmp(REG_WIDTH-1 downto 0) := a;
515
                              pcchg <= '1';
516
                            else
517
                              tmp(REG_WIDTH-1 downto 0) := pc;
518
                            end if;
519
                            wr_flags := '0';
520
          when ALU_JMPLT => if flags(FLAG_Z) = '0' and flags(FLAG_N) /= flags(FLAG_V) then
521
                              tmp(REG_WIDTH-1 downto 0) := a;
522
                              pcchg <= '1';
523
                            else
524
                              tmp(REG_WIDTH-1 downto 0) := pc;
525
                            end if;
526
                            wr_flags := '0';
527
          when ALU_JMPGE => if flags(FLAG_Z) = '1' or flags(FLAG_N) = flags(FLAG_V) then
528
                              tmp(REG_WIDTH-1 downto 0) := a;
529
                              pcchg <= '1';
530
                            else
531
                              tmp(REG_WIDTH-1 downto 0) := pc;
532
                            end if;
533
                            wr_flags := '0';
534
          when ALU_JMPGT => if flags(FLAG_Z) = '0' and flags(FLAG_N) = flags(FLAG_V) then
535
                              tmp(REG_WIDTH-1 downto 0) := a;
536
                              pcchg <= '1';
537
                            else
538
                              tmp(REG_WIDTH-1 downto 0) := pc;
539
                            end if;
540
                            wr_flags := '0';
541
          when ALU_JMPULE => if flags(FLAG_Z) = '1' or flags(FLAG_C) = '1' then
542
                               tmp(REG_WIDTH-1 downto 0) := a;
543
                               pcchg <= '1';
544
                             else
545
                               tmp(REG_WIDTH-1 downto 0) := pc;
546
                             end if;
547
                             wr_flags := '0';
548
          when ALU_JMPULT => if flags(FLAG_Z) = '0' and flags(FLAG_C) = '1' then
549
                               tmp(REG_WIDTH-1 downto 0) := a;
550
                               pcchg <= '1';
551
                             else
552
                               tmp(REG_WIDTH-1 downto 0) := pc;
553
                             end if;
554
                             wr_flags := '0';
555
          when ALU_JMPUGE => if flags(FLAG_Z) = '1' or flags(FLAG_C) = '0' then
556
                               tmp(REG_WIDTH-1 downto 0) := a;
557
                               pcchg <= '1';
558
                             else
559
                               tmp(REG_WIDTH-1 downto 0) := pc;
560
                             end if;
561
                             wr_flags := '0';
562
          when ALU_JMPUGT => if flags(FLAG_Z) = '0' and flags(FLAG_C) = '0' then
563
                               tmp(REG_WIDTH-1 downto 0) := a;
564
                               pcchg <= '1';
565
                             else
566
                               tmp(REG_WIDTH-1 downto 0) := pc;
567
                             end if;
568
                             wr_flags := '0';
569
-------------------------------------------------------------------------------
570
          when ALU_GETFL => tmp(REG_WIDTH-1 downto 0) := flags;
571
                            wr_flags := '0';
572
          when ALU_SETFL => next_flags <= a;
573
                            wr_flags := '0';
574
          when ALU_GETSHFL => tmp(REG_WIDTH-1 downto 0) := shflags;
575
                              wr_flags := '0';
576
          when ALU_SETSHFL => next_shflags <= a;
577
                              wr_flags := '0';
578
          when ALU_INTR => next_shflags <= flags;
579
                           next_flags(FLAG_I) <= '0';
580
                           wr_flags := '0';
581
          when ALU_RETI => next_flags <= shflags;
582
                           wr_flags := '0';
583
          when ALU_SEI => next_flags(FLAG_I) <= '1';
584
                          wr_flags := '0';
585
          when ALU_CLI => next_flags(FLAG_I) <= '0';
586
                          wr_flags := '0';
587
-------------------------------------------------------------------------------
588
          when ALU_NOP => wr_flags := '0';
589
          when others => null;
590
        end case;
591
      when others => null;
592
    end case;
593
 
594
    -- if the result is to be ignored, it will be ignored in the write-back stage
595
    result <= tmp(REG_WIDTH-1 downto 0);
596
 
597
    -- the flags do not make sense with all instructions yet
598
    if wr_flags = '1' then
599
      next_flags(FLAG_C) <= tmp(REG_WIDTH);
600
      next_flags(FLAG_N) <= tmp(REG_WIDTH-1);
601
      next_flags(FLAG_Z) <= zero(tmp(REG_WIDTH-1 downto 0));
602
      next_flags(FLAG_V) <= sgna xor sgnb xor tmp(REG_WIDTH) xor tmp(REG_WIDTH-1);
603
      next_flags(FLAG_P) <= parity(tmp(REG_WIDTH-1 downto 0));
604
    end if;
605
 
606
    if intr = '1' then
607
      next_shflags <= flags;
608
      next_flags(FLAG_I) <= '0';
609
    end if;
610
 
611
  end process compute;
612
 
613
end behaviour;

powered by: WebSVN 2.1.0

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