Project

General

Profile

Download (12.5 KB) Statistics
| Branch: | Tag: | Revision:
1
-------------------------------------------------------------------------------
2
--
3
-- The Arithmetic Logic Unit (ALU).
4
-- It contains the ALU core plus the Accumulator and the Temp Reg.
5
--
6
-- $Id: alu.vhd 295 2009-04-01 19:32:48Z arniml $
7
--
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.t48_alu_pack.alu_op_t;
52

    
53
entity al 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_o        : out std_logic;
71
    alu_op_i           : in  alu_op_t;
72
    use_carry_i        : in  boolean;
73
    da_high_i          : in  boolean;
74
    da_overflow_o      : out boolean;
75
    accu_low_i         : in  boolean;
76
    p06_temp_reg_i     : in  boolean;
77
    p60_temp_reg_i     : in  boolean
78
  );
79

    
80
end al;
81

    
82

    
83
library ieee;
84
	use ieee.numeric_std.all;
85

    
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
use work.t48_pack.nibble_t;
90
use work.t48_alu_pack.all;
91

    
92
-- pragma translate_off
93
use work.t48_tb_pack.tb_accu_s;
94
-- pragma translate_on
95

    
96
architecture rtl of t48_alu is
97

    
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
  signal add_result_s : alu_operand_t;
109

    
110
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 or write_accu_i then
131
			-- testing gives no iformation "A or B or A"
132
          if accu_low_i then
133
            accumulator_q(nibble_t ) <= data_i(nibble_t );
134
          else
135
            accumulator_q <= data_i;
136
          end if;
137
        end if;
138

    
139
        if write_shadow_i then
140
          -- write shadow directly from t48 data bus
141
          accu_shadow_q <= data_i;
142
        else
143
          -- default: update shadow Accumulator from real Accumulator
144
          accu_shadow_q <= accumulator_q;
145
        end if;
146

    
147
        if p06_temp_reg_i then
148
          -- low nibble of DA sequence
149
          temp_req_q  <= "00000110";
150
        elsif p60_temp_reg_i then
151
          -- high nibble of DA sequence
152
          temp_req_q  <= "01100000";
153
        elsif write_temp_reg_i then
154
          -- normal load from T48 bus
155
          temp_req_q  <= data_i;
156
        end if;
157

    
158
      end if;
159

    
160
    end if;
161

    
162
  end process working_regs;
163
  --
164
  -----------------------------------------------------------------------------
165

    
166

    
167
  -----------------------------------------------------------------------------
168
  -- Build the inputs to the ALU core.
169
  -- Input A:
170
  --   Unary operators use only Input A.
171
  --   Is always fed from the shadow Accumulator.
172
  --   Assumption: It never happens that the Accumulator is written and then
173
  --               read for an ALU operation in the next cycle.
174
  --               Its contents can thus be staged through the shadow Accu.
175
  -- Input B:
176
  --   Is always fed from the Temp Reg.
177
  -----------------------------------------------------------------------------
178
  in_a_s <= accu_shadow_q;
179
  in_b_s <= temp_req_q;
180

    
181

    
182
  -----------------------------------------------------------------------------
183
  -- Process alu_core
184
  --
185
  -- Purpose:
186
  --   Implements the ALU core.
187
  --   All operations defined in alu_op_t are handled here.
188
  --
189
  alu_core: process (in_a_s,
190
                     in_b_s,
191
                     alu_op_i,
192
                     carry_i,
193
                     use_carry_i,
194
                     add_result_s)
195

    
196
  begin
197
    -- default assigments
198
    data_s      <= (others => '0');
199
    carry_o     <= '0';
200

    
201
    case alu_op_i is
202
      -- Operation: AND -------------------------------------------------------
203
      when ALU_AND =>
204
        data_s <= in_a_s and in_b_s;
205

    
206
      -- Operation: OR --------------------------------------------------------
207
      when ALU_OR =>
208
        data_s <= in_a_s or in_b_s;
209

    
210
      -- Operation: XOR -------------------------------------------------------
211
      when ALU_XOR =>
212
        data_s <= in_a_s xor in_b_s;
213

    
214
      -- Operation: Add -------------------------------------------------------
215
      when ALU_ADD =>
216
        data_s  <= add_result_s(data_s );
217
        carry_o <= add_result_s(add_result_s'high);
218

    
219
      -- Operation: CPL -------------------------------------------------------
220
      when ALU_CPL =>
221
        data_s <= not in_a_s;
222

    
223
      -- Operation: CLR -------------------------------------------------------
224
      when ALU_CLR =>
225
        data_s <= (others => '0');
226

    
227
      -- Operation: RL --------------------------------------------------------
228
      when ALU_RL =>
229
        data_s(7 downto 1) <= in_a_s(6 downto 0);
230
        carry_o            <= in_a_s(7);
231

    
232
        if use_carry_i then
233
          data_s(0)        <= carry_i;
234
        else
235
          data_s(0)        <= in_a_s(7);
236
        end if;
237

    
238
      -- Operation: RR --------------------------------------------------------
239
      when ALU_RR =>
240
        data_s(6 downto 0) <= in_a_s(7 downto 1);
241
        carry_o            <= in_a_s(0);
242

    
243
        if use_carry_i then
244
          data_s(7)        <= carry_i;
245
        else
246
          data_s(7)        <= in_a_s(0);
247
        end if;
248

    
249
      -- Operation: Swap ------------------------------------------------------
250
      when ALU_SWAP =>
251
        data_s(3 downto 0) <= in_a_s(7 downto 4);
252
        data_s(7 downto 4) <= in_a_s(3 downto 0);
253

    
254
      -- Operation: DEC -------------------------------------------------------
255
      when ALU_DEC =>
256
        data_s <= add_result_s(data_s );
257

    
258
      -- Operation: INC -------------------------------------------------------
259
      when ALU_INC =>
260
        data_s <= add_result_s(data_s );
261

    
262
      -- Operation CONCAT -----------------------------------------------------
263
      when ALU_CONCAT =>
264
        data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
265

    
266
      -- Operation: NOP -------------------------------------------------------
267
      when ALU_NOP =>
268
        data_s <= in_a_s;
269

    
270
      when others =>
271
        -- pragma translate_off
272
        assert false
273
          report "Unknown ALU operation selected!"
274
          severity error;
275
        -- pragma translate_on
276

    
277
    end case;
278

    
279
  end process alu_core;
280
  --
281
  -----------------------------------------------------------------------------
282

    
283

    
284
  -----------------------------------------------------------------------------
285
  -- Process adder
286
  --
287
  -- Purpose:
288
  --   Implements the adder used by several instructions.
289
  --   This way of modelling the adder forces resource sharing of:
290
  --     * ADD
291
  --     * INC
292
  --     * DEC
293
  --
294
  adder: process (in_a_s,
295
                  in_b_s,
296
                  alu_op_i,
297
                  carry_i,
298
                  use_carry_i)
299

    
300
    variable add_a_v, add_b_v : alu_operand_t;
301
    variable c_v              : alu_operand_t;
302
    variable result_v         : UNSIGNED(alu_operand_t );
303
    variable aux_c_v          : std_logic_vector(1 downto 0);
304

    
305
  begin
306
    -- Carry Selection --------------------------------------------------------
307
    c_v      := (others => '0');
308
    if use_carry_i and carry_i = '1' then
309
      c_v(0) := '1';
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    := (others => '0');
320
        add_b_v(0) := '1';
321
      when ALU_DEC =>
322
        add_b_v    := (others => '1');
323
      when others =>
324
        null;
325
    end case;
326

    
327
    -- The Adder --------------------------------------------------------------
328
    result_v := UNSIGNED(add_a_v) +
329
                UNSIGNED(add_b_v) +
330
                UNSIGNED(c_v);
331

    
332
    add_result_s <= std_logic_vector(result_v);
333

    
334
    -- Auxiliary Carry --------------------------------------------------------
335
    aux_c_v           := in_a_s(4) & in_b_s(4);
336

    
337
    aux_carry_o       <= '0';
338
    case aux_c_v is
339
      when "00" | "11" =>
340
        if result_v(4) = '1' then
341
          aux_carry_o <= '1';
342
        end if;
343

    
344
      when "01" | "10" =>
345
        if result_v(4) = '0' then
346
          aux_carry_o <= '1';
347
        end if;
348

    
349
      when others =>
350
        null;
351

    
352
    end case;
353

    
354
  end process adder;
355
  --
356
  -----------------------------------------------------------------------------
357

    
358

    
359
  -----------------------------------------------------------------------------
360
  -- Process da_overflow
361
  --
362
  -- Purpose:
363
  --   Detect overflow situation during DA sequence.
364
  --
365
  da_overflow: process (accu_shadow_q,
366
                        da_high_i)
367

    
368
    variable da_nibble_v : nibble_t;
369

    
370
    function da_overflow_f(data : in nibble_t) return boolean is
371
      variable overflow_v : boolean;
372
    begin
373
      case data is
374
        when "1010" |
375
             "1011" |
376
             "1100" |
377
             "1101" |
378
             "1110" |
379
             "1111" =>
380
          overflow_v := true;
381
        when others =>
382
          overflow_v := false;
383
      end case;
384

    
385
      return(overflow_v);
386
    end;
387

    
388
  begin
389
    if da_high_i then
390
      da_nibble_v := accu_shadow_q(7 downto 4);
391
    else
392
      da_nibble_v := accu_shadow_q(3 downto 0);
393
    end if;
394

    
395
    da_overflow_o <= da_overflow_f(da_nibble_v);
396

    
397
  end process da_overflow;
398
  --
399
  -----------------------------------------------------------------------------
400

    
401

    
402
  -- pragma translate_off
403
  -----------------------------------------------------------------------------
404
  -- Testbench support.
405
  -----------------------------------------------------------------------------
406
  tb_accu_s <= accumulator_q;
407
  -- pragma translate_on
408

    
409
  -----------------------------------------------------------------------------
410
  -- Output Multiplexer.
411
  -----------------------------------------------------------------------------
412
  data_o <=   data_s
413
            when read_alu_i else
414
              (others => bus_idle_level_c);
415

    
416
end rtl;
(2-2/16)