How do I convert a number to two's complement in verilog?
Question
I am trying to design a 4-bit adder subtracter in verilog. This is only the second thing I have ever written in verilog, and I don't know all the correct syntax yet. This is the module I have so far:
module Question3(carryin, X, Y, Z, S, carryout, overflow);
parameter n = 4;
input carryin, Z;
input [n-1:0]X, Y;
output reg [n-1:0]S;
output reg carryout, overflow;
if(Z==0)
begin
Y = not(y) + 4'b0001;
end
always @(X, Y, carryin)
begin
{carryout, S} = X + Y + carryin;
overflow = carryout ^ X[n-1]^Y[n-1]^S[n-1];
end
endmodule
My compiler (xilinx 10.1), keeps saying "Syntax error near if." I have tried many different ways of doing the conversion, including just using a Case that takes Y as an argument, then checks all the possible 4-bit combinations, and converts them to two's complement.
Z is what determines if the adder does subtraction or addition. If it's 0, it means subtraction, and I want to convert y to two's complement, then just do regular addition. I'm sure the rest of the adder is correct, I just do not know what is wrong with the part where I'm trying to convert.
Solution
reg [n-1:0] Y_compl;
always @( Z, Y, X, carryin ) begin
Y_ = ( ~Y + 4'b0001 );
if ( Z == 1'b0 ) begin
{carryout, S} = X + Y_compl + carryin;
overflow = carryout ^ X[n-1] ^ Y_compl[n-1] ^ S[n-1];
end
else begin
{carryout, S} = X + Y + carryin;
overflow = carryout ^ X[n-1] ^ Y[n-1] ^ S[n-1];
end
end
A couple of important points.
- Put the if statement inside the always block. Do not use two always blocks, you'll create a race condition in the simulator.
- I created a new variable, Y_ because using Y, which is an input, remember, on the left hand side of an assignment will probably infer latches or do something else nasty when you synthesize.
- I suggest using the bitwise inversion operator '~' to invert Y instead if the 'not' primitive. The synthesis tool has more freedom to optimize your code this way.
- Double check for correct results, it's been awhile since I built an adder.
OTHER TIPS
You are using a lower case "y" in "Y = not(y) + 4'b0001;"
Also, you're using more additions than you need to. X-Y is the same thing as NOT(NOT(X)+Y).
put the if statement within an initial block
http://www.asic-world.com/verilog/vbehave1.html