Is there automatic vector width coercion in Verilog? - 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.

Related

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

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.

verilog multiplication results is zero?

i'm trying to multiply two 32 bit signed fractional number (1 sign bit, 8 integer bit, 23 fraction bit)
the first one is
32'b0_00000001_00000000000000000000000 // 1.00
the 2nd one is
32'b0_00000100_00000000000000000000000 // 4.00
when i do like this for example
output signed[31:0] a;
assign a = 32'b0_00000001_00000000000000000000000 * 32'b0_00000100_00000000000000000000000;
the results is zero? why it isn't 4?
kindly please help me in which part i am mistaken and what should i do. thank you very much
regards
Isaac
Because you are trying to assign a 64 bit value to a 32 bit wire, and Verilog will truncate the value, keeping only the lower 32 bits of the result, which is zero.
To have a proper result, you can do as this:
module mult;
reg [31:0] a = 32'b0_00000001_00000000000000000000000; // 1.0
reg [31:0] b = 32'b0_00000100_00000000000000000000000; // 4.0
reg [63:0] t;
reg [31:0] c;
initial begin
t = a * b;
c = t[54:23];
$display ("%b",c);
$finish;
end
endmodule

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.

Which is a better method of designing an upcounter in verilog from the ones mentioned below?

I have declared an 8 bit register variable count
reg [7:0]count=0;
count is supposed to increment from 8'h00 to 8'hFF & back to 8'h00 & increment again so on.
Below i am providing 2 ways of doing this
always #(posedge Clk)
begin
if(count==8'hFF)
count<=8'h0;
else
count<=count+1;
end
OR
always #(posedge Clk)
begin
count<=count+1;
end
In the 1st case, count will go from 00 to FF & 00 to FF again & again.
In the 2nd case also, count will go from 00 to FF then overflow to 00 with a carry & increment to FF again & again.
Will that carry affect anything & how? Also which method is better synthesis wise?
Either method will work. The best result is dependent on the how smart/dump your synthesizing tool is. Some tools issue warnings when it sees an overflow is possible. If you want to resolve the warning, you can use the below method:
reg [7:0] count = 0;
wire [8:0] next_count = count + 1'b1; // MSB is overflow bit
always #(posedge Clk)
count <= next_count[7:0]; // overflow bit not used in assignment
The overflow bit could be done in the synchronous block. Unless you plan on using the overflow bit, I would not recommend these as it will either waste a flop (dumb synthesizer) or issue a warning that a flop has been optimized out (smart synthesizer).
reg [7:0] count = 0;
reg overflow;
always #(posedge Clk)
{overflow,count} <= count + 1'b1; // optimization warning OR wasted flop
According to IEEE Std 1364™-2005
should an arithmetic add of two 16-bit values perform the evaluation using 16 bits, or should the evaluation use 17 bits in order to allow for a possible carry overflow? The answer depends on the type of device being modeled and whether that device handles carry overflow. The Verilog HDL uses the bit length of the operands to determine how manybits to use while evaluating an expression. The bit length rules are given in 5.4.1. In the case of the addition operator, the bit length of the largest operand, including the lefthand side of an assignment, shall be used
They have given an example which I think is applicable for this case:
reg[15:0] a, b; // 16-bit regs
reg[15:0] sumA; // 16-bit reg
reg[16:0] sumB; // 17-bit reg
sumA = a + b; // expression evaluates using 16 bits
sumB = a + b; // expression evaluates using 17 bits
So, hopefully it won't affect the synthesis and is better than previous one.

Converting a wire value in Verilog for further processing

I'm new to Verilog.
I have written code to convert a wire value to an integer:
wire [31:0] w1;
integer k;
always # (w1) k = w1;
Source: converting a wire value to an integer in verilog
Now, for the next part I get an ERROR!
wire [63:0] w2; // Suppose it contains some value
wire [63:0] w3;
assign w3[k-1:0] = w2[k-1:0]; // ERROR in this line
ERROR : k is not a constant.
How do I solve this issue?
Verilog requires that part selects (code like [msb:lsb] to select part of a vector) be constant. To access a variable-sized group of bits requires something more complicated. Here is one way to do it:
wire [63:0] src;
wire [6:0] k;
wire [127:0] mask = { { 64 { 1'b0 } }, { 64 { 1'b1 } } } << k;
wire [63:0] dest;
assign dest = mask[127:64] & src;
The technique here is to construct a vector of 64 zeros followed by 64 ones, shift that vector by a variable amount, and then use a portion of the vector as a qualifying mask to control which bits are transferred from src to dest.
A related concept which does not help in your example but which is worth being aware of: Verilog-2001 introduced the "indexed part-select". An indexed part select specifies a base index and a width. The width is required to be constant but the base index does not need to be constant. The syntax for an indexed part select is vec[base+:width] or vec[base-:width].
The part select operators in Verilog 2001 could be useful for what you want to achieve.
Basically verilog allows for the starting index to be variable but needs the width of the assignment to be constant. The "+:" operator indicates counting upwards from the index value and vice-versa for "-:".
You can do something like,
assign w3[k-1 -: 8 ] = w2[k-1 -: 8]; // Where 8 bits is copied downwards
Search for "+:" in the below document.
http://www.sutherland-hdl.com/papers/2001-Wescon-tutorial_using_Verilog-2001_part1.pdf
Word of caution, generally variable part selects is considered as bad verilog.

Resources