the difference between a[b+1] and a[b+1'b1] - verilog

when I try to write to a[b+1] where the bits of b are all '1' ,the value of the reg a[0] do not update,but when I try a[b+1'b1],it updated
awaddr_wa <= awaddr_wa + 2;
awaddr[awaddr_wa] <= AWADDR_M;
awlen [awaddr_wa] <= 4'd0;
awaddr[awaddr_wa+6'd1] <= AWADDR_M+16;
awlen [awaddr_wa+6'd1] <= 4'd0
so ,why?

Here is a reproducible example:
module M;
integer a[0:7] = {0,1,2,3,4,5,6,7};
reg [2:0] b = -1;
initial
begin
$display("a[b+1]=", a[b+1]);
$display("a[b+1'b1]=", b+1'b1);
end
endmodule
https://www.edaplayground.com/x/26Za
(Your question would be better had it included this)
You will see that the output is something like:
a[b+1]= x
a[b+1'b1]=0
1 is 32 bits wide. (All unbased literals in Verilog are 32 bits
wide.)
When you mix bit widths like this in Verilog, Verilog must
decide how many bits to use.
When you index an array out of range in Verilog this is not a catastrophe like it is in C. Instead the default value for the type of the array is returned. a is an array of integers, whose default value is 32'bx.
With a[b+1], Verilog will take the wider of 3 bits (b) and 32 bits (1), ie 32 bits. So, with b=3'b111, 1 is added to b using 32-bit arithmetic. In 32-bit arithmetic, 7+1 is 8, so a[b+1] is the same as a[8] which is out of range and hence 32'bx.
With a[b+1'b1], Verilog will take the wider of 3 bits (b) and 1 bit (1'b1), ie 3 bits. So, with b=3'b111, 1'b1 is added to b using 3-bit arithmetic. In 3-bit arithmetic, 7+1 is 0, so a[b+1'b1] is the same as a[0] which is not out of range and is 32'b0 in my example.
This is a classic trap in Verilog. It is an example of a Verilog self-determined expression. A self-determined expression is one where the number of bits used for the calculation depends only the widths of the operands. There are also context-determined expressions (eg F = A + B) where the number of bits also depends on the width of the variable (or net) being assigned to.

Related

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.

Is there automatic vector width coercion in Verilog?

Suppose I have a small vector:
wire [15:0] a;
and I assign it to a larger vector:
reg [31:0] b;
always #(posedge clk) begin
b <= a;
end
What would be the result? Will b be assigned with zeros in its higher word, or will the high part remain unmodified? Something else?
I've tried searching for the answer in other sources, but all examples I've found had matching widths in the left an right operands of an assignment.
The behaviour of Verilog in this case is well defined. With your example, because by default values are unsigned, you will get this behaviour:
if the left hand bit (bit 15) of a is 1'b0 or 1'b1 then a will be extended to 32 bits wide by zero-padding. ie bits 31 to 16 of b will be 1'b0.
if the left hand bit (bit 15) of a is 1'bx or 1'bz then a will be extended to 32 bits wide by copying that value. ie bits 31 to 16 of b will be 1'bx if bit 15 is 1'bz or 1'bz if bit 15 is 1'bx.
If a were signed, ie if a were declared like this:
wire signed [15:0] a;
then
the behaviour when the left hand bit is 1'bx or 1'bz would be the same as if it were unsigned - the value is just copied.
when the left hand bit is 1'b0 or 1'b1 that left hand bit is sign-extended, ie again the value of that left hand bit is just copied. This behaviour does not depend on whether b is signed or unsigned, only on whether a is signed or unsigned.
the result will assign zeros in the higher order bits. synthesis also possible.
module larger(input [7:0]a, output [15:0] b);
assign b = a;
endmodule
check for your self for this code.

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.

Rounding off a number in verilog

Basically I'm trying to code a synthesizable module in verilog which performs division between 2 numbers and rounds off the result . For example, if I'm doing 56/30 then resulting value is 1.86 and this value should be rounded off to 2 or if I'm doing 42/30 , the resulting value is 1.4 which should be rounded off to 1 . Can synthesizable code be written in verilog to achieve this?
The value of the answers LSB is determined by the input format. If you change the numerator input to Fixed point with at least 1 Fractional bit rather than integers, your output will have a bit representing 0.5 which you can use to control truncate (round down) or round up.
module test;
reg[4:0] a = 5'b0011_0; //3 with 1 Fractional bit
reg[4:0] b = 5'b00010; //2 no fractional bits
reg[9:0] c;
initial begin
c = a/b ; //LSB => 0.5
// c= 5'b01_1 => 1.5
#1 $display("C = %b", c);
end
endmodule
Verilog truncates the end of a number if <size> is smaller than the value returned. So if you divide 42/30, the value returned is 1.4. Simply define the <size> as 1, and the decimal will be truncated.
However, keep in mind that this solution truncates the decimal, and doesn't round it up. I'm not an expert at Verilog, but you could refer here to further solve your problem.

Resources