来自: 这里
Verilog has system function $random ,which can be used to generate random input vectors. With this approach, we can generate values which we wouldn't have got, if listed manually. In this topic I would like to discuss what natural things happening behind $random and how we use it in different manners.
EXAMPLE:
module Tb_mem();
reg clock;
reg read_write;
reg [31:0] data;
reg [31:0] address;
initial
begin
clock = 0;
forever
#10 clock = ~clock;
end
initial
begin
repeat(5)@(negedge clock)
begin read_write = $random ; data = $random;address = $random; end
$finish;
end
initial
$monitor($time,"read_write = %d ; data = %d ; address = %d;",read_write,data,address);
endmodule
RESULT:
20read_write = 0 ; data = 3230228097 ; address = 2223298057;
40read_write = 1 ; data = 112818957 ; address = 1189058957;
60read_write = 1 ; data = 2302104082 ; address = 15983361;
80read_write = 1 ; data = 992211318 ; address = 512609597;
$random() system function returns a new 32-bit random number each time it is called. The random number is a signed integer; it can be positive or negative. The following example demonstrates random generation of signed numbers.
EXAMPLE:
module Tb();
integer address;
initial
begin
repeat(5)
#1 address = $random;
end
initial
$monitor("address = %d;",address);
endmodule
RESULT:
address = 303379748;
address = -1064739199;
address = -2071669239;
address = -1309649309;
address = 112818957;
We have seen how to generate random numbers. But the numbers range from - (2**32 -1) to 2 **32. Most of the time, the requirement don't need this range. For example, take a memory. The address starts from 0 to some 1k or 1m.Generating a random address which DUT is not supporting is meaningless. In verilog there are no constructs to constraint randomization. Fallowing example demonstrated how to generate random number between 0 to 10.Using % operation, the remainder of any number is always between 0 to 10.
EXAMPLE:
module Tb();
integer add_1;
initial
begin
repeat(5)
begin
#1;
add_1 = $random % 10;
end
end
initial
$monitor("add_1 = %d",add_1);
endmodule
RESULT:
add_1 = 8;
add_1 = 4294967287;
add_1 = 4294967295;
add_1 = 9;
add_1 = 9;
OOPS!...... The results are not what is expected. The reason is $random generates negative numbers also. The following example demonstrates proper way of generating a random number between 0 to 10. Concatenation operator returns only bit vector. Bit vectors are unsigned, so the results are correct as we expected. Verilog also has $unsigned systemtask to convert signed numbers to signed number. This can also be used to meet the requirements. The following example shows the usage of concatenation operator and $unsigned.
EXAMPLE:
module Tb();
integer add_2;
reg [31:0] add_1;
integer add_3;
initial
begin
repeat(5)
begin
#1;
add_1 = $random % 10;
add_2 = {$random} %10 ;
add_3 = $unsigned($random) %10 ;
end
end
initial
$monitor("add_3 = %d;add_2 = %d;add_1 = %d",add_3,add_2,add_1);
endmodule
RESULT:
add_3 = 7;add_2 = 7;add_1 = 8
add_3 = 7;add_2 = 7;add_1 = 4294967287
add_3 = 1;add_2 = 2;add_1 = 4294967295
add_3 = 7;add_2 = 8;add_1 = 9
add_3 = 9;add_2 = 2;add_1 = 9
The above example shows the generation of numbers from 0 to N.Some specification require the range to start from non Zero number. MIN + {$random} % (MAX - MIN ) will generate random numbers between MIN and MAX.
EXAMPLE:
module Tb();
integer add;
initial
begin
repeat(5)
begin
#1;
add = 40 + {$random} % (50 - 40) ;
$display("add = %d",add);
end
end
endmodule
RESULT:
add = 48
add = 47
add = 47
add = 47
add = 47
Now how to generate a random number between two ranges? The number should be between MIN1 and MAX1 or MIN2 and MAX2.The following example show how to generate this specification.
EXAMPLE:
module Tb();
integer add;
initial
begin
repeat(5)
begin
#1;
if($random % 2)
add = 40 + {$random} % (50 - 40) ;
else
add = 90 + {$random} % (100 - 90) ;
$display("add = %d",add);
end
end
endmodule
RESULT:
add = 97
add = 47
add = 47
add = 42
add = 49
All the random number generates above generate numbers of 32 vector. Not always the requirements are 32 bit .For example, to generate a 5 bit and 45 bit vector random number, the following method can be used.
EXAMPLE:
module Tb();
reg [4:0] add_1;
reg [44:0] add_2;
initial
begin
repeat(5)
begin
add_1 = $random ;
add_2 = {$random,$random};
$display("add_1 = %b,add_2 = %b ",add_1,add_2);
end
end
endmodule
RESULTS:
add_1 = 00100,add_2 = 111101000000110000100100001001101011000001001
add_1 = 00011,add_2 = 110110000110101000110110111111001100110001101
add_1 = 00101,add_2 = 100100001001000000000111100111110001100000001
add_1 = 01101,add_2 = 100010111011000011110100011011100110100111101
add_1 = 01101,add_2 = 101111000110001111100111111011110100111111001
Some protocols require a random number which is multiple some number. For example, Ethernet packet is always in multiples of 8bits,and PCIExpress packets are multiples of 4byts .Look at the following example. It generates a random number which is multiple of 3 and 5.
EXAMPLE:
module Tb();
integer num_1,num_2,tmp;
initial
begin
repeat(5)
begin
#1;
tmp = {$random} / 3;
num_1 = (tmp) * 3;
tmp = {$random} / 3;
num_2 = (tmp) * 5;
$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule
RESULT:
num_1 = 303379746,num_2 = -1064739195
num_1 = -2071669239,num_2 = -1309649305
num_1 = 112818957,num_2 = 1189058955
num_1 = -1295874969,num_2 = -1992863210
num_1 = 15983361,num_2 = 114806025
All the above example show that the random numbers are integers only. In verilog there is not special construct to generate a random real number. The following method shows the generation of random real number.
EXAMPLE:
module Tb();
integer num_1,num_2,num_3;
real r_num;
initial
begin
repeat(5)
begin
#1;
num_1 = $random;
num_2 = $random;
num_3 = $random;
r_num = num_1 + ((10)**(-(num_2)))*(num_3);
$display("r_num = %e",r_num);
end
end
endmodule
RESULT:
r_num = -2.071669e+03
r_num = 2641.189059e+013
r_num = 976361.598336e+01
r_num = 57645.126096e+02
r_num = 24589.097015e+0
To generate random real number , system function $bitstoreal can also be used.
EXAMPLE:
module Tb();
real r_num;
initial
begin
repeat(5)
begin
#1;
r_num = $bitstoreal({$random,$random});
$display("r_num = %e",r_num);
end
end
endmodule
RESULTS:
r_num = 1.466745e-221
r_num = -6.841798e-287
r_num = 2.874848e-276
r_num = -3.516622e-64
r_num = 4.531144e-304
Verilog has system function $random ,which can be used to generate random input vectors. With this approach, we can generate values which we wouldn't have got, if listed manually. In this topic I would like to discuss what natural things happening behind $random and how we use it in different manners.
EXAMPLE:
module Tb_mem();
reg clock;
reg read_write;
reg [31:0] data;
reg [31:0] address;
initial
begin
clock = 0;
forever
#10 clock = ~clock;
end
initial
begin
repeat(5)@(negedge clock)
begin read_write = $random ; data = $random;address = $random; end
$finish;
end
initial
$monitor($time,"read_write = %d ; data = %d ; address = %d;",read_write,data,address);
endmodule
RESULT:
20read_write = 0 ; data = 3230228097 ; address = 2223298057;
40read_write = 1 ; data = 112818957 ; address = 1189058957;
60read_write = 1 ; data = 2302104082 ; address = 15983361;
80read_write = 1 ; data = 992211318 ; address = 512609597;
$random() system function returns a new 32-bit random number each time it is called. The random number is a signed integer; it can be positive or negative. The following example demonstrates random generation of signed numbers.
EXAMPLE:
module Tb();
integer address;
initial
begin
repeat(5)
#1 address = $random;
end
initial
$monitor("address = %d;",address);
endmodule
RESULT:
address = 303379748;
address = -1064739199;
address = -2071669239;
address = -1309649309;
address = 112818957;
We have seen how to generate random numbers. But the numbers range from - (2**32 -1) to 2 **32. Most of the time, the requirement don't need this range. For example, take a memory. The address starts from 0 to some 1k or 1m.Generating a random address which DUT is not supporting is meaningless. In verilog there are no constructs to constraint randomization. Fallowing example demonstrated how to generate random number between 0 to 10.Using % operation, the remainder of any number is always between 0 to 10.
EXAMPLE:
module Tb();
integer add_1;
initial
begin
repeat(5)
begin
#1;
add_1 = $random % 10;
end
end
initial
$monitor("add_1 = %d",add_1);
endmodule
RESULT:
add_1 = 8;
add_1 = 4294967287;
add_1 = 4294967295;
add_1 = 9;
add_1 = 9;
OOPS!...... The results are not what is expected. The reason is $random generates negative numbers also. The following example demonstrates proper way of generating a random number between 0 to 10. Concatenation operator returns only bit vector. Bit vectors are unsigned, so the results are correct as we expected. Verilog also has $unsigned systemtask to convert signed numbers to signed number. This can also be used to meet the requirements. The following example shows the usage of concatenation operator and $unsigned.
EXAMPLE:
module Tb();
integer add_2;
reg [31:0] add_1;
integer add_3;
initial
begin
repeat(5)
begin
#1;
add_1 = $random % 10;
add_2 = {$random} %10 ;
add_3 = $unsigned($random) %10 ;
end
end
initial
$monitor("add_3 = %d;add_2 = %d;add_1 = %d",add_3,add_2,add_1);
endmodule
RESULT:
add_3 = 7;add_2 = 7;add_1 = 8
add_3 = 7;add_2 = 7;add_1 = 4294967287
add_3 = 1;add_2 = 2;add_1 = 4294967295
add_3 = 7;add_2 = 8;add_1 = 9
add_3 = 9;add_2 = 2;add_1 = 9
The above example shows the generation of numbers from 0 to N.Some specification require the range to start from non Zero number. MIN + {$random} % (MAX - MIN ) will generate random numbers between MIN and MAX.
EXAMPLE:
module Tb();
integer add;
initial
begin
repeat(5)
begin
#1;
add = 40 + {$random} % (50 - 40) ;
$display("add = %d",add);
end
end
endmodule
RESULT:
add = 48
add = 47
add = 47
add = 47
add = 47
Now how to generate a random number between two ranges? The number should be between MIN1 and MAX1 or MIN2 and MAX2.The following example show how to generate this specification.
EXAMPLE:
module Tb();
integer add;
initial
begin
repeat(5)
begin
#1;
if($random % 2)
add = 40 + {$random} % (50 - 40) ;
else
add = 90 + {$random} % (100 - 90) ;
$display("add = %d",add);
end
end
endmodule
RESULT:
add = 97
add = 47
add = 47
add = 42
add = 49
All the random number generates above generate numbers of 32 vector. Not always the requirements are 32 bit .For example, to generate a 5 bit and 45 bit vector random number, the following method can be used.
EXAMPLE:
module Tb();
reg [4:0] add_1;
reg [44:0] add_2;
initial
begin
repeat(5)
begin
add_1 = $random ;
add_2 = {$random,$random};
$display("add_1 = %b,add_2 = %b ",add_1,add_2);
end
end
endmodule
RESULTS:
add_1 = 00100,add_2 = 111101000000110000100100001001101011000001001
add_1 = 00011,add_2 = 110110000110101000110110111111001100110001101
add_1 = 00101,add_2 = 100100001001000000000111100111110001100000001
add_1 = 01101,add_2 = 100010111011000011110100011011100110100111101
add_1 = 01101,add_2 = 101111000110001111100111111011110100111111001
Some protocols require a random number which is multiple some number. For example, Ethernet packet is always in multiples of 8bits,and PCIExpress packets are multiples of 4byts .Look at the following example. It generates a random number which is multiple of 3 and 5.
EXAMPLE:
module Tb();
integer num_1,num_2,tmp;
initial
begin
repeat(5)
begin
#1;
tmp = {$random} / 3;
num_1 = (tmp) * 3;
tmp = {$random} / 3;
num_2 = (tmp) * 5;
$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule
RESULT:
num_1 = 303379746,num_2 = -1064739195
num_1 = -2071669239,num_2 = -1309649305
num_1 = 112818957,num_2 = 1189058955
num_1 = -1295874969,num_2 = -1992863210
num_1 = 15983361,num_2 = 114806025
All the above example show that the random numbers are integers only. In verilog there is not special construct to generate a random real number. The following method shows the generation of random real number.
EXAMPLE:
module Tb();
integer num_1,num_2,num_3;
real r_num;
initial
begin
repeat(5)
begin
#1;
num_1 = $random;
num_2 = $random;
num_3 = $random;
r_num = num_1 + ((10)**(-(num_2)))*(num_3);
$display("r_num = %e",r_num);
end
end
endmodule
RESULT:
r_num = -2.071669e+03
r_num = 2641.189059e+013
r_num = 976361.598336e+01
r_num = 57645.126096e+02
r_num = 24589.097015e+0
To generate random real number , system function $bitstoreal can also be used.
EXAMPLE:
module Tb();
real r_num;
initial
begin
repeat(5)
begin
#1;
r_num = $bitstoreal({$random,$random});
$display("r_num = %e",r_num);
end
end
endmodule
RESULTS:
r_num = 1.466745e-221
r_num = -6.841798e-287
r_num = 2.874848e-276
r_num = -3.516622e-64
r_num = 4.531144e-304
|
本文地址:http://114er.blogspot.com/2010/12/ztverilogsystem-function-random-myth-28.html 原创文章如转载,请注明链接: 转自Welcome Funny Guys |

0 评论: