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}};
Related
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
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 #*
In preparation for an exam, I want to go over some Verilog Code and I'm using https://www.jdoodle.com/ as a compiler. But for some reason the cases throw errors.
jdoodle.v:20: syntax error
jdoodle.v:20: error: Incomprehensible case expression.
jdoodle.v:21: syntax error
jdoodle.v:21: error: Incomprehensible case expression.
jdoodle.v:22: syntax error
jdoodle.v:22: error: Incomprehensible case expression.
jdoodle.v:23: syntax error
jdoodle.v:23: error: Incomprehensible case expression.
jdoodle.v:24: syntax error
jdoodle.v:24: error: Incomprehensible case expression.
module ALU (
input wire [2:0]OPCODE,
input wire [31:0]A,
B,
output reg [31:0]RESULT
);
`define ADD 0;
`define SUB 1;
`define MULT 2;
`define DIV 3;
`define MOD 4;
function [31:0] calculate (
input [31:0] A,
input [31:0] B,
input [2:0] OPCODE
);
case (OPCODE)
`ADD: calculate = A + B;
`SUB: calculate = A - B;
`MULT: calculate = A * B;
`DIV: calculate = A / B;
`MOD: calculate = A % B;
endcase
endfunction
always #(A or B or OPCODE)
RESULT = calculate(A, B, OPCODE);
endmodule
Would appreciate any kind of help.
Remove the semicolon at the end your defines.
You are defining ADD as 0;
Thus your code becomes:
case (OPCODE)
0; : calculate = A + B;
1; : calculate = A - B;
2; : calculate = A * B;
3; : calculate = A / B;
4; : calculate = A % B;
endcase
I just started learning Verilog this semester and I just got stuck on a task to create a Verilog module that has uses multiplexed to do different operations on 2 8-bit inputs. The below is the Verilog code that I wrote, I am getting several errors that I do not understand. Please help!
module eightbit_palu( input[7:0] a, input[7:0] b, input[1:0] sel, output[7:0] f, output ovf );
reg f, ovf;
always # (a , b, sel)
case (sel)
0 : f = a + b;
ovf = f[8]^f[7];
1 : f[0] = ~b[0];
f[1] = ~b[1];
f[2] = ~b[2];
f[3] = ~b[3];
f[4] = ~b[4];
f[5] = ~b[5];
f[6] = ~b[6];
f[7] = ~b[7];
2 : f[0] = a[0]&b[0]; f[1] = a[1]&b[1]; f[2] = a[2]&b[2]; f[3] = a[3]&b[3]; f[4] = a[4]&b[4];
f[5] = a[5]&b[5]; f[6] = a[6]&b[6]; f[7] = a[7]&b[7];
3 : f[0] = a[0]|b[0]; f[1] = a[1]|b[1]; f[2] = a[2]|b[2]; f[3] = a[3]|b[3]; f[4] = a[4]|b[4];
f[5] = a[5]|b[5]; f[6] = a[6]|b[6]; f[7] = a[7]|b[7];
endcase
endmodule
The errors being displayed by the simulators are:
8: syntax error
10: error: Incomprehensible case expression.
11: syntax error
19: error: Incomprehensible case expression.
19: syntax error
22: error: Incomprehensible case expression.
22: syntax error
Two major issues:
First, with Verilog, a series of procedural statements must be surrounded by the begin-end keywords
always # (*) begin
case (sel)
0 : begin
f = a + b;
ovf = f[8]^f[7];
end
1 : begin
f[0] = ~b[0];
...
end
...
endcase
end
Second, you are mixing ANSI and non-ANSI style headers my declaring f and ovf as wires in the portlist, then single bit reg inside. Pick one syntax:
ANSI: (Note the output reg)
module eightbit_palu( input[7:0] a, input[7:0] b,
input[1:0] sel, output reg [7:0] f, output reg ovf );
Non-ANSI:
module eightbit_palu( a, b, sel, f, ovf );
input[7:0] a;
input[7:0] b;
input[1:0] sel;
output [7:0] f;
output ovf;
reg [7:0] f;
reg ovf;
Suggested improvements:
always # (a , b, sel) to always #*
Since 2001, Verilog supports wild card sensitivity lists for combinational logic blocks. This helps prevent agents RTL vs synthesized-gates behavioral mismatches, and is the preferred coding style in Verilog. Defining the sensitivity manually is only required when strictly following the 1995 version of the standard.
you can simplfiy conditions 1, 2, and 3 to bitwise operations: (eg. 1 : f = ~b; , 2 : f = a & b;, 3 : f = a | b;). For-loops are another options
ovf is an inferred latch. Latches are not necessary bad, but you need to know what you are doing with them. It is recommended you use then only when necessary. What is inferred latch and how it is created when it is missing else statement in if condition.can anybody explain briefly?
I am working on an assignment and am a little lost and don't really know how to get started. I need to implement the following flags in a 32Bit ALU:
• Z ("Zero"): Set to 1 ("True") if the result of the operation is zero
• N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number
• O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.
Additionally, a comparison function that compares input a to input b and then set one of three flags:
• LT if input a is less than input b
• GT if input a is greater than input b
• EQ if input a is equal to input b
I need to modify this ALU to include the three flags and comparison outputs then change the test bench to test for all of these modifications.
This was all the information I received for this assignment and there is no textbook or any other resources really. It's an online class, and I cannot get a response from my instructor. So I am a little confused as to how to get started. I am still a total newbie when it comes to digital logic so please bear with me. I just need some help understanding how these flags and comparison works. If any one can explain this a little better to me as far as how they work and what they do, and possibly how I would implement them into the ALU and testbench, I would really appreciate it.
I don't expect anyone to do my assignment, I really just need help understanding it.
ALU
module alu32 (a, b, out, sel);
input [31:0] a, b;
input [3:0] sel;
output [31:0] out,
reg [31:0] out;
//Code starts here
always #(a, b, sel)
begin
case (sel)
//Arithmetic Functions
0 : out <= a + b;
1 : out <= a - b;
2 : out <= b - a;
3 : out <= a * b;
4 : out <= a / b;
5 : out <= b % a;
//Bit-wise Logic Functions
6 : out <= ~a; //Not
7 : out <= a & b; //And
8 : out <= a | b; //Or
9 : out <= a ^ b; //XOR
10 : out <= a ^~ b; //XNOR
//Logic Functions
11 : out <= !a;
12 : out <= a && b;
13 : out <= a || b;
default: out <= a + b;
endcase
end
endmodule
ALU Testbench
module alu32_tb();
reg [31:0] a, b;
reg [3:0] sel;
wire [31:0] out;
initial begin
$monitor("sel=%d a=%d b=%d out=%d", sel,a,b,out);
//Fundamental tests - all a+b
#0 sel=4'd0; a = 8'd0; b = 8'd0;
#1 sel=4'd0; a = 8'd0; b = 8'd25;
#1 sel=4'd0; a = 8'd37; b = 8'd0;
#1 sel=4'd0; a = 8'd45; b = 8'd75;
//Arithmetic
#1 sel=4'd1; a = 8'd120; b = 8'd25; //a-b
#1 sel=4'd2; a = 8'd30; b = 8'd120; //b-a
#1 sel=4'd3; a = 8'd75; b = 8'd3; //a*b
#1 sel=4'd4; a = 8'd75; b = 8'd3; //a/b
#1 sel=4'd5; a = 8'd74; b = 8'd3; //a%b
//Bit-wise Logic Functions
#1 sel=4'd6; a = 8'd31; //Not
#1 sel=4'd7; a = 8'd31; b = 8'd31; //And
#1 sel=4'd8; a = 8'd30; b = 8'd1; //Or
#1 sel=4'd9; a = 8'd30; b = 8'd1; //XOR
#1 sel=4'd10; a = 8'd30; b = 8'd1; //XNOR
//Logic Functions
#1 sel=4'd11; a = 8'd25; //Not
#1 sel=4'd12; a = 8'd30; b = 8'd0; //And
#1 sel=4'd13; a = 8'd0; b = 8'd30; //Or
#1 $finish;
end
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel));
endmodule
You can add these flag outputs to the design. Like the following. Simply connect them in testbench.
// In design:
output zero;
output overflow;
output negative;
// In testbench:
wire zero,overflow,negative;
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel), .zero(zero), .overflow(overflow),.negative(negative));
For logic part, you can do it with continuous assignments. You may need to add some logic for using these flags only during certain values of sel.
Z ("Zero"): Set to 1 ("True") if the result of the operation is zero
So, we can have condition like all the bits of out must be zero. This can be done in many other ways.
// Bit wise OR-ing on out
assign zero = ~(|out);
O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.
According to this description and the code shown, you simply want carry flag here.That is, a signed extension of addition operation. Refer to this page on WikiPedia for overflow condition.
But, Overflow condition is not the same as the carry bit. Overflow represents data loss while carry represents a bit used for calculation in next stage.
So, doing something like following may be useful:
// Extend the result for capturing carry bit
// Simply use this bit if you want result > bus width
{carry,out} <= a+b;
// overflow in signed arithmetic:
assign overflow = ({carry,out[31]} == 2'b01);
N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number
Again this is simply the MSB of the out register. But, the underflow condition is entirely a different thing.
// Depending on sel, subtraction must be performed here
assign negative = (out[31] == 1 && (sel == 1 || sel == 2));
Also, simple condition like assign lt = (a<b) ? 1 : 0; and others can detect the input LT, GT and EQ conditions.
Refer the answer here for the overflow/underflow flag understanding. Overflow-Carry link may also be useful.
Refer Carryout-Overflow, ALU in Verilog and ALU PDF for further information about ALU implementation.