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

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [rtl/] [core/] [neo430_alu.vhd] - Blame information for rev 198

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 198 zero_gravi
-- #################################################################################################
2
-- #  << NEO430 - Arithmetical/Logical Unit >>                                                     #
3
-- # ********************************************************************************************* #
4
-- # Main data processing ALU and operand registers. DADD instruction is not supported!            #
5
-- # ********************************************************************************************* #
6
-- # BSD 3-Clause License                                                                          #
7
-- #                                                                                               #
8
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
9
-- #                                                                                               #
10
-- # Redistribution and use in source and binary forms, with or without modification, are          #
11
-- # permitted provided that the following conditions are met:                                     #
12
-- #                                                                                               #
13
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
14
-- #    conditions and the following disclaimer.                                                   #
15
-- #                                                                                               #
16
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
17
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
18
-- #    provided with the distribution.                                                            #
19
-- #                                                                                               #
20
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
21
-- #    endorse or promote products derived from this software without specific prior written      #
22
-- #    permission.                                                                                #
23
-- #                                                                                               #
24
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
25
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
26
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
27
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
28
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
29
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
30
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
31
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
32
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
33
-- # ********************************************************************************************* #
34
-- # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
35
-- #################################################################################################
36
 
37
library ieee;
38
use ieee.std_logic_1164.all;
39
use ieee.numeric_std.all;
40
 
41
library neo430;
42
use neo430.neo430_package.all;
43
 
44
entity neo430_alu is
45
  port (
46
    -- global control --
47
    clk_i  : in  std_ulogic; -- global clock, rising edge
48
    -- operands --
49
    reg_i  : in  std_ulogic_vector(15 downto 0); -- data from reg file
50
    mem_i  : in  std_ulogic_vector(15 downto 0); -- data from memory
51
    sreg_i : in  std_ulogic_vector(15 downto 0); -- current SR
52
    -- control --
53
    ctrl_i : in  std_ulogic_vector(ctrl_width_c-1 downto 0);
54
    -- results --
55
    data_o : out std_ulogic_vector(15 downto 0); -- result
56
    flag_o : out std_ulogic_vector(04 downto 0)  -- new ALU flags
57
  );
58
end neo430_alu;
59
 
60
architecture neo430_alu_rtl of neo430_alu is
61
 
62
  signal op_data  : std_ulogic_vector(15 downto 0); -- operand data
63
  signal op_a_ff  : std_ulogic_vector(15 downto 0); -- operand register A
64
  signal op_b_ff  : std_ulogic_vector(15 downto 0); -- operand register B
65
  signal add_res  : std_ulogic_vector(17 downto 0); -- adder/subtractor kernel result
66
  signal alu_res  : std_ulogic_vector(15 downto 0); -- alu result
67
  signal data_res : std_ulogic_vector(15 downto 0); -- final alu result
68
  signal zero     : std_ulogic; -- zero detector
69
  signal negative : std_ulogic; -- sign detector
70
  signal parity   : std_ulogic; -- parity detector
71
 
72
begin
73
 
74
  -- Input Operand Selection --------------------------------------------------
75
  -- -----------------------------------------------------------------------------
76
  op_data <= reg_i when (ctrl_i(ctrl_alu_in_sel_c) = '0') else mem_i;-- when (ctrl_i(ctrl_alu_bw_c) = '0') else (x"00" & mem_i(7 downto 0));
77
 
78
 
79
  -- Operand Registers --------------------------------------------------------
80
  -- -----------------------------------------------------------------------------
81
  operand_register: process(clk_i)
82
  begin
83
    if rising_edge(clk_i) then
84
      -- operand registers --
85
      if (ctrl_i(ctrl_alu_opa_wr_c) = '1') then
86
        op_a_ff <= op_data;
87
      end if;
88
      if (ctrl_i(ctrl_alu_opb_wr_c) = '1') then
89
        op_b_ff <= op_data;
90
      end if;
91
    end if;
92
  end process operand_register;
93
 
94
 
95
  -- Binary Arithmetic Core ---------------------------------------------------
96
  -- -----------------------------------------------------------------------------
97
  binary_arithmetic_core: process(ctrl_i, op_a_ff, op_b_ff, sreg_i)
98
    variable op_a_v             : std_ulogic_vector(15 downto 0);
99
    variable carry_v            : std_ulogic;
100
    variable carry_null_v       : std_ulogic;
101
    variable a_lo_v, a_hi_v     : std_ulogic_vector(8 downto 0);
102
    variable b_lo_v, b_hi_v     : std_ulogic_vector(8 downto 0);
103
    variable add_lo_v, add_hi_v : std_ulogic_vector(8 downto 0);
104
    variable carry_in_v         : std_ulogic_vector(0 downto 0);
105
    variable ova_16_v, ova_8_v  : std_ulogic;
106
  begin
107
    -- add/sub control (for operand A= --
108
    if (ctrl_i(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) = alu_add_c) or
109
       (ctrl_i(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) = alu_addc_c) then -- addition
110
      op_a_v       := op_a_ff;
111
      carry_null_v := '0';
112
    else -- subtraction
113
      op_a_v       := not op_a_ff;
114
      carry_null_v := '1';
115
    end if;
116
 
117
    -- carry input --
118
    if (ctrl_i(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) = alu_addc_c) or
119
       (ctrl_i(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) = alu_subc_c) then -- use carry in
120
      carry_in_v(0) := sreg_i(sreg_c_c);
121
    else
122
      carry_in_v(0) := carry_null_v; -- set default NO ACTIVE CARRY input
123
    end if;
124
 
125
    -- operands --
126
    a_lo_v := '0' & op_a_v(07 downto 0);
127
    a_hi_v := '0' & op_a_v(15 downto 8);
128
    b_lo_v := '0' & op_b_ff(07 downto 0);
129
    b_hi_v := '0' & op_b_ff(15 downto 8);
130
 
131
    -- adder core --
132
    add_lo_v := std_ulogic_vector(unsigned(a_lo_v) + unsigned(b_lo_v) + unsigned(carry_in_v(0 downto 0)));
133
    add_hi_v := std_ulogic_vector(unsigned(a_hi_v) + unsigned(b_hi_v) + unsigned(add_lo_v(8 downto 8)));
134
 
135
    -- overflow logic for the actual ADDER CORE (thx Edward!): plus + plus = minus || minus + minus = plus --
136
    ova_16_v := ((not op_a_v(15)) and (not op_b_ff(15)) and add_hi_v(7)) or (op_a_v(15) and op_b_ff(15) and (not add_hi_v(7)));
137
    ova_8_v  := ((not op_a_v(7))  and (not op_b_ff(7))  and add_lo_v(7)) or (op_a_v(7)  and op_b_ff(7)  and (not add_lo_v(7)));
138
 
139
    -- output --
140
    add_res(15 downto 0) <= add_hi_v(7 downto 0) & add_lo_v(7 downto 0); -- result
141
    if (ctrl_i(ctrl_alu_bw_c) = '1') then -- byte mode flags
142
      add_res(16) <= add_lo_v(8);
143
      add_res(17) <= ova_8_v;
144
    else -- word mode flags
145
      add_res(16) <= add_hi_v(8);
146
      add_res(17) <= ova_16_v;
147
    end if;
148
  end process binary_arithmetic_core;
149
 
150
 
151
  -- ALU Core -----------------------------------------------------------------
152
  -- -----------------------------------------------------------------------------
153
  alu_core: process(ctrl_i, op_a_ff, op_b_ff, sreg_i, negative, zero, parity, add_res)
154
  begin
155
    -- defaults --
156
    alu_res <= op_a_ff;
157
    flag_o(flag_c_c) <= sreg_i(sreg_c_c); -- keep
158
    flag_o(flag_v_c) <= sreg_i(sreg_v_c); -- keep
159
    flag_o(flag_n_c) <= negative; -- update
160
    flag_o(flag_z_c) <= zero; -- update
161
    flag_o(flag_p_c) <= parity; -- update
162
 
163
    -- function selection --
164
    case ctrl_i(ctrl_alu_cmd3_c downto ctrl_alu_cmd0_c) is
165
      when alu_add_c | alu_addc_c | alu_sub_c | alu_subc_c | alu_cmp_c =>
166
        -- alu_add_c  : r <= a + b
167
        -- alu_addc_c : r <= a + b + c
168
        -- alu_sub_c  : r <= b - a
169
        -- alu_subc_c : r <= b - a - 1 + c
170
        -- alu_cmp_c  : b - a (no write back, done by ctrl arbiter)
171
        alu_res <= add_res(15 downto 0);
172
        flag_o(flag_c_c) <= add_res(16);
173
        flag_o(flag_v_c) <= add_res(17);
174
 
175
      when alu_and_c => -- r <= a & b
176
        alu_res <= op_a_ff and op_b_ff;
177
        flag_o(flag_c_c) <= not zero;
178
        flag_o(flag_v_c) <= '0';
179
 
180
      when alu_xor_c => -- r <= a xor b
181
        alu_res <= op_a_ff xor op_b_ff;
182
        flag_o(flag_c_c) <= not zero;
183
        flag_o(flag_v_c) <= op_a_ff(15) and op_b_ff(15); -- word mode
184
        if (ctrl_i(ctrl_alu_bw_c) = '1') then -- byte mode
185
          flag_o(flag_v_c) <= op_a_ff(7) and op_b_ff(7);
186
        end if;
187
 
188
      when alu_bic_c => -- r <= !a & b
189
        alu_res <= (not op_a_ff) and op_b_ff;
190
        flag_o(flag_c_c) <= sreg_i(sreg_c_c); -- keep
191
        flag_o(flag_v_c) <= sreg_i(sreg_v_c); -- keep
192
        flag_o(flag_n_c) <= sreg_i(sreg_n_c); -- keep
193
        flag_o(flag_z_c) <= sreg_i(sreg_z_c); -- keep
194
 
195
      when alu_bis_c => -- r <= a | b
196
        alu_res <= op_a_ff or op_b_ff;
197
        flag_o(flag_c_c) <= sreg_i(sreg_c_c); -- keep
198
        flag_o(flag_v_c) <= sreg_i(sreg_v_c); -- keep
199
        flag_o(flag_n_c) <= sreg_i(sreg_n_c); -- keep
200
        flag_o(flag_z_c) <= sreg_i(sreg_z_c); -- keep
201
 
202
      when alu_bit_c => -- r <= a & b (no write back, done by ctrl arbiter)
203
        alu_res <= op_a_ff and op_b_ff;
204
        flag_o(flag_c_c) <= not zero;
205
        flag_o(flag_v_c) <= '0';
206
 
207
      when alu_rra_c | alu_rrc_c =>
208
        -- alu_rra_c : r <= a >> 1, rotate right arithmetically
209
        -- alu_rrc_c : r <= a >> 1, rotate right through carry
210
        if (ctrl_i(ctrl_alu_cmd1_c) = alu_rra_c(1)) then -- alu_rra_c
211
          alu_res <= op_a_ff(15) & op_a_ff(15 downto 1); -- word mode
212
          if (ctrl_i(ctrl_alu_bw_c) = '1') then -- byte mode
213
            alu_res(7) <= op_a_ff(7);
214
          end if;
215
        else -- alu_rrc_c
216
          alu_res <= sreg_i(sreg_c_c) & op_a_ff(15 downto 1); -- word mode
217
          if (ctrl_i(ctrl_alu_bw_c) = '1') then -- byte mode
218
            alu_res(7) <= sreg_i(sreg_c_c);
219
          end if;
220
        end if;
221
        flag_o(flag_c_c) <= op_a_ff(0);
222
        flag_o(flag_v_c) <= '0';
223
 
224
      when alu_sxt_c => -- r <= a, sign extend byte
225
        for i in 8 to 15 loop
226
          alu_res(i) <= op_a_ff(7);
227
        end loop;
228
        alu_res(7 downto 0) <= op_a_ff(7 downto 0);
229
        flag_o(flag_c_c) <= not zero;
230
        flag_o(flag_v_c) <= '0';
231
 
232
      when alu_swap_c => -- r <= swap bytes of a
233
        alu_res <= op_a_ff(7 downto 0) & op_a_ff(15 downto 8);
234
        flag_o(flag_c_c) <= sreg_i(sreg_c_c); -- keep
235
        flag_o(flag_v_c) <= sreg_i(sreg_v_c); -- keep
236
        flag_o(flag_n_c) <= sreg_i(sreg_n_c); -- keep
237
        flag_o(flag_z_c) <= sreg_i(sreg_z_c); -- keep
238
 
239
      when alu_mov_c => -- r <= a
240
        alu_res <= op_a_ff;
241
        flag_o(flag_c_c) <= sreg_i(sreg_c_c); -- keep
242
        flag_o(flag_v_c) <= sreg_i(sreg_v_c); -- keep
243
        flag_o(flag_n_c) <= sreg_i(sreg_n_c); -- keep
244
        flag_o(flag_z_c) <= sreg_i(sreg_z_c); -- keep
245
 
246
      when others => -- undefined
247
        alu_res <= (others => '-');
248
        flag_o(flag_c_c) <= '-';
249
        flag_o(flag_v_c) <= '-';
250
        flag_o(flag_n_c) <= '-';
251
        flag_o(flag_z_c) <= '-';
252
        flag_o(flag_p_c) <= '-';
253
 
254
    end case;
255
  end process alu_core;
256
 
257
 
258
  -- Post processing logic ----------------------------------------------------
259
  -- -----------------------------------------------------------------------------
260
 
261
  -- word/byte mode mask --
262
  data_res(07 downto 0) <= alu_res(07 downto 0);
263
  data_res(15 downto 8) <= alu_res(15 downto 8) when (ctrl_i(ctrl_alu_bw_c) = '0') else x"00";
264
 
265
  -- zero flag --
266
  zero <= not or_all_f(data_res);
267
 
268
  -- parity flag --
269
  parity <= (not xor_all_f(data_res)) when (use_xalu_c = true) else '-'; -- if implemented
270
 
271
  -- negative flag --
272
  negative <= data_res(7) when (ctrl_i(ctrl_alu_bw_c) = '1') else data_res(15);
273
 
274
  -- final data output --
275
  data_o <= data_res;
276
 
277
 
278
end neo430_alu_rtl;

powered by: WebSVN 2.1.0

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