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

Subversion Repositories t48

[/] [t48/] [tags/] [rel_0_6_beta/] [rtl/] [vhdl/] [alu.vhd] - Blame information for rev 40

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 40 arniml
-- $Id: alu.vhd,v 1.4 2004-04-06 18:10:41 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 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
    variable result_v         : alu_operand_t;
301
    variable c_v              : std_logic;
302
    variable aux_c_v          : std_logic_vector(1 downto 0);
303
 
304 26 arniml
  begin
305 40 arniml
    -- Carry Selection --------------------------------------------------------
306
    if use_carry_i then
307
      c_v := carry_i;
308
    else
309
      c_v := '0';
310
    end if;
311
 
312
    -- Operand Selection ------------------------------------------------------
313
    -- defaults for ADD
314
    add_a_v := '0' & in_a_s;
315
    add_b_v := '0' & in_b_s;
316
 
317
    case alu_op_i is
318
      when ALU_INC =>
319
        add_b_v := "000000001";
320
      when ALU_DEC =>
321
        add_b_v := "111111111";
322
      when others =>
323
        null;
324
    end case;
325
 
326
    -- The Adder --------------------------------------------------------------
327
    result_v := UNSIGNED(add_a_v) +
328
                UNSIGNED(add_b_v) +
329
                CONV_UNSIGNED(c_v, alu_operand_t'length);
330
 
331
    add_result_s <= result_v;
332
 
333
    -- Auxiliary Carry --------------------------------------------------------
334 26 arniml
    aux_c_v           := in_a_s(4) & in_b_s(4);
335
 
336
    case aux_c_v is
337
      when "00" | "11" =>
338 40 arniml
        if result_v(4) = '1' then
339 26 arniml
          aux_carry_o <= '1';
340
        end if;
341
 
342
      when "01" | "10" =>
343 40 arniml
        if result_v(4) = '0' then
344 26 arniml
          aux_carry_o <= '1';
345
        end if;
346
 
347
      when others =>
348 40 arniml
          aux_carry_o <= '0';
349 26 arniml
        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 40 arniml
-- Revision 1.3  2004/04/04 14:18:52  arniml
423
-- add measures to implement XCHD
424
--
425 38 arniml
-- Revision 1.2  2004/03/28 21:08:51  arniml
426
-- support for DA instruction
427
--
428 26 arniml
-- Revision 1.1  2004/03/23 21:31:52  arniml
429
-- initial check-in
430 4 arniml
--
431
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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