why output of 2nd function call to 4 bit adder is X(don't care)? - verilog

I am new to verilog, I was building a 32-bit adder using structural modelling. So I made a 1-bit full adder, then used that to construct a 4-bit adder, and that was used to create an 8- bit adder.
Everything works fine until the 4-bit adder but when I use the 4-bit adder as a function this error pops up.
module adder_1bit(Sum,CarryOut,A,B,CarryIn);
output Sum,CarryOut;
input A,B,CarryIn;
assign Sum = A^B^CarryIn;
assign CarryOut = (A&B) | (B&CarryIn) | (A&CarryIn);
endmodule
module adder_4bit(Sum,CarryOut,A,B,CarryIn);
output [3:0] Sum;
output CarryOut;
input [3:0] A,B;
input CarryIn;
wire w[2:0];
assign CarryIn = 1'b0;
adder_1bit add0(Sum[0],w[0],A[0],B[0],CarryIn);
adder_1bit add1(Sum[1],w[1],A[1],B[1],w[0]);
adder_1bit add2(Sum[2],w[2],A[2],B[2],w[1]);
adder_1bit add3(Sum[3],CarryOut,A[3],B[3],w[2]);
endmodule
module adder_8bit(Sum,CarryOut,A,B,CarryIn);
output [7:0] Sum;
output CarryOut;
input [7:0] A,B;
input CarryIn;
wire w;
assign CarryIn = 1'b0;
adder_4bit add4(Sum[3:0],w,A[3:0],B[3:0],CarryIn);
adder_4bit add5(Sum[7:4],CarryOut,A[7:4],B[7:4],w);
endmodule
When I run with the following testbench code I get MSB 4-bit get as don't care
module adder_test;
reg [7:0] A,B;
reg CarryIn;
wire [7:0] Sum;
wire CarryOut;
adder_8bit UUT (Sum,CarryOut,A,B,CarryIn);
initial
begin
A = 8'b00101011;
B = 8'b01010110;
CarryIn = 1'b0;
#10;
end
endmodule
Simulation Result

Your problem is in this statement: assign CarryIn = 1'b0;
The following happens:
module adder_4bit(Sum,CarryOut,A,B,CarryIn);
...
assign CarryIn = 1'b0;
In this case you have carryIn driven by two drivers:
the input port
the assign statement
Unless the value of the port is the same as your driver (1'b0) the resulting value of carryIn will always be 'x'. This interferes with all your results.
To fix the issue just move this statement to your test bench:
module adder_test;
...
wire CarryOut = 0;

Related

I am getting unknown value when doing a 4 bit shifter verilog (gate level)

I am trying to implement a 4 bit right shifter using gate level but i got unknown result for some reason, my mux work ok but when i try testbench for my shifter it give back something like this:
a=0010 b=01 c=0000
a=1111 b=01 c=00xx
Please help!!!! Thank you very much
module mux2(a,b,sel,c);
output c;
input a,b,sel;
wire net0,net1,net2;
not m1(net0,sel);
and m2(net1,a,net0);
and m3(net2,b,sel);
or m4(c,net1,net2);
endmodule
module mux4(a,sel,c);
output c;
input [1:0]sel;
input[3:0]a;
wire mux_1,mux_2;
mux2 m1(a[3],a[2],sel[0],mux_1);
mux2 m2(a[1],a[0],sel[0],mux_2);
mux2 m3(mux_1,mux_2,sel[1],c);
endmodule
module shift4bitright(c,a,b);
output [3:0]c;
input [3:0]a;
input [1:0]b;
wire [3:0]d=4'h0,d1=4'h0,d2=4'h0,d3=4'h0;
assign d[0]=a[3];
assign d1[0]=a[2]; assign d1[1]=a[3];
assign d2[0]=a[1]; assign d2[1]=a[2]; assign d2[2]=a[3];
assign d3[0]=a[0]; assign d3[1]=a[1];assign d3[2]=a[2];assign d3[3]=a[3];
mux4 m1(d,b,c[3]);
mux4 m2(d1,b,c[2]);
mux4 m3(d2,b,c[1]);
mux4 m4(d3,b,c[0]);
endmodule
`timescale 10ns/1ns
module shift4bitright_tb;
wire [3:0]c;
reg [3:0]a;
reg [1:0]b;
shift4bitright s1(.c(c),.a(a),.b(b));
initial begin
$monitor("a=%b b=%b c=%b",a,b,c);
a=4'h2;
b=2'd1;
#50
a=4'hf;
b=2'd1;
end
endmodule
This statement declared a wire type signal d as well as its driver cone (NOT initial value), which is a constant 0 in this case:
wire [3:0]d=4'h0;
Just below it, there's another a[3] driving d[0]:
assign d[0]=a[3];
This creates a multi-driven logic, hence x occurs.
To solve it, change it similar to:
wire [3:0] d;
assign d = {3'h0, a[3]};

4-bit counter using T-flipflop in verilog

I'm trying to design a 4-bit counter with T-flipflop, here's what i did:
1- From a D-flipflop to T-flipflop:
module T_FlipFlop( clk,T, Q);
input wire clk;
input wire T;
output reg Q;
wire D;
initial
begin
Q<=1'b0;
end
assign D= T ^ Q;
always #(negedge clk)
begin
Q<=D;
end
endmodule
with RTL shematic :
following this "D_ff to T_ff" conversion:
2- Then, i instantiated 4 T-flipflops in the top module and connected the output of each flipflop to the clk of the next one:
module Counters_FreqDividers( sysclk,Q1,Q2,Q3,Q4);
input sysclk;
output wire Q1;
output wire Q2;
output wire Q3;
output wire Q4;
T_FlipFlop num_1(.clk(sysclk),.T(1'b1),.Q(Q1));
T_FlipFlop num_2(.clk(Q1),.T(1'b1),.Q(Q2));
T_FlipFlop num_3(.clk(Q2),.T(1'b1),.Q(Q3));
T_FlipFlop num_4(.clk(Q3),.T(1'b1),.Q(Q4));
endmodule
with RTL schematic :
to follow this diagram:
We know that T-flipflop is just a JK-flipflop with J and K connected to each other and that's what we have here, so consider them as T-flipflops.
3-The simulation:
4- Finally, my questions:
1) why Q1 is the ONLY output that operates properly?
2) Why Q2, Q3, Q4 starts with 1 although i have initialized them as 0?
I can't figure out what's missing, i tried to play around but nothing worked and i'm stuck here!
Edit: my testbench:
module test;
// Inputs
reg sysclk;
// Outputs
wire Q1;
wire Q2;
wire Q3;
wire Q4;
// Instantiate the Unit Under Test (UUT)
Counters_FreqDividers uut (
.sysclk(sysclk),
.Q1(Q1),
.Q2(Q2),
.Q3(Q3),
.Q4(Q4)
);
initial begin
// Initialize Inputs
sysclk <= 1'b1;
#200 $finish();
end
always #5 sysclk=~sysclk;
endmodule

Verilog hdl magnitude comparator error

I have written the simple code below for a magnitude comparator. The 6 bits of C give the values of A=B,A!=B,etc; However, i am getting the following error when i run the code. How can i fix the error?
c2q39.v:7: error: C['sd5] is not a valid l-value in testbench.m.
c2q39.v:3: : C['sd5] is declared here as wire.
My code is
module mag(A,B,C);
input [3:0] A,B;
output [5:0] C;
always # (A or B)
assign C[5]=(A==B);
assign C[4]=(A!=B);
assign C[3]=(A>B);
assign C[2]=(A<B);
assign C[1]=(A>=B);
assign C[0]=(A<=B);
endmodule
module testbench;
reg [3:0] A,B;
wire [5:0] C;
mag m(A,B,C);
initial
begin
A=4'b0000;B=4'b0000;
#10 A=4'b1000;
#10 B=4'b1001;
#10 A=4'b1000;
end
initial
$monitor("%0d %b %b %b",$time,A,B,C);
endmodule
It is not a good idea to use assign statement in always block ( for more details refer here ). So you can define your output C as reg and implement the following way:
module mag(A,B,C);
input [3:0] A,B;
output reg [5:0] C;
always # (A or B)
begin
C[5]=(A==B);
C[4]=(A!=B);
C[3]=(A>B);
C[2]=(A<B);
C[1]=(A>=B);
C[0]=(A<=B);
end
endmodule
The other way to implement is just use assign statements.
module mag(A,B,C);
input [3:0] A,B;
output [5:0] C;
//always # (A or B)
assign C[5]=(A==B);
assign C[4]=(A!=B);
assign C[3]=(A>B);
assign C[2]=(A<B);
assign C[1]=(A>=B);
assign C[0]=(A<=B);
endmodule

Connect 5-bit bus to 32-bit output bus

My design needs multiple multiplexers, all of them have two inputs and most are 32 bits wide. I started with designing the 32 bit, 2:1 multiplexer.
Now I need a 5 bit, 2:1 multiplexer and I want to reuse my 32 bit design. Connecting the inputs is easy (see code below), but I struggle to connect the output.
This is my code:
reg [4:0] a, b; // Inputs to the multiplexer.
reg select; // Select multiplexer output.
wire [4:0] result; // Output of the multiplexer.
multiplex32_2 mul({27'h0, a}, {27'h0, b}, select, result);
When I run the code through iverilog, I get a warning that says that the multiplexer expects a 32 bit output, but the connected bus is only 5 bit wide. The simulation shows the expected results, but I want to get rid of the warning.
Is there a way to tell iverilog to ignore the 27 unused bits of the multiplexer output or do I have to connect a 32 bit wide bus to the output of the multiplexer?
I don't know of a #pragma or something like that (similar to #pragma argsused from C) that can be used in Verilog.
Xilinx ISE, for example, has a feature called "message filtering", which allows the designer to silence specific warning messages. You find them once, select them, choose to ignore, and subsequent synthesis won't trigger those warnings.
Maybe you can design your multiplexer in a way you don't need to "waste" connections (not actually wasted though, as the synthesizer will prune unused connections from the netlist). A more elegant solution would be to use a parametrized module, and instantiate it with the required width. Something like this:
module mux #(parameter WIDTH=32) (
input wire [WIDTH-1:0] a,
input wire [WIDTH-1:0] b,
input wire sel,
output wire [WIDTH-1:0] o
);
assign o = (sel==1'b0)? a : b;
endmodule
This module has been tested with this simple test bench, which shows you how to instantiate a module with params:
module tb;
reg [31:0] a1,b1;
reg sel;
wire [31:0] o1;
reg [4:0] a2,b2;
wire [4:0] o2;
mux #(32) mux32 (a1,b1,sel,o1);
mux #(5) mux5 (a2,b2,sel,o2);
// Best way to instantiate them:
// mux #(.WIDTH(32)) mux32 (.a(a1),.b(b1),.sel(sel),o(o1));
// mux #(.WIDTH(5)) mux5 (.a(a2),.b(b2),.sel(sel),.o(o2));
initial begin
$dumpfile ("dump.vcd");
$dumpvars (1, tb);
a1 = 32'h01234567;
b1 = 32'h89ABCDEF;
a2 = 5'b11111;
b2 = 5'b00000;
repeat (4) begin
sel = 1'b0;
#10;
sel = 1'b1;
#10;
end
end
endmodule
You can test it yourself using this Eda Playground link:
http://www.edaplayground.com/x/Pkz
I think the problem relates to the output of the multiplexer which is still 5 bits wide. You can solve it by doing something like this:
reg [4:0] a, b; // Inputs to the multiplexer.
reg select; // Select multiplexer output.
wire [31:0] temp;
wire [4:0] result; // Output of the multiplexer.
multiplex32_2 mul({27'h0, a}, {27'h0, b}, select, temp);
assign result = temp[4:0];
This can be easily tested in http://www.edaplayground.com/ using the code below:
( I have re-used #mcleod_ideafix's code)
// Code your testbench here
// or browse Examples
module mux #(parameter WIDTH=32) (
input wire [WIDTH-1:0] a,
input wire [WIDTH-1:0] b,
input wire sel,
output wire [WIDTH-1:0] o
);
assign o = (sel==1'b0)? a : b;
endmodule
module tb;
reg [31:0] a,b;
wire [31:0] o;
wire [4:0] r;
reg sel;
initial begin
$dumpfile("dump.vcd"); $dumpvars;
a = 10; b = 20; sel = 1;
end
mux MM(a,b,sel,o);
assign r = o[4:0];
endmodule
Let me know if you are still getting a warning.

How do I run the verilog code on a testbench?

I wrote the code for a ripple carry adder. Testbench is also available. How do I run this test bench on my Verilog code? I don't have a simulator. I am using the iverilog compiler.
ripple_carry_adder.v
module half_adder(a,b,sum,carry);
input a,b;
output sum,carry;
assign sum=a^b;
assign carry=a&b;
endmodule
module full_adder(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
wire t1,t2;
half_adder h(a,b,t1,t2);
assign cout=t1&cin;
assign sum=t1^cin;
assign cout=t2|cout;
endmodule // full_adder
module ripple_carry_adder(input1,input2,answer);
input [31:0] input1,input2;
output [31:0] answer;
wire [31:0] carry;
full_adder f(input1[0],input2[0],1'b0,answer[0],carry[0]);
genvar i;
generate
for(i=1;i<=31;i=i+1)
begin : my_mabel
full_adder f(input1[i],input2[i],carry[i-1],answer[i],carry[i]);
end
endgenerate
endmodule
testbench
module test;
reg [31:0] input1,input2, expected;
wire [31:0] actual;
integer seed;
ripple_carry_adder dut(input1,input2,actual);
initial begin
seed = 0;
repeat(10) begin
input1 = $random(seed);
input2 = $random(seed);
expected = input1 + input2;
#1;
if(actual!=expected) $display("ERROR: %0d+%0d was %0d expected %0d",
input1,input2,actual, expected);
#9;
end
end
endmodule
Use:
$ iverilog -o ripple ripple_carry_adder.v ripple_carry_adder_tb.v
$ vvp ripple
to compile and run your code in terminal. You might add a $monitor to your testbench to be able to print some more results than just errors.
There is also a companion program called GTKWave that allows you to plot waveforms.

Resources