Comparing two numbers without comparison operators in verilog - verilog

Two 8-bit inputs are fed to the comparator, and if first one is greater than second, they are supposed to be subtracted, else they are supposed to be added. But, > and < operators aren't supposed to be used to compare them.
So, I have written my logic as:
input[7:0] in1,in2;
output select;
assign select=(in1-in2)?0:1;
It is always subtracting, unless difference equals 0. If I use division, 0 cannot be an input or my program can crash. Any suggestions on how to solve this problem?
Thanks a lot for your time.

Remember that the leftmost bit of a negative number is aways 1. So you can use it to check the sign of the difference.
input[7:0] in1,in2;
output select;
wire [7:0] difference = in1-in2;
wire sign_of_difference = difference[7];
assign select = sign_of_difference? 0:1;

Related

Verilog Module Instantiation and empty begin end

I have made two verilog modules. The first one takes a nine-bit number and returns the position of first occurrence of 1 in it.
module findPositionOf_1(
input [8:0] data,
output reg [3:0] position
);
always #(data)
begin
if(data==9'b0000_00000)
position=4'b0000;
else if(data[0]==1)
position=4'b0000;
else if(data[1]==1)
position=4'b0001;
else if(data[2]==1)
position=4'b0010;
else if(data[3]==1)
position=4'b0011;
else if(data[4]==1)
position=4'b0100;
else if(data[5]==1)
position=4'b0101;
else if(data[6]==1)
position=4'b0110;
else if(data[7]==1)
position=4'b0111;
else if(data[8]==1)
position=4'b1000;
end
endmodule
The second module is returning the second occurrence of 1. It is calling the first module first changing that bit to zero and again finding the occurrence of 1.
module findPositionOf_2nd_1(
input [8:0] r1_data,
output [3:0] position1
);
reg [3:0] pos,pos2;
reg [8:0] temp;
integer i;
always #(r1_data)
begin
findPositionOf_1 f1(.data(r1_data), .position(pos));
i=pos;
temp=r1_data;
temp[i]=0;
findPositionOf_1 f2(temp,pos2);
if(pos2==4'b0000)
position1=0;
else
position1=pos2;
end
endmodule
I am getting the following errors during compilation. Please help.
Checker 'findPositionOf_1' not found. Instantiation 'f1' must be of a
visible checker.
A begin/end block was found with an empty body. This
is permitted in SystemVerilog, but not permitted in Verilog. Please
look for any stray semicolons.
By the way you write code it seems like you've not completely grasped how verilog(and other HDL languages) is different from "normal", procedural, coding.
You seem to assume that everything inside your always# block will execute from top to bottom, and that modules are similar to functions. This is not the case. You need to think about how you expect the hardware to look when you've designed your module.
In this case you know that you want two findPositionOf_1 modules. You know that you want the result from the first (u_f1) to affect the input of the second (u_f2). To do this, instantiate the two modules and then determine the interconnect between them.
We can create a vector with a 1 in position pos by left-shifting '1 pos number of times (1<<pos). By xor-ing the bits together, the statement r1_data ^ 1<<pos will remove the unwanted 1.
module findPositionOf_2nd_1(input [8:0] r1_data, output [3:0] position1 );
wire [3:0] pos,pos2;
wire [8:0] temp;
findPositionOf_1 u_f1(.data(r1_data), .position(pos));
findPositionOf_1 u_f2(.data(temp), .position(pos2));
assign temp = r1_data ^ (1<<pos);
assign position1 = pos2;
endmodule
You have instantiated your module inside an always block which is a procedural block, which is syntactically incorrect. Secondly, you have used your first module as a function call, which is not permitted. As said, you need to have a separate testbench, where you can connect your both modules and check. Make the position of occurance of 1st one as input to the findPositionOf_2nd_1 module. For your question, perhaps this should help
Why can't I instantiate inside the procedural block in Verilog

Verilog module cannot calculate a&b and a|b

I am creating the verilog module that calculate either one of a+b, a-b, a & b or a | b.
The problem is that it does calculate for a+b and a-b.
but it cannot calculate a & b and a | b and return nothing.
input [31:0] a, b;
input [2:0] op;
output [31:0] z;
output ex;
wire[31:0]a0,a1,a2,a3;
assign a0 = a & b;
assign a1 = a | b;
assign a2 = a + b;
assign a3 = a - b;
assign z=a0;
//assign z=a1;
//assign z=a2;
//assign z=a3;
endmodule
the module basically calculate a+b, a-b, a&b, and a|b and assign its calculated value to z.
And it does successfully calculate for a+b and a-b and put calculated value to z.
But for a&b and a|b, it doesn't assign anything to z.
How can I solve this?
Thank you very much if you can help me.
I'm sure it does assign something to z. The problem is that you are trying to assign too much to z.
Each assign statement represents some hardware, which in this case drives the wire z. So, you are driving z 4 times in parallel from 4 separate lumps of hardware. If you like, you have a short circuit. (Remember Verilog is a hardware description language. You are designing hardware here, not writing software. If you assign to a wire from more than one place, you have shorted the outputs of some lumps of hardware together.)
I notice there is an input [2:0] op. This looks like homework to me and I guess you have been asked to design an ALU. An ALU is a lump of hardware (combinational logic in this case) that can perform various operations on it's inputs (its operands), which in this case are a and b. Which operation it performs needs to be selected by some other control input, which in this case is almost certainly supposed to be op.
So, you need some code that tests op and drives z with either a+b, a-b, a&b or a|b. The obvious construct to me for this job is a case statement:
case (op)
3'b000:
z = // some expression, eg a + b, it depends on what op code 000 is supposed to mean
3'b001:
z = // some other expression here
// etc etc
default: // perhaps...
z = // ...something to drive z if none of the other branches are used
endcase
A case statement should go inside an always block. As I suspect this is homework, I won't feed you the answer, I'll let you work out how to do that.
Finally, I see that op is 3 bits wide. This suggests that you ALU has more than 4 different operations to carry out. I also see there is an ex output, which presumably needs to do something.
There's some confusion here. Your original posted code is fine; z will be assigned as you want. The other answer is incorrect - there are no multiple drivers; they're commented out. The delay suggestion is also incorrect - a delay will make no difference whatever to your logic.

I can't understand the result of this $random(seed) code

module random;
reg [31:0] addr;
integer seed;
initial begin
seed = 5;
$monitor("%t->%d", $time, addr);
#30 $stop;
end
always #5 addr = $random(seed);
endmodule
In this code, if I declare seed with integer, the seed value changes every #5. But, if I declare seed with reg[3:0], the seed value is 5 continuously. I can't understand why this is happening.
Your code generates a very small sample size (5). You should generate more random numbers. When I did so, I saw more than one value with reg [3:0] seed;. Change #30 to #300, for example.
When I use reg [31:0] seed;, I get the same type of distribution as when I use integer. I don't see any explanation of this behavior in the IEEE Std 1800-2012 for $random, but section 20.15.2 "Distribution functions" mentions:
For each system function, the seed argument is an inout argument; that
is, a value is passed to the function, and a different value is
returned. The system functions shall always return the same value
given the same seed.
You should see seed changing on every call.
$monitor("addr=%d seed=%d", addr, seed);
I strongly recommend that you start using $urandom instead of $random. It makes it easy to control the seed from the command line without having to recompile, and you get better random stability as well.
The seed to $random is supposed to be at least a 32-bit integer (Although it is not explained in the LRM, the code for $random is in the append). A 32-bit seed does not mean you will get 2**32-1 random numbers. As you shorten the width of the seed, you shorten the number of random numbers that it takes to repeat the cycle of random numbers. By the time you get down to 4 bits, the probability that the cycle for a particular seed goes to 1 is pretty high.

Verilog: Passing parameters

I have written two verilog modules. The first one is named topmodule.v and the second one is tx.v. The module topmodule.v pass a parameter data[31:0] to tx.v. I want to take the variables Rmax and Cmax from data[31:0]. After that I want to make Rmax and Cmax to be the width of a bus. Moreover, I want to define a reg matrix called Mat with dimensions Cmax-x-Rmax. I receive the error at the 6th line of the code, "Range must be bounded by constant expression". Kindly help me to resolve this problem. The code is given below.
tx (data, output)
input [31:0] data;
reg [15:0] Rmax, Cmax;
assign Rmax [15:0] = data [31:16];
assign Cmax [15:0] = data [15:0];
reg [Rmax-1:0] Matrix [0:Cmax-1];
The error means pretty much what it says, you cannot have a variable size bus or array.
Declare your matrix to be the maximum size that you ever need, and if you want to use a smaller one, then just use a subsection of it while leaving the rest vacant.
Remember that the width of buses are physical objects, they can't change when the circuit is running, only during synthesis.
If you really want these to be parameters then use that:
module tx #(parameter DATA=32'h00000000) (
// inputs and outputs here
);
reg [DATA[31:16]-1:0] Matrix [0:DATA[15:0]-1];
However, I'm not really sure of what you are trying to accomplish. Show some more pseudo code and get a more useful answer.

Verilog: Order of reg

Simple question
If I need to use 4 8-bit numbers, I would declare the following reg.
reg [7:0] numbers [3:0]
I'm quite confused about the difference between the first and second declaration ([7:0] and [3:0]). In what order should they come? Does first one stay for the size of a number while the second is for the number of numbers or vice versa? And is [7:0] or [0:7] give the right order?
Thanks in advance.
EDIT:
Ordinary arrays of numbers look like this, for example
0000
0110
0001
There are three 4-bit numbers (0000, 0110, 0001). We can access them by using array indices. So, accessing the first digit of the second number is done by something like this
a[0][1]
assuming that this array is stored in a variable a.
Returning to Verilog, how would accessing elements change if I would swap values in reg or declare them in reverse order ([0:7]), for example?
reg[7:0] is an 8-bit "register", or variable
reg[7:0] numbers[3:0] is a 1-D array with 4 elements, named
numbers, each of which is an 8-bit register
An element of numbers is accessed as numbers[index]
numbers[i][j] is a bit-select of numbers[i]. It accesses bit
j in the ith element of numbers
As toolic says, it's more conventional for array indices to be
numbered [lsb:msb], but there's no good reason for this.
When assigning two objects, bits are copied left-to-right, as for VHDL.
Verilog has (very) poor checking of bit and part selects and array indexes. See the code below.
module top;
initial
test;
task test;
reg[3:0] a[0:1];
reg[0:3] b[0:1];
reg[2:5] c[0:1];
begin
a[0] = 4'b1101;
a[1] = 4'b0110;
a[2] = 4'b0001; // error, but not caught by Verilog
$display("a[2] is %d", a[2]); // modelsim produces no warning, prints 'a[2] is x'
$display("a[0][4] is %b", a[0][4]); // modelsim warns, and prints 'a[0][4] is x'
$display( // produces '1.1.0.1'
"a[0][3:0] is %b.%b.%b.%b", a[0][3], a[0][2], a[0][1], a[0][0]);
b[0] = a[0];
$display("b[0] is %d", b[0]); // produces '13'
$display( // produces '1.1.0.1'
"b[0][0:3] is %b.%b.%b.%b", b[0][0], b[0][1], b[0][2], b[0][3]);
c[0] = a[0];
$display("c[0] is %d", c[0]); // produces '13'
$display( // produces '1.1.0.1'
"c[0][2:5] is %b.%b.%b.%b", c[0][2], c[0][3], c[0][4], c[0][5]);
end
endtask
endmodule
Yes, that syntax can be used to declare 4 8-bit numbers, however it is more conventional for 0 to be left of the colon for the number of words:
reg [7:0] numbers [0:3]

Resources