I am trying to convert signed binary numbers to integer in verilog for synthesis to display, I have a couple of questions. Below is my code,
.....
if(acc[i][j]>10) //acc is a 2d register
begin
m_reg <= j-const_10; // const_10 is 16'b0000000000001010
m_int <= m_reg;
$display("Current value of M(bits)=%b",m_reg);
$display("Current value of M(int)=%d",m_int);
end
else
....
j can be less than 10, meaning m_reg can be negative. In that case, I am assuming m_reg will give me a signed binary negative number.
If it does, how do I convert it to an integer to display because I guess m_int = m_reg will give me only unsigned.
All data is 'binary' when displaying we have the choice of visualising in binary, decimal of hexadecimal. When inputing data we have the same choice but what is set and stored remains the same.
These are all the same:
a = 4'b1111;
a = 4'd15;
a = 4'hf;
To display in the given format:
$display("Binary %b", a);
$display("Decimal %d", a);
$display("Hex %h", a);
Leading 0's are not displayed, at least for decimal so min widths can be used.
$display("min of 2 Decimal %2d", a);
Dealing with signed numbers: declare the reg, logic or wire as signed, or convert when displaying.
reg [3:0] a;
reg signed [3:0] a_s;
initial begin
a = 4'b1111; // is this 15 or -1 depends on if you read as signed
a_s = 4'b1111; // -1
#1ns;
$display("Decimal converted to signed %d", $signed(a));
$display("Signed Decimal %d", a_s);
end
Related
Tried implementing Karatsuba multiplier for multiplying two binary numbers, the logic below works well for unsigned numbers, but getting incorrect answer when I change one of the inputs to a negative. In the example below a=1010011111000000(equals -88.25) and b= 0001010001000000(equals 20.25). The answer should be 11111001000001001111000000000000(equals:-1787.0625)but I end up getting the incorect answer. Have used fixed point logic, with inputs 16 bits and fraction point 8 bits, output being 32 bits with fraction bits 16.
module karatsuba( input signed [15:0] a,
input signed [15:0] b,
output signed [31:0] out
);
reg [15:0] ac,bd;
reg [31:0] t1;
reg [31:0]t2;
reg [24:0] psum;
initial begin
assign ac = a[15:8]*b[15:8];
assign bd = a[7:0]*b[7:0];
assign t2= bd;
assign t1={ac,16'b0000000000000000};
assign psum = {(a[15:8]+a[7:0])*(b[15:8]+b[7:0])-ac-bd,8'b00000000};
end
assign out= t1+psum+t2;
endmodule
module karatsuba_tb();
reg signed [15:0]a,b;
wire signed [31:0]out;
karatsuba uut(.a(a),.b(b),.out(out));
initial begin
a=16'b0101100001000000;
b=16'b0001010001000000;
end
endmodule
enter image description here
enter image description here
There are two issues pertaining to the signed multiply in the post:
Slices of vector variables (even slices of signed vectors) are treated as unsigned in Verilog. This is because when a slice is taken there is no way to identify the original sign bit, therefore it must be treated as unsigned
The solution is to cast the slices to signed so that Verilog treats them as signed. Like this:
assign ac = signed'(a[3:2]) * signed'(b[3:2]);
Make the line that defines the variable ac,bd to be treated as signed using the signed keyword (default is unsigned).
You will need to propagate these changes to other places in the posted code which have the same issues.
Here is a simplified version of the post using small numbers to illustrate the cast and keyword use:
module karatsuba(
input signed [3:0] a,
input signed [3:0] b
);
reg signed [3:0] ac;
assign ac = signed'(a[3:2]) * signed'(b[3:2]);
endmodule
module karatsuba_tb();
reg signed [3:0]a,b;
karatsuba uut(.a(a),.b(b));
initial begin
a = 4'b1110;
b = 4'b1111;
#1;
//
$display("---------------");
$display("uut.a[3:2] = %b",uut.a[3:2]);
$display("uut.b[3:2] = %b",uut.b[3:2]);
$display("uut.ac = %b",uut.ac);
$display("---------------");
//
$display("uut.a[3:2] = %d",signed'(uut.a[3:2]));
$display("uut.b[3:2] = %d",signed'(uut.b[3:2]));
$display("uut.ac = %d",uut.ac);
$display("---------------");
end
endmodule
The example displays this message at runtime:
---------------
uut.a[3:2] = 11
uut.b[3:2] = 11
uut.ac = 0001
---------------
uut.a[3:2] = -1
uut.b[3:2] = -1
uut.ac = 1
---------------
If I reduce the number of bits after arithmetic right shift in verilog, do I still get the correct signed number? Is this valid?
number of bits reduced = shift value
A = 1110_1110
A>>>1
new A = 111_0111
Yes, but you should use three '>' not four and of course the new variable should be big enough:
wire signed [7:0] A,B;
wire signed [6:0] just_fits;
wire signed [5:0] oops;
assign B = A >>> 1; // Signed divide by two
assign just_fits = A >>> 1; // Signed divide by two
assign oops = A >>> 1; // Goes wrong
I am designing a processor in Verilog. I'm working on the ALU, specifically the multiplier for the ALU. I can get the correct results when performing multiplication with small, positive numbers, but if I try to multiply signed numbers I get issues. When a positive number multiplies a negative the result will not sign extend all the way to 64 bits, and if two negative numbers are multiplied the number is incorrect altogether (sign and value). Can anyone see where the issue lies? I assumed I was not performing an arithmetic shift but I adjusted that and am still getting the wrong results.
module multiplier(
input[31:0] operand1,
input[31:0] operand2,
output reg [63:0] product
);
reg [64:0] prod;
reg [31:0] mcand;
reg [31:0] sum;
integer i = 0;
always #* begin
prod = {32'b0,operand1};
mcand = operand2;
for(i=0;i<32;i=i+1) begin
//test 0 bit of product
case(prod[0])
1'b0:begin //if prod[0] == 0, arithmetic shift right
prod = prod>>>1;
end
1'b1:begin //if prod[0] == 1, add multiplicand to upper 32
//bits and arithmetic shift right
prod = {(prod[63:32]+mcand[31:0]),prod[31:0]};
prod = prod>>>1;
end
endcase
end
product = prod[63:0];
end
endmodule
For >>> to perform signed shift the variable must be declared as signed.
reg signed [64:0] prod;
Short example on eda playground.
Also note that prod = {32'b0,operand1}; is not a sign extension. You should probably be using:
prod = { {32{operand[31]}}, operand1 };
`include "bcd.v"
module bcd_4(A,B,Cin,S,Cout);
input [15:0] A,B;
input Cin;
output [15:0] S;
output Cout;
wire w1,w2,w3;
bcd_adder U1(.A(A[3:0]),.B(B[3:0]),.Cin(Cin),.S(S[3:0]),.Cout(w1));
bcd_adder U2(.A(A[7:4]),.B(B[7:4]),.Cin(w1),.S(S[7:4]),.Cout(w2));
bcd_adder U3(.A(A[11:8]),.B(B[11:8]),.Cin(w2),.S(S[11:8]),.Cout(w3));
bcd_adder U4(.A(A[15:12]),.B(B[15:12]),.Cin(w3),.S(S[15:12]),.Cout(Cout));
endmodule
I have designed a 4-digit BCD adder using four 4-bit BCD adders. The inputs 'A' and 'B' are taking hexadecimal values. How can I write a testbench so that the input values should be decimal only? I have to check the following condition also:
if({Cout,S}==A+B+Cin) $display("pass");
else $stop;
The inputs of your adder do not take hexadecimal values. They are 16-bit inputs which represent 4 BCD digits of 4 bits each. The input for each digit can range from 0 to 15 in decimal, but since they are BCD any value greater than 9 would be invalid.
The inputs can be specified in any base (binary, octal, decimal or hexadecimal).
The following are all equivalent:
A <= 10;
A <= 4'd10;
A <= 4'hA;
A <= 4'b1010;
If you want to only generate valid BCD values inputs in your testbench, you should generate the entire 4-digit number as an integer and then convert each digit to the appropriate bits to drive your design.
For example, to drive every valid value for input A (0 to 9999) you could do the following:
integer a;
for (a = 0; a < 10000; a = a + 1) begin
// a is an integer
// A is a 16-bit, 4-digit BCD value
A[3:0] = a % 10; // digit 0, ones place
A[7:4] = (a / 10) % 10; // digit 1, tens place
A[11:8] = (a / 100) % 10; // digit 2, hundreds place
A[15:12] = (a / 1000) % 10; // digit 3, thousands place
end
For sampling the output, you would do the inverse - convert 4 4-bit BCD digits to an integer.
Here is a full, runnable example which includes code for sampling and verifying the output: http://www.edaplayground.com/x/2pT
I got it. I can write it using following function
function integer hexatodecimal;
input [16:0] a;
integer b;
begin
b=a[3:0]+a[7:4]*10+a[11:8]*100+a[15:12]*1000+a[16]*10000;
hexatodecimal=b;
end
endfunction
I can call this function to convert {Cout,S} into hexadecimal.
For instance, say I have a reg [7:0] myReg
I assign it the value -8'D69
I know Verilog stores it as 2's complement so it should be stored as
10111011
The question I have now is if I were to perform an operation on it, say myReg/2
Would it evaluate to -34? Or would it take 10111011 and turn it into 187 then perform the division, returning 93?
You need to remember that -8d69 is just a bit pattern. reg is a type which holds bit patterns. It is the type of variable that instructs / to perform signed or unsigned arithmetic.
If this is for synthesis bare in mind that you want to try and avoid dividers, you really want to try and avoid signed dividers. It will likely synthesis smaller with >>> 1
reg [7:0] a;
reg signed [7:0] b;
reg [7:0] c;
reg signed [7:0] d;
initial begin
a = -8'd69 ;
b = -8'd69 ;
c = -8'd69 ;
d = -8'd69 ;
#10ns;
a = a/2 ;
b = b/2 ;
#10ns;
$display("a : %8b, %d", a, a);
$display("b : %8b, %d", b, b);
$display("c >>>1 : %8b, %d", c>>>1, c>>>1);
$display("d >>>1 : %8b, %d", d>>>1, d>>>1);
end
Gives:
a : 01011101, 93
b : 11011110, -34
c >>>1 : 01011101, 93
d >>>1 : 11011101, -35
>> x Shifts right by x places, >>> x Shifts right x places but sign extends for signed types.
NB: the /2 is also rounding up in my examples, >>> will round down/truncate.
For instance, say I have a reg [7:0] myReg I assign it the value
-8'D69
This actually isn't a signed number but instead an expression consisting of a unary negation applied to a positive constant. If the expression was -8'd130 the result would overflow. Signed constants are declared as 8'sd69 or just 69.
The question I have now is if I were to perform an operation on it,
say myReg/2
myReg is unsigned so the expression result will also be unsigned*. If you need the result to be signed than all operands must be signed. There are a couple ways to achieve this:
//Declare the reg as signed and divide by a signed value
reg signed [7:0] myReg;
assign result = myReg/2;
//Use system functions
assign result = $signed(myReg)/2;
*The complete rules regarding expression evaluation are much more complex but basically the result of any expression is unsigned, unless all operands are signed.
reg signed [7:0] a;
reg [7:0] b;
initial
begin
result = a; //Signed
result = a * a; //Signed
result = a * 10; //Signed
result = $unsigned(a); //Unsigned
result = a[0]; //Unsigned
result = a[7:0]; //Unsigned
result = {a,a}; //Unsigned
result = 10{a}; //Unsigned
result = a + b; //Unsigned
result = a * b; //Unsigned
end
I'll add that
1. Data types bit and reg are unsigned, by default.
2. Data types int, integer, longint, shortint, and byte are signed, by default.
3. All these data types can take a signed or unsigned qualifier to change the default.
So, assigning -8'D69 to myReg does an implicit conversion to 187. Then, myReg/2 = 187/2 = 93, unsigned. It's important to understand when and how SystemVerilog does implicit type conversions in expressions and assignments.
The best place to check is the Language Reference Manual. Predictably, given Verilog's "eh" attitude to proper typing, it's a bit of a mess.
Basically signed doesn't affect the actual data stored in the variable/net, but it does affect what the arithmetic operators do in some case. The obvious case is comparison, but also multiplication and division would behave differently. Addition and subtraction should be the same for both signed and unsigned.
Note especially that when one or more of the operands is unsigned it is treated as an unsigned comparison, which is different to what you would expect from C. So if we have
byte a = -10; // byte is signed
logic [7:0] b = 10; // this is unsigned
Then a > b is true.
Again if at least one operator is unsigned then it treats them both as unsigned so if we have:
byte a = -1;
logic [7:0] b = 255;
Then a == b is true.