verilog power operator ** result size - verilog

Can the power operator ** be used with arbitrarily large operands?
Ex:
reg [100:0] c;
reg [15:0] a;
reg [15:0] b;
c = a**b;
Does there is some maximum limit on operand size?

IEEE 1800-2012 doesn't mention any maximum size of operands.
But... different IDE might have some limitations in ** operator usage, e.g. it works only in case like 2**n or length of the operands is limited. However, there should be no limitations in simulations (e.g. Riviera-PRO allowed to simulate a**b operation, with a and b length equal to 150, without any warning).
When using power operator for synthesis, it's sythesizable as long as a=2. In that case the power operator simply "change" to shifter.

Related

How to get the square and cube of a fractional number (say 0.78) in verilog?

I am new to Verilog/System Verilog and I wanted to implement the square and cube a fractional number. Consider the following example
module test(
input wire [31:0] input,
output reg [63:0] output
);
reg [63:0] temp;
always # (*) begin
temp = input*input;
output <= temp*input;
end
endmodule
So, when my input is 32'h0_C7AE147 (0.78 in the hexadecimal number system using the 32 bits representation and assuming _ is the equivalent of . in Verilog) I expect an output of 32'h0_797C3D6 (0.4745 in decimal number system)
But I am getting an output of 64'hD546_4A9C_ED94_2917
Also, how to handle the increasing bit sizes in a multiplication?
When we multiply two N-bit wide operands, we get an output of width 2N-bits. When we multiply this 2N-bit wide number with a k bit wide number, we get a number of widths 2N+k-bit wide and this process goes on.
You mean you want to represent fractional number in 32-bit fixed point notation with 4-bit integer part + 28-bit fractional part? And why do you need 64 bits for output?
Anyway I think you need to shift the product to the right by 28 bits for each multiplication.
Try:
temp = input * input >> 28;
output <= temp * input >> 28;
If you need proper rounding, do it before each shifting.

How can I determine the register bit widths correctly?

This is the simple code I wrote.From 'outt' I get 122116. But if I change 'outt' width to be 33 bits ([32:0]) then code seems to work and give the correct answer -140028. What is the reason for this behaviour??
`timescale 1ns / 1ps
module valu_parser(clk,outt);
input clk;
reg signed [31:0] r_1;
reg signed [31:0] r_2;
output reg signed [31:0] outt;
initial begin
r_1 = -47938;
r_2 = -150096;
end
always # (posedge clk) begin
outt <= ((r_1 + r_2)* 11585 + 8192)>>>14;
end
endmodule
You are performing an operation that needs at least 33 bits (the temporary result before the right shift uses 33 bits) and theoretically it could need 32+"the size of the multiplicand constant" assuming that r_1 and r_2 are not constants.
If you think of the hardware your code will generate, these bits needs to be stored somewhere temporarily to allow the hardware to first perform multiplication, then addition followed by the right shift.
This will do the trick, but will also generate more registers than you wanted initially. If you are using this module to generate a constant, I would recommend hard-coding the constant.
module valu_parser(clk,outt);
input clk;
reg signed [31:0] r_1;
reg signed [31:0] r_2;
reg signed [32:0] temp;
output reg signed [31:0] outt;
initial begin
r_1 = -47938;
r_2 = -150096;
end
always # (posedge clk) begin
temp <= ((r_1 + r_2)* 11585 + 8192);
end
assign outt = temp>>>14;
endmodule
The concept can be seen here: https://www.edaplayground.com/x/3BXy.
In an expression Verilog needs to decide how many bits to use in the calculation.
The + and * operators result in what are called context-determined expressions. With the expression F = A + B; the number of bits used is the maximum of F, A, and B. This usually works fine, because normally you would ensure that F was wide enough to store the result of adding A and B. Likewise with the expression F = A * B; would usually work fine, because normally you would ensure that F was wide enough to store the result of multiplying A and B.
However, by adding the shift right operator you have been able to make the variable being assigned narrower than the number of bits actually needed to calculate the expression on the left of the shift operator. The number of bits Verilog uses in the calculation is the maximum of the width of outt, r_1, r_2, 11585 and 8192. All of these are 32 bits wide (including 11585 and 8192), so 32 bits are used in the calculation. As you have discovered, 32 bits is not enough, but, with the values you have chosen, 33 bits is. With other values, 33 bits wouldn't be enough either. For a completely flexible solution, you should be using 66 bits (32 + 32 + 1 + 1) - 32 bits + 32 bits for the multiplication plus 1 more bit for each addition.
The solution to your problem is to make r_1 and/or r_2 wider or to use an intermediate value (as suggested by Hida's answer here).
When you multiply -198034 (r1+r1) on 11585 you have in result highest bit is 0 (outt[31]), then if you have 32bit signed value its start be positive and in answer you have positive result. And when you change it for 33bit your highest bit is 1 (outt[32]) and result is negative value and you have correct answer.

Unsigned reg subtraction in Verilog

I have some troubles with unsigned reg subtraction in Verilog.
The following Verilog code is designed for a 4-bit ALU :
module p2(in_1,in_2,s,out);
input [3:0]in_1,in_2;
input [1:0]s;
output [4:0]out;
reg [4:0]out;
parameter ADD=2'b00;
parameter SUBTRACT=2'b01;
parameter AND=2'b10;
parameter OR=2'b11;
always #(in_1,in_2,s)
begin
case (s)
ADD: out=in_1+in_2;
SUBTRACT: out=in_1-in_2;
AND: out={1'b0,(in_1&in_2)};
OR: out={1'b0,(in_1|in_2)};
endcase
end
endmodule
Problem1:
For the case in_1=4'b0000,in_2=4'b0001,s=2'b01
I think in_1-in_2 should be: 0000-0001=0000+(1110+1)=1111
So 1111 should be zero-extended(due to unsigned subtraction) to 01111,
then is assigned to out=5'b01111
However,the correct result show that out=5'b11111
Why?
Problem2:
For the case in_1=4'b0001,in_2=4'b0001,s=2'b01
I think in_1-in_2 should be: 0001-0001=0001+(1110+1)=10000
Then it is assigned to out=5'b10000
However,the correct result show that out=5'b00000
Why?
For physical hardware, a register contains only the binary data, signed unsigned are of just a matter of human interpretations.
Here, in your case, it is a matter of Expression width evaluation. Referring to SystemVerilog LRM 1800-2012, section 11.6:
The number of bits of an expression is determined by the operands and the context.
SystemVerilog uses the bit length of the operands to determine how many bits to use while evaluating an expression.
The bit length rules are given in 11.6.1. In the case of the addition operator, the bit length of the
largest operand, including the left-hand side of an assignment, shall be used.
The number of bits of an expression (known as the size of the expression) shall be determined by the
operands involved in the expression and the context in which the expression is given.
Referring to example given in LRM:
logic [15:0] a, b; // 16-bit variable
logic [15:0] sumA;
logic [16:0] sumB; // 17-bit variable
sumA = a + b; // expression evaluates using 16 bits
sumB = a + b; // expression evaluates using 17 bits
The mistake you are making here is calculating 2's complement for 4-bits and expecting a 5-bit output. While the language uses maximum bit length in an expression to do the same.
Here, out is a 5-bit register. So the 2's complement of minuend is taken for five bits. That is, 2's complement of 4'b0001 is 5'b11111. Adding this to an extension of 4'b0000 as 5'b00000, we get 5'b11111. Henceforth your first problem's result.
Similar, comments applies for your Problem-2, Adding 5'b11111 to 5'b00001 results in 5'b00000.
For more information about signed subtraction, refer to this, this and this links.

How range overflow affects the simulation and synthesis?

module dut ( a,b_out,array,c);
input [2:0] a;
input [3:0] array;
input c;
output reg b_out;
always#( a or c or array) begin
if(c)
b_out = 1'b0;
else
b_out = array[a];
end
endmodule
There is a possible range overflow in the above RTL, how it exactly affects the simulation and synthesis?
When a > 3 and !c then b_out will be undef in simulation because an out-of bounds access to a vector returns undef (i.e. 1'bx). See 5.2.1 in IEEE Std 1364-2005:
A part-select of any type that addresses a range of bits that are
completely out of the address bounds of the net, reg, integer, time
variable, or parameter or a part-select that is x or z shall yield the
value x when read and shall have no effect on the data stored when
written. Part-selects that are partially out of range shall, when
read, return x for the bits that are out of range and shall, when
written, only affect the bits that are in range.
In synthesis this don't care will be transformed into whatever the synthesis tool deems the most efficient. Very likely that means that only the bottom two bits of a are used in array[a], i.e. it is identical to array[a[1:0]]. But there is no guarantee for that whatsoever and it would be equally correct to create a circuit that for example always returns 1 or 0 when a[2] is high.

Logarithm in Verilog

I've a statement in verilog looking like integer level = log(N) (Where N is a parameter and level is to be determined) But I understand I cannot do complex math statements in verilog, so I'm wondering if there is an alternative solution to the above problem?
Any feedback appreciated!
If it is a logarithm base 2 you are trying to do, you can use the built-in function $clog2().
The answer to ADDRESS WIDTH from RAM DEPTH describes a couple ways to evaluate constant logarithms in this situation.
Verilog has functions for natural logarithm ($ln()), decadic logarithm ($log10()) and ceiling of binary logarithm ($clog2()). In constant expressions they should be synthesizable, but actual support by tools varies.
The following is synthesizable Verilog code:
module test(output [31:0] a, b, c);
assign a = 1000 * $ln(123);
assign b = 1000 * $log10(123);
assign c = 1000 * $clog2(123);
endmodule
E.g. after RTL synthesis with Yosys (e.g. yosys -p 'prep; write_verilog -noattr' test.v):
module test(a, b, c);
output [31:0] a;
output [31:0] b;
output [31:0] c;
assign a = 32'd4812;
assign b = 32'd2090;
assign c = 32'd7000;
endmodule
But I understand I cannot do complex math statements in Verilog
Verilog is first and foremost a hardware description language. What hardware log(N) statement is describing? Modern FPGAs consist of LUTs, flops, small embedded memories, simple DSPs that implement MAC (multiply-accumulate) primitives. log(N) and other complex math statements cannot be mapped directly into those primitives. The same goes with ASICs.
By analogy, log(N) doesn't get executed by a processor. It calls a bunch of lower-level assembly instructions to do so. Those assembly instructions are part of the log(N) library (C, C++, etc.)
To be able to synthesize log(N) for ASIC/FPGA it requires an instance of a log(N) IP core.
I like to think of (logarithm base n of value) as answering the question "How many base n digits do I need to represent 'value' independent numbers?" (Keeping in mind that 0 counts as a number)
Thinking of it that way, you can implement your own log base 2 in SystemVerilog:
function bit [31:0] log_base_2 (bit [31:0] log_input);
bit [31:0] input_copy;
bit [31:0] log_out = 0;
input_copy = log_input;
while(input_copy > 0)begin
input_copy = input_copy >> 1;
log_out = log_out + 1;
end
log_out = log_out - 1;
if(log_input != (1 << log_out))
log_out = log_out + 1;
return log_out;
endfunction

Resources