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

Subversion Repositories light52

[/] [light52/] [trunk/] [vhdl/] [light52_muldiv.vhdl] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ja_rd
--------------------------------------------------------------------------------
2
-- light52_muldiv.vhdl -- Simple multiplier/divider module.
3
--------------------------------------------------------------------------------
4
-- The 8051 mul and div instructions are both unsigned and operands are 8 bit.
5
--
6
-- This module implements the division as a sequential state machine which takes
7
-- 8 cycles to complete. 
8
-- The multiplier can be implemented as sequential or as combinational, in which
9
-- case it will use a DSP block in those architectures that support it.
10
-- No attempt has been made to make this module generic or reusable.
11
--
12
-- If you want a combinational multiplier but don't want to waste a DSP block 
13
-- in this module, you need to modify this file adding whatever synthesis 
14
-- pragmas your tool of choice needs.
15
--
16
-- Note that unlike the division state machine, the combinational product logic
17
-- is always operating: when SEQUENTIAL_MULTIPLIER=true, prod_out equals 
18
-- data_a * data_b with a latency of 1 clock cycle, and mul_ready is hardwired
19
-- to '1'.
20
--
21
-- FIXME explain division algorithm.
22
--------------------------------------------------------------------------------
23
-- GENERICS:
24
-- 
25
-- SEQUENTIAL_MULTIPLIER        -- Sequential vs. combinational multiplier.
26
--  When true, a sequential implementation will be used for the multiplier, 
27
--  which will usually save a lot of logic or a dedicated multiplier.
28
--  When false, a combinational registered multiplier will be used.
29
--
30
--------------------------------------------------------------------------------
31
-- INTERFACE SIGNALS:
32
--
33
-- clk :            Clock, active rising edge.
34
-- reset :          Synchronous reset. Clears only the control registers not
35
--                  visible to the programmer -- not the output registers.
36
-- 
37
-- data_a :         Numerator input, should be connected to the ACC register.
38
-- data_b :         Denominator input, should be connected to the B register.
39
-- start :          Assert for 1 cycle to start the division state machine
40
--                  (and the product if SEQUENTIAL_MULTIPLIER=true);
41
-- 
42
-- prod_out :       Product output, valid only when mul_ready='1'.
43
-- quot_out :       Quotient output, valid only when div_ready='1'.
44
-- rem_out :        Remainder output, valid only when div_ready='1'.
45
-- div_ov_out :     Division overflow flag, valid only when div_ready='1'.
46
-- mul_ov_out :     Product overflow flag, valid only when mul_ready='1'.
47
-- 
48
-- mul_ready :      Asserted permanently if SEQUENTIAL_MULTIPLIER=false.
49
-- div_ready :      Deasserted the cycle after start is asserted.
50
--                  Asserted when the division has completed.
51
--
52
--------------------------------------------------------------------------------
53
-- Copyright (C) 2012 Jose A. Ruiz
54
--                                                              
55
-- This source file may be used and distributed without         
56
-- restriction provided that this copyright statement is not    
57
-- removed from the file and that any derivative work contains  
58
-- the original copyright notice and the associated disclaimer. 
59
--                                                              
60
-- This source file is free software; you can redistribute it   
61
-- and/or modify it under the terms of the GNU Lesser General   
62
-- Public License as published by the Free Software Foundation; 
63
-- either version 2.1 of the License, or (at your option) any   
64
-- later version.                                               
65
--                                                              
66
-- This source is distributed in the hope that it will be       
67
-- useful, but WITHOUT ANY WARRANTY; without even the implied   
68
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      
69
-- PURPOSE.  See the GNU Lesser General Public License for more 
70
-- details.                                                     
71
--                                                              
72
-- You should have received a copy of the GNU Lesser General    
73
-- Public License along with this source; if not, download it   
74
-- from http://www.opencores.org/lgpl.shtml
75
--------------------------------------------------------------------------------
76
 
77
library ieee;
78
use ieee.std_logic_1164.all;
79
use ieee.numeric_std.all;
80
 
81
use work.light52_pkg.all;
82
use work.light52_ucode_pkg.all;
83
 
84
entity light52_muldiv is
85
    generic (
86
        SEQUENTIAL_MULTIPLIER : boolean := false
87
    );
88
    port(
89
        clk :                   in std_logic;
90
        reset :                 in std_logic;
91
 
92
        data_a :                in t_byte;
93
        data_b :                in t_byte;
94
        start :                 in std_logic;
95
 
96
        prod_out :              out t_word;
97
        quot_out :              out t_byte;
98
        rem_out :               out t_byte;
99
        div_ov_out :            out std_logic;
100
        mul_ov_out :            out std_logic;
101
 
102
        mul_ready :             out std_logic;
103
        div_ready :             out std_logic
104
    );
105
end entity light52_muldiv;
106
 
107
architecture sequential of light52_muldiv is
108
 
109
signal bit_ctr :            integer range 0 to 8;
110
 
111
signal b_shift_reg :        t_word;
112
 
113
signal den_ge_256 :         std_logic;
114
signal num_ge_den :         std_logic;
115
signal sub_num :            std_logic;
116
 
117
signal denominator :        t_byte;
118
signal rem_reg :            t_byte;
119
signal quot_reg :           t_byte;
120
signal prod_reg :           t_word;
121
signal ready :              std_logic;
122
 
123
signal load_regs :          std_logic;
124
 
125
begin
126
 
127
-- Control logic ---------------------------------------------------------------
128
 
129
control_counter:
130
process(clk)
131
begin
132
    if clk'event and clk='1' then
133
        if reset='1' then
134
            bit_ctr <= 8;
135
        else
136
            if load_regs='1' then
137
                bit_ctr <= 0;
138
            elsif bit_ctr /= 8 then
139
                bit_ctr <= bit_ctr + 1;
140
            end if;
141
        end if;
142
    end if;
143
end process control_counter;
144
 
145
-- Internal signal ready is asserted after 8 cycles.
146
-- The sequential multiplier will use this signal too, IF it takes 8 cycles.
147
 
148
ready <= '1' when bit_ctr >= 8 else '0';
149
 
150
 
151
---- Divider logic -------------------------------------------------------------
152
 
153
-- What we do is a simple base-2 'shift-and-subtract' algorithm that takes
154
-- 8 cycles to complete. We can get away with this because we deal with unsigned
155
-- numbers only.
156
 
157
divider_registers:
158
process(clk)
159
begin
160
    if clk'event and clk='1' then
161
        -- denominator shift register
162
        if load_regs='1' then
163
            b_shift_reg <= "0" & data_b & "0000000";
164
            -- Division overflow can be determined upon loading B reg data.
165
            -- OV will be raised only on div-by-zero.
166
            if data_b=X"00" then
167
                div_ov_out <= '1';
168
            else
169
                div_ov_out <= '0';
170
            end if;
171
        else
172
            b_shift_reg <= "0" & b_shift_reg(b_shift_reg'high downto 1);
173
        end if;
174
 
175
        -- numerator register
176
        if load_regs='1' then
177
            rem_reg <= data_a;
178
        elsif bit_ctr/=8 and sub_num='1' then
179
            rem_reg <= rem_reg - denominator;
180
        end if;
181
 
182
        --- quotient register
183
        if load_regs='1' then
184
            quot_reg <= (others => '0');
185
        elsif bit_ctr/=8 then
186
            quot_reg <= quot_reg(quot_reg'high-1 downto 0) & sub_num;
187
        end if;
188
 
189
        load_regs <= start;
190
    end if;
191
end process divider_registers;
192
 
193
denominator <= b_shift_reg(7 downto 0);
194
 
195
-- The 16-bit comparison between b_shift_reg (denominator) and the zero-extended 
196
-- rem_reg (numerator) can be simplified by splitting it in 2: 
197
-- If the shifted denominator high byte is not zero, it is >=256...
198
den_ge_256 <= '1' when b_shift_reg(15 downto 8) /= X"00" else '0';
199
-- ...otherwise we need to compare the low bytes.
200
num_ge_den <= '1' when rem_reg >= denominator else '0';
201
sub_num <= '1' when den_ge_256='0' and num_ge_den='1' else '0';
202
 
203
 
204
quot_out <= quot_reg;
205
prod_out <= prod_reg;
206
rem_out <= rem_reg;
207
 
208
div_ready <= ready;
209
 
210
---- Multiplier logic ----------------------------------------------------------
211
 
212
---- Combinational multiplier -----------------------------
213
multiplier_combinational:
214
if not SEQUENTIAL_MULTIPLIER generate
215
 
216
registered_combinational_multiplier:
217
process(clk)
218
begin
219
    if clk'event and clk='1' then
220
        prod_reg <= data_a * data_b; -- t_byte is unsigned
221
    end if;
222
end process registered_combinational_multiplier;
223
 
224
-- The multiplier output is valid in the cycle after the operands are loaded,
225
-- so by the time MUL is executed it's already done.
226
mul_ready <= '1';
227
 
228
mul_ov_out <= '1' when prod_reg(15 downto 8)/=X"00" else '0';
229
prod_out <= prod_reg;
230
 
231
end generate multiplier_combinational;
232
 
233
---- Sequential multiplier --------------------------------
234
multiplier_sequential:
235
if SEQUENTIAL_MULTIPLIER generate
236
 
237
assert false
238
report "Sequential multiplier implementation not done yet."&
239
       " Use combinational implementation."
240
severity failure;
241
 
242
end generate multiplier_sequential;
243
 
244
end sequential;

powered by: WebSVN 2.1.0

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