Unsigned reg subtraction in Verilog - 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.

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.

Why is wire variable causing illegal left-hand side in continuous assignment?

I have read through all similar posts, but none address the issue I'm having, namely that line 41 assign Y[b]=~Y[b]; causes error "Illegal left-hand side in continuous assignment."
I haven't assigned any regs so I don't see what the issue is. If I replace b with an actual number (say, 3) it works fine. But I need b as a variable here.
// Hamming code 1-bit error correction
module HCG(I,e,O);
input [4:1] I; // input BCD
input [7:1] e; // noise simulation
wire [7:1] X; // Hamming code
wire [7:1] Y; // Hamming code after addition of noise
wire [3:1] P; // Parity at start
wire [3:1] S; // Parity at end
wire b; // the error bit
output [4:1] O; // corrected output
assign X[1]=I[1]^I[2]^I[4]; // Hamming code generator
assign X[2]=I[1]^I[3]^I[4];
assign X[3]=I[1];
assign X[4]=I[2]^I[3]^I[4];
assign X[5]=I[2];
assign X[6]=I[3];
assign X[7]=I[4];
assign P[1]=X[1]; // Parity at start
assign P[2]=X[2];
assign P[3]=X[4];
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
assign S[1]=Y[3]^Y[5]^Y[7]; // Parity at end
assign S[2]=Y[3]^Y[6]^Y[7];
assign S[3]=Y[5]^Y[6]^Y[7];
assign b=(S[1]!=P[1])? b:b+1; // if parity of 2^0 not the same, add 1 to b
assign b=(S[2]!=P[2])? b:b+2; // if parity of 2^1 not the same, add 2 to b
assign b=(S[3]!=P[3])? b:b+4; // if parity of 2^2 not the same, add 4 to b
assign Y[b]=~Y[b]; // correct the incorrect bit
assign O[1]=Y[3]; // assigning outputs
assign O[2]=Y[5];
assign O[3]=Y[6];
assign O[4]=Y[7];
endmodule
The lines between module and endmodule are executed concurently. (It seems like you think they are executed sequentially.) Therefore, you are driving all the bits of Y in these lines
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
and then are driving one of the bits of Y again in this line:
assign Y[b]=~Y[b]; // correct the incorrect bit
So (a) you have a short circuit and (b) which bit has the short circuit? That depends on b. So, the position of the short circuit depends on the state of one of the internal wires. You have described a circuit that can reconfigure itself depending on its inputs. Verilog won't let you do that. Verilog is a hardware description language. Conventional digital hardware can't reconfigure itself depending on the state of its inputs.
The problem is the continuous assignment you are doing. To quote from the IEEE Std 1800-2012. (Section 10.3) on continuous assignments:
Continuous assignments shall drive values onto nets or variables, both vector (packed) and scalar. This assignment shall occur whenever the value of the right-hand side changes. Continuous assignments provide a way to model combinational logic without specifying an interconnection of gates.
When you do assign Y[b]=~Y[b], the assignment itself automatically causes the right-hand side to change again, which triggers the assignment again.
Verilog standard lists legal lhs values for the continuous assignment as the following (Table 10-1):
Net or variable (vector or scalar)
Constant bit-select of a vector net or packed variable
Constant part-select of a vector net or packed variable
Concatenation or nested concatenation of any of the above left-hand sides
in your case Y[b] is not a constant selection, because b is not a constant. Therefore syntactically your lhs is illegal and you get this message from the compiler.
On a side note you have a zero-delay loop here. See other answers for explanation.

Signed binary multiplication and signed binary division

What is the difference between the result of the multiplication when multiplying two unsigned numbers vs multiplying two signed numbers?
What is the difference between the remainder and quotient when dividing two signed numbers vs dividing two unsigned numbers?
An example may be illuminating.
module top;
reg [3:0] a;
reg [3:0] b;
reg [7:0] r1;
reg [7:0] r2;
initial begin
a = 4'hc;
b = 4'h5;
r1 = a * b; // 12 * 5
r2 = $signed(a) * $signed(b); //-4 * 5
$display("r1 = %b", r1);
$display("r2 = %b", r2);
end
endmodule
Result:
r1 = 00111100 (60)
r2 = 11101100 (-20)
The difference is that signed numbers utilize the MSB of the vector as an indicator of sign (see here, no really, read this) that shifts the range of expressible numbers from [0..2^n-1] to [-2^(n-1)..2^(n-1)-1]
A couple of things to note:
Verilog is odd and will only produce a signed results if both
operands are signed.
You can mark a reg/wire as signed like reg signed [3:0] foo or with the $signed system task. The latter is often useful if you have sub-expressions you want to treat as signed. For example, taking a bit slice of a vector is always unsigned even if the original var is signed.
The link I provided also covers the slight changes in mechanics required to get the right answer when multiplying signed quantities.
For purposes of Verilog's behavior division is essentially the same although unless dealing with strict powers of 2 is not usually synthesisable.
just a bit different view based on Brian's example
Signed vs unsigned arithmetic in verilog causes differences in sign propagation and relational operations. Regular arithmetic on 2-complement data produces the same results for signed and unsigned if no sign extension is involved
so in this case, if r1 and r2 would be of size '4' (as the operands) you would get the same results:
r1 = 1100 was (60)
r2 = 1100 was (-20)
In Brian's case the size of the result of the expression is 8; Verilog will extend your operands to occupy the 8-bit space. In case of the signed 'a' it will sing extend it and this will make the difference:
unsigned a[3:0] <1100> --> tmp[7:0] --> 00001100
signed a[3:0] <1100> --> tmp[7:0] --> 11111100
So, if a[3] is '1', it is considered a sign and gets sign promoted to the left. now, your arithmetic looks like the following:
unsigned: tmpa(00001100) * tmpb(00000101) --> 00111100
signed: tmpa(11111100) * tmpb(00000101) --> 11101100
When you display the second result as an integer, it will yet be sign extended to 32 bits and will be displayed as (-20)

verilog power operator ** result size

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.

i can't understand the following verilog code

i can't understand the two lines at the end of this code
input [15:0] offset ;
output [31:0] pc;
output [31:0] pc_plus_4;
reg [31:0] pc;
wire [31:0] pcinc ;
assign pcinc = pc +4 ;
assign pc_plus_4 = {pc[31],pcinc};
assign branch_aadr = {0,pcinc + {{13{offset[15]}},offset[15:0],2'b00}};
If you are unfamiliar with curly braces {}, they are concatenation operators. You can read about them in the IEEE Std for Verilog (for example, 1800-2009, Section 11.4.12).
assign pc_plus_4 = {pc[31],pcinc};
This concatenates the MSB of pc with all bits of pcinc to assemble the pc_plus_4 signal. However, in this case, since pcinc and pc_plus_4 are both 32 bits wide, pc[31] is ignored. A good linting tool will notify you that the RHS is 33 bits and the LHS is 32 bits, and that the most significant bit will be lost. The line can be more simply coded as:
assign pc_plus_4 = pcinc;
The last line is a compile error for one simulator I'm using. You did not explicitly declare the width of the branch_aadr signal, and the width of the 0 constant is unspecified.
The last line also contains a replication operator, which uses two sets of curly braces.
{13{offset[15]}}
This replicates the bit offset[15] thirteen times. It looks like the author is doing a sign extension on offset before adding it to pcinc. A better way might be to declare offset as signed.
//Three ways to replicate bits
wire [3:0] repeated;
wire value;
//These two assignments have the same effect
assign repeated = {4{value}}; //Replication operator
assign repeated = {value,value,value,value}; //Concatenation operator
//These four taken together have the same effect as the above two
assign repeated[3] = value; //Bit selects
assign repeated[2] = value;
assign repeated[1] = value;
assign repeated[0] = value;

Resources