We currently have a graduate student working on OpenShader, and then
there's another open source graphics project we're working on, which will
go public when we get it published. Also, we're working on getting funding
to do more OGP/GPU stuff.
Anyhow, I'm also working on another open source hardware project involving
neural networks, and I was wondering if anyone might have comments on these
sign-magnitude adder implementations. I'm using sign-magnitude because it
makes the sigmoid function (tanh) and multiplication simpler.
The challenges are dealing with negative numbers, not having too many
adders or comparisons, and keeping the critical path short. The "fast"
version computes A-B and B-A (or A+B and A+B), picks the positive
magnitude, and figures out the sign. The critical path is through one
adder, and having two gives us the comparison information. The "small"
version does a comparison up front, reducing the logic to one comparison
and one adder, but the critical path is though the comparison plus the
adder. The small version is probably only a little bit smaller than the
fast version, because the comparator is basically going to do a subtract
anyhow; it's just that we're effectively only using the sign bit of the
difference instead of the whole thing.
module addsub_fast
#(parameter WIDTH=8)
(input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
output [WIDTH:0] c);
// Signs differ
wire sub = a[WIDTH-1] ^ b[WIDTH-1];
// Extend a and b with extra bits on right and left
wire [WIDTH:0] a_ext = {0'b0, a[WIDTH-2:0], sub};
wire [WIDTH:0] b_ext = {0'b0, b[WIDTH-2:0], sub};
// Extended inverted a and b
wire [WIDTH:0] a_inv = {sub, {(WIDTH-1){sub}} ^ a[WIDTH-2:0], sub};
wire [WIDTH:0] b_inv = {sub, {(WIDTH-1){sub}} ^ b[WIDTH-2:0], sub};
// Compute two differences
wire [WIDTH:0] amb = a_ext + b_inv;
wire [WIDTH:0] bma = a_inv + b_ext;
// Adding might get a extra bit
wire [WIDTH-1:0] sum = amb[WIDTH:1];
// If we're subtracting, choose the positive magnitude
wire [WIDTH-2:0] dif = amb[WIDTH] ? bma[WIDTH-1:1] : amb[WIDTH-1:1];
// Choose between sum and dif
assign c[WIDTH-1:0] = sub ? dif : sum;
assign c[WIDTH] = (a[WIDTH-1] && bma[WIDTH]) || (b[WIDTH-1] &&
amb[WIDTH]) || (a[WIDTH-1] && b[WIDTH-1]);
endmodule
module addsub_small
#(parameter WIDTH=8)
(input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
output [WIDTH:0] c);
// Signs differ
wire sub = a[WIDTH-1] ^ b[WIDTH-1];
// Which has smaller magnitude?
wire b_smaller = b[WIDTH-2:0] < a[WIDTH-2:0];
// Invert the smaller magnitude
wire invert_a = !b_smaller && sub;
wire invert_b = b_smaller && sub;
// Extend and invert the smaller of a or b
wire [WIDTH:0] a_inv = {invert_a, {(WIDTH-1){invert_a}} ^ a[WIDTH-2:0],
sub};
wire [WIDTH:0] b_inv = {invert_b, {(WIDTH-1){invert_b}} ^ b[WIDTH-2:0],
sub};
// Compute the sum (or difference)
wire [WIDTH:0] sum = a_inv + b_inv;
assign c[WIDTH-1:0] = sum[WIDTH:1];
assign c[WIDTH] = b_smaller ? a[WIDTH-1] : b[WIDTH-1];
endmodule
--
Timothy Normand Miller, PhD
Assistant Professor of Computer Science, Binghamton University
http://www.cs.binghamton.edu/~millerti/
Open Graphics Project
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)