I have a 8-bit ALU unit in verilog that can do addition, invert, etc. This single unit is tested and performs correctly. When I combine 4 of these to make a bigger ALU every output is correct except when I choose the addition operation it comes out as
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010101, basically the first alu does the work right then the output from the second is xxxxxxxx as is the third and fourth. This is really frustrating!!
the 8 bit module( it would be nice to point if this model is behavioral or structural model i go for the former!)
module alu_8bit(
output reg [7:0] out,
output reg cout,g,e,
input [7:0] A,B,
input cin,
input [2:0] S
);
//used functions
parameter BUF_A = 3'b000;
parameter NOT_A = 3'b001;
parameter ADD = 3'b010;
parameter OR = 3'b011;
parameter AND = 3'b100;
parameter NOT_B = 3'b101;
parameter BUF_B = 3'b110;
parameter LOW = 3'b111;
always #(A or B or S) begin
//Comparator
g = A>B;
e = A==B;
//Other selective functions
case(S)
BUF_A: out = A;
NOT_A: out = ~A;
ADD: {cout,out} = A+B+cin;
OR: out = A | B;
AND: out = A & B;
NOT_B: out = ~B;
BUF_B: out = B;
LOW: out = {8{1'b0}};
endcase
end
endmodule
Here is the code of the bigger one:
module alu_32bit(
output [31:0] out,
output cout,g,e,
input [31:0] A,B,
input cin,
input [2:0] S
);
wire e1,e2,e3,e4;
wire g1,g2,g3,g4;
alu_8bit ALU1(out[7:0],cin2,g1,e1,A[7:0],B[7:0],cin,S);
alu_8bit ALU2(out[15:8],cin3,g2,e2,A[15:8],B[15:8],cin2,S);
alu_8bit ALU3(out[23:16],cin4,g3,e3,A[23:16],B[23:16],cin3,S);
alu_8bit ALU4(out[31:24],cout,g4,e4,A[31:24],B[31:24],cin4,S);
assign g = g4 | (e4 & g3) |(e4 & e3 & g2) | (e4& e3 & e2 & g1);
assign e = e4 & e3 & e2 & e1;
endmodule
Can any one give some help?! if you need more info just tell me.
Edited:
Waveform pic clearly input comes in correct but output not
The dataflow diagram shows that ALU1 output is just fine
Your sensitivity list for the main part of the ALU doesn't include cin.
Related
For a lab in a digital design course, I am designing a partial ALU. I have defined its operations and am required to use a casez statement to govern which function (either addition of a & b w/ overflow checking, bitwise inversion of b, a AND b, and a OR b) is selected by the four 2-bit combos of sel:
module eightbit_palu(input wire[7:0] a, b,
input wire[1:0] sel,
output wire[7:0] f,
output wire ovf);
wire[7:0] sum, bitInv, bitAnd, bitOr;
wire sumOvf;
assign sum = a + b;
assign sumOvf = (a+b>127)||(a+b<-128) ? 1 : 0;
assign bitInv = !b;
assign bitAnd = a & b;
assign bitOr = a | b;
always #(a or b or sel) begin
casez(sel)
2'b00: f = sum; ovf = sumOvf;
2'b01: f = bitInv; ovf = 0;
2'b10: f = bitAnd; ovf = 0;
2'b11: f = bitOr; ovf = 0;
endcase
end
endmodule
I have embedded the casez statement within an always #, but I am getting a syntax error that I believe might be due to the outputs being wires. I am not sure how to work around that seemingly simple issue.
I tried turning the variables declared before the assign statements into regs, but then there was a problem converting them to wires. I would really appreciate some insight as to how Verilog works — unfortunately my professor is teaching in SystemVerilog, yet our labs are required to be in Verilog.
Yes, you should change your output wires to reg since you are making procedural assignments to them (inside an always block).
The other error is that you need to add begin/end keywords around multiple statements in each case item. Here is code that compiles cleanly for me:
module eightbit_palu(input wire[7:0] a, b,
input wire[1:0] sel,
output reg [7:0] f,
output reg ovf);
wire[7:0] sum, bitInv, bitAnd, bitOr;
wire sumOvf;
assign sum = a + b;
assign sumOvf = (a+b>127)||(a+b<-128) ? 1 : 0;
assign bitInv = !b;
assign bitAnd = a & b;
assign bitOr = a | b;
always #(a or b or sel) begin
casez(sel)
2'b00: begin f = sum; ovf = sumOvf; end
2'b01: begin f = bitInv; ovf = 0; end
2'b10: begin f = bitAnd; ovf = 0; end
2'b11: begin f = bitOr; ovf = 0; end
endcase
end
endmodule
You also have a problem with this line:
always #(a or b or sel) begin
A sensitivity list should include only signals on the RHS of assignments within the block. Your list incorrectly includes a and b, and it misses others like sum. You should use an implicit sensitivity list which automatically includes the appropriate signals.
always #*
I am having some trouble displaying the result of my 8 bit adder verilog
module Adder(a,b,cin,s,co);
input [7:0]a;
input [7:0]b;
output [7:0]s;
output co;
wire [6:0] u;
input cin;
Carry c1(a[0],b[0],cin,s[0],u[0]);
Carry c2(a[1],b[1],u[0],s[1],u[1]);
Carry c3(a[2],b[2],u[1],s[2],u[2]);
Carry c4(a[3],b[3],u[2],s[3],u[3]);
Carry c5(a[4],b[4],u[3],s[4],u[4]);
Carry c6(a[5],b[5],u[4],s[5],u[5]);
Carry c7(a[6],b[6],u[5],s[6],u[6]);
Carry c8(a[7],b[7],u[6],s[7],co);
endmodule
module Carry(a,b,cin,s,co);
input wire a;
input wire b;
input wire cin;
output wire co;
output wire s;
assign co = (a & b) | (b & cin) | (a & cin);
assign s = (~a & ~b & cin) | (~a & b & ~cin) | (a & ~b & ~cin)| (a & b & cin);
endmodule
module testbench;
reg [7:0]a;
reg [7:0]b;
reg cin;
wire [7:0]s;
wire co;
Adder add(a, b, cin, s, co);
initial begin
$dumpfile("result.vcd");
$dumpvars;
a <= 00000010; b <= 00000010; cin <= 0;
#5
$monitor("time=%4d: %b + %b + %b: sum = %b, carry = %b\n",$time,a,b,cin,s,co);
end
endmodule
although it adds everything correctly, it's not adding the numbers I originally wanted.
time= 5: 00001010 + 00001010 + 0: sum = 00010100, carry = 0
How can i fix it so that instead of adding those numbers, it would add the numbers i'd want.
(a = 00000010; b = 00000010; cin = 0;)
I already tried changing the numbers around and it does not work except when they're 00000001.
By default, Verilog interprets a numerical literal value as decimal. The value 00000010 is decimal 10. The $monitor statement uses %b, and it correctly displays the decimal value 10 as 1010. The sum of 10 + 10 is 20 (decimal), which is correctly displayed as 10100 (binary).
For Verilog to interpret 00000010 as binary, you need to specify the base as 'b00000010:
a <= 'b00000010; b <= 'b00000010; cin <= 0;
Refer to IEEE Std 1800-2012, section 5.7.1 Integer literal constants.
The reason that 1 + 1 works is that 1 is the special case where 00000001 (decimal) is the same value as 'b00000001 (binary).
I'm new to Verilog programming. I'm trying to put together an 8-bit Carry Lookahead Adder as a step toward building a 64-bit CLA. Basically, the way I implemented it is I use 2 4-bit CLA "blocks" to create the 8-bit CLA. I'll provide my code, then an explanation of the problem I'm having.
Code below:
// 4-BIT CLA CODE
module CLA4Bit(A, B, carryIn, carryOut, PG, GG, Sum);
input[3:0] A, B;
input carryIn;
output carryOut;
output PG;
output GG;
output[3:0] Sum;
wire[3:0] G, P, C;
assign G = A & B;
assign P = A ^ B;
assign Sum = P ^ C;
assign C[0] = carryIn;
assign C[1] = G[0] | (P[0] & C[0]);
assign C[2] = G[1] | (P[1] & G[0]) | (P[1] & P[0] & C[0]);
assign C[3] = G[2] | (P[2] & G[1]) | (P[2] & P[1] & G[0]) | (P[2] & P[1] & P[0] & C[0]);
assign PG = P[3] & P[2] & P[1] & P[0];
assign GG = G[3] | (P[3] & G[2]) | (P[3] & P[2] & G[1]) | (P[3] & P[2] & P[1] & G[0]);
endmodule
// 8-BIT CLA CODE BELOW
module CLA8Bit(A, B, carryIn, carryOut, Sum);
// 8-bit wire for the inputs A and B
input[7:0] A, B;
// Wire for the ORIGINAL carry-in
input carryIn;
// Wire for the carryOut
output carryOut;
// Wire that carries the Sum of this CLA
output[7:0] Sum;
// Wires for the propagate of the first 4-bit block (p3)
// and the second (p7)
wire p3, p7;
// Wires for the generate of the first 4-bit block (g3)
// and the second (g7)
wire g3, g7;
// Wires for the carry of the first block (c3) and the
// second (c7)
wire c3, c7;
// The two 4-bit CLA blocks that make up the 8-bit CLA
CLA4Bit block1(A[3:0], B[3:0], carryIn, c3, p3, g3, Sum[3:0]);
CLA4Bit block2(A[7:4], B[7:4], c3, c7, p7, g7, Sum[7:4]);
endmodule
I wrote a basic testbench to test my code:
module CLA_TB();
// TEST THE 8-BIT CLA
// Inputs
reg[7:0] A;
reg[7:0] B;
reg carryIn;
// Outputs
wire carryOut;
wire[7:0] Sum;
wire PG;
wire GG;
// Instantiate the 8-bit CLA
CLA8Bit CLA8BitDUT (
.A(A),
.B(B),
.carryIn(carryIn),
.carryOut(carryOut),
.Sum(Sum)
);
// Initialize the testbench signals
initial
begin
// Start with the carryIn set to 0
assign carryIn = 0;
// The standard first test. Set
// A = b0000 0001 and B = b0000 0001
// Answer should be Sum = b0000 0010
assign A = 8'b00000001;
assign B = 8'b00000001;
#20
// Next, set A = b0001 1011 and
// B = b1101 0111. Answer should
// be Sum = b1111 0010 = hF2.
assign A = 8'b00011011;
assign B = 8'b11010111;
#20
// Finally, try setting the carryIn
// to 1 and then test A = b0111 1011
// and B = b1101 0011. Answer should be
// Sum = 0100 1111 w/ overflow carry
assign carryIn = 1'b1;
assign A = 8'b01111011;
assign B = 8'b11010011;
#20
$finish;
end
endmodule
So the problem is, in my simulations of the testbench (I use ModelSim), the first 4 bits of the Sum (which correspond to the first 4-bit CLA instance in the 8-bit CLA module) are given as X in the Wave page. The second 4 bits add just fine, though.
After doing some research, I found out that X's are displayed in Verilog when a wire has more than one driver (source of the signal?). However, I don't see any place where I send more than one signal to my first 4-Bit CLA instance in the 8-Bit CLA module. Also, if something like that were the cause, then I don't know why it wouldn't happen to the second set of 4 bits as well, since both the 4-bit CLAs are set up very similarly.
Why is this happening?
X's are displayed in Verilog when a wire has more than one driver
That is true but it is only part of the story. There are other cases which produce X'es:
If a reg is not given a value it will be X.
If a Z is used in an expression it will produce an X .
Your waveform has some obvious 'Z' (blue) lines one it.
If you following the signals back to where they originate: your 4-bit adder never assigns a value to carryOut.
Then you make the same error in CLA8Bit.
If you see a 'Z' in a simulation: jump on it! 99.9% of the time you have an wire which has not been given a value!
I'm trying to implement in hardware (using Verilog) the function described by this pseudo code:
if A then
output [63:0] = b[63:56], c[X-1:0], b[Y-1:0]
else output [63:0] = c[X-1:0], b[Y-1:0]
A is a boolean value, while output, b and c are 64 bits long.
X and Y change at runtime so they can't be Verilog variables.
The value of X changes with A:
if A then
X = 56 - Y
else X = 63 - Y
while Y is read from a 6 bit register so it can be any number from 0 to 63.
So for both cases of A all 64 bits of output will be assigned.
I know bit masking and mux selection with A is required but it is a bit complex and I can't quite get a clear picture on how to implement this in Verilog.
The runtime dependent bit selection can be implemented with shift(<<), variable bit selection(a[k+:8]), a smartly designed for loop(a[i] = condition ? b:c) or a completely expressed case. And all of them should have similar synthesis result. Based on experience, the case implementation should have best area performance.
Here is an example (with testbench) for shift implementation:
`timescale 1ns/1ps
module example(
input A,
input [5:0] Y,
input [63:0] b, c,
output [63:0] result
);
reg [63:0] o_a, o_abar;
assign result = A ? o_a : o_abar;
wire [5:0] X = A ? (56-Y) : (63-Y);
reg [63:0] c1_tmp, b1_tmp, mask;
always#(*)begin
c1_tmp = (c << Y) & {8'd0, {56{1'b1}}};
mask = (({64{1'b1}}>>X) << Y) | ({64{1'b1}} >> (64-Y));
b1_tmp = mask & b;
o_a = c1_tmp | b1_tmp;
end
reg [63:0] c2_tmp, b2_tmp;
always#(*)begin
c2_tmp = c << Y;
b2_tmp = b & ({64{1'b1}} >> Y);
o_abar = c2_tmp | b2_tmp;
end
endmodule
module test;
reg A;
reg [5:0] Y;
reg [63:0] b, c;
wire [63:0] result;
example ex(.A(A), .Y(Y), .b(b), .c(c), .result(result));
initial begin
A = 1;
Y = 6;
c = -1;
b = 0;
#10
$display("%b", result);
$finish;
end
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.