diff options
author | Clifford Wolf <clifford@clifford.at> | 2014-08-16 21:07:29 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2014-08-16 21:07:29 +0200 |
commit | 976bda71029b9d25ffad9ec8fbf3ceed2d1287e1 (patch) | |
tree | b13268a7e2f75e3b681cbef5de42755ba93fc1dd /techlibs/common/techmap.v | |
parent | 3b9157f9a605b5ae2f535c4da932891e504dc57e (diff) | |
download | yosys-976bda71029b9d25ffad9ec8fbf3ceed2d1287e1.tar.gz yosys-976bda71029b9d25ffad9ec8fbf3ceed2d1287e1.tar.bz2 yosys-976bda71029b9d25ffad9ec8fbf3ceed2d1287e1.zip |
Multiply using a carry-save accumulator
Diffstat (limited to 'techlibs/common/techmap.v')
-rw-r--r-- | techlibs/common/techmap.v | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 9b733c6f0..9bdff4f33 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -502,21 +502,61 @@ module \$__arraymul (A, B, Y); input [WIDTH-1:0] A, B; output [WIDTH-1:0] Y; - wire [1023:0] _TECHMAP_DO_ = "proc;;"; + wire [1023:0] _TECHMAP_DO_ = "proc;; opt"; integer i; - reg [WIDTH-1:0] x, y; + reg [WIDTH-1:0] x; + reg [2*WIDTH-1:0] y; + + function [2*WIDTH-1:0] acc_set; + input [WIDTH-1:0] value; + integer k; + begin + for (k = 0; k < WIDTH; k = k+1) begin + acc_set[2*k +: 2] = value[k]; + end + end + endfunction + + function [2*WIDTH-1:0] acc_add; + input [2*WIDTH-1:0] old_acc; + input [WIDTH-1:0] value; + integer k; + reg a, b, c; + begin + for (k = 0; k < WIDTH; k = k+1) begin + a = old_acc[2*k]; + b = k ? old_acc[2*k-1] : 1'b0; + c = value[k]; + acc_add[2*k] = (a ^ b) ^ c; + acc_add[2*k+1] = (a & b) | ((a ^ b) & c); + end + end + endfunction + + function [WIDTH-1:0] acc_get; + input [2*WIDTH-1:0] acc; + integer k; + begin + // at the end of the multiplier chain the carry-save accumulator + // should also have propagated all carries. thus we just need to + // copy the even bits from the carry accumulator to the output. + for (k = 0; k < WIDTH; k = k+1) begin + acc_get[k] = acc[2*k]; + end + end + endfunction always @* begin x = B; - y = A[0] ? x : 0; + y = acc_set(A[0] ? x : 0); for (i = 1; i < WIDTH; i = i+1) begin x = {x[WIDTH-2:0], 1'b0}; - y = y + (A[i] ? x : 0); + y = acc_add(y, A[i] ? x : 0); end end - assign Y = y; + assign Y = acc_get(y); endmodule module \$mul (A, B, Y); |