Signed and Unsigned Multiplication Problem in Verilog - verilog

I have been working on approximate multiplication recently and I want to write a Verilog code for dynamic segment multiplication (DSM) . It suggest that you find the first index in you number which has a value of 1 and then take other 3 indexes next to it to form a 4 bit number that represent an 8 bit number then you should multiply these 4 bit numbers instead of 8 bits then some shifts to have the final result it helps a lot on hardware actually.. but my problem is about multiplication of these segments because sometimes they should be considered signed and some time unsigned I have the last 3 lines of my code: (a and b are input 8 bit numbers) and m1 and m2 are segments I wrote m,m2 as reg signed [3:0] and a and b as input signed [7:0]
Here is my code:
assign out = ({a[7],b[7]}==2'b11)||({a[7],b[7]}==2'b00) ? ($unsigned(m1)*$unsigned(m2)) << (shift_m1+shift_m2) : 16'dz;
assign out = ({a[7],b[7]}==2'b01) ? ($signed({1'b0,m1})*$signed(m2)) << (shift_m1+shift_m2) : 16'dz;
assign out = ({a[7],b[7]}==2'b10) ? ($signed(m1)*$signed({1'b0,m2})) << (shift_m1+shift_m2) : 16'dz;
But in simulation Verilog always considers segments as unsigned and does unsigned multiplication even though I noted signed or unsigned mark...
Can anyone help? I read all of the questions about this problem in stackoverflow and other places but still cannot solve this issue...

The rules for non-self determined operands say that if one operand is unsigned, the result is unsigned. 16'dz is unsigned.
The conditional operator i ? j : k has the condition operand i self-determined, but the two selections j and k are in a context based on the assignment or expression it is a part of. The shift operator i << j has the shift amount operand j self-determined.
All of the context rules are explained in section 11.6.1 Rules for expression bit lengths in the IEEE 1800-2017 SystemVerilog LRM.
You can get your desired result by using the signed literal 16'sdz.
However the logic you wrote may not be synthesizable for certain technologies that do not allow using a z state inside your device. The correct and more readable way is using a case statement:
alway #(*) case({a[7],b[7]})
2'b00,
2'b11: out = $unsigned(m1)*$unsigned(m2) << shift_m1+shift_m2;
2'b01: out = $signed({1'b0,m1})*m2 << shift_m1+shift_m2;
2'b10: out = m1*$signed({1'b0,m2}) << shift_m1+shift_m2;
endcase

Related

Verilog assign statement result check

new to Verilog (well, SystemVerilog really, but I found that for the very basic keywords like assign and initialize I am able to learn from Verilog resources as well). I am following example 2 on this link chipverify example 2. It's simple so I'll write it down. I feel as if they've made a mistake, but since I am a newbie it's hard to know if my feeling is correct or not.
module xyz (input [3:0] x, //let x='hC or x='b1100 for this example's purposes
input y, //y is a 1bit scalar y='h1 = 'b1
output [4:0] z);
//case 8
assign z = {3{y}};
endmodule
For case 8, they are saying that z will result in z='b00111. I don't think it's correct! Following their case 3, where z only got bits [4:1] assigned,it stated that the reaming bit will be undriven and thus result in high impedance Z. Shouldn't the result of case 8 then be z ='bZZ111 and not z='b00111?
Let me know, thanks! =)
From section 10.7 (Assignment extension and truncation) in IEEE Std 1800-2017 (the SystemVerilog standard),
When the right-hand side evaluates to fewer bits than the left-hand side, the right-hand side value is padded to the size of the
left-hand side.
In your case, {3{y}} is an unsigned value, so it is 0-padded to 5 bits, that is 5'b00111, and then assigned to z.

Delay associated with xor of 1023 10 bit vectors in Verilog

I am somewhat new to verilog and I have a question that is confusing me .
I have a number of constant parameters , specifically nearly 1023 of them c0 , c1,c2 ..... c1022, each one being 10 bit in length . I also have a vector r[1022:0] , which is 1023 bits in length . My task is to compute ci*r[i] where i varies from 0 to 1022 and finally take the xor of the 1023 10 bit vectors that i get.When I do this in simulation , verilog generates the output at time 0 for the assign statement . How can verilog generate the output at time 0 ? Will there be no delay associated with these 1023 xors?
Also, if I need to do this succinctly , is there a short form that I can use or do I need to manually write c0 *r[0] ^ c1 *r[1] ......^ c[1022]*r[1022] which is synthesizable ?
A Verilog simulator will execute whatever legal syntax you give it—the tool knows nothing about what the implementation eventually looks like. It's up to you to feed timing constraints to the synthesis tool and it tells you if it can fit the logic to meet the constraints (or you might have to run another tool to see if it meets timing constraints).
Since you named your parameters c0, c1, c2, ..., you might as well named them czero, cone, ctwo, ... which gives you no options for shortcuts.
If you tool supports SystemVerilog, you can write your parameter as an array and then use the array xor reduction operator
parameter [9:0] C[1023] = {10'h123, 10'h234, ...};
assign out = C.xor() with (item*r[item.index]);
If you synthesis tool does not support this SystemVerilog syntax you, you can pack the parameter values into a single vector and use an indexed part select in Verilog.
parameter [10220-1:0] C = {10'h123, 10'h234, ...};
function [9:0] xor_reduction (input [1022:0] r);
integer I;
begin
xor_reduction = 0;
for(I=0;I<1023;I=I+1)
xor_reduction = xor_refuction ^ (r[1022-I]*C[I-:10]);
end
endfunction
assign out = xor_reduction(r);

Using " * " for multiplication of binary numbers, only gives me addition, why? (Code here)

I'm learning operations with " + ", " - " and " * ", addition and subtraction works well, but multiplication gives me only additions, link for the code:
http://www.edaplayground.com/x/NvT
I checked the code, can't understand what's going on. I gave enough space (bits) the result variable.
BTW, It's a code intended for fixed-point operations including fractional numbers, but everything is calculated as integers.
Your select signal is only on 1bit.
Then when you set select = 2 it assigns the lower bit of 2(2'b10) i.e. 0.
You should change select declaration by :
input [1:0] select; // In the module
reg [1:0] select; // In the testbench
To avoid such errors I would advise you to use the complete notation of values:
x'tnnn...nnn
where x is the width of the signal, t is the type (d for decimal, h for hexa, b for binary,...) and nnn...nnn the value in the type specified.
For example for the decimal value 2 you will have several notations that will make sense in certain situations:
2'd2 //2 bits decimal
2'h2 //2 bits hexadecimal
2'b10//2 bits binary
For more informations about these notations you can read this pdf.

Non-integer values in verilog

Is there a way to store and compute non-integer values in verilog, (say x = 5/2 = 2.5 ).
Can I compute and store 2.5 in x defined above?
Yes, you can use real registers to store real values, i.e.:
real float; // a register to store real value
Usually it's a 64-bit wide data type that stores floating-point values. But not all Verilog operators can be used with expression involving real numbers and real registers. Concatenations, modulus operator, case equality, bit-wise operators, reduction operators shift operators, bit-selects and part-selects on real type variables are not allowed.
Simple example:
module ecample;
real r;
initial begin
r = 123456e-3;
$display("r=%f",r); // r = 123.456000
#20 r = r / 2;
$display("r=%f",r); // r = 61.728000
$finish;
end
endmodule

How to implement an n-bit adder whose input vectors are represented in octal?

I'm somewhat stumped on this problem:
"Write a verilog module for full addition of n-bit integers. Let the parameter, the number of bits, equal 3. Call this module from a test bench, and in the test bench specify the numbers to be added in the arrays. Assign octal values to the X and Y arrays. The carryin is 0."
And yes, this is homework.
I was able to write the module for the n-bit adder:
module addern(carryin, X, Y, S, carryout, overflow);
parameter n = 3;
input carryin;
input [n-1:0] X, Y;
output reg [n-1:0] S;
output reg carryout, overflow;
always #(X,Y, carryin)
begin
{carryout, S} = X + Y + carryin;
overflow = (X[n-1] & Y[n-1] & ~S[n-1]) | (~X[n-1] & ~Y[n-1] & S[n-1]);
end
endmodule
I understand this component of the problem. However, I'm not sure how to implement the octal number addition. Is there a way in verilog to indicate that the arrays are holding octal values, rather than binary?
Is there anything like a typecast in verilog? For instance, input (octal) [n-1:0] X, Y, and do something likewise in the test bench.
Any constructive input is appreciated.
I'm pretty sure I'm in the same class as you. I think what you need to do is create a hierarchical Verilog module and then assign your values there. That would be your testbench. for example if you want to make X you write input [n-1:0] X = 3'o013, or maybe it's X = 9'o013 if Oli is correct. you don't change n, but it's kind of like BCD where they are in groups and you have a certain amount of bits you can represent before it overflows.
To help solve the problem thik about the question:
Q) How are numbers stored in digital hardware?
A) Binary, in digital logic we can only represent 2 values 1 and 0, but with this we can represent Integer, fixed point or floating point numbers.
Therefore digital numbers are base 2 (two possible values), while being able to represent any number. Other bases such as Octal (base 8) hex (base 16) and decimal (base 10) exist but these are just way of representing numbers, similar to the way binary just represents a number.
A decimal 1, is represented by 1 n all the bases, and when stored as binary they are all the same. An example of some values in verilog and there binary equivalents.
Octal Decimal Hex Binary
3'O7 => 3'd7 => 3'h7 => 3'b111
6'O10 => 6'd8 => 6'h8 => 6'b001000
Octal, Decimal and Hex in verilog are just representations of a binary format, a way of viewing the data. Since the low level electronics has no way of representing any thing other than 0 and 1.
The interesting thing about Octal and Hex is that they have a power of 2 values so they use an exact number of bits so an 9'O123 is the same as treating each Octal place separately and concatenating them together, 9'O123 == {3'O1, 3'O2, 3'O3}. This is also true for hexadecimal values but not decimal (base 10) values, as 10 is not a power of 2 and does not fully occupy the number space.
This does allow 'Octal' ports to be created, which are just 3 bit binary ports:
module octal_concat (
input [2:0] octal_2,
input [2:0] octal_1,
input [2:0] octal_0,
output [8:0] concat
);
assign concat = {octal_2, octal_1, octal_0};
endmodule
octal_concat octal_concat_0 (
.octal_2(3'O1),
.octal_1(3'O2),
.octal_0(3'O3),
.concat() //Drives 9'O123 which is also 9'b001_010_011
);

Resources