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

Subversion Repositories amber

[/] [amber/] [trunk/] [hw/] [vlog/] [amber25/] [a25_multiply.v] - Blame information for rev 35

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

Line No. Rev Author Line
1 16 csantifort
//////////////////////////////////////////////////////////////////
2
//                                                              //
3
//  Multiplication Module for Amber 25 Core                     //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  64-bit Booth signed or unsigned multiply and                //
10
//  multiply-accumulate supported. It takes about 38 clock      //
11
//  cycles to complete an operation.                            //
12
//                                                              //
13
//  Author(s):                                                  //
14
//      - Conor Santifort, csantifort.amber@gmail.com           //
15
//                                                              //
16
//////////////////////////////////////////////////////////////////
17
//                                                              //
18
// Copyright (C) 2011 Authors and OPENCORES.ORG                 //
19
//                                                              //
20
// This source file may be used and distributed without         //
21
// restriction provided that this copyright statement is not    //
22
// removed from the file and that any derivative work contains  //
23
// the original copyright notice and the associated disclaimer. //
24
//                                                              //
25
// This source file is free software; you can redistribute it   //
26
// and/or modify it under the terms of the GNU Lesser General   //
27
// Public License as published by the Free Software Foundation; //
28
// either version 2.1 of the License, or (at your option) any   //
29
// later version.                                               //
30
//                                                              //
31
// This source is distributed in the hope that it will be       //
32
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
33
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
34
// PURPOSE.  See the GNU Lesser General Public License for more //
35
// details.                                                     //
36
//                                                              //
37
// You should have received a copy of the GNU Lesser General    //
38
// Public License along with this source; if not, download it   //
39
// from http://www.opencores.org/lgpl.shtml                     //
40
//                                                              //
41
//////////////////////////////////////////////////////////////////
42
 
43
 
44
 
45
// bit 0 go, bit 1 accumulate
46
// Command:
47
//  4'b01 :  MUL   - 32 bit multiplication
48
//  4'b11 :  MLA   - 32 bit multiply and accumulate
49
//
50
//  34-bit Booth adder
51
//  The adder needs to be 34 bit to deal with signed and unsigned 32-bit
52
//  multiplication inputs. This adds 1 extra bit. Then to deal with the
53
//  case of two max negative numbers another bit is required.
54
//
55
 
56
module a25_multiply (
57
input                       i_clk,
58 35 csantifort
input                       i_core_stall,
59 16 csantifort
 
60
input       [31:0]          i_a_in,         // Rds
61
input       [31:0]          i_b_in,         // Rm
62
input       [1:0]           i_function,
63
input                       i_execute,
64
 
65
output      [31:0]          o_out,
66
output      [1:0]           o_flags,        // [1] = N, [0] = Z
67
output reg                  o_done = 'd0    // goes high 2 cycles before completion                                          
68
);
69
 
70
 
71
wire        enable;
72
wire        accumulate;
73
wire [33:0] multiplier;
74
wire [33:0] multiplier_bar;
75
wire [33:0] sum;
76
wire [33:0] sum34_b;
77
 
78
reg  [5:0]  count = 'd0;
79
reg  [5:0]  count_nxt;
80
reg  [67:0] product = 'd0;
81
reg  [67:0] product_nxt;
82
reg  [1:0]  flags_nxt;
83
reg         sum_acc1_carry = 'd0;
84
reg         sum_acc1_carry_nxt;
85
wire [32:0] sum_acc1;           // the MSB is the carry out for the upper 32 bit addition
86
 
87
 
88
assign enable         = i_function[0];
89
assign accumulate     = i_function[1];
90
 
91
assign multiplier     =  { 2'd0, i_a_in} ;
92
assign multiplier_bar = ~{ 2'd0, i_a_in} + 34'd1 ;
93
 
94
assign sum34_b        =  product[1:0] == 2'b01 ? multiplier     :
95
                         product[1:0] == 2'b10 ? multiplier_bar :
96
                                                 34'd0          ;
97
 
98
 
99
// Use DSP modules from Xilinx Spartan6 FPGA devices
100
`ifdef XILINX_FPGA
101
    // -----------------------------------
102
    // 34-bit adder - booth multiplication
103
    // -----------------------------------
104
    `ifdef XILINX_SPARTAN6_FPGA
105
        xs6_addsub_n #(.WIDTH(34))
106
    `endif
107
    `ifdef XILINX_VIRTEX6_FPGA
108
        xv6_addsub_n #(.WIDTH(34))
109
    `endif
110
 
111
        u_xx_addsub_34_sum (
112
        .i_a    ( product[67:34]        ),
113
        .i_b    ( sum34_b               ),
114
        .i_cin  ( 1'd0                  ),
115
        .i_sub  ( 1'd0                  ),
116
        .o_sum  ( sum                   ),
117
        .o_co   (                       )
118
    );
119
 
120
    // ------------------------------------
121
    // 33-bit adder - accumulate operations
122
    // ------------------------------------
123
    `ifdef XILINX_SPARTAN6_FPGA
124
        xs6_addsub_n #(.WIDTH(33))
125
    `endif
126
    `ifdef XILINX_VIRTEX6_FPGA
127
        xv6_addsub_n #(.WIDTH(33))
128
    `endif
129
        u_xx_addsub_33_acc1 (
130
        .i_a    ( {1'd0, product[32:1]} ),
131
        .i_b    ( {1'd0, i_a_in}        ),
132
        .i_cin  ( 1'd0                  ),
133
        .i_sub  ( 1'd0                  ),
134
        .o_sum  ( sum_acc1              ),
135
        .o_co   (                       )
136
    );
137
 
138
`else
139
 
140
    // -----------------------------------
141
    // 34-bit adder - booth multiplication
142
    // -----------------------------------
143
    assign sum =  product[67:34] + sum34_b;
144
 
145
    // ------------------------------------
146
    // 33-bit adder - accumulate operations
147
    // ------------------------------------
148
    assign sum_acc1 = {1'd0, product[32:1]} + {1'd0, i_a_in};
149
 
150
`endif
151
 
152
 
153
always @*
154
    begin
155
    // Defaults
156
    count_nxt           = count;
157
    sum_acc1_carry_nxt  = sum_acc1_carry;
158
    product_nxt         = product;
159
 
160
    // update Negative and Zero flags
161
    // Use registered value of product so this adds an extra cycle
162
    // but this avoids having the 64-bit zero comparator on the
163
    // main adder path
164
    flags_nxt   = { product[32], product[32:1] == 32'd0 };
165
 
166
 
167
    if ( count == 6'd0 )
168
        product_nxt = {33'd0, 1'd0, i_b_in, 1'd0 } ;
169
    else if ( count <= 6'd33 )
170
        product_nxt = { sum[33], sum, product[33:1]} ;
171
    else if ( count == 6'd34 && accumulate )
172
        begin
173
        // Note that bit 0 is not part of the product. It is used during the booth
174
        // multiplication algorithm
175
        product_nxt         = { product[64:33], sum_acc1[31:0], 1'd0}; // Accumulate
176
        sum_acc1_carry_nxt  = sum_acc1[32];
177
        end
178
 
179
    // Multiplication state counter
180
    if (count == 6'd0)  // start
181
        count_nxt   = enable ? 6'd1 : 6'd0;
182
    else if ((count == 6'd34 && !accumulate) ||  // MUL
183
             (count == 6'd35 &&  accumulate)  )  // MLA
184
        count_nxt   = 6'd0;
185
    else
186
        count_nxt   = count + 1'd1;
187
    end
188
 
189
 
190
always @ ( posedge i_clk )
191 35 csantifort
    if ( !i_core_stall )
192 16 csantifort
        begin
193
        count           <= i_execute ? count_nxt          : count;
194
        product         <= i_execute ? product_nxt        : product;
195
        sum_acc1_carry  <= i_execute ? sum_acc1_carry_nxt : sum_acc1_carry;
196
        o_done          <= i_execute ? count == 6'd31     : o_done;
197
        end
198
 
199
// Outputs
200
assign o_out   = product[32:1];
201
assign o_flags = flags_nxt;
202
 
203
endmodule
204
 
205
 

powered by: WebSVN 2.1.0

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