This is my Verilog code for the procedural modeling of the 4 Demux:
//4 Bit demux in Gate level
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
always#(*)
begin
case(Sel)
1'b0: begin
A = ~Sel&I;
end
1'b1: begin
B = Sel&I;
end
default: begin
end
endcase
end
endmodule
And I input to receive this error:
eos$ ncverilog +access+r HW3_PM.v HW2_Demux4_tb.v +gui
ncverilog: 09.20-s019: (c) Copyright 1995-2010 Cadence Design Systems, Inc.
file: HW3_PM.v
A = ~Sel&I;
|
ncvlog: *E,WANOTL (HW3_PM.v,8|6): A net is not a legal lvalue in this context [9.3.1(IEEE)].
B = Sel&I;
|
ncvlog: *E,WANOTL (HW3_PM.v,11|6): A net is not a legal lvalue in this context [9.3.1(IEEE)].
module worklib.HW3_PM:v
errors: 2, warnings: 0
file: HW2_Demux4_tb.v
ncverilog: *E,VLGERR: An error occurred during parsing.
Review the log file for errors with the code *E and fix
those identified problems to proceed. Exiting with code (status 1).
I've tried changing and adding A and B as both reg and wire but it causes higher errors. I tried changing to posedge of the clock and get a different error. Your help is appreciated.
NEW:
Changed code:
//4 Bit demux in Gate level
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
reg A, B;
always#(*)
begin
case(Sel)
1'b0: begin
A = ~Sel&I;
end
1'b1: begin
B = Sel&I;
end
default: begin
end
endcase
end
endmodule
Received error:
file: HW3_PM.v
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
|
ncvlog: *E,BADIOO (HW3_PM.v,2|53): input/output/inout 'A' declared as vector, then redeclared as scalar [3.3(IEEE)].
reg A, B;
|
ncvlog: *W,ILLPDX (HW3_PM.v,4|5): Multiple declarations for a port not allowed in module with ANSI list of port declarations (port 'A') [12.3.4(IEEE-2001)].
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
|
ncvlog: *E,BADIOO (HW3_PM.v,2|69): input/output/inout 'B' declared as vector, then redeclared as scalar [3.3(IEEE)].
reg A, B;
|
ncvlog: *W,ILLPDX (HW3_PM.v,4|8): Multiple declarations for a port not allowed in module with ANSI list of port declarations (port 'B') [12.3.4(IEEE-2001)].
module worklib.HW3_PM:v
errors: 2, warnings: 2
file: HW2_Demux4_tb.v
ncverilog: *E,VLGERR: An error occurred during parsing.
Review the log file for errors with the code *E and fix
those identified problems to proceed. Exiting with code (status 1)
module HW3_PM(
input [3:0] I,
input Sel,
output reg [3:0] A,
output reg [3:0] B
);
always#(*)
begin
if(~Sel) begin
A = I;
B = 0;
end else begin
A = 0;
B = I;
end
end
endmodule
or
module HW3_PM(
input [3:0] I,
input Sel,
output wire [3:0] A,
output wire [3:0] B
);
assign A = ~sel&I;
assign B = sel&I;
endmodule
or
module HW3_PM(
input [3:0] I,
input Sel,
output reg [3:0] A,
output reg [3:0] B
);
always#(*)
begin
case(Sel)
0: begin
A = I;
B = 0;
end
1: begin
A = 0;
B = I;
end
endcase
end
endmodule
or
module HW3_PM(input [3:0] I,input Sel,output wire [3:0] A, output wire [3:0] B);
and selA[3:0] (A, ~sel, I);
and selB[3:0] (B, sel, I);
endmodule
Related
I am trying to do a 4-bit adder subtractor in Verilog code, but there is some kind of problem in my code that I couldn't figure out. I'm not sure if the testbench or the Verilog is wrong. Can someone please help me with it? Also, when I try to simulate it, it gives Loading Errors.
My Verilog code:
module addsubparameter (A, B, OP, C_out, Sum);
input A,B;
input OP;
output C_out;
output Sum;
wire C_out, Sum;
reg assigning;
always#(OP)
begin
if (OP == 0)
assigning = A + B + OP;
else
assigning = A + (~B + 1) + OP;
end
assign {C_out, Sum} = assigning;
endmodule
module adder (a, b, op, cout, sum);
parameter size = 4 ;
input [3:0] a, b;
output [3:0] sum;
input op;
output cout;
wire [2:0] c;
genvar i;
generate
for (i = 0; i < size; i = i + 1) begin: adder
if (i == 0)
addsubparameter (a[i], b[i], op, sum[i], c[i]);
else if (i == 3)
addsubparameter (a[i], b[i], c[i-1], cout, sum[i]);
else
addsubparameter (a[i], b[i], c[i-1], sum[i], c[i]);
end
endgenerate
endmodule
And this is my testbench:
module addsub_tb();
reg [3:0] a;
reg [3:0] b;
reg op;
wire [3:0] sum;
wire cout;
adder DUT (a,b,op,sum,cout);
initial begin
a = 4'b1010; b = 4'b1100; op = 1'b0; #100;
a = 4'b1111; b = 4'b1011; op = 1'b1; #100;
a = 4'b1010; b = 4'b1010; op = 1'b0; #100;
end
endmodule
Your simulator should generate error and/or warning messages because you have syntax errors. If it does not, sign up for a free account on edaplayground, where you will have access to multiple simulators which will produce helpful messages.
You need to add instance names. For example, I added i0 in the line below:
addsubparameter i0 (a[i], b[i], op, sum[i], c[i]);
You have port connection width mismatches, and these indicate connection errors. This is a common type of error when you use connections by position. You mistakenly connected the sum signal to the cout port, and vice versa. You should use connections by name instead. For example, change:
adder DUT (a,b,op,sum,cout);
to:
adder dut (
.a (a),
.b (b),
.op (op),
.cout (cout),
.sum (sum)
);
Use this coding style for all your instances.
You won't get a simulation warning, but you might get a synthesis warnings about an incomplete sensitivity list. Change:
always#(OP)
to:
always #*
I'm trying to build an 8-bit multiplier in Verilog, but I keep running in to this weird error when I go to simulate my module's test bench. It says:
Too many port connections. Expected 8, found 9
This doesn't really make any sense seeing as how both the module AND the test bench have 9 variables listed. Any help will be much appreciated!
Multiplier Module
module my8bitmultiplier (output [15:0] O, output Done, Cout, input [7:0] A, B, input Load, Clk, Reset, Cin);
reg Done;
reg [1:0] state;
reg [7:0] A_reg, B_reg;
reg [15:0] A_temp, B_temp, O_temp, O_reg;
my16bitadder Adding(O_temp, Cout,A_temp,B_temp, Cin);
always#(posedge Clk)
begin
if(Reset) assign state = {2'b00};
case(state)
0:
if(Load)
begin
A_reg = A;
B_reg = B;
O_reg = A_reg;
state = 1;
end
1:
begin
A_temp = A_reg;
B_temp = O_reg;
B_reg = B_reg - 1;
state = 2;
end
2:
begin
O_reg = O_temp;
if(B_temp)
begin
state = 1;
end
else
begin
state = 3;
Done = 1'b1;
end
end
3:
begin
Done = 1'b0;
state = 0;
end
endcase
end
endmodule
Testbench
module my8bitmultiplier_tb;
reg Load, Clk, Reset, Cin;
reg [7:0] A, B;
wire [15:0] O;
wire Done, Cout;
my8bitmultiplier dut(O, Done, Cout, A, B, Load, Clk, Reset, Cin);
always #5 Clk = ~Clk;
initial
begin
A = 8'b10;
B = 8'b10;
Load = 1;
Cin = 0;
#10 Load = 0;
#3000 A = 8'd100;
#3000 B = 8'd100;
#3000 Load = 1;
#3010 Load = 0;
#6000 A = 8'd150;
#6000 B = 8'd150;
#6000 Load = 1;
#6000 Load = 0;
begin
$display ($time,"A= %d B= %d O=%d ", A, B, O);
end
#10000 $finish;
end
endmodule
When I run you code on another simulator, I get a more helpful warning message:
reg Done;
|
xmvlog: *W,ILLPDX : Multiple declarations for a port not allowed in module with ANSI list of port declarations (port 'Done') [12.3.4(IEEE-2001)].
The warning goes away when I delete this line:
reg Done;
and change:
module my8bitmultiplier (output [15:0] O, output Done, Cout, input [7:0] A, B, input Load, Clk, Reset, Cin);
to:
module my8bitmultiplier (output [15:0] O, output reg Done, Cout, input [7:0] A, B, input Load, Clk, Reset, Cin);
Perhaps that solves your problem on modelsim. You can also try your code on different simulators on edaplayground. You will sometimes get more helpful messages.
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 decided to start playing around with Verilog this weekend. I am really new to this and don't entirely understand what I am doing. I copied this adder code out of a PDF tutorial. The issue is that the tutorial does not give any test code to run it with. I tried to write my own but the output I am getting is zzzz. I am thinking that maybe it is trying to produce the output before the addition function has finished executing.
module addbit(a, b, ci, sum, co);
input a, b, ci;
output sum, co;
wire a, b, ci, sum, co;
assign {co, sum} = a + b + ci;
endmodule
module adder(result, carry, r1, r2, ci);
input [3:0] r1;
input [3:0] r2;
input ci;
output [3:0] result;
output carry;
wire [3:0] r1;
wire [3:0] r2;
wire ci;
wire [3:0] result;
wire carry;
wire c1, c2, c3;
addbit u0(r1[0], r2[0], ci, result[0], c1);
addbit u1(r1[1], r2[1], c1, result[0], c2);
addbit u2(r1[2], r2[2], c2, result[0], c3);
addbit u3(r1[3], r2[3], c3, result[0], carry);
endmodule
module test();
wire [3:0] a = 4'b1000;
wire [3:0] b = 4'b0100;
wire [3:0] result;
wire carry = 0;
wire ocarry;
adder x(result, ocarry, a, b, carry);
initial begin
$display("%b", result);
end
endmodule
the output I am getting is zzzz
The reason why you are getting an output zzzz is from your adder circuit (see mcleod_ideafix's comment below).
You might want to change you're input type of a and b as reg type so you can assign them inside a procedural block and assign them with different values.
module test();
reg [3:0] a = 4'b1000;
reg [3:0] b = 4'b0100;
wire [3:0] result;
wire carry = 0;
wire ocarry;
adder x(result, ocarry, a, b, carry);
initial begin
$display("# %0dns a: %0d b: %0d result: %0d", $time, a, b, result);
#1ns;
a = 5;
b = 6;
$display("# %0dns a: %0d b: %0d result: %0d", $time, a, b, result);
end
endmodule
Using the RTL that you posted and the test bench I modified above, it will produce an output:
# 0ns a: 8 b: 4 result: X
# 1ns a: 5 b: 6 result: X
You're adder does not work as expected for an adder circuit.
To help you further, I created an adder circuit for you.
module adder(result, carry, r1, r2, ci);
input [3:0] r1;
input [3:0] r2;
input ci;
output [3:0] result;
output carry;
assign {carry, result} = r1 + r2 + ci;
endmodule
And a working test bench that initializes the input to 0 then loops 10 times. Inside the loop, we create a delay of 1ns and changes the input to a random value from 0 to 15.
module test();
reg [3:0] a;
reg [3:0] b;
wire [3:0] result;
wire carry = 0;
wire ocarry;
adder x(result, ocarry, a, b, carry);
initial begin
$monitor("#%0dns [a: %0d] + [b: %0d] = [result: %0d] [carry = %0d] [ocarry = %0d] ", $time, a, b, result, carry, ocarry);
end
initial begin
a = 0;
b = 0;
repeat (10) begin
#1ns;
a = $random % 'h10;
b = $random % 'h10;
end
end
endmodule
You can run this code in edaplayground and see the output.
For every change of a, b, result, carry, ocarry, this code is executed.
$monitor("#%0dns [a: %0d] + [b: %0d] = [result: %0d] [carry = %0d] [ocarry = %0d] ", $time, a, b, result, carry, ocarry);
Half Adder:
`timescale = 1ns/100ps //timescale ratio //actual HDL
module half_add(a,b,sum, carry);
input a,b;
output sum, carry;
wire sum, carry;
and(sum,a,b);
xor(carry,a,b);
endmodule
Test bench:
module half_addTB;
reg a,b;
wire carry, sum;
//instantiation
half_add half_add1(
.a(a),.b(b),.carry(carry),.sum(sum));
//port assignments with 10ns delays
initial begin
#10 a = 0; b= 0;
#10 b = 1;
#10 a = 1;
#10 b = 0;
end
endmodule
Code compiles fine...but when I try to simulate it, all my values are in a z state....I don't understand why..
You cannot drive inputs to the module from within the module.
Just instantiate your "half_add" module in another module/program (e.g. "half_add_tb") which doesn't have any inputs. then add two local regs "a" and "b", and drive those from an initial block like the one you wrote - but in the "half_add_tb" module instead.
Then just wire up the inputs "a" and "b" of the "half_add" instance to the local "a" and "b" regs.
You need to instantiate your design in a testharness then drive the inputs.
//Half Adder
module half_add(a, b, sum, carry);
input a,b;
output sum, carry;
wire sum, carry; //Outputs are wires by default this is not required
and(sum, a, b);
xor(carry,a, b);
endmodule
module testharness();
//create test signals
reg a; //1 bit reg (regs driven from always and initial blocks)
reg b;
wire sum; // 1 bit wires for outputs to drive
wire carry;
//instantiate DUT (Device under test)
half_add half_add_1(
.a ( a ),
.b ( b ),
.sum ( sum ),
.carry ( carry)
);
//begin testbench
initial begin
#100 $finish;
end
initial begin
#10 a = 0; b= 0;
#10 b = 1;
#10 a = 1;
#10 b = 0;
end
endmodule
NB: if your simulator supports verilog-2001 your port lists can be easier to read and more compact:
//Half Adder
module half_add(
input a,
input b,
output wire sum,
output wire carry
//for regs :
// output reg [WIDTH-1:0] out_reg
//multi-bit wires :
// output [WIDTH-1:0] out_wire
);
and(sum, a, b);
xor(carry,a, b);
endmodule