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

Subversion Repositories t48

[/] [t48/] [tags/] [rel_1_0/] [rtl/] [vhdl/] [alu.vhd] - Blame information for rev 294

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

Line No. Rev Author Line
1 4 arniml
-------------------------------------------------------------------------------
2
--
3
-- The Arithmetic Logic Unit (ALU).
4
-- It contains the ALU core plus the Accumulator and the Temp Reg.
5
--
6 179 arniml
-- $Id: alu.vhd,v 1.9 2005-06-11 10:08:43 arniml Exp $
7 4 arniml
--
8
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
9
--
10
-- All rights reserved
11
--
12
-- Redistribution and use in source and synthezised forms, with or without
13
-- modification, are permitted provided that the following conditions are met:
14
--
15
-- Redistributions of source code must retain the above copyright notice,
16
-- this list of conditions and the following disclaimer.
17
--
18
-- Redistributions in synthesized form must reproduce the above copyright
19
-- notice, this list of conditions and the following disclaimer in the
20
-- documentation and/or other materials provided with the distribution.
21
--
22
-- Neither the name of the author nor the names of other contributors may
23
-- be used to endorse or promote products derived from this software without
24
-- specific prior written permission.
25
--
26
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
28
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
30
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
-- POSSIBILITY OF SUCH DAMAGE.
37
--
38
-- Please report bugs to the author, but before you do so, please
39
-- make sure that this is not a derivative work and that
40
-- you have the latest version of this file.
41
--
42
-- The latest version of this file can be found at:
43
--      http://www.opencores.org/cvsweb.shtml/t48/
44
--
45
-------------------------------------------------------------------------------
46
 
47
library ieee;
48
use ieee.std_logic_1164.all;
49
 
50
use work.t48_pack.word_t;
51 179 arniml
use work.t48_alu_pack.alu_op_t;
52 4 arniml
 
53 179 arniml
entity t48_alu is
54 4 arniml
 
55
  port (
56
    -- Global Interface -------------------------------------------------------
57
    clk_i              : in  std_logic;
58
    res_i              : in  std_logic;
59
    en_clk_i           : in  boolean;
60
    -- T48 Bus Interface ------------------------------------------------------
61
    data_i             : in  word_t;
62
    data_o             : out word_t;
63
    write_accu_i       : in  boolean;
64
    write_shadow_i     : in  boolean;
65
    write_temp_reg_i   : in  boolean;
66
    read_alu_i         : in  boolean;
67
    -- Decoder Interface ------------------------------------------------------
68
    carry_i            : in  std_logic;
69
    carry_o            : out std_logic;
70
    aux_carry_o        : out std_logic;
71
    alu_op_i           : in  alu_op_t;
72 26 arniml
    use_carry_i        : in  boolean;
73
    da_high_i          : in  boolean;
74
    da_overflow_o      : out boolean;
75 38 arniml
    accu_low_i         : in  boolean;
76 26 arniml
    p06_temp_reg_i     : in  boolean;
77
    p60_temp_reg_i     : in  boolean
78 4 arniml
  );
79
 
80 179 arniml
end t48_alu;
81 4 arniml
 
82
 
83
library ieee;
84 77 arniml
use ieee.numeric_std.all;
85 4 arniml
 
86
use work.t48_pack.clk_active_c;
87
use work.t48_pack.res_active_c;
88
use work.t48_pack.bus_idle_level_c;
89 26 arniml
use work.t48_pack.nibble_t;
90 179 arniml
use work.t48_alu_pack.all;
91 4 arniml
 
92
-- pragma translate_off
93
use work.t48_tb_pack.tb_accu_s;
94
-- pragma translate_on
95
 
96 179 arniml
architecture rtl of t48_alu is
97 4 arniml
 
98
  -- the Accumulator and Temp Reg
99
  signal accumulator_q,
100
         accu_shadow_q,
101
         temp_req_q     : word_t;
102
  -- inputs to the ALU core
103
  signal in_a_s,
104
         in_b_s  : word_t;
105
  -- output of the ALU core
106
  signal data_s  : word_t;
107
 
108 40 arniml
  signal add_result_s : alu_operand_t;
109
 
110 4 arniml
begin
111
 
112
  -----------------------------------------------------------------------------
113
  -- Process working_regs
114
  --
115
  -- Purpose:
116
  --   Implements the working registers:
117
  --    + Accumulator
118
  --    + Temp Reg
119
  --
120
  working_regs: process (res_i, clk_i)
121
  begin
122
    if res_i = res_active_c then
123
      accumulator_q     <= (others => '0');
124
      accu_shadow_q     <= (others => '0');
125
      temp_req_q        <= (others => '0');
126
 
127
    elsif clk_i'event and clk_i = clk_active_c then
128
      if en_clk_i then
129
 
130
        if write_accu_i then
131 38 arniml
          if accu_low_i then
132
            accumulator_q(nibble_t'range) <= data_i(nibble_t'range);
133
          else
134
            accumulator_q <= data_i;
135
          end if;
136 4 arniml
        end if;
137
 
138
        if write_shadow_i then
139
          -- write shadow directly from t48 data bus
140
          accu_shadow_q <= data_i;
141
        else
142
          -- default: update shadow Accumulator from real Accumulator
143
          accu_shadow_q <= accumulator_q;
144
        end if;
145
 
146 26 arniml
        if p06_temp_reg_i then
147
          -- low nibble of DA sequence
148
          temp_req_q  <= "00000110";
149
        elsif p60_temp_reg_i then
150
          -- high nibble of DA sequence
151
          temp_req_q  <= "01100000";
152
        elsif write_temp_reg_i then
153
          -- normal load from T48 bus
154
          temp_req_q  <= data_i;
155 4 arniml
        end if;
156
 
157
      end if;
158
 
159
    end if;
160
 
161
  end process working_regs;
162
  --
163
  -----------------------------------------------------------------------------
164
 
165
 
166
  -----------------------------------------------------------------------------
167
  -- Build the inputs to the ALU core.
168
  -- Input A:
169
  --   Unary operators use only Input A.
170
  --   Is always fed from the shadow Accumulator.
171
  --   Assumption: It never happens that the Accumulator is written and then
172
  --               read for an ALU operation in the next cycle.
173
  --               Its contents can thus be staged through the shadow Accu.
174
  -- Input B:
175
  --   Is always fed from the Temp Reg.
176
  -----------------------------------------------------------------------------
177
  in_a_s <= accu_shadow_q;
178
  in_b_s <= temp_req_q;
179
 
180
 
181
  -----------------------------------------------------------------------------
182
  -- Process alu_core
183
  --
184
  -- Purpose:
185
  --   Implements the ALU core.
186
  --   All operations defined in alu_op_t are handled here.
187
  --
188
  alu_core: process (in_a_s,
189
                     in_b_s,
190
                     alu_op_i,
191 43 arniml
                     carry_i,
192
                     use_carry_i,
193 40 arniml
                     add_result_s)
194 4 arniml
 
195
  begin
196
    -- default assigments
197 40 arniml
    data_s      <= (others => '0');
198
    carry_o     <= '0';
199 4 arniml
 
200
    case alu_op_i is
201
      -- Operation: AND -------------------------------------------------------
202
      when ALU_AND =>
203
        data_s <= in_a_s and in_b_s;
204
 
205
      -- Operation: OR --------------------------------------------------------
206
      when ALU_OR =>
207
        data_s <= in_a_s or in_b_s;
208
 
209
      -- Operation: XOR -------------------------------------------------------
210
      when ALU_XOR =>
211
        data_s <= in_a_s xor in_b_s;
212
 
213
      -- Operation: Add -------------------------------------------------------
214
      when ALU_ADD =>
215 40 arniml
        data_s  <= add_result_s(data_s'range);
216
        carry_o <= add_result_s(add_result_s'high);
217 4 arniml
 
218
      -- Operation: CPL -------------------------------------------------------
219
      when ALU_CPL =>
220
        data_s <= not in_a_s;
221
 
222
      -- Operation: CLR -------------------------------------------------------
223
      when ALU_CLR =>
224
        data_s <= (others => '0');
225
 
226
      -- Operation: RL --------------------------------------------------------
227
      when ALU_RL =>
228
        data_s(7 downto 1) <= in_a_s(6 downto 0);
229
        carry_o            <= in_a_s(7);
230
 
231
        if use_carry_i then
232
          data_s(0)        <= carry_i;
233
        else
234
          data_s(0)        <= in_a_s(7);
235
        end if;
236
 
237
      -- Operation: RR --------------------------------------------------------
238
      when ALU_RR =>
239
        data_s(6 downto 0) <= in_a_s(7 downto 1);
240
        carry_o            <= in_a_s(0);
241
 
242
        if use_carry_i then
243
          data_s(7)        <= carry_i;
244
        else
245
          data_s(7)        <= in_a_s(0);
246
        end if;
247
 
248
      -- Operation: Swap ------------------------------------------------------
249
      when ALU_SWAP =>
250
        data_s(3 downto 0) <= in_a_s(7 downto 4);
251
        data_s(7 downto 4) <= in_a_s(3 downto 0);
252
 
253
      -- Operation: DEC -------------------------------------------------------
254
      when ALU_DEC =>
255 40 arniml
        data_s <= add_result_s(data_s'range);
256 4 arniml
 
257
      -- Operation: INC -------------------------------------------------------
258
      when ALU_INC =>
259 40 arniml
        data_s <= add_result_s(data_s'range);
260 4 arniml
 
261 38 arniml
      -- Operation CONCAT -----------------------------------------------------
262
      when ALU_CONCAT =>
263
        data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
264 4 arniml
 
265
      -- Operation: NOP -------------------------------------------------------
266
      when ALU_NOP =>
267
        data_s <= in_a_s;
268
 
269
      when others =>
270
        -- pragma translate_off
271
        assert false
272
          report "Unknown ALU operation selected!"
273
          severity error;
274
        -- pragma translate_on
275
 
276
    end case;
277
 
278
  end process alu_core;
279
  --
280
  -----------------------------------------------------------------------------
281
 
282
 
283 26 arniml
  -----------------------------------------------------------------------------
284 40 arniml
  -- Process adder
285 26 arniml
  --
286
  -- Purpose:
287 40 arniml
  --   Implements the adder used by several instructions.
288
  --   This way of modelling the adder forces resource sharing of:
289
  --     * ADD
290
  --     * INC
291
  --     * DEC
292 26 arniml
  --
293 40 arniml
  adder: process (in_a_s,
294
                  in_b_s,
295
                  alu_op_i,
296
                  carry_i,
297
                  use_carry_i)
298
 
299
    variable add_a_v, add_b_v : alu_operand_t;
300 77 arniml
    variable c_v              : alu_operand_t;
301
    variable result_v         : UNSIGNED(alu_operand_t'range);
302 40 arniml
    variable aux_c_v          : std_logic_vector(1 downto 0);
303
 
304 26 arniml
  begin
305 40 arniml
    -- Carry Selection --------------------------------------------------------
306 77 arniml
    c_v      := (others => '0');
307
    if use_carry_i and carry_i = '1' then
308
      c_v(0) := '1';
309 40 arniml
    end if;
310
 
311
    -- Operand Selection ------------------------------------------------------
312
    -- defaults for ADD
313
    add_a_v := '0' & in_a_s;
314
    add_b_v := '0' & in_b_s;
315
 
316
    case alu_op_i is
317
      when ALU_INC =>
318 77 arniml
        add_b_v    := (others => '0');
319
        add_b_v(0) := '1';
320 40 arniml
      when ALU_DEC =>
321 77 arniml
        add_b_v    := (others => '1');
322 40 arniml
      when others =>
323
        null;
324
    end case;
325
 
326
    -- The Adder --------------------------------------------------------------
327
    result_v := UNSIGNED(add_a_v) +
328
                UNSIGNED(add_b_v) +
329 77 arniml
                UNSIGNED(c_v);
330 40 arniml
 
331 77 arniml
    add_result_s <= std_logic_vector(result_v);
332 40 arniml
 
333
    -- Auxiliary Carry --------------------------------------------------------
334 26 arniml
    aux_c_v           := in_a_s(4) & in_b_s(4);
335
 
336 44 arniml
    aux_carry_o       <= '0';
337 26 arniml
    case aux_c_v is
338
      when "00" | "11" =>
339 40 arniml
        if result_v(4) = '1' then
340 26 arniml
          aux_carry_o <= '1';
341
        end if;
342
 
343
      when "01" | "10" =>
344 40 arniml
        if result_v(4) = '0' then
345 26 arniml
          aux_carry_o <= '1';
346
        end if;
347
 
348
      when others =>
349
        null;
350
 
351
    end case;
352
 
353 40 arniml
  end process adder;
354 26 arniml
  --
355
  -----------------------------------------------------------------------------
356
 
357
 
358
  -----------------------------------------------------------------------------
359
  -- Process da_overflow
360
  --
361
  -- Purpose:
362
  --   Detect overflow situation during DA sequence.
363
  --
364
  da_overflow: process (accu_shadow_q,
365
                        da_high_i)
366
 
367
    variable da_nibble_v : nibble_t;
368
 
369
    function da_overflow_f(data : in nibble_t) return boolean is
370
      variable overflow_v : boolean;
371
    begin
372
      case data is
373
        when "1010" |
374
             "1011" |
375
             "1100" |
376
             "1101" |
377
             "1110" |
378
             "1111" =>
379
          overflow_v := true;
380
        when others =>
381
          overflow_v := false;
382
      end case;
383
 
384
      return(overflow_v);
385
    end;
386
 
387
  begin
388
    if da_high_i then
389
      da_nibble_v := accu_shadow_q(7 downto 4);
390
    else
391
      da_nibble_v := accu_shadow_q(3 downto 0);
392
    end if;
393
 
394
    da_overflow_o <= da_overflow_f(da_nibble_v);
395
 
396
  end process da_overflow;
397
  --
398
  -----------------------------------------------------------------------------
399
 
400
 
401 4 arniml
  -- pragma translate_off
402
  -----------------------------------------------------------------------------
403
  -- Testbench support.
404
  -----------------------------------------------------------------------------
405
  tb_accu_s <= accumulator_q;
406
  -- pragma translate_on
407
 
408
  -----------------------------------------------------------------------------
409
  -- Output Multiplexer.
410
  -----------------------------------------------------------------------------
411
  data_o <=   data_s
412
            when read_alu_i else
413
              (others => bus_idle_level_c);
414
 
415
end rtl;
416
 
417
 
418
-------------------------------------------------------------------------------
419
-- File History:
420
--
421
-- $Log: not supported by cvs2svn $
422 179 arniml
-- Revision 1.8  2004/04/24 23:43:56  arniml
423
-- move from std_logic_arith to numeric_std
424
--
425 77 arniml
-- Revision 1.7  2004/04/07 22:09:03  arniml
426
-- remove unused signals
427
--
428 45 arniml
-- Revision 1.6  2004/04/07 20:56:23  arniml
429
-- default assignment for aux_carry_o
430
--
431 44 arniml
-- Revision 1.5  2004/04/06 20:21:53  arniml
432
-- fix sensitivity list
433
--
434 43 arniml
-- Revision 1.4  2004/04/06 18:10:41  arniml
435
-- rework adder and force resource sharing between ADD, INC and DEC
436
--
437 40 arniml
-- Revision 1.3  2004/04/04 14:18:52  arniml
438
-- add measures to implement XCHD
439
--
440 38 arniml
-- Revision 1.2  2004/03/28 21:08:51  arniml
441
-- support for DA instruction
442
--
443 26 arniml
-- Revision 1.1  2004/03/23 21:31:52  arniml
444
-- initial check-in
445 4 arniml
--
446
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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