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

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_mul_opt.vhd] - Blame information for rev 10

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

Line No. Rev Author Line
1 9 ring0_mipt
---------------------------------------------------------------------
2
-- Optimized multiplier
3
--
4
-- Part of the LXP32 CPU
5
--
6
-- Copyright (c) 2016 by Alex I. Kuznetsov
7
--
8
-- This multiplier is designed for technologies that don't provide
9
-- fast 16x16 multipliers. One multiplication takes 6 cycles.
10
--
11
-- The multiplication algorithm is based on carry-save accumulation
12
-- of partial products.
13
---------------------------------------------------------------------
14
 
15
library ieee;
16
use ieee.std_logic_1164.all;
17
use ieee.numeric_std.all;
18
 
19
entity lxp32_mul_opt is
20
        port(
21
                clk_i: in std_logic;
22
                rst_i: in std_logic;
23
                ce_i: in std_logic;
24
                op1_i: in std_logic_vector(31 downto 0);
25
                op2_i: in std_logic_vector(31 downto 0);
26
                ce_o: out std_logic;
27
                result_o: out std_logic_vector(31 downto 0)
28
        );
29
end entity;
30
 
31
architecture rtl of lxp32_mul_opt is
32
 
33
function csa_sum(a: unsigned; b: unsigned; c: unsigned; n: integer) return unsigned is
34
        variable r: unsigned(n-1 downto 0);
35
begin
36
        for i in r'range loop
37
                r(i):=a(i) xor b(i) xor c(i);
38
        end loop;
39
        return r;
40
end function;
41
 
42
function csa_carry(a: unsigned; b: unsigned; c: unsigned; n: integer) return unsigned is
43
        variable r: unsigned(n-1 downto 0);
44
begin
45
        for i in r'range loop
46
                r(i):=(a(i) and b(i)) or (a(i) and c(i)) or (b(i) and c(i));
47
        end loop;
48
        return r&"0";
49
end function;
50
 
51
signal reg1: unsigned(op1_i'range);
52
signal reg2: unsigned(op2_i'range);
53
 
54
type pp_type is array (7 downto 0) of unsigned(31 downto 0);
55
signal pp: pp_type;
56
 
57
type pp_sum_type is array (7 downto 0) of unsigned(31 downto 0);
58
signal pp_sum: pp_sum_type;
59
 
60
type pp_carry_type is array (7 downto 0) of unsigned(32 downto 0);
61
signal pp_carry: pp_carry_type;
62
 
63
signal acc_sum: unsigned(31 downto 0);
64
signal acc_carry: unsigned(31 downto 0);
65
 
66
signal cnt: integer range 0 to 4:=0;
67
 
68
signal result: std_logic_vector(result_o'range);
69
signal ceo: std_logic:='0';
70
 
71
begin
72
 
73
-- Calculate 8 partial products in parallel
74
 
75
pp_gen: for i in pp'range generate
76
        pp(i)<=shift_left(reg1,i) when reg2(i)='1' else (others=>'0');
77
end generate;
78
 
79
-- Add partial products to the accumulator using carry-save adder tree
80
 
81
pp_sum(0)<=csa_sum(pp(0),pp(1),pp(2),32);
82
pp_carry(0)<=csa_carry(pp(0),pp(1),pp(2),32);
83
 
84
pp_sum(1)<=csa_sum(pp(3),pp(4),pp(5),32);
85
pp_carry(1)<=csa_carry(pp(3),pp(4),pp(5),32);
86
 
87
pp_sum(2)<=csa_sum(pp(6),pp(7),acc_sum,32);
88
pp_carry(2)<=csa_carry(pp(6),pp(7),acc_sum,32);
89
 
90
pp_sum(3)<=csa_sum(pp_sum(0),pp_carry(0),pp_sum(1),32);
91
pp_carry(3)<=csa_carry(pp_sum(0),pp_carry(0),pp_sum(1),32);
92
 
93
pp_sum(4)<=csa_sum(pp_carry(1),pp_sum(2),pp_carry(2),32);
94
pp_carry(4)<=csa_carry(pp_carry(1),pp_sum(2),pp_carry(2),32);
95
 
96
pp_sum(5)<=csa_sum(pp_sum(3),pp_carry(3),pp_sum(4),32);
97
pp_carry(5)<=csa_carry(pp_sum(3),pp_carry(3),pp_sum(4),32);
98
 
99
pp_sum(6)<=csa_sum(pp_sum(5),pp_carry(5),pp_carry(4),32);
100
pp_carry(6)<=csa_carry(pp_sum(5),pp_carry(5),pp_carry(4),32);
101
 
102
pp_sum(7)<=csa_sum(pp_sum(6),pp_carry(6),acc_carry,32);
103
pp_carry(7)<=csa_carry(pp_sum(6),pp_carry(6),acc_carry,32);
104
 
105
-- Multiplier state machine
106
 
107
process (clk_i) is
108
begin
109
        if rising_edge(clk_i) then
110
                if rst_i='1' then
111
                        ceo<='0';
112
                        cnt<=0;
113
                        reg1<=(others=>'-');
114
                        reg2<=(others=>'-');
115
                        acc_sum<=(others=>'-');
116
                        acc_carry<=(others=>'-');
117
                else
118
                        if cnt=1 then
119
                                ceo<='1';
120
                        else
121
                                ceo<='0';
122
                        end if;
123
 
124
                        if ce_i='1' then
125
                                cnt<=4;
126
                                reg1<=unsigned(op1_i);
127
                                reg2<=unsigned(op2_i);
128
                                acc_sum<=(others=>'0');
129
                                acc_carry<=(others=>'0');
130
                        else
131
                                acc_sum<=pp_sum(7);
132
                                acc_carry<=pp_carry(7)(acc_carry'range);
133
                                reg1<=reg1(reg1'high-8 downto 0)&X"00";
134
                                reg2<=X"00"&reg2(reg2'high downto 8);
135
                                if cnt>0 then
136
                                        cnt<=cnt-1;
137
                                end if;
138
                        end if;
139
                end if;
140
        end if;
141
end process;
142
 
143
result<=std_logic_vector(acc_sum+acc_carry);
144
 
145
result_o<=result;
146
ce_o<=ceo;
147
 
148
-- A simulation-time multiplication check
149
 
150
-- synthesis translate_off
151
 
152
process (clk_i) is
153
        variable p: unsigned(op1_i'length+op2_i'length-1 downto 0);
154
begin
155
        if rising_edge(clk_i) then
156
                if ce_i='1' then
157
                        p:=unsigned(op1_i)*unsigned(op2_i);
158
                elsif ceo='1' then
159
                        assert result=std_logic_vector(p(result'range))
160
                                report "Incorrect multiplication result"
161
                                severity failure;
162
                end if;
163
        end if;
164
end process;
165
 
166
-- synthesis translate_on
167
 
168
end architecture;

powered by: WebSVN 2.1.0

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