How to get MAX or MIN in Verilog? - verilog

I want to build a simple module to compare two 2-bit numbers and get the maximum number in the output.
I've used the code posted here: How to find MAX or MIN in Verilog coding?
module max (input [1:0] a,
input [1:0] b,
output reg [1:0] out);
always #* begin
if (a>b)
out = a;
else
out = b;
end
endmodule
But the problem I have, is that the output "out" does not give me a 2-bit number, and also the code is not working well as you can see in the screenshot.
This is the testbench I'm using:
`timescale 1ns/10ps
module maxTB();
reg [1:0] a, b;
max dut (.a(a),.b(b),.out(out));
initial
begin
a = 2'b1; b= 2'b0;
#20 a = 2'b10;
#40 b = 2'b11;
#50 a = 2'b01;
end
endmodule
modelsim screenshot

You haven't declared out in your TB, so it has defaulted to a 1-bit net (a wire). This is a rather major failing in the language. To turn this behaviour off, add this outside any module:
`default_nettype none

Related

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

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;

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]};

ALU in Verilog: "Unable to bind wire/reg/memory"

I am trying to make a simple 32 bit ALU with an overflow flag, and then output the inputs and results of the ALU to the screen, but I encountered some problems with connecting the elements for the test bench. I got this error:
test_32bALU.v:15: error: Wrong number of ports. Expecting 4, got 5.
test_32bALU.v:33: error: Unable to bind wire/reg/memory
test_unit.overflow' inalu_test'
2 error(s) during elaboration.
I am just starting with Verilog and I have a basic idea of the syntax. I know I am not supposed to ask debugging questions, but this is my only hope. My professor or TA wouldn't respond to me requests for help. I would appreciate it if anyone here could help me point out my mistakes.
This is my 32bALU.v file:
module alu(
input signed[31:0] a,b,
input[3:0] opcode;
output signed[31:0] c;
output overflow;
);
reg signed[31:0] result;
assign c = result;
reg tmp;
parameter
add = 4'b0000,
sub = 4'b0110,
sla = 4'b0001,
srai = 4'b0011;
always #(a,b,opcode)
begin
case(opcode)
add:
begin
c = a + b;
end
endcase
end
always #(c)
begin
if (c[32:31] == (2'b11 | 2'b10)) // Overflow
begin
tmp = 1'b1;
assign overflow = tmp;
end
else begin
tmp = 1'b0;
assign overflow = tmp;
end
end
assign result = c[31:0];
endmodule
test_32bALU.v
`timescale 1ns/1ps
module alu_test;
// Inputs
reg[31:0] a,b;
reg[2:0] opcode;
// Outputs
wire[31:0] c;
//wire [1:0] zero;
wire [1:0] overflow;
//wire [1:0] neg;
alu test_unit(
a,b, // Inputs
opcode,
c,
overflow
);
parameter
add = 4'b0000,
sub = 4'b0110,
sla = 4'b0001,
srai = 4'b0011;
initial begin
$display("op: a : b : c : reg_A : reg_B : reg_C");
$monitor(" %h:%h:%h:%h:%h:%h:%h",
opcode, a, b, c, test_unit.a, test_unit.b, test_unit.c);
$monitor("%h", test_unit.overflow);
//// add
#10 a=32'b0000_0000_0000_0000_0000_0000_0000_0001;
#10 b=32'b0000_0000_0000_0000_0000_0000_0000_0001;
opcode= add;//3'b000
#10 $finish;
end
endmodule
I am confused as to why it says "wrong number of ports"? I assume it's the number of parameters in module alu and alu test_unit? They have the same number of parameters (a, b, c, opcode and overflow), so what exactly am I missing? How exactly do I get the value of overflow? It works fine before I added the overflow parameter, so I assume I'm doing it wrong?
For the second error, I read somewhere on here that it might be due to a missing declaration, but I have declared all of them... so I am not sure what's making it wrong.
I am not sure if this is the issue, but your module definition is not correct. It should be as follows:
module alu(
input signed[31:0] a,b,
input[3:0] opcode,
output signed[31:0] c,
output overflow
);
Perhaps this may help with your issue.
Commas separate inputs and outputs in the module declaration.
NEVER rely on the order of arguments to modules and ALWAYS try to use, for a module called A;
module A(output wire c,
input wire a,
input wire b);
...
endmodule // A
use an instance of it using;
A yourAname(.c(Bar),
.a(Foo1),
.b(Foo2));
so that if the definition and order of the I/O of the module changes, this instantiation will track those changes and/or give appropriate errors when simulated/synethesised.
You might find it useful to follow a few simple rules in your source code when naming;
inputs are denoted by i_yourinputname
outputs are denoted by o_youroutputname
inout are denoted by io_yourinputoutputname
wire are denoted by w_yourwirename
reg are denoted by r_yourregname
as this avoid confusion and is a good habit to get into as soon as possible when starting to learn verilog.

I have magnitude comparator 4-bit Verilog code and I have wrong output

I have Verilog code: magnitude comparator 4-bit.
I don't know what is wrong.
I have output without (a great than b) and (a less than b).
Where is my mistake?
`timescale 1ns/1ns
module magnitudecomparator(agtb,altb,aeqb,a,b);
input [3:0]a,b;
output agtb,altb,aeqb;
wire [3:0]x;
assign x=!(a^b);
assign agtb=(a[3]&(!b[3]))|(x[3]&a[2]&(!b[2]))|(x[3]&x[2]&a[1]&(!b[1]))|(x[3]&x[2]&x[1]&a[0]&(!b[0]));
assign altb=((!a[3])&b[3])|(x[3]&(!a[2])&b[2])|(x[3]&x[2]&(!a[1])&b[1])|(x[3]&x[2]&x[1]&(!a[0])&b[0]);
assign aeqb=x[3]&x[2]&x[1]&x[0];
endmodule
`timescale 1ns/1ns
module testmagnitudecomparator;
reg a,b;
wire agtb,aeqb,altb;
magnitudecomparator m0(agtb,altb,aeqb,a,b);
initial
begin
#10 a=4'b0110;b=4'b1110;
#20 a=4'b1101;b=4'b0111;
#30 a=4'b1011;b=4'b1011;
end
initial
$monitor($time, "THE VALUE OF INPUT IS a=%b ,b=%b AND OUTPUT IS agtb=%b ,aeqb=%b ,altb=%b",a,b,agtb,aeqb,altb);
endmodule
In your testbench, you connected 1-bit signals to 4-bit ports.
In the testmagnitudecomparator module, change:
reg a,b;
to:
reg [3:0]a,b;
Also, you could simplify your code:
assign agtb = (a > b);
assign altb = (a < b);
assign aeqb = (a == b);
Or you can also use a behavioral code by using if else statements..
always#(*)
begin
if(a>b)
agtb=1'b1;
else if(a<b)
altb=1'b1;
else
aeqb=q'b1;
end

number of ones in array

I am trying to count the number of ones in a 4-bit binary number in Verilog, but my output is unexpected. I've tried several approaches; this is the one I think should work, but it doesn't.
module ones(one,in);
input [3:0]in;
output [1:0]one;
assign one = 2'b00;
assign one = one+in[3]+in[2]+in[1]+in[0] ;
endmodule
First, you can't assign the variable twice.
Second, your range is off, 2 bits can only go from 0 to 3. You need a 3 bit output to count up to 4.
This is more like what you need:
module ones(
output wire [2:0] one,
input wire [3:0] in
);
assign one = in[3]+in[2]+in[1]+in[0] ;
endmodule
$countones can be used for this purpose (refer to IEEE Std 1800-2012, 20.9 Bit vector system functions):
module tb;
reg [3:0] in;
wire [2:0] one = $countones(in);
initial begin
$monitor("in=%b one=%d", in, one);
#1 in = 4'b0000;
#1 in = 4'b0001;
#1 in = 4'b1101;
end
endmodule
Output:
in=xxxx one=0
in=0000 one=0
in=0001 one=1
in=1101 one=3

Resources