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?
Related
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 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
Here is my code:
module Adder_8b_df (A, B, opcode, S, Cout);
input [7:0] A, B;
input [3:0] opcode;
output [7:0] S;
output Cout;
wire [8:0] tmp;
assign tmp = (opcode[0] == 0) ? (A + B) : (A + (~B + 8'b1));
assign S = tmp [7:0];
assign Cout = tmp [8];
endmodule
Addition is performed when the first bit of the opcode is a 0, otherwise subtraction through two's complement is performed. Looking at the waveform, both operations perform correctly. However there is only a carry out (Cout) when addition is performed.
For instance when trying to subtract 0110_0011 from 1100_0110. The operation should be 1100_0110 + 1001_1101 which results in an overflow. The waveform still shows the correct answer: 0110_0011. But Cout is low not high. Any ideas why this is the case?
Edit:
I think this is happening because "~B" is extended to 9 bits (like tmp) and then it is overflows to bit 10 which you don't have.
This seems to have solved the problem:
module Adder_8b_df (A, B, opcode, S, Cout);
input [7:0] A, B;
input [3:0] opcode;
output [7:0] S;
output Cout;
wire [8:0] tmp;
wire [8:0] twos_comp;
assign twos_comp = (opcode[0] == 1) ? (~B + 8'b1) : 0;
assign tmp = (opcode[0] == 0) ? (A + B) : (A + (twos_comp [7:0]));
assign S = tmp [7:0];
or(Cout, twos_comp[8], tmp[8]);
endmodule
I'm trying to make an arithmetic logic unit in verilog and I received the following error when I tried to simulate in ISim Simulator (No errors reported at Behavioral Check Syntax):
ERROR:Simulator:754 - Signal EXCEPTION_ACCESS_VIOLATION received
Here is the code:
module alu(
input [3:0] right,
input [3:0] left,
input [2:0] sel,
input CarryIn,
output reg CarryOut,
output reg [3:0] out
);
function [3:0] add;
input [3:0] a;
input [3:0] b;
input CarryIn;
assign add = a + b + CarryIn;
endfunction
function [3:0] substract;
input [3:0] a;
input [3:0] b;
input CarryIn;
assign subtract = a - b + (~CarryIn);
endfunction
function [3:0] AND;
input [3:0] a;
input [3:0] b;
assign AND = {1'b0 , a & b};
endfunction
function [3:0] OR;
input [3:0] a;
input [3:0] b;
assign OR = {1'b0 , a | b};
endfunction
function [3:0] XOR;
input [3:0] a;
input [3:0] b;
assign XOR = {1'b0 , a ^ b};
endfunction
function [3:0] increment;
input [3:0] a;
assign increment = a + 1;
endfunction
function [3:0] left_shift;
input [3:0] a;
assign left_shift = a << 1;
endfunction
function [3:0] right_shift;
input [3:0] a;
assign right_shift = a >> 1;
endfunction
always # (left or right or sel) begin
case (sel)
0 : {CarryOut , out} = add(left,right,CarryIn);
1 : {CarryOut , out} = substract(left,right,CarryIn);
2 : {CarryOut , out} = AND(left,right);
3 : {CarryOut , out} = OR(left,right);
4 : {CarryOut , out} = XOR(left,right) ;
5 : {CarryOut , out} = increment(left);
6 : begin
CarryOut = left[3];
out = left_shift(left);
end
7 : begin
CarryOut = left[0];
out = right_shift(left);
end
default : {CarryOut , out} = {1'b0,left};
endcase
end
endmodule
Any ideas ?
Remove the keyword assign from all your functions. assign statements are for continuous assignments that should only be declared in a module; not a task, function, initial or always.
There is a typo too. A couple places you have "substract" and should be "subtract".
You are also missing CarryIn from your sensitivity list. If your sensitivity list is not complete it will infer complex latching logic. Better yet, switch to a IEEE 1364-2001 coding style and use always #(*) or always #* instead of always # (left or right or sel or CarryIn). They auto construct the sensitivity list for combinational logic.
One of the reasons for happening this is that the simulator does not understand a syntax.
I had run into similar problem in VIVADO for a silly mistake while writing a verilog syntax. For a concatenation in verilog, mistakenly i used ":" instead of ",". That caused the same problem. To find out exactly which module is causing the problem it is good to look at the tcl console message. The module causing the problem is simply after compiling which module this message shows.
This is silly but sometimes it may take a lot of time to figure out.
These two modules seem to be interchangeable. How does their behavior differ?
module Add_half (sum, c_out, a, b);
input a, b;
output reg c_out;
output reg sum;
always#(a, b)
begin
sum = a ^ b;
c_out = a & b;
end
endmodule
module Add_half (sum, c_out, a, b);
input a, b;
output c_out, sum;
assign sum = a ^ b;
assign c_out = a & b;
endmodule
There are subtle differences in event scheduling, which may result in different behavior at time 0.
When a or b are initialized to a certain non-X value at time zero, the always block may not see that as a change, and hence it may not be triggered. Consequently, the outputs may be inconsistent with the inputs.
In contrast, the outputs of continuous assignments will always be consistent with their inputs.