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

Subversion Repositories neo430

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 198 zero_gravi
-- #################################################################################################
2
-- #  << NEO430 - 16-Bit Unsigned Multiplier & Divider Unit >>                                     #
3
-- # ********************************************************************************************* #
4
-- # NOTE: This unit uses "repeated trial subtraction" as division algorithm (restoring).          #
5
-- # NOTE: This unit uses "shifted add" as multiplication algorithm. Set 'use_dsp_mul_c' in the    #
6
-- # package file to TRUE to use DSP slices for multiplication.                                    #
7
-- #                                                                                               #
8
-- # The division unit only supports unsigned divisions.                                           #
9
-- # The multiplication unit supports signed and unsigned division.                                #
10
-- #                                                                                               #
11
-- # Division: DIVIDEND / DIVIDER = QUOTIENT + REMAINDER (16-bit) / DIVIDER (16-bit)               #
12
-- # Multiplication: FACTOR1 * FACTOR2 = PRODUCT (32-bit)                                          #
13
-- # ********************************************************************************************* #
14
-- # BSD 3-Clause License                                                                          #
15
-- #                                                                                               #
16
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
17
-- #                                                                                               #
18
-- # Redistribution and use in source and binary forms, with or without modification, are          #
19
-- # permitted provided that the following conditions are met:                                     #
20
-- #                                                                                               #
21
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
22
-- #    conditions and the following disclaimer.                                                   #
23
-- #                                                                                               #
24
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
25
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
26
-- #    provided with the distribution.                                                            #
27
-- #                                                                                               #
28
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
29
-- #    endorse or promote products derived from this software without specific prior written      #
30
-- #    permission.                                                                                #
31
-- #                                                                                               #
32
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
33
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
34
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
35
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
36
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
37
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
38
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
39
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
40
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
41
-- # ********************************************************************************************* #
42
-- # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
43
-- #################################################################################################
44
 
45
library ieee;
46
use ieee.std_logic_1164.all;
47
use ieee.numeric_std.all;
48
 
49
library neo430;
50
use neo430.neo430_package.all;
51
 
52
entity neo430_muldiv is
53
  port (
54
    -- host access --
55
    clk_i  : in  std_ulogic; -- global clock line
56
    rden_i : in  std_ulogic; -- read enable
57
    wren_i : in  std_ulogic; -- write enable
58
    addr_i : in  std_ulogic_vector(15 downto 0); -- address
59
    data_i : in  std_ulogic_vector(15 downto 0); -- data in
60
    data_o : out std_ulogic_vector(15 downto 0)  -- data out
61
  );
62
end neo430_muldiv;
63
 
64
architecture neo430_muldiv_rtl of neo430_muldiv is
65
 
66
  -- IO space: module base address --
67
  constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
68
  constant lo_abb_c : natural := index_size_f(muldiv_size_c); -- low address boundary bit
69
 
70
  -- access control --
71
  signal acc_en : std_ulogic; -- module access enable
72
  signal addr   : std_ulogic_vector(15 downto 0); -- access address
73
  signal wr_en  : std_ulogic; -- only full 16-bit word accesses!
74
  signal rd_en  : std_ulogic;
75
 
76
  -- accessible regs --
77
  signal opa, opb   : std_ulogic_vector(15 downto 0);
78
  signal resx, resy : std_ulogic_vector(15 downto 0);
79
  signal operation  : std_ulogic; -- '1' division, '0' multiplication
80
  signal signed_op  : std_ulogic;
81
 
82
  -- arithmetic core & arbitration --
83
  signal start       : std_ulogic;
84
  signal run         : std_ulogic;
85
  signal enable      : std_ulogic_vector(15 downto 0);
86
  signal try_sub     : std_ulogic_vector(16 downto 0);
87
  signal remainder   : std_ulogic_vector(15 downto 0);
88
  signal quotient    : std_ulogic_vector(15 downto 0);
89
  signal product     : std_ulogic_vector(31 downto 0);
90
  signal do_add      : std_ulogic_vector(16 downto 0);
91
  signal sign_cycle  : std_ulogic;
92
  signal opa_sext    : std_ulogic;
93
  signal opb_sext    : std_ulogic;
94
  signal p_sext      : std_ulogic;
95
  signal dsp_mul_res : std_ulogic_vector(33 downto 0);
96
 
97
begin
98
 
99
  -- Access Control -----------------------------------------------------------
100
  -- -----------------------------------------------------------------------------
101
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = muldiv_base_c(hi_abb_c downto lo_abb_c)) else '0';
102
  addr   <= muldiv_base_c(15 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 1) & '0'; -- word aligned
103
  wr_en  <= acc_en and wren_i;
104
  rd_en  <= acc_en and rden_i;
105
 
106
 
107
  -- Write access -------------------------------------------------------------
108
  -- -----------------------------------------------------------------------------
109
  wr_access: process(clk_i)
110
  begin
111
    if rising_edge(clk_i) then
112
      start    <= '0';
113
      opa_sext <= opa(opa'left) and signed_op;
114
      opb_sext <= opb(opb'left) and signed_op;
115
      if (wr_en = '1') then -- only full word accesses!
116
        -- operands --
117
        if (addr = muldiv_opa_resx_addr_c) then -- dividend or factor 1
118
          opa <= data_i;
119
        end if;
120
        if (addr = muldiv_opb_umul_resy_addr_c) or
121
           (addr = muldiv_opb_smul_addr_c) or
122
           (addr = muldiv_opb_udiv_addr_c) then -- divisor or factor 2
123
          opb   <= data_i;
124
          start <= '1'; -- trigger operation
125
        end if;
126
        -- operation: division/multiplication --
127
        if (addr = muldiv_opb_umul_resy_addr_c) or (addr = muldiv_opb_smul_addr_c) then -- multiplication
128
          operation <= '0';
129
        else -- division
130
          operation <= '1';
131
        end if;
132
        -- signed/unsigned operation --
133
        if (addr = muldiv_opb_smul_addr_c) then
134
          signed_op <= '1';
135
        else
136
          signed_op <= '0';
137
        end if;
138
      end if;
139
    end if;
140
  end process wr_access;
141
 
142
 
143
  -- Arithmetic core ----------------------------------------------------------
144
  -- -----------------------------------------------------------------------------
145
  arithmetic_core: process(clk_i)
146
  begin
147
    if rising_edge(clk_i) then
148
      -- arbitration --
149
      enable <= enable(14 downto 0) & start;
150
      if (start = '1') then
151
        run <= '1';
152
      elsif (enable(15) = '1') then -- all done?
153
        run <= '0';
154
      end if;
155
 
156
      -- division core --
157
      if (operation = '1') then
158
        if (start = '1') then -- load dividend
159
          quotient  <= opa;
160
          remainder <= (others => '0');
161
        elsif (run = '1') then
162
          quotient <= quotient(14 downto 0) & (not try_sub(16));
163
          if (try_sub(16) = '0') then -- still overflowing
164
            remainder <= try_sub(15 downto 0);
165
          else -- underflow
166
            remainder <= remainder(14 downto 0) & quotient(15);
167
          end if;
168
        end if;
169
      -- multiplication core --
170
      else
171
        if (use_dsp_mul_c = false) then -- implement serial multiplication
172
          if (start = '1') then -- load factor 1
173
            product(31 downto 16) <= (others => opa_sext);
174
            product(15 downto  0) <= opa;
175
          elsif (run = '1') then
176
            product(31 downto 15) <= do_add(16 downto 0);
177
            product(14 downto  0) <= product(15 downto 1);
178
          end if;
179
        else -- use DSP for multiplication
180
          product(31 downto 0) <= dsp_mul_res(31 downto 0);
181
        end if;
182
      end if;
183
    end if;
184
  end process arithmetic_core;
185
 
186
  -- DSP multiplication --
187
  dsp_mul_res <= std_ulogic_vector(signed(opa_sext & opa) * signed(opb_sext & opb));
188
 
189
  -- DIV: try another subtraction --
190
  try_sub <= std_ulogic_vector(unsigned('0' & remainder(14 downto 0) & quotient(15)) - unsigned('0' & opb));
191
 
192
  -- MUL: do another addition --
193
  mul_update: process(product, sign_cycle, p_sext, opb_sext, opb)
194
  begin
195
    if (product(0) = '1') then
196
      if (sign_cycle = '1') then -- for signed operation only: take care of negative weighted MSB
197
        do_add <= std_ulogic_vector(unsigned(p_sext & product(31 downto 16)) - unsigned(opb_sext & opb));
198
      else
199
        do_add <= std_ulogic_vector(unsigned(p_sext & product(31 downto 16)) + unsigned(opb_sext & opb));
200
      end if;
201
    else
202
      do_add <= p_sext & product(31 downto 16);
203
    end if;
204
  end process mul_update;
205
 
206
  sign_cycle <= enable(enable'left) and signed_op;
207
  p_sext     <= product(product'left) and signed_op;
208
 
209
 
210
  -- Read access --------------------------------------------------------------
211
  -- -----------------------------------------------------------------------------
212
  rd_access: process(clk_i)
213
  begin
214
    if rising_edge(clk_i) then
215
      data_o <= (others => '0');
216
      if (rd_en = '1') then -- valid read access
217
        if (addr = muldiv_opa_resx_addr_c) then
218
          data_o <= resx; -- quotient or product low word
219
        else -- muldiv_opb_umul_resy_addr_c =>
220
          data_o <= resy; -- remainder or product high word
221
        end if;
222
      end if;
223
    end if;
224
  end process rd_access;
225
 
226
  -- result selection --
227
  resx <= product(15 downto  0) when (operation = '0') else quotient;
228
  resy <= product(31 downto 16) when (operation = '0') else remainder;
229
 
230
 
231
end neo430_muldiv_rtl;

powered by: WebSVN 2.1.0

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