My desired functionality will be to add A, B, and cin (where A and B are 64 bits, and cin is one bit). So the actual sum (the actual result) can either be 64 bits or even 65 bits, right? So I want the output "sum" to be 64 bits, and then the carryout output "cout" would hold the most significant bit of the result. Tried doing this by an assign statement, but I guess that's not how you do it as it gives an error. Any other way?
module addsub(A, B, cin, sum, cout);
input [63:0] A, B;
input cin;
output reg [63:0] sum;
output cout;
reg [64:0] actualsum; // the actual result of the addition, which I want to then "split" into cout & sum
always #(A or B or cin) begin
actualsum = A + B + cin;
sum <= actualsum[63:0];
cout <= actualsum[64];
end
endmodule
The compile error I got was due to a procedural assignment to cout (inside an always block). To fix that, you would declare cout as a reg.
Good coding practices recommend that you use blocking assignments (=) instead of nonblocking assignments (<=) for combinational logic.
A much simpler and more conventional way to code this is:
module addsub (
input [63:0] A, B,
input cin,
output [63:0] sum,
output cout
);
assign {cout, sum} = A + B + cin;
endmodule
I have a circuit whose truth value looks like this A =BC+^C[(B and C) or (not C)]
Here I give,
output A;
input B, C;
wire w1, w2;
and (w1, B, C);
not (w2, C);
or (A, w1, w2);
My question is why do we write input B, C; Can we write it as reg B, C;?
What exactly is the difference?.
You are not showing a complete example, but inputs and outputs are part of a hierarchical module declaration. reg is a data type associated with a signal. Typically one encapsulates your circuit in a module, and then you instantiate that module in a top-level module to provide stimulus and observe the outputs.
module circuit( output wire A;
input wire B, C;
wire w1, w2; // internal wires
and (w1, B, C);
not (w2, C);
or (A, w1, w2);
endmodule
module top;
reg B,C; // these are different signals that get connected to the circuit wires
wire A;
circuit c(A,B,C);
initial begin
B = 0; C = 0;
...
endmodule
comparing input and reg is similar to comparing a keyboard to a verilog code. input defines a direction of a port. reg defines a data type.
However, every port has a data type associated with it. Default data type for an input/output port is wire. So input B is the same as input wire B.
Now, the right question is: what would be a differnce between wire and reg.
wire is a data type for describing connection between module instances. Its main characteristic is that it should always be connected and cannot keep is state otherwise. reg can keep the state if not connected. There are multiple differences in usage which you can find in corresponding verilog tutorials.
I have two files named: summation.v and summationtest.v
Code for summation.v::
module summation(a, b, c);
input [3:0] a;
input [3:0] b;
output reg[7:0] c;
reg[3:0] anum;
reg[3:0] bnum;
always #(a) begin
anum <=a;
bnum <=b;
c = anum + bnum;
end
endmodule
The purpose of summation.v is to take two decimal input from summationtest.v, process the decimal values and send the result c back to the output (summationtest.v) again.
Code for summationtest.v:
module summationtest;
reg[3:0] a;
reg[3:0] b;
wire[7:0] c;
summation a1(a, b, c);
initial begin
a = 3;
b = 4;
$display("%d", c);
end
endmodule
When the program runs, no value of a and b passes from summationtest.v to summation.v; as a result, no value is assigned to c.
That is not the proper way to model combinational logic. You have an incomplete sensitivity list and you should not use nonblocking assignments (<=). You should use $monitor instead of display to view all signal changes.
Here is a much simpler way to code your adder:
module summation(a, b, c);
input [3:0] a;
input [3:0] b;
output [7:0] c;
assign c = a + b;
endmodule
module summationtest;
reg[3:0] a;
reg[3:0] b;
wire[7:0] c;
summation a1(a, b, c);
initial begin
$monitor("%d", c);
a = 3;
b = 4;
end
endmodule
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.
Binary addition on A and B and outputs it along with proper carry bit. I'm not sure how to implement the carry bit
A and B are 4 bit inputs
C is 1 bit output that is used for the carry bit
module addop(C , O , A , B);
input [3:0] A;
input [3:0] B;
output [3:0] O;
output C;
assign C1 = A[0] + B[0];
assign C2 = A[0] + B[1];
endmodule
You may want to use a concatenation operator {} here.
module addop(C, O, A, B);
input [3:0] A;
input [3:0] B;
output [3:0] O;
output C;
assign {C, O} = A + B;
endmodule
Your synthesis tool will be responsible in converting them
into logic gates.
See this question which is related to concatenation:
What do curly braces mean in Verilog?