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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [bigsmpy.v] - Blame information for rev 34

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    bigsmpy.v
4
//
5
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
6
//
7 34 dgisselq
// Purpose:     To multiply two 32-bit numbers into a 64-bit number.  We try
8
//              to use the hardware multiply to do this, but just what kind of
9
//      hardware multiply is actually available ... can be used to determine
10
//      how many clocks to take.
11 3 dgisselq
//
12 34 dgisselq
//      If you look at the algorithm below, it's actually a series of a couple
13
//      of independent algorithms dependent upon the parameter NCLOCKS.  If your
14
//      timing through here becomes a problem, set NCLOCKS to a higher number
15
//      and see if that doesn't help things.
16
//
17 3 dgisselq
// Creator:     Dan Gisselquist, Ph.D.
18
//              Gisselquist Technology, LLC
19
//
20
////////////////////////////////////////////////////////////////////////////////
21
//
22
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
23
//
24
// This program is free software (firmware): you can redistribute it and/or
25
// modify it under the terms of  the GNU General Public License as published
26
// by the Free Software Foundation, either version 3 of the License, or (at
27
// your option) any later version.
28
//
29
// This program is distributed in the hope that it will be useful, but WITHOUT
30
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
31
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
32
// for more details.
33
//
34
// You should have received a copy of the GNU General Public License along
35
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
36
// target there if the PDF file isn't present.)  If not, see
37
// <http://www.gnu.org/licenses/> for a copy.
38
//
39
// License:     GPL, v3, as defined and found on www.gnu.org,
40
//              http://www.gnu.org/licenses/gpl.html
41
//
42
//
43
////////////////////////////////////////////////////////////////////////////////
44
//
45
//
46
module  bigsmpy(i_clk, i_sync, i_sgn, i_a, i_b, o_r, o_sync);
47 34 dgisselq
        parameter       NCLOCKS = 1;
48 3 dgisselq
        input                   i_clk, i_sync, i_sgn;
49
        input           [31:0]   i_a, i_b;
50
        output  reg     [63:0]   o_r;
51
        output  reg             o_sync;
52
 
53 25 dgisselq
        generate
54 34 dgisselq
        if (NCLOCKS == 1)
55 25 dgisselq
        begin
56
                wire    signed  [31:0]   w_sa, w_sb;
57
                wire            [31:0]   w_ua, w_ub;
58 3 dgisselq
 
59 25 dgisselq
                assign  w_sa = i_a;
60
                assign  w_sb = i_b;
61
                assign  w_ua = i_a;
62
                assign  w_ub = i_b;
63
 
64
                always @(posedge i_clk)
65
                begin
66
                        o_sync <= i_sync;
67
                        if (i_sgn)
68
                                o_r <= w_sa * w_sb;
69
                        else
70
                                o_r <= w_ua * w_ub;
71
                end
72
 
73 34 dgisselq
        end else if (NCLOCKS == 2)
74 3 dgisselq
        begin
75 34 dgisselq
                reg     r_sync;
76 25 dgisselq
                reg     signed  [31:0]   r_sa, r_sb;
77
                wire            [31:0]   w_ua, w_ub;
78
 
79 34 dgisselq
                initial r_sync = 1'b0;
80 25 dgisselq
                always @(posedge i_clk)
81 3 dgisselq
                begin
82 34 dgisselq
                        r_sync <=i_sync;
83
                        r_sa <= i_a;
84
                        r_sb <= i_b;
85 3 dgisselq
                end
86
 
87 25 dgisselq
                assign  w_ua = r_sa;
88
                assign  w_ub = r_sb;
89 3 dgisselq
 
90 25 dgisselq
                always @(posedge i_clk)
91
                begin
92 34 dgisselq
                        o_sync <= r_sync;
93 25 dgisselq
                        if (i_sgn)
94
                                o_r <= r_sa * r_sb;
95
                        else
96
                                o_r <= w_ua * w_ub;
97
                end
98
 
99
 
100 34 dgisselq
        end else if (NCLOCKS == 5)
101 3 dgisselq
        begin
102 25 dgisselq
                //
103
                // A pipeline, shift register, to track our
104
                // synchronization pulse as it transits our pipeline
105
                //
106
                reg     [3:0]    r_s;
107 3 dgisselq
 
108 25 dgisselq
                //
109
                // Clock #1: Register our inputs, copy the value of the sign
110
                //              bit.
111
                reg             r_mpy_signed;
112
                reg     [31:0]   r_mpy_a_input, r_mpy_b_input;
113
                always @(posedge i_clk)
114
                begin
115
                        if (i_sgn)
116
                        begin
117
                                // This is about more than making the inputs
118
                                // unsigned, as you'll notice it makes positive
119
                                // inputs otherwise negative.  Instead,
120
                                // this is about making the inputs have offset
121
                                // mode.  Hence
122
                                //      i_a = r_mpy_a_input - 2^31
123
                                // and so forth
124
                                r_mpy_a_input <= {(~i_a[31]), i_a[30:0] };
125
                                r_mpy_b_input <= {(~i_b[31]), i_b[30:0] };
126
                        end else begin
127
                                r_mpy_a_input <= i_a[31:0];
128
                                r_mpy_b_input <= i_b[31:0];
129
                        end
130 3 dgisselq
 
131 25 dgisselq
                        r_mpy_signed <= i_sgn;
132
                        r_s[0] <= i_sync;
133
                end
134 3 dgisselq
 
135 25 dgisselq
                reg     [31:0]   pp_f, pp_o, pp_i, pp_l;
136
                reg     [32:0]   pp_s;
137
                always @(posedge i_clk)
138
                begin
139
                        pp_f <= r_mpy_a_input[31:16] * r_mpy_b_input[31:16];
140
                        pp_o <= r_mpy_a_input[31:16] * r_mpy_b_input[15: 0];
141
                        pp_i <= r_mpy_a_input[15: 0] * r_mpy_b_input[31:16];
142
                        pp_l <= r_mpy_a_input[15: 0] * r_mpy_b_input[15: 0];
143 3 dgisselq
 
144 25 dgisselq
                        if (r_mpy_signed)
145
                                pp_s <= 32'h8000_0000 - (r_mpy_a_input[31:0]
146
                                        + r_mpy_b_input[31:0]);
147
                        else
148
                                pp_s <= 33'h0;
149
                        r_s[1] <= r_s[0];
150
                end
151 3 dgisselq
 
152 25 dgisselq
                reg     [32:0]   partial_mpy_oi, partial_mpy_lo;
153
                reg     [31:0]   partial_mpy_hi;
154
                always @(posedge i_clk)
155
                begin
156
                        partial_mpy_lo[30: 0] <= pp_l[30:0];
157
                        partial_mpy_lo[32:31] <= pp_s[0] + pp_l[31];
158
                        partial_mpy_oi[32: 0] <= pp_o + pp_i;
159
                        partial_mpy_hi[31: 0] <= pp_s[32:1] + pp_f;
160
                        r_s[2] <= r_s[1];
161
                end
162 3 dgisselq
 
163 25 dgisselq
                reg             partial_mpy_2cl, partial_mpy_2ch;
164
                reg     [31:0]   partial_mpy_2lo, partial_mpy_2hi;
165
                always @(posedge i_clk)
166
                begin
167
                        partial_mpy_2lo[15:0] <= partial_mpy_lo[15:0];
168
                        { partial_mpy_2cl, partial_mpy_2lo[31:16] }
169
                                <= { 1'b0, partial_mpy_oi[15:0]}
170
                                                + partial_mpy_lo[32:16];
171
                        { partial_mpy_2ch, partial_mpy_2hi[16:0] }
172
                                <= partial_mpy_oi[32:16] + partial_mpy_hi[16:0];
173
                        partial_mpy_2hi[31:16] <= { partial_mpy_2hi[31:17],
174
                                                        1'b0 };
175
                        r_s[3] <= r_s[2];
176
                end
177
 
178
                always @(posedge i_clk)
179
                begin
180
                        o_r[31: 0] <= partial_mpy_2lo[31:0];
181
                        o_r[63:32] <= partial_mpy_2hi
182
                                + { 14'h0, partial_mpy_2ch, 1'b0,
183
                                                15'h0, partial_mpy_2cl };
184
                        o_sync <= r_s[3];
185
                end
186
        end endgenerate
187
 
188
 
189 3 dgisselq
endmodule

powered by: WebSVN 2.1.0

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