Last active
January 22, 2019 03:54
-
-
Save buttercutter/0f46d5478735960b9efed32c0c4254f2 to your computer and use it in GitHub Desktop.
Signed Multiplier verilog code from https://github.com/ZipCPU/fwmpy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Filename: bimpy | |
// | |
// Project: A multiply core generator | |
// | |
// Purpose: An unsigned 2-bit multiply based upon the fact that LUT's allow | |
// 6-bits of input, but a 2x2 bit multiply will never carry more | |
// than one bit. While this multiply is hardware independent, it is | |
// really motivated by trying to optimize for a specific piece of | |
// hardware (Xilinx-7 series ...) that has 4-input LUT's with carry | |
// chains. | |
// | |
// Creator: Dan Gisselquist, Ph.D. | |
// Gisselquist Technology, LLC | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Copyright (C) 2015,2017-2019, Gisselquist Technology, LLC | |
// | |
// This program is free software (firmware): you can redistribute it and/or | |
// modify it under the terms of the GNU General Public License as published | |
// by the Free Software Foundation, either version 3 of the License, or (at | |
// your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
// for more details. | |
// | |
// You should have received a copy of the GNU General Public License along | |
// with this program. If not, see <http://www.gnu.org/licenses/> for a | |
// copy. | |
// | |
// License: GPL, v3, as defined and found on www.gnu.org, | |
// http://www.gnu.org/licenses/gpl.html | |
// | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
module bimpy(i_clk, i_reset, i_ce, i_a, i_b, o_r); | |
parameter BW=2, LUTB=2; | |
input i_clk, i_reset, i_ce; | |
input [(LUTB-1):0] i_a; | |
input [(BW-1):0] i_b; | |
output reg [(BW+LUTB-1):0] o_r; | |
// See https://stackoverflow.com/questions/54247731/understanding-a-binary-multiplier-using-gate-level-diagram | |
// for general overview of this module | |
/* wire [(BW+LUTB-2):0] w_r; | |
wire [(BW+LUTB-3):1] c; | |
assign w_r = { ((i_a[1])?i_b:{(BW){1'b0}}), 1'b0 } | |
^ { 1'b0, ((i_a[0])?i_b:{(BW){1'b0}}) }; | |
assign c = { ((i_a[1])?i_b[(BW-2):0]:{(BW-1){1'b0}}) } | |
& ((i_a[0])?i_b[(BW-1):1]:{(BW-1){1'b0}}); | |
*/ | |
initial o_r = 0; | |
always @(posedge i_clk) | |
if (i_reset) | |
o_r <= 0; | |
else if (i_ce) | |
o_r <= (i_a[0] ? i_b : 2'b0) + ((i_a[1] ? i_b : 2'b0)<<1);//o_r <= w_r + { c, 2'b0 }; | |
// similar to 2 bits by 2 bits multiplication as in o_r <= (i_a[0]*i_b) + ((i_a[1]*i_b)<< 1) | |
endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[*] | |
[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI | |
[*] Fri Jan 18 07:53:14 2019 | |
[*] | |
[dumpfile] "/home/phung/Documents/phung/multiplier/multiply_2x2.vcd" | |
[dumpfile_mtime] "Fri Jan 18 02:14:27 2019" | |
[dumpfile_size] 2026 | |
[savefile] "/home/phung/Documents/phung/multiplier/multiply_2x2.gtkw" | |
[timestart] 0 | |
[size] 1920 1115 | |
[pos] -39 -39 | |
*-5.274622 45 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 | |
[treeopen] test. | |
[treeopen] test.s2_2. | |
[treeopen] test.s2_2.umpy. | |
[sst_width] 229 | |
[signals_width] 434 | |
[sst_expanded] 1 | |
[sst_vpaned_height] 319 | |
@420 | |
test.i_a[1:0] | |
@28 | |
test.i_aux | |
@420 | |
test.i_b[1:0] | |
@28 | |
test.i_ce | |
test.i_clk | |
test.i_reset | |
test.o_aux | |
@420 | |
test.o_p[3:0] | |
@28 | |
test.s2_2.i_a[1:0] | |
test.s2_2.i_aux | |
test.s2_2.i_b[1:0] | |
test.s2_2.i_ce | |
test.s2_2.i_clk | |
test.s2_2.i_l[1:0] | |
test.s2_2.i_reset | |
test.s2_2.i_s[1:0] | |
test.s2_2.o_aux | |
@22 | |
test.s2_2.o_p[3:0] | |
@28 | |
test.s2_2.u_aux | |
test.s2_2.u_l[1:0] | |
@22 | |
test.s2_2.u_r[3:0] | |
@28 | |
test.s2_2.u_s[1:0] | |
test.s2_2.u_sgn[1:0] | |
test.s2_2.w_aux | |
test.s2_2.umpy.A_0 | |
@22 | |
test.s2_2.umpy.S_0_00[3:0] | |
@28 | |
test.s2_2.umpy.i_a[1:0] | |
test.s2_2.umpy.i_aux | |
test.s2_2.umpy.i_b[1:0] | |
test.s2_2.umpy.i_ce | |
test.s2_2.umpy.i_clk | |
test.s2_2.umpy.i_l[1:0] | |
test.s2_2.umpy.i_reset | |
test.s2_2.umpy.i_s[1:0] | |
test.s2_2.umpy.o_aux | |
@22 | |
test.s2_2.umpy.o_p[3:0] | |
@25 | |
test.s2_2.umpy.initialmpy_0_0.c[1] | |
test.s2_2.umpy.initialmpy_0_0.i_a[1:0] | |
test.s2_2.umpy.initialmpy_0_0.i_b[1:0] | |
@28 | |
test.s2_2.umpy.initialmpy_0_0.i_ce | |
test.s2_2.umpy.initialmpy_0_0.i_clk | |
test.s2_2.umpy.initialmpy_0_0.i_reset | |
@25 | |
test.s2_2.umpy.initialmpy_0_0.o_r[3:0] | |
test.s2_2.umpy.initialmpy_0_0.w_r[2:0] | |
[pattern_trace] 1 | |
[pattern_trace] 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$date | |
Fri Jan 18 18:39:41 2019 | |
$end | |
$version | |
Icarus Verilog | |
$end | |
$timescale | |
1s | |
$end | |
$scope module test $end | |
$var wire 4 ! o_p [3:0] $end | |
$var wire 1 " o_aux $end | |
$var reg 2 # i_a [1:0] $end | |
$var reg 1 $ i_aux $end | |
$var reg 2 % i_b [1:0] $end | |
$var reg 1 & i_ce $end | |
$var reg 1 ' i_clk $end | |
$var reg 1 ( i_reset $end | |
$scope module s2_2 $end | |
$var wire 2 ) i_a [1:0] $end | |
$var wire 1 $ i_aux $end | |
$var wire 2 * i_b [1:0] $end | |
$var wire 1 & i_ce $end | |
$var wire 1 ' i_clk $end | |
$var wire 1 ( i_reset $end | |
$var wire 1 + w_aux $end | |
$var wire 4 , u_r [3:0] $end | |
$var wire 2 - i_s [1:0] $end | |
$var wire 2 . i_l [1:0] $end | |
$var reg 1 " o_aux $end | |
$var reg 4 / o_p [3:0] $end | |
$var reg 1 0 u_aux $end | |
$var reg 2 1 u_l [1:0] $end | |
$var reg 2 2 u_s [1:0] $end | |
$var reg 2 3 u_sgn [1:0] $end | |
$scope begin genblk2 $end | |
$upscope $end | |
$scope module umpy $end | |
$var wire 2 4 i_a [1:0] $end | |
$var wire 1 0 i_aux $end | |
$var wire 2 5 i_b [1:0] $end | |
$var wire 1 & i_ce $end | |
$var wire 1 ' i_clk $end | |
$var wire 1 ( i_reset $end | |
$var wire 1 + o_aux $end | |
$var wire 4 6 o_p [3:0] $end | |
$var wire 2 7 i_s [1:0] $end | |
$var wire 2 8 i_l [1:0] $end | |
$var wire 4 9 S_0_00 [3:0] $end | |
$var reg 1 : A_0 $end | |
$scope begin genblk2 $end | |
$upscope $end | |
$scope module initialmpy_0_0 $end | |
$var wire 2 ; i_a [1:0] $end | |
$var wire 2 < i_b [1:0] $end | |
$var wire 1 & i_ce $end | |
$var wire 1 ' i_clk $end | |
$var wire 1 ( i_reset $end | |
$var reg 4 = o_r [3:0] $end | |
$upscope $end | |
$upscope $end | |
$upscope $end | |
$upscope $end | |
$enddefinitions $end | |
#0 | |
$dumpvars | |
b0 = | |
b0 < | |
b0 ; | |
0: | |
b0 9 | |
b0 8 | |
b0 7 | |
b0 6 | |
b0 5 | |
b0 4 | |
b0 3 | |
b0 2 | |
b0 1 | |
00 | |
b0 / | |
b0 . | |
b0 - | |
b0 , | |
0+ | |
b0 * | |
b0 ) | |
0( | |
0' | |
0& | |
b0 % | |
0$ | |
b0 # | |
0" | |
b0 ! | |
$end | |
#5 | |
1' | |
#10 | |
0' | |
#15 | |
1( | |
1' | |
#20 | |
0' | |
#25 | |
0( | |
1' | |
#30 | |
0' | |
#35 | |
1' | |
#40 | |
0' | |
#45 | |
10 | |
b10 7 | |
b10 ; | |
b10 1 | |
b10 5 | |
b1 8 | |
b1 < | |
b1 2 | |
b1 4 | |
b1 3 | |
1$ | |
b1 - | |
b1 % | |
b1 * | |
b10 . | |
b10 # | |
b10 ) | |
1& | |
1' | |
#50 | |
0' | |
#55 | |
b11 3 | |
1+ | |
1: | |
b10 , | |
b10 6 | |
b10 9 | |
b10 = | |
1' | |
#60 | |
0' | |
#65 | |
b1110 ! | |
b1110 / | |
1" | |
1' | |
#70 | |
0' | |
#75 | |
1' | |
#80 | |
0' | |
#85 | |
1' | |
#90 | |
0' | |
#95 | |
1' | |
#100 | |
0' | |
#105 | |
1' | |
#110 | |
0' | |
#115 | |
1' | |
#120 | |
0' | |
#125 | |
1' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[*] | |
[*] GTKWave Analyzer v3.3.94 (w)1999-2018 BSI | |
[*] Thu Jan 17 13:56:12 2019 | |
[*] | |
[dumpfile] "/home/phung/Documents/Grive/Personal/Digital/verification_example/multiplier/multiply_3x3.vcd" | |
[dumpfile_mtime] "Thu Jan 17 13:27:50 2019" | |
[dumpfile_size] 2498 | |
[savefile] "/home/phung/Documents/Grive/Personal/Digital/verification_example/multiplier/multiply_3x3.gtkw" | |
[timestart] 0 | |
[size] 1920 995 | |
[pos] -1 -1 | |
*-5.266698 45 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 | |
[treeopen] test. | |
[treeopen] test.s3_3. | |
[treeopen] test.s3_3.umpy. | |
[sst_width] 228 | |
[signals_width] 380 | |
[sst_expanded] 1 | |
[sst_vpaned_height] 279 | |
@421 | |
test.i_a[2:0] | |
@420 | |
test.i_aux | |
@421 | |
test.i_b[2:0] | |
@420 | |
test.i_ce | |
test.i_clk | |
test.i_reset | |
test.o_aux | |
@421 | |
test.o_p[5:0] | |
@420 | |
test.s3_3.i_a[2:0] | |
test.s3_3.i_aux | |
test.s3_3.i_b[2:0] | |
test.s3_3.i_ce | |
test.s3_3.i_clk | |
test.s3_3.i_l[2:0] | |
test.s3_3.i_reset | |
test.s3_3.i_s[2:0] | |
test.s3_3.o_aux | |
test.s3_3.o_p[5:0] | |
test.s3_3.u_aux | |
test.s3_3.u_l[2:0] | |
test.s3_3.u_r[5:0] | |
test.s3_3.u_s[2:0] | |
test.s3_3.u_sgn[2:0] | |
test.s3_3.w_aux | |
test.s3_3.umpy.A_0 | |
test.s3_3.umpy.A_1 | |
test.s3_3.umpy.S_0_00[4:0] | |
test.s3_3.umpy.S_0_01[4:0] | |
test.s3_3.umpy.S_1_00[5:0] | |
test.s3_3.umpy.i_a[2:0] | |
test.s3_3.umpy.i_aux | |
test.s3_3.umpy.i_b[2:0] | |
test.s3_3.umpy.i_ce | |
test.s3_3.umpy.i_clk | |
test.s3_3.umpy.i_l[2:0] | |
test.s3_3.umpy.i_reset | |
test.s3_3.umpy.i_s[2:0] | |
test.s3_3.umpy.o_aux | |
test.s3_3.umpy.o_p[5:0] | |
test.s3_3.umpy.unused | |
test.s3_3.umpy.initialmpy_0_0.c[2:1] | |
test.s3_3.umpy.initialmpy_0_0.i_a[1:0] | |
test.s3_3.umpy.initialmpy_0_0.i_b[2:0] | |
test.s3_3.umpy.initialmpy_0_0.i_ce | |
test.s3_3.umpy.initialmpy_0_0.i_clk | |
test.s3_3.umpy.initialmpy_0_0.i_reset | |
test.s3_3.umpy.initialmpy_0_0.o_r[4:0] | |
test.s3_3.umpy.initialmpy_0_0.w_r[3:0] | |
test.s3_3.umpy.initialmpy_1_0.c[2:1] | |
test.s3_3.umpy.initialmpy_1_0.i_a[1:0] | |
test.s3_3.umpy.initialmpy_1_0.i_b[2:0] | |
test.s3_3.umpy.initialmpy_1_0.i_ce | |
test.s3_3.umpy.initialmpy_1_0.i_clk | |
test.s3_3.umpy.initialmpy_1_0.i_reset | |
test.s3_3.umpy.initialmpy_1_0.o_r[4:0] | |
test.s3_3.umpy.initialmpy_1_0.w_r[3:0] | |
[pattern_trace] 1 | |
[pattern_trace] 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$date | |
Thu Jan 17 21:27:50 2019 | |
$end | |
$version | |
Icarus Verilog | |
$end | |
$timescale | |
1s | |
$end | |
$scope module test $end | |
$var wire 6 ! o_p [5:0] $end | |
$var wire 1 " o_aux $end | |
$var reg 3 # i_a [2:0] $end | |
$var reg 1 $ i_aux $end | |
$var reg 3 % i_b [2:0] $end | |
$var reg 1 & i_ce $end | |
$var reg 1 ' i_clk $end | |
$var reg 1 ( i_reset $end | |
$scope module s3_3 $end | |
$var wire 3 ) i_a [2:0] $end | |
$var wire 1 $ i_aux $end | |
$var wire 3 * i_b [2:0] $end | |
$var wire 1 & i_ce $end | |
$var wire 1 ' i_clk $end | |
$var wire 1 ( i_reset $end | |
$var wire 1 + w_aux $end | |
$var wire 6 , u_r [5:0] $end | |
$var wire 3 - i_s [2:0] $end | |
$var wire 3 . i_l [2:0] $end | |
$var reg 1 " o_aux $end | |
$var reg 6 / o_p [5:0] $end | |
$var reg 1 0 u_aux $end | |
$var reg 3 1 u_l [2:0] $end | |
$var reg 3 2 u_s [2:0] $end | |
$var reg 3 3 u_sgn [2:0] $end | |
$scope begin genblk2 $end | |
$upscope $end | |
$scope module umpy $end | |
$var wire 3 4 i_a [2:0] $end | |
$var wire 1 0 i_aux $end | |
$var wire 3 5 i_b [2:0] $end | |
$var wire 1 & i_ce $end | |
$var wire 1 ' i_clk $end | |
$var wire 1 ( i_reset $end | |
$var wire 1 + o_aux $end | |
$var wire 6 6 o_p [5:0] $end | |
$var wire 1 7 unused $end | |
$var wire 3 8 i_s [2:0] $end | |
$var wire 3 9 i_l [2:0] $end | |
$var wire 5 : S_0_01 [4:0] $end | |
$var wire 5 ; S_0_00 [4:0] $end | |
$var reg 1 < A_0 $end | |
$var reg 1 = A_1 $end | |
$var reg 6 > S_1_00 [5:0] $end | |
$scope begin genblk2 $end | |
$upscope $end | |
$scope module initialmpy_0_0 $end | |
$var wire 2 ? c [2:1] $end | |
$var wire 2 @ i_a [1:0] $end | |
$var wire 3 A i_b [2:0] $end | |
$var wire 1 & i_ce $end | |
$var wire 1 ' i_clk $end | |
$var wire 1 ( i_reset $end | |
$var wire 4 B w_r [3:0] $end | |
$var reg 5 C o_r [4:0] $end | |
$upscope $end | |
$scope module initialmpy_1_0 $end | |
$var wire 2 D c [2:1] $end | |
$var wire 2 E i_a [1:0] $end | |
$var wire 3 F i_b [2:0] $end | |
$var wire 1 & i_ce $end | |
$var wire 1 ' i_clk $end | |
$var wire 1 ( i_reset $end | |
$var wire 4 G w_r [3:0] $end | |
$var reg 5 H o_r [4:0] $end | |
$upscope $end | |
$upscope $end | |
$upscope $end | |
$upscope $end | |
$enddefinitions $end | |
#0 | |
$dumpvars | |
b0 H | |
b0 G | |
b0 F | |
b0 E | |
b0 D | |
b0 C | |
b0 B | |
b0 A | |
b0 @ | |
b0 ? | |
b0 > | |
0= | |
0< | |
b0 ; | |
b0 : | |
b0 9 | |
b0 8 | |
07 | |
b0 6 | |
b0 5 | |
b0 4 | |
b0 3 | |
b0 2 | |
b0 1 | |
00 | |
b0 / | |
b0 . | |
b0 - | |
b0 , | |
0+ | |
b0 * | |
b0 ) | |
0( | |
0' | |
0& | |
b0 % | |
0$ | |
b0 # | |
0" | |
b0 ! | |
$end | |
#5 | |
1' | |
#10 | |
0' | |
#15 | |
1( | |
1' | |
#20 | |
0' | |
#25 | |
0( | |
1' | |
#30 | |
0' | |
#35 | |
1' | |
#40 | |
0' | |
#45 | |
b101 B | |
b1 ? | |
b11 @ | |
10 | |
b11 8 | |
b11 1 | |
b11 5 | |
b11 9 | |
b11 A | |
b11 F | |
b11 2 | |
b11 4 | |
b1 3 | |
1$ | |
b101 - | |
b101 % | |
b101 * | |
b11 . | |
b11 # | |
b11 ) | |
1& | |
1' | |
#50 | |
0' | |
#55 | |
b11 3 | |
1< | |
b1001 ; | |
b1001 C | |
1' | |
#60 | |
0' | |
#65 | |
b1001 , | |
b1001 6 | |
b1001 > | |
1+ | |
1= | |
b111 3 | |
1' | |
#70 | |
0' | |
#75 | |
1" | |
b110111 ! | |
b110111 / | |
1' | |
#80 | |
0' | |
#85 | |
1' | |
#90 | |
0' | |
#95 | |
1' | |
#100 | |
0' | |
#105 | |
1' | |
#110 | |
0' | |
#115 | |
1' | |
#120 | |
0' | |
#125 | |
1' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Filename: sgnmpy_2x2.v | |
// | |
// Project: A multiply core generator | |
// | |
// Purpose: Turns a signed multiply into an unsigned multiply, at the cost | |
// of two clocks and a negation. | |
// | |
// | |
// Creator: Dan Gisselquist, Ph.D. | |
// Gisselquist Tecnology, LLC | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Copyright (C) 2015,2017, Gisselquist Technology, LLC | |
// | |
// This program is free software (firmware): you can redistribute it and/or | |
// modify it under the terms of the GNU General Public License as published | |
// by the Free Software Foundation, either version 3 of the License, or (at | |
// your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
// for more details. | |
// | |
// You should have received a copy of the GNU General Public License along | |
// with this program. If not, see <http://www.gnu.org/licenses/> for a | |
// copy. | |
// | |
// License: GPL, v3, as defined and found on www.gnu.org, | |
// http://www.gnu.org/licenses/gpl.html | |
// | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
module sgnmpy_2x2(i_clk, i_reset, i_ce, i_a, i_b, i_aux, o_p, o_aux); | |
parameter NA=2, NB=2, DLY=2; | |
input i_clk, i_reset, i_ce; | |
input signed [(NA-1):0] i_a; | |
input signed [(NB-1):0] i_b; | |
input i_aux; | |
output reg signed [(NA+NB-1):0] o_p; | |
output reg o_aux; | |
localparam NS = (NA < NB) ? NA : NB; | |
localparam NL = (NA < NB) ? NB : NA; | |
wire [(NS-1):0] i_s; // Smaller input | |
wire [(NL-1):0] i_l; // larger input | |
// | |
// Adjust our inputs so that i_s has the fewest bits, and i_b the most | |
generate if (NA < NB) | |
begin : BITADJ | |
assign i_s = i_a; | |
assign i_l = i_b; | |
end else begin | |
assign i_s = i_b; | |
assign i_l = i_a; | |
end endgenerate | |
reg [(NS-1):0] u_s; | |
reg [(NL-1):0] u_l; | |
reg [(DLY-1):0] u_sgn; | |
reg u_aux; | |
initial u_aux = 1'b0; | |
always @(posedge i_clk) | |
if(i_reset) | |
u_aux <= 1'b0; | |
else if (i_ce) | |
u_aux <= i_aux; | |
initial u_s = 0; | |
initial u_l = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
begin | |
u_s <= 0; | |
u_l <= 0; | |
end else if (i_ce) | |
begin | |
u_s <= (i_s[NS-1])?(-i_s):i_s; | |
u_l <= (i_l[NL-1])?(-i_l):i_l; | |
end | |
initial u_sgn = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
u_sgn <= 0; | |
else if (i_ce) | |
u_sgn <= { u_sgn[(DLY-2):0], ((i_s[NS-1])^(i_l[NL-1])) }; | |
wire [(NA+NB-1):0] u_r; | |
wire w_aux; | |
umpy_2x2 umpy(i_clk, i_reset, i_ce, u_s, u_l, u_aux, u_r, w_aux); | |
initial o_p = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
o_p <= 0; | |
else if (i_ce) | |
o_p <= (u_sgn[DLY-1])?(-u_r):u_r; | |
initial o_aux = 1'b0; | |
always @(posedge i_clk) | |
if(i_reset) | |
o_aux <= 1'b0; | |
else if (i_ce) | |
o_aux <= w_aux; | |
endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Filename: sgnmpy_3x3.v | |
// | |
// Project: A multiply core generator | |
// | |
// Purpose: Turns a signed multiply into an unsigned multiply, at the cost | |
// of two clocks and a negation. | |
// | |
// | |
// Creator: Dan Gisselquist, Ph.D. | |
// Gisselquist Technology, LLC | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Copyright (C) 2015,2017-2019, Gisselquist Technology, LLC | |
// | |
// This program is free software (firmware): you can redistribute it and/or | |
// modify it under the terms of the GNU General Public License as published | |
// by the Free Software Foundation, either version 3 of the License, or (at | |
// your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
// for more details. | |
// | |
// You should have received a copy of the GNU General Public License along | |
// with this program. If not, see <http://www.gnu.org/licenses/> for a | |
// copy. | |
// | |
// License: GPL, v3, as defined and found on www.gnu.org, | |
// http://www.gnu.org/licenses/gpl.html | |
// | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
module sgnmpy_3x3(i_clk, i_reset, i_ce, i_a, i_b, i_aux, o_p, o_aux); | |
parameter NA=3, NB=3, DLY=3; | |
input i_clk, i_reset, i_ce; | |
input signed [(NA-1):0] i_a; | |
input signed [(NB-1):0] i_b; | |
input i_aux; | |
output reg signed [(NA+NB-1):0] o_p; | |
output reg o_aux; | |
localparam NS = (NA < NB) ? NA : NB; | |
localparam NL = (NA < NB) ? NB : NA; | |
wire [(NS-1):0] i_s; // Smaller input | |
wire [(NL-1):0] i_l; // larger input | |
// | |
// Adjust our inputs so that i_s has the fewest bits, and i_b the most | |
generate if (NA < NB) | |
begin : BITADJ | |
assign i_s = i_a; | |
assign i_l = i_b; | |
end else begin | |
assign i_s = i_b; | |
assign i_l = i_a; | |
end endgenerate | |
reg [(NS-1):0] u_s; | |
reg [(NL-1):0] u_l; | |
reg [(DLY-1):0] u_sgn; | |
reg u_aux; | |
initial u_aux = 1'b0; | |
always @(posedge i_clk) | |
if(i_reset) | |
u_aux <= 1'b0; | |
else if (i_ce) | |
u_aux <= i_aux; | |
initial u_s = 0; | |
initial u_l = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
begin | |
u_s <= 0; | |
u_l <= 0; | |
end else if (i_ce) | |
begin | |
u_s <= (i_s[NS-1])?(-i_s):i_s; | |
u_l <= (i_l[NL-1])?(-i_l):i_l; | |
end | |
initial u_sgn = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
u_sgn <= 0; | |
else if (i_ce) | |
u_sgn <= { u_sgn[(DLY-2):0], ((i_s[NS-1])^(i_l[NL-1])) }; | |
wire [(NA+NB-1):0] u_r; | |
wire w_aux; | |
umpy_3x3 umpy(i_clk, i_reset, i_ce, u_s, u_l, u_aux, u_r, w_aux); | |
initial o_p = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
o_p <= 0; | |
else if (i_ce) | |
o_p <= (u_sgn[DLY-1])?(-u_r):u_r; | |
initial o_aux = 1'b0; | |
always @(posedge i_clk) | |
if(i_reset) | |
o_aux <= 1'b0; | |
else if (i_ce) | |
o_aux <= w_aux; | |
endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Testbench | |
module test; | |
parameter NA=2, NB=2, DLY=2; | |
reg i_clk; | |
reg i_reset; | |
reg i_ce; | |
reg signed[(NA-1):0] i_a; | |
reg signed[(NB-1):0] i_b; | |
reg i_aux; | |
wire signed[(NA+NB-1):0] o_p; | |
wire o_aux; | |
// Instantiate design under test | |
sgnmpy_2x2 s2_2(.i_clk(i_clk), .i_reset(i_reset), .i_ce(i_ce), .i_a(i_a), .i_b(i_b), .i_aux(i_aux), .o_p(o_p), .o_aux(o_aux)); | |
initial begin | |
// Dump waves | |
$dumpfile("multiply_2x2.vcd"); | |
$dumpvars(0); | |
$display("Reset flop."); | |
i_clk = 0; | |
i_reset = 0; | |
i_ce = 0; | |
i_a = 0; | |
i_b = 0; | |
i_aux = 0; | |
end | |
always #5 i_clk = !i_clk; | |
initial begin | |
@(posedge i_clk); | |
@(posedge i_clk); | |
i_reset = 1; | |
@(posedge i_clk); | |
i_reset = 0; | |
@(posedge i_clk); | |
@(posedge i_clk); | |
i_ce = 1; | |
i_a = 2; | |
i_b = 1; | |
i_aux = 1; | |
#80 $finish; | |
end | |
endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Testbench | |
/* | |
iverilog -o multiply_3x3.vvp -Wall -g2012 testbench_3x3.v sgnmpy_3x3.v umpy_3x3.v bimpy.v | |
vvp multiply_3x3.vvp | |
gtkwave multiply_3x3.gtkw | |
*/ | |
module test; | |
parameter NA=3, NB=3, DLY=3; | |
reg i_clk; | |
reg i_reset; | |
reg i_ce; | |
reg signed[(NA-1):0] i_a; | |
reg signed[(NB-1):0] i_b; | |
reg i_aux; | |
wire signed[(NA+NB-1):0] o_p; | |
wire o_aux; | |
// Instantiate design under test | |
sgnmpy_3x3 s3_3(.i_clk(i_clk), .i_reset(i_reset), .i_ce(i_ce), | |
.i_a(i_a), .i_b(i_b), .i_aux(i_aux), .o_p(o_p), .o_aux(o_aux)); | |
initial begin | |
// Dump waves | |
$dumpfile("multiply_3x3.vcd"); | |
$dumpvars(0); | |
$display("Reset flop."); | |
i_clk = 0; | |
i_reset = 0; | |
i_ce = 0; | |
i_a = 0; | |
i_b = 0; | |
i_aux = 0; | |
end | |
always #5 i_clk = !i_clk; | |
initial begin | |
@(posedge i_clk); | |
@(posedge i_clk); | |
i_reset = 1; | |
@(posedge i_clk); | |
i_reset = 0; | |
@(posedge i_clk); | |
@(posedge i_clk); | |
i_ce = 1; | |
i_a = 'b011; | |
i_b = 'b101; | |
i_aux = 1; | |
#80 $finish; | |
end | |
endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Filename: umpy_2x2.v | |
// | |
// Project: A multiply core generator | |
// | |
// Purpose: This verilog file multiplies two unsigned numbers together, | |
// without using any hardware acceleration. This file is | |
// computer generated, so please (for your sake) don't make any edits | |
// to this file lest you regenerate it and your edits be lost. | |
// | |
// | |
// Creator: Dan Gisselquist, Ph.D. | |
// Gisselquist Tecnology, LLC | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Copyright (C) 2015,2017, Gisselquist Technology, LLC | |
// | |
// This program is free software (firmware): you can redistribute it and/or | |
// modify it under the terms of the GNU General Public License as published | |
// by the Free Software Foundation, either version 3 of the License, or (at | |
// your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
// for more details. | |
// | |
// You should have received a copy of the GNU General Public License along | |
// with this program. If not, see <http://www.gnu.org/licenses/> for a | |
// copy. | |
// | |
// License: GPL, v3, as defined and found on www.gnu.org, | |
// http://www.gnu.org/licenses/gpl.html | |
// | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
module umpy_2x2(i_clk, i_reset, i_ce, i_a, i_b, i_aux, o_p, o_aux); | |
parameter NA=2, NB=2; | |
input i_clk, i_reset, i_ce; | |
input signed [(NA-1):0] i_a; | |
input signed [(NB-1):0] i_b; | |
input i_aux; | |
output reg signed [(NA+NB-1):0] o_p; | |
output reg o_aux; | |
localparam NS = (NA < NB) ? NA : NB; | |
localparam NL = (NA < NB) ? NB : NA; | |
wire [(NS-1):0] i_s; // Smaller input | |
wire [(NL-1):0] i_l; // larger input | |
// | |
// Adjust our inputs so that i_s has the fewest bits, and i_b the most | |
generate if (NA < NB) | |
begin : BITADJ | |
assign i_s = i_a; | |
assign i_l = i_b; | |
end else begin | |
assign i_s = i_b; | |
assign i_l = i_a; | |
end endgenerate | |
// Clock zero: build our Tableau only. | |
// There will be one row for every pair of bits in i_a, and each | |
// row will contain (AW+3) bits, to allow | |
// for signed arithmetic manipulation. | |
// | |
reg A_0; | |
wire [3:0] S_0_00; | |
bimpy #(NB) initialmpy_0_0(i_clk, i_reset, i_ce, i_s[1:0], i_l, S_0_00); | |
initial A_0 = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
A_0 <= 1'b0; | |
else if (i_ce) | |
A_0 <= i_aux; | |
assign o_p = S_0_00[(NA+NB-1):0]; | |
assign o_aux = A_0; | |
// Make verilator happy | |
// verilator lint_off UNUSED | |
//wire [0-1:0] unused; | |
//assign unused = { }; | |
// verilator lint_on UNUSED | |
`ifdef FORMAL | |
reg f_past_valid; | |
initial f_past_valid = 0; | |
always @(posedge i_clk) | |
f_past_valid <= 1'b1; | |
wire [0+1:0] f_auxpipe; | |
assign f_auxpipe = { A_0, i_aux }; | |
initial assume(!i_aux); | |
always @(posedge i_clk) | |
if ((i_reset)||((f_past_valid)&&($past(i_reset)))) | |
assume(!i_aux); | |
initial assert(f_auxpipe == 0); | |
always @(posedge i_clk) | |
if ((f_past_valid)&&($past(i_reset))) | |
assert(f_auxpipe == 0); | |
always @(posedge i_clk) | |
if ((f_past_valid)&&(!$past(i_reset))&&($past(i_ce))) | |
assert(f_auxpipe[0+1:1] == $past(f_auxpipe[0:0])); | |
always @(posedge i_clk) | |
if ((f_past_valid)&&(!$past(i_reset))&&(!$past(i_ce))) | |
assert(f_auxpipe[0+1:1] == $past(f_auxpipe[0+1:1])); | |
localparam F_DELAY = 0; | |
reg [NA+NB-1:0] f_result; | |
integer ik; | |
initial f_result = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
f_result = 0; | |
else if (i_ce) | |
begin | |
f_result = 0; | |
for(ik=0; ik<NS; ik=ik+1) | |
if(i_a[ik]) | |
f_result = f_result + { {(NL-ik-1){1'b0}}, | |
i_b, { (ik){1'b0} } }; | |
end | |
reg [F_DELAY*(NA+NB)-1:0] f_result_pipe; | |
initial f_result_pipe = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
f_result_pipe <= 0; | |
else if (i_ce) | |
f_result_pipe <= { f_result, f_result_pipe[((F_DELAY)*(NA+NB)-1):(NA+NB)] }; | |
always @(posedge i_clk) | |
assert(o_p == f_result_pipe[(NA+NB-1):0]); | |
always @(posedge i_clk) | |
assume((i_ce) | |
||((f_past_valid)&&($past(i_ce))) | |
// ||(($past(f_past_valid))&&($past(i_ce,2))) | |
); | |
`endif | |
endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Filename: umpy_3x3.v | |
// | |
// Project: A multiply core generator | |
// | |
// Purpose: This verilog file multiplies two unsigned numbers together, | |
// without using any hardware acceleration. This file is | |
// computer generated, so please (for your sake) don't make any edits | |
// to this file lest you regenerate it and your edits be lost. | |
// | |
// | |
// Creator: Dan Gisselquist, Ph.D. | |
// Gisselquist Technology, LLC | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// Copyright (C) 2015,2017-2019, Gisselquist Technology, LLC | |
// | |
// This program is free software (firmware): you can redistribute it and/or | |
// modify it under the terms of the GNU General Public License as published | |
// by the Free Software Foundation, either version 3 of the License, or (at | |
// your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
// for more details. | |
// | |
// You should have received a copy of the GNU General Public License along | |
// with this program. If not, see <http://www.gnu.org/licenses/> for a | |
// copy. | |
// | |
// License: GPL, v3, as defined and found on www.gnu.org, | |
// http://www.gnu.org/licenses/gpl.html | |
// | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
module umpy_3x3(i_clk, i_reset, i_ce, i_a, i_b, i_aux, o_p, o_aux); | |
parameter NA=3, NB=3; | |
input i_clk, i_reset, i_ce; | |
input signed [(NA-1):0] i_a; | |
input signed [(NB-1):0] i_b; | |
input i_aux; | |
output reg signed [(NA+NB-1):0] o_p; | |
output reg o_aux; | |
localparam NS = (NA < NB) ? NA : NB; | |
localparam NL = (NA < NB) ? NB : NA; | |
wire [(NS-1):0] i_s; // Smaller input | |
wire [(NL-1):0] i_l; // larger input | |
// | |
// Adjust our inputs so that i_s has the fewest bits, and i_b the most | |
generate if (NA < NB) | |
begin : BITADJ | |
assign i_s = i_a; | |
assign i_l = i_b; | |
end else begin | |
assign i_s = i_b; | |
assign i_l = i_a; | |
end endgenerate | |
// Clock zero: build our Tableau only. | |
// There will be one row for every pair of bits in i_a, and each | |
// row will contain (AW+3) bits, to allow | |
// for signed arithmetic manipulation. | |
// | |
reg A_0; | |
wire [4:0] S_0_00; | |
bimpy #(NB) initialmpy_0_0(i_clk, i_reset, i_ce, i_s[1:0], i_l, S_0_00); | |
//Extra (odd) row | |
wire [4:0] S_0_01; | |
bimpy #(NB) initialmpy_1_0(i_clk, i_reset, i_ce, { {(1){1'b0}}, i_s[2:2]}, i_l, S_0_01); | |
initial A_0 = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
A_0 <= 1'b0; | |
else if (i_ce) | |
A_0 <= i_aux; | |
// | |
// Round #1, clock = 1, nz = 2, nbits = 5, nrows_in = 2 | |
// | |
reg [(6-1):0] S_1_00; // maxbits = 6 | |
reg A_1; | |
initial S_1_00 = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
begin | |
S_1_00 <= 0; | |
end else if (i_ce) | |
begin | |
S_1_00 <= { 1'b0, S_0_00 } + { S_0_01// Adding to unused: 8, 6 | |
[3:0], 2'b0 }; | |
// unused = 1, ustr = S_0_01[4:4] | |
end | |
initial A_1 = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
A_1 <= 1'b0; | |
else if (i_ce) | |
A_1 <= A_0; | |
assign o_p = S_1_00[(NA+NB-1):0]; | |
assign o_aux = A_1; | |
// Make verilator happy | |
// verilator lint_off UNUSED | |
wire [1-1:0] unused; | |
assign unused = { S_0_01[4:4] }; | |
// verilator lint_on UNUSED | |
`ifdef FORMAL | |
reg f_past_valid; | |
initial f_past_valid = 0; | |
always @(posedge i_clk) | |
f_past_valid <= 1'b1; | |
wire [1+1:0] f_auxpipe; | |
assign f_auxpipe = { A_1,A_0, i_aux }; | |
initial assume(!i_aux); | |
always @(posedge i_clk) | |
if ((i_reset)||((f_past_valid)&&($past(i_reset)))) | |
assume(!i_aux); | |
initial assert(f_auxpipe == 0); | |
always @(posedge i_clk) | |
if ((f_past_valid)&&($past(i_reset))) | |
assert(f_auxpipe == 0); | |
always @(posedge i_clk) | |
if ((f_past_valid)&&(!$past(i_reset))&&($past(i_ce))) | |
assert(f_auxpipe[1+1:1] == $past(f_auxpipe[1:0])); | |
always @(posedge i_clk) | |
if ((f_past_valid)&&(!$past(i_reset))&&(!$past(i_ce))) | |
assert(f_auxpipe[1+1:1] == $past(f_auxpipe[1+1:1])); | |
localparam F_DELAY = 1; | |
reg [NA+NB-1:0] f_result; | |
integer ik; | |
initial f_result = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
f_result = 0; | |
else if (i_ce) | |
begin | |
f_result = 0; | |
for(ik=0; ik<NS; ik=ik+1) | |
if(i_a[ik]) | |
f_result = f_result + { {(NL-ik-1){1'b0}}, | |
i_b, { (ik){1'b0} } }; | |
end | |
reg [F_DELAY*(NA+NB)-1:0] f_result_pipe; | |
initial f_result_pipe = 0; | |
always @(posedge i_clk) | |
if(i_reset) | |
f_result_pipe <= 0; | |
else if (i_ce) | |
f_result_pipe <= { f_result, f_result_pipe[((F_DELAY)*(NA+NB)-1):(NA+NB)] }; | |
always @(posedge i_clk) | |
assert(o_p == f_result_pipe[(NA+NB-1):0]); | |
always @(posedge i_clk) | |
assume((i_ce) | |
||((f_past_valid)&&($past(i_ce))) | |
// ||(($past(f_past_valid))&&($past(i_ce,2))) | |
); | |
`endif | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment