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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog2/] [BCDMath.sv] - Blame information for rev 69

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

Line No. Rev Author Line
1 66 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//        __
4
//   \\__/ o\    (C) 2012-2022  Robert Finch, Waterloo
5
//    \  __ /    All rights reserved.
6
//     \/_//     robfinch@finitron.ca
7
//       ||
8
//
9
//      BCDMath.sv
10
//
11
// BSD 3-Clause License
12
// Redistribution and use in source and binary forms, with or without
13
// modification, are permitted provided that the following conditions are met:
14
//
15
// 1. Redistributions of source code must retain the above copyright notice, this
16
//    list of conditions and the following disclaimer.
17
//
18
// 2. Redistributions in binary form must reproduce the above copyright notice,
19
//    this list of conditions and the following disclaimer in the documentation
20
//    and/or other materials provided with the distribution.
21
//
22
// 3. Neither the name of the copyright holder nor the names of its
23
//    contributors may be used to endorse or promote products derived from
24
//    this software without specific prior written permission.
25
//
26
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
//
37
// ============================================================================
38
//
39
// Could use the following approach for add/sub but it ends up being larger
40
// than using an adjustment lookup table.
41
 
42
module BCDAddNyb(ci,a,b,o,c);
43
input ci;               // carry input
44
input [3:0] a;
45
input [3:0] b;
46
output [3:0] o;
47
output c;
48
 
49
wire c0;
50
 
51
reg [4:0] hsN0;
52
always  @*
53
begin
54
        hsN0 = a[3:0] + b[3:0] + ci;
55
        if (hsN0 > 5'd9)
56
                hsN0 = hsN0 + 3'd6;
57
end
58
assign o = hsN0[3:0];
59
assign c = hsN0[4];
60
 
61
endmodule
62
 
63
module BCDAdd(ci,a,b,o,c);
64
input ci;               // carry input
65
input [7:0] a;
66
input [7:0] b;
67
output [7:0] o;
68
output c;
69
 
70
wire c0,c1;
71
 
72
wire [4:0] hsN0 = a[3:0] + b[3:0] + ci;
73
wire [4:0] hsN1 = a[7:4] + b[7:4] + c0;
74
 
75
BCDAddAdjust u1 (hsN0,o[3:0],c0);
76
BCDAddAdjust u2 (hsN1,o[7:4],c);
77
 
78
endmodule
79
 
80
module BCDAdd4(ci,a,b,o,c,c8);
81
input ci;               // carry input
82
input [15:0] a;
83
input [15:0] b;
84
output [15:0] o;
85
output c;
86
output c8;
87
 
88
wire c0,c1,c2;
89
assign c8 = c1;
90
 
91
wire [4:0] hsN0 = a[3:0] + b[3:0] + ci;
92
wire [4:0] hsN1 = a[7:4] + b[7:4] + c0;
93
wire [4:0] hsN2 = a[11:8] + b[11:8] + c1;
94
wire [4:0] hsN3 = a[15:12] + b[15:12] + c2;
95
 
96
BCDAddAdjust u1 (hsN0,o[3:0],c0);
97
BCDAddAdjust u2 (hsN1,o[7:4],c1);
98
BCDAddAdjust u3 (hsN2,o[11:8],c2);
99
BCDAddAdjust u4 (hsN3,o[15:12],c);
100
 
101
endmodule
102
 
103
module BCDAddN(ci,a,b,o,co);
104
parameter N=24;
105
input ci;               // carry input
106
input [N*4-1:0] a;
107
input [N*4-1:0] b;
108
output [N*4-1:0] o;
109
output co;
110
 
111
genvar g;
112
generate begin : gBCDAddN
113
reg [4:0] hsN [0:N-1];
114
wire [N:0] c;
115
 
116
assign c[0] = ci;
117
assign co = c[N];
118
 
119
for (g = 0; g < N; g = g + 1)
120
        always @*
121
                hsN[g] = a[g*4+3:g*4] + b[g*4+3:g*4] + c[g];
122
 
123
for (g = 0; g < N; g = g + 1)
124
        BCDAddAdjust u1 (hsN[g],o[g*4+3:g*4],c[g+1]);
125
end
126
endgenerate
127
 
128
endmodule
129
/*
130
module BCDAdd8NClk(clk, a, b, o, ci, co);
131
parameter N=33;
132
input clk;
133
input [N*8-1:0] a;
134
input [N*8-1:0] b;
135
output [N*8-1:0] o;
136
input ci;
137
output co;
138
 
139
reg [N:0] c;
140
wire [N:0] d;
141
assign c[0] = ci;
142
assign co = c[N];
143
 
144
genvar g;
145
generate begin : gBCDadd
146
for (g = 0; g < N; g = g + 1) begin
147
        BCDAdd u1 (c[g],a[g*8+7:g*8],b[g*8+7:g*8],o[g*8+7:g*8],d[g+1]);
148
 
149
        always_ff @(posedge clk)
150
                c[g+1] <= d[g+1];
151
end
152
end
153
endgenerate
154
endmodule
155
*/
156
 
157
module BCDSub(ci,a,b,o,c);
158
input ci;               // carry input
159
input [7:0] a;
160
input [7:0] b;
161
output [7:0] o;
162
output c;
163
 
164
wire c0,c1;
165
 
166
wire [4:0] hdN0 = a[3:0] - b[3:0] - ci;
167
wire [4:0] hdN1 = a[7:4] - b[7:4] - c0;
168
 
169
BCDSubAdjust u1 (hdN0,o[3:0],c0);
170
BCDSubAdjust u2 (hdN1,o[7:4],c);
171
 
172
endmodule
173
 
174
module BCDSub4(ci,a,b,o,c,c8);
175
input ci;               // carry input
176
input [15:0] a;
177
input [15:0] b;
178
output [15:0] o;
179
output c;
180
output c8;
181
 
182
wire c0,c1,c2;
183
assign c8 = c1;
184
 
185
wire [4:0] hdN0 = a[3:0] - b[3:0] - ci;
186
wire [4:0] hdN1 = a[7:4] - b[7:4] - c0;
187
wire [4:0] hdN2 = a[11:8] - b[11:8] - c1;
188
wire [4:0] hdN3 = a[15:12] - b[15:12] - c2;
189
 
190
BCDSubAdjust u1 (hdN0,o[3:0],c0);
191
BCDSubAdjust u2 (hdN1,o[7:4],c1);
192
BCDSubAdjust u3 (hdN2,o[11:8],c2);
193
BCDSubAdjust u4 (hdN3,o[15:12],c);
194
 
195
endmodule
196
 
197
module BCDSubN(ci,a,b,o,co);
198
parameter N=24;
199
input ci;               // carry input
200
input [N*4-1:0] a;
201
input [N*4-1:0] b;
202
output [N*4-1:0] o;
203
output co;
204
 
205
genvar g;
206
generate begin : gBCDSubN
207
reg [4:0] hdN [0:N-1];
208
wire [N:0] c;
209
 
210
assign c[0] = ci;
211
assign co = c[N];
212
 
213
for (g = 0; g < N; g = g + 1)
214
        always @*
215
                hdN[g] = a[g*4+3:g*4] - b[g*4+3:g*4] - c[g];
216
 
217
for (g = 0; g < N; g = g + 1)
218
        BCDSubAdjust u1 (hdN[g],o[g*4+3:g*4],c[g+1]);
219
end
220
endgenerate
221
 
222
endmodule
223
 
224
/*
225
module BCDSub8NClk(clk, a, b, o, ci, co);
226
parameter N=33;
227
input clk;
228
input [N*8-1:0] a;
229
input [N*8-1:0] b;
230
output [N*8-1:0] o;
231
input ci;
232
output co;
233
 
234
reg [N:0] c;
235
wire [N:0] d;
236
assign c[0] = ci;
237
assign co = c[N];
238
 
239
genvar g;
240
generate begin : gBCDsub
241
for (g = 0; g < N; g = g + 1) begin
242
        BCDSub u1 (c[g],a[g*8+7:g*8],b[g*8+7:g*8],o[g*8+7:g*8],d[g+1]);
243
 
244
        always_ff @(posedge clk)
245
                c[g+1] <= d[g+1];
246
end
247
end
248
endgenerate
249
endmodule
250
*/
251
 
252
module BCDAddAdjust(i,o,c);
253
input [4:0] i;
254
output [3:0] o;
255
reg [3:0] o;
256
output c;
257
reg c;
258
always @(i)
259
case(i)
260
5'h0: begin o = 4'h0; c = 1'b0; end
261
5'h1: begin o = 4'h1; c = 1'b0; end
262
5'h2: begin o = 4'h2; c = 1'b0; end
263
5'h3: begin o = 4'h3; c = 1'b0; end
264
5'h4: begin o = 4'h4; c = 1'b0; end
265
5'h5: begin o = 4'h5; c = 1'b0; end
266
5'h6: begin o = 4'h6; c = 1'b0; end
267
5'h7: begin o = 4'h7; c = 1'b0; end
268
5'h8: begin o = 4'h8; c = 1'b0; end
269
5'h9: begin o = 4'h9; c = 1'b0; end
270
5'hA: begin o = 4'h0; c = 1'b1; end
271
5'hB: begin o = 4'h1; c = 1'b1; end
272
5'hC: begin o = 4'h2; c = 1'b1; end
273
5'hD: begin o = 4'h3; c = 1'b1; end
274
5'hE: begin o = 4'h4; c = 1'b1; end
275
5'hF: begin o = 4'h5; c = 1'b1; end
276
5'h10:  begin o = 4'h6; c = 1'b1; end
277
5'h11:  begin o = 4'h7; c = 1'b1; end
278
5'h12:  begin o = 4'h8; c = 1'b1; end
279
5'h13:  begin o = 4'h9; c = 1'b1; end
280
default:        begin o = 4'h9; c = 1'b1; end
281
endcase
282
endmodule
283
 
284
module BCDSubAdjust(i,o,c);
285
input [4:0] i;
286
output [3:0] o;
287
reg [3:0] o;
288
output c;
289
reg c;
290
always @(i)
291
case(i)
292
5'h0: begin o = 4'h0; c = 1'b0; end
293
5'h1: begin o = 4'h1; c = 1'b0; end
294
5'h2: begin o = 4'h2; c = 1'b0; end
295
5'h3: begin o = 4'h3; c = 1'b0; end
296
5'h4: begin o = 4'h4; c = 1'b0; end
297
5'h5: begin o = 4'h5; c = 1'b0; end
298
5'h6: begin o = 4'h6; c = 1'b0; end
299
5'h7: begin o = 4'h7; c = 1'b0; end
300
5'h8: begin o = 4'h8; c = 1'b0; end
301
5'h9: begin o = 4'h9; c = 1'b0; end
302
5'h16: begin o = 4'h0; c = 1'b1; end
303
5'h17: begin o = 4'h1; c = 1'b1; end
304
5'h18: begin o = 4'h2; c = 1'b1; end
305
5'h19: begin o = 4'h3; c = 1'b1; end
306
5'h1A: begin o = 4'h4; c = 1'b1; end
307
5'h1B: begin o = 4'h5; c = 1'b1; end
308
5'h1C: begin o = 4'h6; c = 1'b1; end
309
5'h1D: begin o = 4'h7; c = 1'b1; end
310
5'h1E: begin o = 4'h8; c = 1'b1; end
311
5'h1F: begin o = 4'h9; c = 1'b1; end
312
default: begin o = 4'h9; c = 1'b1; end
313
endcase
314
endmodule
315
 
316
// Multiply two BCD digits
317
// Method used is table lookup
318
module BCDMul1(a,b,o);
319
input [3:0] a;
320
input [3:0] b;
321
output [7:0] o;
322
reg [7:0] o;
323
 
324
always @(a or b)
325
casex({a,b})
326
8'h00: o = 8'h00;
327
8'h01: o = 8'h00;
328
8'h02: o = 8'h00;
329
8'h03: o = 8'h00;
330
8'h04: o = 8'h00;
331
8'h05: o = 8'h00;
332
8'h06: o = 8'h00;
333
8'h07: o = 8'h00;
334
8'h08: o = 8'h00;
335
8'h09: o = 8'h00;
336
8'h10: o = 8'h00;
337
8'h11: o = 8'h01;
338
8'h12: o = 8'h02;
339
8'h13: o = 8'h03;
340
8'h14: o = 8'h04;
341
8'h15: o = 8'h05;
342
8'h16: o = 8'h06;
343
8'h17: o = 8'h07;
344
8'h18: o = 8'h08;
345
8'h19: o = 8'h09;
346
8'h20: o = 8'h00;
347
8'h21: o = 8'h02;
348
8'h22: o = 8'h04;
349
8'h23: o = 8'h06;
350
8'h24: o = 8'h08;
351
8'h25: o = 8'h10;
352
8'h26: o = 8'h12;
353
8'h27: o = 8'h14;
354
8'h28: o = 8'h16;
355
8'h29: o = 8'h18;
356
8'h30: o = 8'h00;
357
8'h31: o = 8'h03;
358
8'h32: o = 8'h06;
359
8'h33: o = 8'h09;
360
8'h34: o = 8'h12;
361
8'h35: o = 8'h15;
362
8'h36: o = 8'h18;
363
8'h37: o = 8'h21;
364
8'h38: o = 8'h24;
365
8'h39: o = 8'h27;
366
8'h40: o = 8'h00;
367
8'h41: o = 8'h04;
368
8'h42: o = 8'h08;
369
8'h43: o = 8'h12;
370
8'h44: o = 8'h16;
371
8'h45: o = 8'h20;
372
8'h46: o = 8'h24;
373
8'h47: o = 8'h28;
374
8'h48: o = 8'h32;
375
8'h49: o = 8'h36;
376
8'h50: o = 8'h00;
377
8'h51: o = 8'h05;
378
8'h52: o = 8'h10;
379
8'h53: o = 8'h15;
380
8'h54: o = 8'h20;
381
8'h55: o = 8'h25;
382
8'h56: o = 8'h30;
383
8'h57: o = 8'h35;
384
8'h58: o = 8'h40;
385
8'h59: o = 8'h45;
386
8'h60: o = 8'h00;
387
8'h61: o = 8'h06;
388
8'h62: o = 8'h12;
389
8'h63: o = 8'h18;
390
8'h64: o = 8'h24;
391
8'h65: o = 8'h30;
392
8'h66: o = 8'h36;
393
8'h67: o = 8'h42;
394
8'h68: o = 8'h48;
395
8'h69: o = 8'h54;
396
8'h70: o = 8'h00;
397
8'h71: o = 8'h07;
398
8'h72: o = 8'h14;
399
8'h73: o = 8'h21;
400
8'h74: o = 8'h28;
401
8'h75: o = 8'h35;
402
8'h76: o = 8'h42;
403
8'h77: o = 8'h49;
404
8'h78: o = 8'h56;
405
8'h79: o = 8'h63;
406
8'h80: o = 8'h00;
407
8'h81: o = 8'h08;
408
8'h82: o = 8'h16;
409
8'h83: o = 8'h24;
410
8'h84: o = 8'h32;
411
8'h85: o = 8'h40;
412
8'h86: o = 8'h48;
413
8'h87: o = 8'h56;
414
8'h88: o = 8'h64;
415
8'h89: o = 8'h72;
416
8'h90: o = 8'h00;
417
8'h91: o = 8'h09;
418
8'h92: o = 8'h18;
419
8'h93: o = 8'h27;
420
8'h94: o = 8'h36;
421
8'h95: o = 8'h45;
422
8'h96: o = 8'h54;
423
8'h97: o = 8'h63;
424
8'h98: o = 8'h72;
425
8'h99: o = 8'h81;
426
default:        o = 8'h00;
427
endcase
428
endmodule
429
 
430
 
431
// Multiply two pairs of BCD digits
432
// handles from 0x0 to 99x99
433
module BCDMul2(a,b,o);
434
input [7:0] a;
435
input [7:0] b;
436
output [15:0] o;
437
 
438
wire [7:0] p1,p2,p3,p4;
439
wire [15:0] s1;
440
 
441
BCDMul1 u1 (a[3:0],b[3:0],p1);
442
BCDMul1 u2 (a[7:4],b[3:0],p2);
443
BCDMul1 u3 (a[3:0],b[7:4],p3);
444
BCDMul1 u4 (a[7:4],b[7:4],p4);
445
 
446
BCDAdd4 u5 (1'b0,{p4,p1},{4'h0,p2,4'h0},s1);
447
BCDAdd4 u6 (1'b0,s1,{4'h0,p3,4'h0},o);
448
 
449
endmodule
450
 
451
module BCDMul4(a,b,o);
452
input [15:0] a;
453
input [15:0] b;
454
output [31:0] o;
455
 
456
wire [15:0] p1,p2,p3,p4;
457
wire [31:0] s1;
458
 
459
BCDMul2 u1 (a[7:0],b[7:0],p1);
460
BCDMul2 u2 (a[15:8],b[7:0],p2);
461
BCDMul2 u3 (a[7:0],b[15:8],p3);
462
BCDMul2 u4 (a[15:8],b[15:8],p4);
463
 
464
BCDAddN #(.N(8)) u5 (1'b0,{p4,p1},{8'h0,p2,8'h0},s1);
465
BCDAddN #(.N(8)) u6 (1'b0,s1,{8'h0,p3,8'h0},o);
466
 
467
endmodule
468
 
469
module BCDMul8(a,b,o);
470
input [31:0] a;
471
input [31:0] b;
472
output [63:0] o;
473
 
474
wire [31:0] p1,p2,p3,p4;
475
wire [63:0] s1;
476
 
477
BCDMul4 u1 (a[15:0],b[15:0],p1);
478
BCDMul4 u2 (a[31:16],b[15:0],p2);
479
BCDMul4 u3 (a[15:0],b[31:16],p3);
480
BCDMul4 u4 (a[31:16],b[31:16],p4);
481
 
482
BCDAddN #(.N(16)) u5 (1'b0,{p4,p1},{16'h0,p2,16'h0},s1);
483
BCDAddN #(.N(16)) u6 (1'b0,s1,{16'h0,p3,16'h0},o);
484
 
485
endmodule
486
 
487
module BCDMul16(a,b,o);
488
input [63:0] a;
489
input [63:0] b;
490
output [127:0] o;
491
 
492
wire [63:0] p1,p2,p3,p4;
493
wire [127:0] s1;
494
 
495
BCDMul8 u1 (a[31:0],b[31:0],p1);
496
BCDMul8 u2 (a[63:32],b[31:0],p2);
497
BCDMul8 u3 (a[31:0],b[63:32],p3);
498
BCDMul8 u4 (a[63:32],b[63:32],p4);
499
 
500
BCDAddN #(.N(32)) u5 (1'b0,{p4,p1},{32'h0,p2,32'h0},s1);
501
BCDAddN #(.N(32)) u6 (1'b0,s1,{32'h0,p3,32'h0},o);
502
 
503
endmodule
504
 
505
module BCDMul32(a,b,o);
506
input [127:0] a;
507
input [127:0] b;
508
output [255:0] o;
509
 
510
wire [127:0] p1,p2,p3,p4;
511
wire [255:0] s1;
512
 
513
BCDMul16 u1 (a[63:0],b[63:0],p1);
514
BCDMul16 u2 (a[127:64],b[63:0],p2);
515
BCDMul16 u3 (a[63:0],b[127:64],p3);
516
BCDMul16 u4 (a[127:64],b[127:64],p4);
517
 
518
BCDAddN #(.N(64)) u5 (1'b0,{p4,p1},{64'h0,p2,64'h0},s1);
519
BCDAddN #(.N(64)) u6 (1'b0,s1,{64'h0,p3,64'h0},o);
520
 
521
endmodule
522
 
523
module BCDMul_tb();
524
 
525
wire [15:0] o1,o2,o3,o4;
526
 
527
BCDMul2 u1 (8'h00,8'h00,o1);
528
BCDMul2 u2 (8'h99,8'h99,o2);
529
BCDMul2 u3 (8'h25,8'h18,o3);
530
BCDMul2 u4 (8'h37,8'h21,o4);
531
 
532
endmodule
533
 
534
module BinToBCD(i, o);
535
input [7:0] i;
536
output [11:0] o;
537
 
538
reg [11:0] tbl [0:255];
539
 
540
genvar g;
541
generate begin : gTbl
542
reg [3:0] n0 [0:255];
543
reg [3:0] n1 [0:255];
544
reg [3:0] n2 [0:255];
545
 
546
for (g = 0; g < 256; g = g + 1) begin
547
        initial begin
548
                n0[g] = g % 10;
549
                n1[g] = g / 10;
550
                n2[g] = g / 100;
551
                tbl[g] <= {n2[g],n1[g],n0[g]};
552
        end
553
end
554
 
555
assign o = tbl[i];
556
 
557
end
558
endgenerate
559
 
560
endmodule
561
 
562
// Perform a logical shift to the right.
563
module BCDSRL(ci, i, o, co);
564
parameter N=4;
565
input ci;
566
input [N*4-1:0] i;
567
output reg [N*4-1:0] o;
568
output co;
569
 
570
reg [N:0] c;
571
 
572
genvar g;
573
generate begin
574
always @*
575
        c[N] = ci;
576
for (g = N - 1; g >= 0; g = g - 1)
577
always @*
578
        c[g] = i[g*4];
579
for (g = N - 1; g >= 0; g = g - 1)
580
always @*
581
begin
582
        o[g*4+3:g*4] = {1'b0,i[g*4+3:g*4+1]};
583
        // Because there is a divide by two, the value will range between 0 and 4.
584
        // Adding 5 keeps it within deicmal boundaries of 0 to 9. No carry can be
585
        // generated
586
        if (c[N+1])
587
                o[g*4+3:g*4] = o[g*4+3:g*4] + 4'd5;
588
end
589
        assign co = c[0];
590
end
591
endgenerate
592
 
593
endmodule

powered by: WebSVN 2.1.0

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