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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [positVerilog/] [positMultiply.sv] - Blame information for rev 47

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

Line No. Rev Author Line
1 47 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2020  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch@finitron.ca
6
//       ||
7
//
8
//      positMultiply.v
9
//    - posit number multiplier, pipelined with latency of 13
10
//    - can issue every other clock cycle
11
//    - parameterized width
12
//
13
//
14
// This source file is free software: you can redistribute it and/or modify
15
// it under the terms of the GNU Lesser General Public License as published
16
// by the Free Software Foundation, either version 3 of the License, or
17
// (at your option) any later version.
18
//
19
// This source file is distributed in the hope that it will be useful,
20
// but WITHOUT ANY WARRANTY; without even the implied warranty of
21
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
// GNU General Public License for more details.
23
//
24
// You should have received a copy of the GNU General Public License
25
// along with this program.  If not, see .
26
//
27
// ============================================================================
28
 
29
`include "positConfig.sv"
30
 
31
module positMultiply(clk, ce, a, b, o, zero, inf);
32
`include "positSize.sv"
33
localparam rs = $clog2(PSTWID-1);
34
input clk;
35
input ce;
36
input [PSTWID-1:0] a;
37
input [PSTWID-1:0] b;
38
output reg [PSTWID-1:0] o;
39
output reg zero;
40
output reg inf;
41
 
42
wire sa, sb, so;
43
wire [rs-1:0] rgma, rgmb;
44
wire rgsa, rgsb;
45
wire [es-1:0] expa, expb;
46
wire [PSTWID-es-1:0] siga, sigb;
47
wire zera, zerb;
48
wire infa, infb;
49
wire [PSTWID-1:0] aa, bb;
50
 
51
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
52
// Clock #1
53
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54
 
55
positDecomposeReg #(PSTWID,es) u1 (
56
  .clk(clk),
57
  .ce(ce),
58
  .i(a),
59
  .sgn(sa),
60
  .rgs(rgsa),
61
  .rgm(rgma),
62
  .exp(expa),
63
  .sig(siga),
64
  .zer(zera),
65
  .inf(infa)
66
);
67
 
68
positDecomposeReg #(PSTWID,es) u2 (
69
  .clk(clk),
70
  .ce(ce),
71
  .i(b),
72
  .sgn(sb),
73
  .rgs(rgsb),
74
  .rgm(rgmb),
75
  .exp(expb),
76
  .sig(sigb),
77
  .zer(zerb),
78
  .inf(infb)
79
);
80
 
81
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
82
// Clock #2
83
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
84
reg [rs+1:0] rgm1, rgm2;
85
reg [es-1:0] expa2, expb2;
86
reg so2;
87
reg inf2;
88
reg zero2;
89
reg [(PSTWID-es)*2-1:0] prod2;
90
 
91
always @(posedge clk)
92
  if (ce) prod2 <= siga * sigb;
93
always @(posedge clk)
94
  if (ce) so2 <= sa ^ sb;  // compute sign
95
always @(posedge clk)
96
  if (ce) inf2 <= infa|infb;
97
always @(posedge clk)
98
  if (ce) zero2 <= zera|zerb;
99
// Convert to the real +/- regime value
100
always @(posedge clk)
101
  if (ce) rgm1 <= rgsa ? rgma : -rgma;
102
always @(posedge clk)
103
  if (ce) rgm2 <= rgsb ? rgmb : -rgmb;
104
always @(posedge clk)
105
  if (ce) expa2 <= expa;
106
always @(posedge clk)
107
  if (ce) expb2 <= expb;
108
 
109
// The product could have one or two whole digits before the point. Detect which it is
110
// and realign the product.
111
wire mo = prod2[(PSTWID-es)*2-1];
112
 
113
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
114
// Clock #3
115
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116
reg [(PSTWID-es)*2-1:0] prod3;
117
reg [rs+es+1:0] rxtmp;
118
 
119
always @(posedge clk)
120
  if (ce) prod3 <= mo ? prod2 : {prod2,1'b0};  // left align product
121
 
122
// Compute regime and exponent, include product alignment shift.
123
always @(posedge clk)
124
  if (ce) rxtmp <= {rgm1,expa2} + {rgm2,expb2} + mo;
125
 
126
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
127
// Clock #4
128
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
129
reg [rs+es+1:0] rxtmp2c;
130
reg [es-1:0] exp;
131
reg [(PSTWID-es)*2-1:0] prod4;
132
reg [rs+es+1:0] rxtmp4;
133
reg srxtmp;
134
 
135
// Make a negative rx positive
136
always @(posedge clk)
137
  if (ce) rxtmp2c <= rxtmp[rs+es+1] ? ~rxtmp + 2'd1 : rxtmp;
138
 
139
always @(posedge clk)
140
  if (ce) prod4 <= prod3;
141
always @(posedge clk)
142
  if (ce) rxtmp4 <= rxtmp;
143
// Break out the exponent and regime portions
144
always @(posedge clk)
145
  if (ce) exp <= rxtmp[es-1:0];
146
// Take absolute value of regime portion
147
always @(posedge clk)
148
  if (ce) srxtmp <= rxtmp[rs+es+1];
149
 
150
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
151
// Clock #5
152
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153
reg [rs:0] rgm;
154
reg [rs+es+1:0] rxn;
155
reg [rs+es+1:0] rxtmp2c5;
156
reg [(PSTWID-es)*2-1:0] prod5;
157
reg [es-1:0] exp5;
158
reg srxtmp5;
159
 
160
always @(posedge clk)
161
  if (ce) rgm = srxtmp ? -rxtmp4[rs+es+1:es] : rxtmp4[rs+es+1:es];
162
 
163
// Compute the length of the regime bit string, +1 for positive regime
164
always @(posedge clk)
165
  if (ce) rxn <= rxtmp4[rs+es+1] ? rxtmp2c : rxtmp4;
166
 
167
always @(posedge clk)
168
  if (ce) prod5 <= prod4;
169
always @(posedge clk)
170
  if (ce) exp5 <= exp;
171
always @(posedge clk)
172
  if (ce) srxtmp5 <= srxtmp;
173
always @(posedge clk)
174
  if (ce) rxtmp2c5 <= rxtmp2c;
175
 
176
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
177
// Clock #6
178
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
179
reg [rs:0] rgml;
180
reg [PSTWID*2-1+3:0] tmp;
181
 
182
always @(posedge clk)
183
  if (ce) rgml <= (~srxtmp5 | |(rxn[es-1:0])) ? rxtmp2c5[rs+es:es] + 2'd1 : rxtmp2c5[rs+es:es];
184
 
185
// Build expanded posit number:
186
// trim one leading bit off the product bits
187
// and keep guard, round bits, and create sticky bit
188
always @(posedge clk)
189
  if (ce) tmp <= {{PSTWID-1{~srxtmp5}},srxtmp5,exp5,prod5[(PSTWID-es)*2-2:(PSTWID-es-2)],|prod5[(PSTWID-es-3):0]};
190
 
191
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
192
// Clock #7
193
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
194
reg [PSTWID*3-1+3:0] tmp7;
195
reg [rs:0] rgml7;
196
 
197
always @(posedge clk)
198
  if (ce) tmp7 <= {tmp,{PSTWID{1'b0}}} >> rgml;
199
always @(posedge clk)
200
  if (ce) rgml7 <= rgml;
201
 
202
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
203
// Clock #8
204
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
205
// Rounding
206
// Guard, Round, and Sticky
207
reg L, G, R, St;
208
reg [PSTWID*3-1+3:0] tmp8;
209
reg [rs:0] rgml8;
210
 
211
always @(posedge clk)
212
  if (ce) rgml8 <= rgml7;
213
always @(posedge clk)
214
  if (ce) L <= tmp7[PSTWID+4];
215
always @(posedge clk)
216
  if (ce) G <= tmp7[PSTWID+3];
217
always @(posedge clk)
218
  if (ce) R <= tmp7[PSTWID+2];
219
always @(posedge clk)
220
  if (ce) St <= |tmp7[PSTWID+1:0];
221
always @(posedge clk)
222
  if (ce) tmp8 <= tmp7;
223
 
224
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
225
// Clock #9
226
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
227
reg ulp;
228
wire [PSTWID-1:0] rnd_ulp;
229
reg [PSTWID*3-1+3:0] tmp9;
230
reg [rs:0] rgml9;
231
 
232
always @(posedge clk)
233
  if (ce) ulp <= ((G & (R | St)) | (L & G & ~(R | St)));
234
always @(posedge clk)
235
  if (ce) tmp9 <= tmp8;
236
always @(posedge clk)
237
  if (ce) rgml9 <= rgml8;
238
assign rnd_ulp = {{PSTWID-1{1'b0}},ulp};
239
 
240
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
241
// Clock #10
242
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
243
reg [PSTWID:0] tmp10_rnd_ulp;
244
reg [PSTWID*3-1+3:0] tmp10;
245
reg [rs:0] rgml10;
246
 
247
always @(posedge clk)
248
  if (ce) tmp10 <= tmp9;
249
always @(posedge clk)
250
  if (ce) tmp10_rnd_ulp <= tmp9[2*PSTWID-1+3:PSTWID+3] + rnd_ulp;
251
always @(posedge clk)
252
  if (ce) rgml10 <= rgml9;
253
 
254
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
255
// Clock #11
256
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
257
reg [PSTWID-1:0] tmp11_rnd;
258
 
259
always @(posedge clk)
260
  if (ce) tmp11_rnd <= (rgml10 < PSTWID-es-2) ? tmp10_rnd_ulp[PSTWID-1:0] : tmp10[2*PSTWID-1+3:PSTWID+3];
261
 
262
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
263
// Clock #12
264
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
265
reg [PSTWID-1:0] abs_tmp;
266
wire so11;
267
reg so12;
268
delay #(.WID(1),.DEP(9)) udly1 (.clk(clk), .ce(ce), .i(so2), .o(so11));
269
 
270
always @(posedge clk)
271
  if (ce) abs_tmp <= so11 ? -tmp11_rnd : tmp11_rnd;
272
always @(posedge clk)
273
  if (ce) so12 <= so11;
274
 
275
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276
// Clock #13
277
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
278
wire zero12, inf12;
279
 
280
delay #(.WID(1),.DEP(10)) udly2 (.clk(clk), .ce(ce), .i(zero2), .o(zero12));
281
delay #(.WID(1),.DEP(10)) udly3 (.clk(clk), .ce(ce), .i(inf2), .o(inf12));
282
 
283
always @(posedge clk)
284
  if (ce) zero <= zero12;
285
always @(posedge clk)
286
  if (ce) inf <= inf12;
287
 
288
always @(posedge clk)
289
  if (ce)
290
    casez({zero12,inf12})
291
    2'b1?: o <= {PSTWID{1'b0}};
292
    2'b01: o <= {1'b1,{PSTWID-1{1'b0}}};
293
    default:  o <= {so12,abs_tmp[PSTWID-1:1]};
294
    endcase
295
 
296
endmodule

powered by: WebSVN 2.1.0

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