Verilog module for ALU but doesn't work properly - verilog

I am trying to write down ALU for verilog.
And there are several error I experiences.
First of all, here is my code:
module yAlu(z, ex, a, b, op);
input [31:0] a, b;
input [2:0] op;
output [31:0] z, ztemp;
output ex;
wire[31:0]a0,a1,a2,a3,a4, atemp;
assign slt = 0;
assign ex = 0;
assign a0 = a & b;
assign a1 = a | b;
assign a2 = a + b;
assign a3 = a - b;
assign a4 = a[31] ^ b[31];
yMux #(32) lo(zLo, a0, a1, op[0]);
yMux #(32) hi(zHi, a2, a3, op[0]);
yMux #(32) temp(atemp, zLo, zHi, op[1]);
assign z = (op[2] == 1) ? a4 : atemp;
assign slt = z;
endmodule
And yAlu.v uses following:
module yMux(z, a, b, c);
parameter SIZE = 2;
output [SIZE-1:0] z;
input [SIZE-1:0] a, b;
input c;
yMux1 mine[SIZE-1:0](z, a, b, c); // 2-­bit 2 -­to-­1 mux and it would be cumbersome to write 32 mux instantiation lines.
endmodule
Lastly above yMux uses following:
module yMux1(z, a, b, c);
output z;
input a, b, c;
wire notC, upper, lower;
// Gates and interconnections for MUX
// if c is 0, z=a.
// if c is 1, z=b
not my_not(notC, c);
and upperAnd(upper, a, notC);
and lowerAnd(lower, c, b);
or my_or(z, upper, lower);
endmodule
Here is is what it tests above yAlu:
module lab8;
reg [31:0] a, b;
reg [31:0] expect;
reg [2:0] op;
wire ex;
wire [31:0] z;
reg ok, flag;
yAlu mine(z, ex, a, b, op);
initial begin
repeat (10) begin
a = $random; b = $random;
if(op==0)
expect = a & b;
else if (op==1)
expect = a | b;
else if (op==2)
expect = a + b;
else if (op==3)
expect = a - b;
else if (op==4)
expect = (a < b) ? 1 : 0;
#1;
if(expect == z)
$display("PASS : expected=%d, a=%d, b=%d, z=%d, op=%d", expect,a,b,z,op);
#1;
$finish;
end
end
endmodule
My questions in order as follow:
Question 1.
Code above only works for 0 and 1. It doesn't work more than that.
For example, on the 2nd source code, there is
a = $random; b = $random;
it doesn't work for this. it only works when a=1 or 0 and b=1 or 0.
Question 2.
I am not sure "slt" function is working correctly. The instructor who teaches this never told me what slt does in lecture but have us design slt, by googling or something.
Question 3.
Whenever I compile, i get following Error. Why is this?
yAlu.v:38: warning: Port 1 (z) of yMux expects 32 bits, got 1.
yAlu.v:38: : Padding 31 high bits of the port.
yAlu.v:39: warning: Port 1 (z) of yMux expects 32 bits, got 1.
yAlu.v:39: : Padding 31 high bits of the port.
yAlu.v:40: warning: Port 2 (a) of yMux expects 32 bits, got 1.
yAlu.v:40: : Padding 31 high bits of the port.
yAlu.v:40: warning: Port 3 (b) of yMux expects 32 bits, got 1.
yAlu.v:40: : Padding 31 high bits of the port.
I can't fix this at all.
I don't even know I am doing it correctly. The manual that directs me to do what it says has no enough explanation as well as no sample output.
I couldn't finish in time anyway, so I guess it doesn't matter but I think I have to know solution for my problems.
Thank you very much if you can help me out.

As shown by the warnings, your port connection width are mismatched. Refer to single warning and other are the same to tackle.
yAlu.v:38: warning: Port 1 (z) of yMux expects 32 bits, got 1.
yAlu.v:38: : Padding 31 high bits of the port.
The module declares ports a,b,c and z, each of width defined by SIZE parameter.
module yMux(z, a, b, c);
parameter SIZE = 2;
output [SIZE-1:0] z;
input [SIZE-1:0] a, b;
Moreover, the SIZE is overridden while instantiating. Now, the value of SIZE is 32. Hence the width of each of a,b,c and z is 32-bits.
yMux #(32) lo(zLo, a0, a1, op[0]);
yMux #(32) hi(zHi, a2, a3, op[0]);
yMux #(32) temp(atemp, zLo, zHi, op[1]);
Here, the ports zLo,zHi is not declared and used directly in port connection.
Referring to IEEE 1800-2012, section 6.10- Implicit declarations:
If an identifier is used in a port expression declaration, then an
implicit net of default net type shall be assumed, with the vector
width of the port expression declaration.
This, if an undeclared identifier is used as a connection to an instance then an implicit net is inferred.
Thus, zLo,zHi are implicitly declared as single bit nets and the rest 32-bits are padded with zeros. Just declare them as follows and all warnings shall be removed:
wire [31:0] zLo,zHi;
To get an error in such a situation, use default_nettype none compiler directive.
For more information, refer Sutherland SV Gotchas paper, section 2.2 and SystemVerilog IEEE 1800-2012 for implicit declarations.

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

Turn 2 bit module (Multiplier) into more bits

I have the following code for a 2 bit multiplier:
module Multiplier (a0, a1, b0, b1, c[3:0]);
output [3:0]c;
input a0, a1, b0, b1;
wire a0b1, a1b0, ha0c, a1b1;
and (c[0], a0, b0);
and (a0b1, a0, b1);
and (a1b0, a1, b0);
HalfAdder ha0 (a1b0, a0b1, c[1], ha0c);
and (a1b1, a1, b1);
HalfAdder ha1 (ha0c, a1b1, c[2], c[3]);
endmodule
I want to be able to expand this to more than 2 bits though (32 bits). The structure of my code poses a challenge for this though. First off I would have to have 68 parameters for the module. Also I would have to manually create 64 wires (duplicates of wire a0b1, a1b0, ha0c, a1b1). Finally I would need to manually write out a bunch of logic gates and HalfAdder modules to connect all the logic. Because of this I am wondering if there is a way that I can refactor my code to be able to instantiate a binary multiplier of n (a passed parameter) size.
You need to parameterize and use a generate block. (And it is much better to use a synchronous circuit then an asynchronous circuit).
Here is an incomplete example, you can fill in the necessary logic :
module Multiplier (a, b, c, clk);
parameter WIDTH = 64;
output [2*WIDTH:0]c;
input [WIDTH-1:0]a;
input [WIDTH-1:0]b;
input clk;
genvar i;
generate for (i = 0; i < WIDTH; i <= i + 1)
begin : shifts
// shift a 1-bit for each i and 'logical and' it with b
reg [WIDTH + i :0]carry;
wire [WIDTH + i -1:0]shifted = {a,i{0}} & b[i];
// sum the result of shift and 'logical and'
always # (posedge clk)
begin
carry <= shifted + shifts[i-1].carry ;
end
end
assign c = shifts[WIDTH].carry;
endgenerate
endmodule

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.

vectored input port driving output port of single bit net

Why are these two codes not equivalent? I am checking the logical equivalence between the two, they are failing, what could be the error?
Will it take it as width mismatch, or net driven by multiple drivers? I am using cadence LEC for formal verification
module driver (a, b);
input [3:0] a;
output wand b;
assign b = a;
endmodule
module driver (a, b);
input [3:0] a;
output wand b;
assign b = a[3];
assign b = a[2];
assign b = a[1];
assign b = a[0];
endmodule
assign b = a is equivalent to assign b = a[0]. The upper bits of a are out range for b.
Same reason with overflow. For example assign sum[3:0]=a[3:0]+b[3:0] if a=15 and b=2, sum will be 1 because there are not enough bits to represent 17 (17 mod (2^bitwidth(4)) = 1).

How do I fix "Error-[IBLHS-NT] Illegal behavioral left hand side"?

I am trying to debug this code shown below. I can not get it to work at all. The attached Verilog file has two modues: 1) "equality" which defines the Device Under Test (DUT) and 2) "test" which generates the inputs to test the DUT. The module "equality" has a coding error. Let me know if you can give me a hint. Thanks!
The errors I am receiving are:
Error-[IBLHS-NT] Illegal behavioral left hand side
ECE413/src/Equality_bugs_Test_Bench.v, 7
Net type cannot be used on the left side of this assignment.
The offending expression is : Equal
Source info: Equal = 1;
Error-[IBLHS-NT] Illegal behavioral left hand side
ECE413/src/Equality_bugs_Test_Bench.v, 9
Net type cannot be used on the left side of this assignment.
The offending expression is : Equal
Source info: Equal = 0;
My SystemVerilog Code is:
module equality (Equal, a, b); // This module defines the DUT.
input[3:0] a, b;
output Equal;
always # (a or b)
begin
if (a == b)
Equal = 1;
else
Equal = 0;
end
endmodule
//
//
//
module test; // This is the test bench. It specifies input signals to drive the DUT.
reg [3:0] a, b;
wire Equal;
equality Eq1 (Equal, a, b); // This line instantiates the DUT.
initial
begin
a = 4'b0000; // Initialize "a" to 0.
b = 4'b0000; // Initialize "b" to 0.
#512 $finish; // Simulate for 32x16 = 512 time steps to exercise the entire truth table.
// (32 steps/cycle x 16 cycles)
end
// The next four lines clock the bits of input "b" so as to count up from 0 to 15.
always #2 b[0] = ~b[0]; // (Note: all procedural blocks run concurrently.)
always #4 b[1] = ~b[1];
always #8 b[2] = ~b[2];
always #16 b[3] = ~b[3]; // One complete cycle is 2x16 = 32 time steps.
always #32 a = a+1; // "a" is incremented by one after each complete count of "b".
endmodule
Procedural assignments (inside always blocks) must be made to signals declared as reg. Change:
output Equal;
to:
output reg Equal;
For a shorter, equivalent version:
module equality (
output Equal,
input [3:0] a, b
);
assign Equal = (a == b);
endmodule

Resources