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 43

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 43 arniml
-- $Id: alu.vhd,v 1.5 2004-04-06 20:21:53 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
use work.alu_pack.alu_op_t;
52
 
53
entity alu is
54
 
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_i        : in  std_logic;
71
    aux_carry_o        : out std_logic;
72
    alu_op_i           : in  alu_op_t;
73 26 arniml
    use_carry_i        : in  boolean;
74
    da_low_i           : in  boolean;
75
    da_high_i          : in  boolean;
76
    da_overflow_o      : out boolean;
77 38 arniml
    accu_low_i         : in  boolean;
78 26 arniml
    p06_temp_reg_i     : in  boolean;
79
    p60_temp_reg_i     : in  boolean
80 4 arniml
  );
81
 
82
end alu;
83
 
84
 
85
library ieee;
86
use ieee.std_logic_arith.all;
87
 
88
use work.t48_pack.clk_active_c;
89
use work.t48_pack.res_active_c;
90
use work.t48_pack.bus_idle_level_c;
91 26 arniml
use work.t48_pack.nibble_t;
92 4 arniml
use work.alu_pack.all;
93
 
94
-- pragma translate_off
95
use work.t48_tb_pack.tb_accu_s;
96
-- pragma translate_on
97
 
98
architecture rtl of alu is
99
 
100
  -- the Accumulator and Temp Reg
101
  signal accumulator_q,
102
         accu_shadow_q,
103
         temp_req_q     : word_t;
104
  -- inputs to the ALU core
105
  signal in_a_s,
106
         in_b_s  : word_t;
107
  -- output of the ALU core
108
  signal data_s  : word_t;
109
 
110 40 arniml
  signal add_result_s : alu_operand_t;
111
 
112 4 arniml
begin
113
 
114
  -----------------------------------------------------------------------------
115
  -- Process working_regs
116
  --
117
  -- Purpose:
118
  --   Implements the working registers:
119
  --    + Accumulator
120
  --    + Temp Reg
121
  --
122
  working_regs: process (res_i, clk_i)
123
  begin
124
    if res_i = res_active_c then
125
      accumulator_q     <= (others => '0');
126
      accu_shadow_q     <= (others => '0');
127
      temp_req_q        <= (others => '0');
128
 
129
    elsif clk_i'event and clk_i = clk_active_c then
130
      if en_clk_i then
131
 
132
        if write_accu_i then
133 38 arniml
          if accu_low_i then
134
            accumulator_q(nibble_t'range) <= data_i(nibble_t'range);
135
          else
136
            accumulator_q <= data_i;
137
          end if;
138 4 arniml
        end if;
139
 
140
        if write_shadow_i then
141
          -- write shadow directly from t48 data bus
142
          accu_shadow_q <= data_i;
143
        else
144
          -- default: update shadow Accumulator from real Accumulator
145
          accu_shadow_q <= accumulator_q;
146
        end if;
147
 
148 26 arniml
        if p06_temp_reg_i then
149
          -- low nibble of DA sequence
150
          temp_req_q  <= "00000110";
151
        elsif p60_temp_reg_i then
152
          -- high nibble of DA sequence
153
          temp_req_q  <= "01100000";
154
        elsif write_temp_reg_i then
155
          -- normal load from T48 bus
156
          temp_req_q  <= data_i;
157 4 arniml
        end if;
158
 
159
      end if;
160
 
161
    end if;
162
 
163
  end process working_regs;
164
  --
165
  -----------------------------------------------------------------------------
166
 
167
 
168
  -----------------------------------------------------------------------------
169
  -- Build the inputs to the ALU core.
170
  -- Input A:
171
  --   Unary operators use only Input A.
172
  --   Is always fed from the shadow Accumulator.
173
  --   Assumption: It never happens that the Accumulator is written and then
174
  --               read for an ALU operation in the next cycle.
175
  --               Its contents can thus be staged through the shadow Accu.
176
  -- Input B:
177
  --   Is always fed from the Temp Reg.
178
  -----------------------------------------------------------------------------
179
  in_a_s <= accu_shadow_q;
180
  in_b_s <= temp_req_q;
181
 
182
 
183
  -----------------------------------------------------------------------------
184
  -- Process alu_core
185
  --
186
  -- Purpose:
187
  --   Implements the ALU core.
188
  --   All operations defined in alu_op_t are handled here.
189
  --
190
  alu_core: process (in_a_s,
191
                     in_b_s,
192
                     alu_op_i,
193 43 arniml
                     carry_i,
194
                     use_carry_i,
195 40 arniml
                     add_result_s)
196 4 arniml
 
197
  begin
198
    -- default assigments
199 40 arniml
    data_s      <= (others => '0');
200
    carry_o     <= '0';
201 4 arniml
 
202
    case alu_op_i is
203
      -- Operation: AND -------------------------------------------------------
204
      when ALU_AND =>
205
        data_s <= in_a_s and in_b_s;
206
 
207
      -- Operation: OR --------------------------------------------------------
208
      when ALU_OR =>
209
        data_s <= in_a_s or in_b_s;
210
 
211
      -- Operation: XOR -------------------------------------------------------
212
      when ALU_XOR =>
213
        data_s <= in_a_s xor in_b_s;
214
 
215
      -- Operation: Add -------------------------------------------------------
216
      when ALU_ADD =>
217 40 arniml
        data_s  <= add_result_s(data_s'range);
218
        carry_o <= add_result_s(add_result_s'high);
219 4 arniml
 
220
      -- Operation: CPL -------------------------------------------------------
221
      when ALU_CPL =>
222
        data_s <= not in_a_s;
223
 
224
      -- Operation: CLR -------------------------------------------------------
225
      when ALU_CLR =>
226
        data_s <= (others => '0');
227
 
228
      -- Operation: RL --------------------------------------------------------
229
      when ALU_RL =>
230
        data_s(7 downto 1) <= in_a_s(6 downto 0);
231
        carry_o            <= in_a_s(7);
232
 
233
        if use_carry_i then
234
          data_s(0)        <= carry_i;
235
        else
236
          data_s(0)        <= in_a_s(7);
237
        end if;
238
 
239
      -- Operation: RR --------------------------------------------------------
240
      when ALU_RR =>
241
        data_s(6 downto 0) <= in_a_s(7 downto 1);
242
        carry_o            <= in_a_s(0);
243
 
244
        if use_carry_i then
245
          data_s(7)        <= carry_i;
246
        else
247
          data_s(7)        <= in_a_s(0);
248
        end if;
249
 
250
      -- Operation: Swap ------------------------------------------------------
251
      when ALU_SWAP =>
252
        data_s(3 downto 0) <= in_a_s(7 downto 4);
253
        data_s(7 downto 4) <= in_a_s(3 downto 0);
254
 
255
      -- Operation: DEC -------------------------------------------------------
256
      when ALU_DEC =>
257 40 arniml
        data_s <= add_result_s(data_s'range);
258 4 arniml
 
259
      -- Operation: INC -------------------------------------------------------
260
      when ALU_INC =>
261 40 arniml
        data_s <= add_result_s(data_s'range);
262 4 arniml
 
263 38 arniml
      -- Operation CONCAT -----------------------------------------------------
264
      when ALU_CONCAT =>
265
        data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
266 4 arniml
 
267
      -- Operation: NOP -------------------------------------------------------
268
      when ALU_NOP =>
269
        data_s <= in_a_s;
270
 
271
      when others =>
272
        -- pragma translate_off
273
        assert false
274
          report "Unknown ALU operation selected!"
275
          severity error;
276
        -- pragma translate_on
277
 
278
    end case;
279
 
280
  end process alu_core;
281
  --
282
  -----------------------------------------------------------------------------
283
 
284
 
285 26 arniml
  -----------------------------------------------------------------------------
286 40 arniml
  -- Process adder
287 26 arniml
  --
288
  -- Purpose:
289 40 arniml
  --   Implements the adder used by several instructions.
290
  --   This way of modelling the adder forces resource sharing of:
291
  --     * ADD
292
  --     * INC
293
  --     * DEC
294 26 arniml
  --
295 40 arniml
  adder: process (in_a_s,
296
                  in_b_s,
297
                  alu_op_i,
298
                  carry_i,
299
                  use_carry_i)
300
 
301
    variable add_a_v, add_b_v : alu_operand_t;
302
    variable result_v         : alu_operand_t;
303
    variable c_v              : std_logic;
304
    variable aux_c_v          : std_logic_vector(1 downto 0);
305
 
306 26 arniml
  begin
307 40 arniml
    -- Carry Selection --------------------------------------------------------
308
    if use_carry_i then
309
      c_v := carry_i;
310
    else
311
      c_v := '0';
312
    end if;
313
 
314
    -- Operand Selection ------------------------------------------------------
315
    -- defaults for ADD
316
    add_a_v := '0' & in_a_s;
317
    add_b_v := '0' & in_b_s;
318
 
319
    case alu_op_i is
320
      when ALU_INC =>
321
        add_b_v := "000000001";
322
      when ALU_DEC =>
323
        add_b_v := "111111111";
324
      when others =>
325
        null;
326
    end case;
327
 
328
    -- The Adder --------------------------------------------------------------
329
    result_v := UNSIGNED(add_a_v) +
330
                UNSIGNED(add_b_v) +
331
                CONV_UNSIGNED(c_v, alu_operand_t'length);
332
 
333
    add_result_s <= result_v;
334
 
335
    -- Auxiliary Carry --------------------------------------------------------
336 26 arniml
    aux_c_v           := in_a_s(4) & in_b_s(4);
337
 
338
    case aux_c_v is
339
      when "00" | "11" =>
340 40 arniml
        if result_v(4) = '1' then
341 26 arniml
          aux_carry_o <= '1';
342
        end if;
343
 
344
      when "01" | "10" =>
345 40 arniml
        if result_v(4) = '0' then
346 26 arniml
          aux_carry_o <= '1';
347
        end if;
348
 
349
      when others =>
350 40 arniml
          aux_carry_o <= '0';
351 26 arniml
        null;
352
 
353
    end case;
354
 
355 40 arniml
  end process adder;
356 26 arniml
  --
357
  -----------------------------------------------------------------------------
358
 
359
 
360
  -----------------------------------------------------------------------------
361
  -- Process da_overflow
362
  --
363
  -- Purpose:
364
  --   Detect overflow situation during DA sequence.
365
  --
366
  da_overflow: process (accu_shadow_q,
367
                        da_high_i)
368
 
369
    variable da_nibble_v : nibble_t;
370
 
371
    function da_overflow_f(data : in nibble_t) return boolean is
372
      variable overflow_v : boolean;
373
    begin
374
      case data is
375
        when "1010" |
376
             "1011" |
377
             "1100" |
378
             "1101" |
379
             "1110" |
380
             "1111" =>
381
          overflow_v := true;
382
        when others =>
383
          overflow_v := false;
384
      end case;
385
 
386
      return(overflow_v);
387
    end;
388
 
389
  begin
390
    if da_high_i then
391
      da_nibble_v := accu_shadow_q(7 downto 4);
392
    else
393
      da_nibble_v := accu_shadow_q(3 downto 0);
394
    end if;
395
 
396
    da_overflow_o <= da_overflow_f(da_nibble_v);
397
 
398
  end process da_overflow;
399
  --
400
  -----------------------------------------------------------------------------
401
 
402
 
403 4 arniml
  -- pragma translate_off
404
  -----------------------------------------------------------------------------
405
  -- Testbench support.
406
  -----------------------------------------------------------------------------
407
  tb_accu_s <= accumulator_q;
408
  -- pragma translate_on
409
 
410
  -----------------------------------------------------------------------------
411
  -- Output Multiplexer.
412
  -----------------------------------------------------------------------------
413
  data_o <=   data_s
414
            when read_alu_i else
415
              (others => bus_idle_level_c);
416
 
417
end rtl;
418
 
419
 
420
-------------------------------------------------------------------------------
421
-- File History:
422
--
423
-- $Log: not supported by cvs2svn $
424 43 arniml
-- Revision 1.4  2004/04/06 18:10:41  arniml
425
-- rework adder and force resource sharing between ADD, INC and DEC
426
--
427 40 arniml
-- Revision 1.3  2004/04/04 14:18:52  arniml
428
-- add measures to implement XCHD
429
--
430 38 arniml
-- Revision 1.2  2004/03/28 21:08:51  arniml
431
-- support for DA instruction
432
--
433 26 arniml
-- Revision 1.1  2004/03/23 21:31:52  arniml
434
-- initial check-in
435 4 arniml
--
436
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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