Verilog if statement always returns false - verilog

I need help with my if/else statement that's not working. No matter what I enter, it just doesn't work. It only ever assigns 1 to operand2. What am I doing wrong with the if/else statement?
module TestMod; // the "main" thing
parameter STDIN = 32'h8000_0000; // I/O address of keyboard input channel
reg [7:0] str [1:3]; // typing in 2 chars at a time (decimal # and Enter key)
reg [4:0] X, Y; // 5-bit X, Y to sum
wire [4:0] S; // 5-bit Sum to see as result
wire C5; // like to know this as well from result of Adder
reg operand, operand2; //operand
wire E; //exception overflow inidicator
AddSub addOrSub(X, Y, S, C5, E, operand2);
initial begin
$display("Enter X (two digit 00~15 (since max is 01111)):");
...
$display("Enter Y (two digit 00~15 (since max is 01111)):");
...
$display("Enter + or -");
operand = $fgetc(STDIN);
if (operand == "+") begin
operand2 = 0;
end
else begin
operand2 = 1;
end
#1; // wait until Adder getsthem processed
$display("operand", operand);
$display("X =",X, " (%b",X, ") Y =",Y, " (%b",Y,")", "C0=",operand2);
$display("Result =", S," (%b",S, ") C5 = ",C5);
end
endmodule

From IEEE Std 1800-2017, section 21.3.4.1 Reading a character at a time, $fgetc:
reads a byte from the file
A byte is 8 bits. If the user inputs + on STDIN, then $fgetc returns the string +, which in a numeric context is represented by the ASCII value 43.
You declared operand to be reg, which is a 1-bit value. Therefore, operand can only take on the value 0 or 1. In the case where $fgetc returns the string +, which is 43 (or 'b0010_1011), operand just gets the LSB, which is 1.
(operand == "+") compares 1 to 43, which is false, and the else code is executed.
As you pointed out in a Comment, you need to declare operand as 8 bits wide:
reg [7:0] operand;

Related

Expression width 32 does not match width 1 of logic gate array port 1

I have two questions.
No output
Expression width 32 does not match width 1 of logic gate array port 1.
When I write and( OutAnd, a, b);, it shows an error.
Expression width 32 does not match width 1 of logic gate array port 1.
How can I fix it?
By the way. I forbid to use & operator, Procedure Assignment, and always block.
Here's my code:
ALU.v
module ALU(
input [5:0] Signal,
input [31:0] a, b,
output reg[31:0] Output
);
wire[31:0] OutAnd;
and( OutAnd, a, b); // AND <-- error
AluMux alumax0( .Signal(Signal), .in_And( OutAnd ) ); // AND
endmodule
AluMax.v
module AluMux(
input [5:0] Signal,
input [31:0] in_And, in_Or,
output reg[31:0] Output
);
parameter AND = 6'd36;
always # ( * )
begin
case ( Signal )
AND : Output = in_And;
default : Output = 32'd11;
endcase
end
endmodule
The output of the and gate defined to be 1 bit and you want to put 32 bits in it which may cause an error or a warning to solve this you have 2 way either instantiate 32 and gates with the following syntax
and u1 (OutAnd[0], a[0], b[0]);
and u1 (OutAnd[1], a[1], b[1]);
and u1 (OutAnd[2], a[2], b[2]);
.
.
.
and u1 (OutAnd[31], a[31], b[31]);
or use a generate statement here is a sample code
genvar i;
generate
for(i = 0;i < 32;i = i + 1) begin
and u1(OutAnd[i], a[i], b[i]);
end
endgenerate

Verilog Design of a 32-bit ALU

Can you help me guys do a 32-bit ALU and explain me some things?
Wanna do:
0 bitwise AND: out = inA & inB.
1 bitwise OR: out = inA | inB.
2 addition: out = inA + inB.
6 subtraction: out = inA – inB //2's complement
7 Set On Less Than: out = ((inA < inB)?1:0)
12 NOR: out = ~( inA | inB)
Done this so far:
module ALU #(parameter N=32)(ALUOut, Zero, ALUinA, ALUinB, ALUop);
output [N-1:0] ALUOut;
reg [N-1:0] ALUOut;
output Zero;
reg Zero;
input [3:0] ALUop;
input [N-1:0] ALUinA, ALUinB;
always #(ALUinA or ALUinB or ALUop)
begin
case (ALUop)
4'b0000: ALUOut = ALUinA & ALUinB ; // 0:AND
Your code is good. Just some modifications required. ALUOut must be [N:0], since you'll require a carry bit in case of addition. Also, borrow bit must be required in case of subtraction.
Referring to SystemVerilog LRM 1800-2012 Section 11.6 Expression bit lengths,
SystemVerilog uses the bit length of the operands to determine how many bits to use while evaluating an
expression.
So, ALUOut[N-1:0] = ALUinA[N-1:0] + ALUinB[N-1:0]; will strictly evaluate an expression of N, while ALUOut = ALUinA + ALUinB; will
evaluate depending on size of ALUOut. Here, you can not see the difference, since all youe operands are N bits wide, but when ALUOut is increased to N+1 bits(including carry), then it can create a difference.
For example,
module top();
bit [3:0] a,b;
logic [3:0] sum;
bit carry;
assign sum[3:0] = a[3:0] + b[3:0];
// assign {carry,sum}= a + b;
initial
$monitor("a = %0d b = %0d carry = %0d sum = %0d",a,b,carry,sum);
initial
begin
a = 5; b = 1;
#5 ; a = 15; b = 1;
end
endmodule
shall execute to a = 15 b = 1 carry = 0 sum = 0 while, using the commented assign statement executes to a = 15 b = 1 carry = 1 sum = 0
Refer to LRM 1800-2012, Section 11.6 for further information.
Also, this and this links regarding ALU design can be useful.
In 2's complement -B is ~B+1 (~ is bit invert). Therefor A - B == A + (-B) == A + ~B + 1. But your doing RTL, so you don't need to write the 2's complement for subtraction as it is default. A - B and A + ~B + 1 will synthesize the same.
A[N-1:0] + B[N-1:0] is always an unsigned operation. A + B can be a signed operation if A and B are declared as input signed [N-1:0] A, B, otherwise it is an unsigned operation.
Other notes:
There is an issue with your header. Many simulators, synthesizers, and other Verilog tools will accept what you have, but it is not complaint with the IEEE standard. There are two header styles, ANSI and non-ANSI. I recommend ANSI unless required to follow the IEEE1364-1995 version of the standard.
ANSI style (IEEE Std 1364-2001 and above):
module ALU #(parameter N=32)(
output reg [N-1:0] ALUOut,
output reg Zero,
input [N-1:0] ALUinA, ALUinB,
input [3:0] ALUop );
Non-ANSI style (IEEE Std 1364-1995 and above):
module ALU (ALUOut, Zero, ALUinA, ALUinB, ALUop);
parameter N=32;
output [N-1:0] ALUOut;
output Zero;
input [3:0] ALUop;
input [N-1:0] ALUinA, ALUinB;
reg [N-1:0] ALUOut;
reg Zero;
always #(ALUinA or ALUinB or ALUop) is syntax legal. However since IEEE1364-2001 combinational logic is recommenced to be written as always #* or always #(*) (#* and #(*) are synonymous, user preference). With SystemVerilog (IEEE1800), the successor of Verilog (IEEE1364), always_comb is recommend over always #* for combinational logic, and always_latch for level-sensitive latching logic.

Verilog Case Block Concatenation Syntax

I can't seem to figure out what the proper syntax is to do {c_out, result} = {a + b + c_in} within a case block. The c_out doesn't work in my test bench, if I add 32'hffffffff + 1'b1 I get c_out = 0, result = 32'b0. What's the correct way to do this?
module verification_alu(
input c_in
input [W-1:0] a, b,
input [2:0] operation,
output reg [W-1:0] result
output reg c_out
);
parameter W = 32;
always#*
begin
case(operation)
0: result = a;
1: result = ~a;
2: {c_out, result} = {a + b + c_in};
3: {c_out, result} = {a - b + c_in};
4: result = a | b;
5: result = a & b;
default: {c_out, result} = {W-2'b0}; // will this line fill with zeros properly?
endcase
end
endmodule
Also, side question, what should be the proper output of 32'b0 - 1'b1? Should I be getting 32'hffffffff?
The reason the addition and subtraction operations are not working is because you are wrapping the calculation in the concatenation operator ({}). Verilog determines the bit size of an operation partially based on the operands in an expression as well as by the context of that expression. In your case, the expression a + b + c_in is being evaluated as W-bits because the maximum length of any of the variables in that expression is W (ie, a and b are that length and because Verilog will first evaluate this addition (or two additions) before moving on to evaluating the {} operator wrapping it). By removing this unneeded step, you should get the proper (W+1)-bit evaluation of a + b + c_in; so the line would be: 3: {c_out, result} = a - b + c_in;. For more on this, see IEEE1800-2012, section 11.6.
To answer two of your other questions:
No, the expression {W-2'b0} will not zero fill but will instead result in the value W as you are telling the simulator to subtract 2'b0 from W. You are thinking of {(W-2){1'b0}}, or specially for zero filling '0 (because its so common, you can also use '1, 'x, or 'z for filling 1, don't care or high-Z respectively). (Note {c_out, result} has width W+1, not W-2 though)
Finally, 32'b0 - 1'b1 will most likely yield 32'hffffffff, but it is subject to the rules above on sizing (and sign extension rules as well).
A revised description:
module verification_alu #(parameter W=32) (
input wire c_in,
input wire [W-1:0] a,
input wire [W-1:0] b,
input wire [2:0] operation,
output reg [W-1:0] result,
output reg c_out
);
always #* begin
case(operation)
0: result = a;
1: result = ~a;
2: {c_out, result} = a + b + c_in;
3: {c_out, result} = a - b + c_in;
4: result = a | b;
5: result = a & b;
default: {c_out, result} = 0; // will this line fill with zeros properly?
endcase
end
endmodule
The point is to assure that at least one of the operands have the same size as the result you want, so I prepend a 0 bit to both a and b.
I have verified this to work even for sizes far beyond the size of an ordinary integer:
module tb;
reg c_in;
reg [127:0] a;
reg [127:0] b;
reg [2:0] op;
wire [127:0] res;
wire c_out;
verification_alu #(.W(128)) uut (c_in, a, b, op, res, c_out);
initial begin
c_in = 0;
a = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
b = 128'h00000000000000000000000000000001;
op = 3'd2;
#100;
$display ("RES = %H C_OUT = %d\n", res, c_out);
#100;
c_in = 0;
a = 128'h00000000000000000000000000000000;
b = 128'h00000000000000000000000000000001;
op = 3;
#100;
$display ("RES = %H C_OUT = %d\n", res, c_out);
#100;
op = 7;
#100;
$display ("RES = %H C_OUT = %d\n", res, c_out);
$finish;
end
endmodule
Chronologic VCS simulator copyright 1991-2014
Contains Synopsys proprietary information.
Compiler version J-2014.12-SP1-1; Runtime version J-2014.12-SP1-1; Oct 11 17:47 2015
RES = 00000000000000000000000000000000 C_OUT = 1
RES = ffffffffffffffffffffffffffffffff C_OUT = 1
RES = 00000000000000000000000000000000 C_OUT = 0
$finish called from file "testbench.sv", line 35.
$finish at simulation time 500
You can edit and/or run the testbench along with the revised module at http://www.edaplayground.com/x/CJV
EDIT: ouch! I didn't realized the OP had used the concatenation operator { } for embracing the three operands. Yes! your code is way much simpler. I'll edit the code in my answer.
First of all as per your code the parameter definitions in the input ports will not be accessible by compiler and will throw syntax error, you have to mention the parameter definitions before your i/o declarations since it is been accessed in i/o declarations, verilog comes with a syntax as to avoid this
module module_name #(parameter W =value)
{} is a concatenation operator used with "," eg: a=1bit b= 1bit c=2bit so we can give c={a,b}; so the correct syntax is as simple as
2: {c_out, result} = a + b + c_in;
3: {c_out, result} = a - b + c_in;
to fill it with zeros a mix of parameter with curly braces will help in resolving (the inner curly brace will act as replication operator)
default: {c_out, result} = {(W-2){1'b0}};

How to convert 4-digit hexadecimal number to bcd in verilog testbench

`include "bcd.v"
module bcd_4(A,B,Cin,S,Cout);
input [15:0] A,B;
input Cin;
output [15:0] S;
output Cout;
wire w1,w2,w3;
bcd_adder U1(.A(A[3:0]),.B(B[3:0]),.Cin(Cin),.S(S[3:0]),.Cout(w1));
bcd_adder U2(.A(A[7:4]),.B(B[7:4]),.Cin(w1),.S(S[7:4]),.Cout(w2));
bcd_adder U3(.A(A[11:8]),.B(B[11:8]),.Cin(w2),.S(S[11:8]),.Cout(w3));
bcd_adder U4(.A(A[15:12]),.B(B[15:12]),.Cin(w3),.S(S[15:12]),.Cout(Cout));
endmodule
I have designed a 4-digit BCD adder using four 4-bit BCD adders. The inputs 'A' and 'B' are taking hexadecimal values. How can I write a testbench so that the input values should be decimal only? I have to check the following condition also:
if({Cout,S}==A+B+Cin) $display("pass");
else $stop;
The inputs of your adder do not take hexadecimal values. They are 16-bit inputs which represent 4 BCD digits of 4 bits each. The input for each digit can range from 0 to 15 in decimal, but since they are BCD any value greater than 9 would be invalid.
The inputs can be specified in any base (binary, octal, decimal or hexadecimal).
The following are all equivalent:
A <= 10;
A <= 4'd10;
A <= 4'hA;
A <= 4'b1010;
If you want to only generate valid BCD values inputs in your testbench, you should generate the entire 4-digit number as an integer and then convert each digit to the appropriate bits to drive your design.
For example, to drive every valid value for input A (0 to 9999) you could do the following:
integer a;
for (a = 0; a < 10000; a = a + 1) begin
// a is an integer
// A is a 16-bit, 4-digit BCD value
A[3:0] = a % 10; // digit 0, ones place
A[7:4] = (a / 10) % 10; // digit 1, tens place
A[11:8] = (a / 100) % 10; // digit 2, hundreds place
A[15:12] = (a / 1000) % 10; // digit 3, thousands place
end
For sampling the output, you would do the inverse - convert 4 4-bit BCD digits to an integer.
Here is a full, runnable example which includes code for sampling and verifying the output: http://www.edaplayground.com/x/2pT
I got it. I can write it using following function
function integer hexatodecimal;
input [16:0] a;
integer b;
begin
b=a[3:0]+a[7:4]*10+a[11:8]*100+a[15:12]*1000+a[16]*10000;
hexatodecimal=b;
end
endfunction
I can call this function to convert {Cout,S} into hexadecimal.

How does Verilog behave with negative numbers?

For instance, say I have a reg [7:0] myReg
I assign it the value -8'D69
I know Verilog stores it as 2's complement so it should be stored as
10111011
The question I have now is if I were to perform an operation on it, say myReg/2
Would it evaluate to -34? Or would it take 10111011 and turn it into 187 then perform the division, returning 93?
You need to remember that -8d69 is just a bit pattern. reg is a type which holds bit patterns. It is the type of variable that instructs / to perform signed or unsigned arithmetic.
If this is for synthesis bare in mind that you want to try and avoid dividers, you really want to try and avoid signed dividers. It will likely synthesis smaller with >>> 1
reg [7:0] a;
reg signed [7:0] b;
reg [7:0] c;
reg signed [7:0] d;
initial begin
a = -8'd69 ;
b = -8'd69 ;
c = -8'd69 ;
d = -8'd69 ;
#10ns;
a = a/2 ;
b = b/2 ;
#10ns;
$display("a : %8b, %d", a, a);
$display("b : %8b, %d", b, b);
$display("c >>>1 : %8b, %d", c>>>1, c>>>1);
$display("d >>>1 : %8b, %d", d>>>1, d>>>1);
end
Gives:
a : 01011101, 93
b : 11011110, -34
c >>>1 : 01011101, 93
d >>>1 : 11011101, -35
>> x Shifts right by x places, >>> x Shifts right x places but sign extends for signed types.
NB: the /2 is also rounding up in my examples, >>> will round down/truncate.
For instance, say I have a reg [7:0] myReg I assign it the value
-8'D69
This actually isn't a signed number but instead an expression consisting of a unary negation applied to a positive constant. If the expression was -8'd130 the result would overflow. Signed constants are declared as 8'sd69 or just 69.
The question I have now is if I were to perform an operation on it,
say myReg/2
myReg is unsigned so the expression result will also be unsigned*. If you need the result to be signed than all operands must be signed. There are a couple ways to achieve this:
//Declare the reg as signed and divide by a signed value
reg signed [7:0] myReg;
assign result = myReg/2;
//Use system functions
assign result = $signed(myReg)/2;
*The complete rules regarding expression evaluation are much more complex but basically the result of any expression is unsigned, unless all operands are signed.
reg signed [7:0] a;
reg [7:0] b;
initial
begin
result = a; //Signed
result = a * a; //Signed
result = a * 10; //Signed
result = $unsigned(a); //Unsigned
result = a[0]; //Unsigned
result = a[7:0]; //Unsigned
result = {a,a}; //Unsigned
result = 10{a}; //Unsigned
result = a + b; //Unsigned
result = a * b; //Unsigned
end
I'll add that
1. Data types bit and reg are unsigned, by default.
2. Data types int, integer, longint, shortint, and byte are signed, by default.
3. All these data types can take a signed or unsigned qualifier to change the default.
So, assigning -8'D69 to myReg does an implicit conversion to 187. Then, myReg/2 = 187/2 = 93, unsigned. It's important to understand when and how SystemVerilog does implicit type conversions in expressions and assignments.
The best place to check is the Language Reference Manual. Predictably, given Verilog's "eh" attitude to proper typing, it's a bit of a mess.
Basically signed doesn't affect the actual data stored in the variable/net, but it does affect what the arithmetic operators do in some case. The obvious case is comparison, but also multiplication and division would behave differently. Addition and subtraction should be the same for both signed and unsigned.
Note especially that when one or more of the operands is unsigned it is treated as an unsigned comparison, which is different to what you would expect from C. So if we have
byte a = -10; // byte is signed
logic [7:0] b = 10; // this is unsigned
Then a > b is true.
Again if at least one operator is unsigned then it treats them both as unsigned so if we have:
byte a = -1;
logic [7:0] b = 255;
Then a == b is true.

Resources