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

Subversion Repositories t48

[/] [t48/] [tags/] [rel_0_1_beta/] [rtl/] [vhdl/] [alu.vhd] - Blame information for rev 26

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

powered by: WebSVN 2.1.0

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