Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] how to calculate log2(n) in verilog

Status
Not open for further replies.

UFK

Member level 3
Joined
Mar 8, 2010
Messages
60
Helped
3
Reputation
6
Reaction score
3
Trophy points
1,288
Location
Pakistan
Activity points
1,728
Hiii
can someone please help me to calculate log base 2 in Verilog. What i need to do is to simply calculate the log base to of a variable n. Please help
 

Code:
function integer clogb2;
   input [31:0] value;
   integer 	i;
   begin
      clogb2 = 0;
      for(i = 0; 2**i < value; i = i + 1)
	clogb2 = i + 1;
   end
endfunction
 

    UFK

    Points: 2
    Helpful Answer Positive Rating
Thanks alot RBB. I hope my code starts behaving well now. Thanks again.
 

Dear RBB

The function code you gave me is good but i cant call it. Im simply trying to calculate the log base 2 of 26 n save it to a register n_var. Please correct this code for me. Its as follows

module sample11(n_var);

output [15:0]n_var;
n_var = clogb2(26);



function integer clogb2;
input [31:0] value;
integer i;
begin
clogb2 = 0;
for(i = 0; 2**i < value; i = i + 1)
clogb2 = i + 1;
end
endfunction

endmodule

Thanks alot
 

Code:
module sample11(v,n_var);

input  [15:0]v;
output [15:0]n_var;

wire [15:0] v;
reg [15:0]n_var;
reg [15:0]value;

always @ (v)
n_var = clogb2(v);



function integer clogb2;
input [31:0] value;
integer i;
begin
clogb2 = 0;
for(i = 0; 2**i < value; i = i + 1)
clogb2 = i + 1;
end
endfunction

endmodule


it is a simple testbench:

Code:
module test();
  
  reg [15:0] v;
  reg i;
  wire [15:0] n_var;
  
  sample11 s1(v,n_var);
 
 initial
  v = 2; 
  
  initial
  #2000 $finish;
   
 always
  begin
      #5 v = v+1;
  end
  
  always @ (v)
  $monitor ("log%d = %d", v, n_var);
  
endmodule
 

    UFK

    Points: 2
    Helpful Answer Positive Rating
Dear meher81

Thankyou very much for your code. It simulates great. I just have to figure out a thing or two in it. Thanks alot.

Im stuck in another little piece of code now. I wondr if you can help me with it. Its supposed to scan an array for 16 elements and calculate the maximum value. Its as follows:

module maxvalue(b_array);

input [0:15] b_array;
integer i;
reg [0:15] mxm;

initial
begin
mxm = 16'b0;

for (i=0;i<15;i=i+1)
begin
if (b_array > mxm)
mxm = b_array;
end
end

endmodule

I just cant figure out how to write the testbench for it. I gave initial values to the b_array in the tb as follows:

module max11_tb();

// Inputs
reg [0:15] b_array;

// Instantiate the Unit Under Test (UUT)
maxvalue uut (
.b_array(b_array)
);

initial begin
// Initialize Inputs
b_array [0]= 13;
b_array [1]= 1;
b_array [2]= 2;
b_array [3]=14;
b_array [4]=12;
b_array [5]=0;
b_array [6]=-1;
b_array [7]=21;
b_array [8]=12;
b_array [9]=2;
b_array [10]=-4;
b_array [11]=0;
b_array [12]=9;
b_array [13]=13;
b_array [14]=10;
b_array [15]=-2;


// Wait 100 ns for global reset to finish
#100;

// Add stimulus here

end

endmodule

It isnt giving me the largest value as expected.
Please let me know if you can find a solution to it. Thanks alot
 

Dear UFK
Verilog doesn't allow an I/O port to be a 2-D array.
but if it it is necessary, you could flatten your array into a vector and pass that through the port.
Code:
module maxvalue(
                b_array,
                mxm,
                reset
                );

input  [255:0] b_array;
input reset;
output [15:0] mxm;


reg  [15:0] array [0:15];
integer i;
reg [15:0] mxm;


always @ (b_array)
	begin
   if (reset)
     mxm = 0;

  	{array[15],array[14],array[13],array[12],array[11],array[10],array[9],array[8],array[7],array[6],array[5],array[4],array[3],array[2],array[1],array[0]}=b_array;	
  	
	 for (i=0;i<16;i=i+1)	
		 	if (array[i] > mxm)
		 	mxm = array [i];
	end

endmodule

simple test module
Code:
module max11_tb();

reg  [255:0] b_array;
wire [15:0] max;
reg reset;

maxvalue uut (
			 .b_array(b_array),
			 .mxm (max),
			 .reset (reset)
			 );
			 
initial
  begin
    reset = 1;
   #10 reset = 0;
  end
 

initial
  begin
    #7 b_array = 255'd1;
    #10 b_array = 255'd2;
    #15 b_array = 255'd197879804;
    #20 b_array = 255'd200000000000000000003;
  end

always @ (b_array)
	$monitor  ($time, "maximum value component = %d", max );

endmodule
 

    UFK

    Points: 2
    Helpful Answer Positive Rating
Dear meher81

Thanks alot for your help. You just made my life easier :)
 

Dear meher81

I am using the code u helped me with to scan values in a bram and then calculate maximum value. I stored 16 values in a bram by a coe file. Now im trying to run the following code by invoking the bram (spiht_mem). Since i already gave the values in the coe file i have no clue what to write in the testbench. Can u please help me? Thankyou in advance.

The code is
module maxvalue( b_array,mxm,reset,addrA,clkA);

input [255:0] b_array;
input reset;
output [15:0] mxm;
input clkA;
input [15:0] addrA;


Spiht_mem M1 (
.clka(clkA),
.wea(), // Bus [0 : 0]
.addra(addrA), // Bus [15 : 0]
.dina(), // Bus [15 : 0]
.douta(array)); // Bus [15 : 0]

reg [15:0] array [0:15];
integer i;
reg [15:0] mxm;


always @ (b_array)
begin
if (reset)
mxm = 0;
//[15:0] array[0:15]= b_array;
{array[15],array[14],array[13],array[12],array[11],array[10],array[9],array[8],array[7],array[6],array[5],array[4],array[3],array[2],array[1],array[0]}=b_array;

for (i=0;i<16;i=i+1)
if (array > mxm)
mxm = array ;
end

endmodule
 

I don't know what you want.
I guess that you have stored some values in a file (as bram.dat) and want to apply them to your code, which detect maximum value. yes?
 

Hii meher81

Yes that is exactly what i want. I was testing my algorithm to work for 16 values initially but i wanted my code to work for as many values as i want, say for a 128 x128 image which means that if i load 16384 decimal values in my bram as a .coe file it should call the values from the bram and then scan for the maximum decimal value.
Btw if i call values from the bram using (.dout(w1[0:b]) where w1 is a wire do u think it will work?

Part of my code is like this
reg [31:0] LIS5a [1023:0];
.
.
.
FiveA M1 (.douta(LIS5a));

here FiveA is my bram in which i have loaded a .coe file of 1024 decimal values. I want to call those values so i tried moving them directly in to the reg LIS5a instead of using wire w1. Any suggestions or comments?

Thanks alot for all the help :)
 

Dear UFK
you can do this in a testbench. at first, store file content in an array using $readmemb. after that you can do, with the array elements, what you want.
 

meher81 said:
Dear UFK
you can do this in a testbench. at first, store file content in an array using $readmemb. after that you can do, with the array elements, what you want.

Dear meher81

I did what u suggested and everything worked brilliantly, until i realized that $readmemh will not take negative hex values from my text file. Im back at square one now ! :(((( Do u have a solution to this problem?
Previously i tried using a bram, but i couldnt figure out how to move its .coe file contents in to my array.
Please help me.
And thanks alot for everything
 

Dear UFK

you should change your negative numbers to 2's complement format. (perhaps with MATLAB or manually!)
 

Hii meher81

I did change it to negative format (e.g -1 to FFFFFFFF) and it still isnt quite working. Please do me this big favour. Im posting my code, test bench and txt file. Can u plz run it and see the results? I know ull know wat im doing wrong.

module max_val(mxm,
reset
);
input reset;
output [31:0] mxm;
reg [31:0] Mem [0:3];


integer i;
reg [31:0] mxm;

initial $readmemh("D15.txt",Mem);

always @ *
begin
if (reset)
mxm = 0;

for (i=0;i<=3;i=i+1)
if (Mem > mxm)
mxm = Mem ;
end
endmodule


Testbench
module max_val_tb;

// Inputs
reg reset;

// Outputs
wire [31:0] mxm;

// Instantiate the Unit Under Test (UUT)
max_val uut (
.mxm(mxm),
.reset(reset)
);

initial begin
// Initialize Inputs
reset = 0;

#100;

reset = 1;

end

endmodule

and the text file
//D15 =


29B
043
FFFFFE72
FFFFFEE7

//667
//67
//-398
//-281

wat i figured is that if my text file has the following numbers in hex form i.e -10,-11,-12,10,11,12, the code simply ignores the positive values and computes the maximum of the negative values, for instance in this case it will return -10 which is the max.

Maybe ud know a solution.
And thanks a million for always coming to my rescue :)
 

Code:
module max_val (
				mxm,
				in,
				reset
				);
input reset;
input  [ 31 : 0 ] in;

output [ 31 : 0 ] mxm;

wire   [ 31 : 0 ] in;

integer k;
integer i;
integer  mxm;

always @ (in or reset)
	begin
		if (reset)
			mxm = 0;
		else 
			k=in;
		if (k>mxm)
			mxm <= k;
	end

endmodule

Testbench:
Code:
module max_val_tb;

wire [31:0] mxm;

reg reset,clk;
reg [31:0] Mem [0:3];

integer i;
integer input_data;

max_val uut (
			.mxm(mxm),
			.in(input_data),
			.reset(reset)
			);

initial $readmemh("D15.txt",Mem);

initial 
	begin
		reset = 1;
		#2 reset = 0;
	end

initial
	clk =0;

always
	#5 clk=~clk;

initial 
	i=0;

always @ (posedge clk)
	begin
		input_data = Mem[i];
		i = i+1;
		$monitor ("max = %d, input=%d", mxm, input_data);
	end

endmodule

Added after 24 minutes:

I did that same as you, but in this way, after the reset, mxm is set to zero. therefore this code neglect negative numbers. to solve that, you can do same as below:
Code:
module max_val (
				mxm,
				in,
				reset
				);
input reset;
input  [ 31 : 0 ] in;

output [ 31 : 0 ] mxm;

wire   [ 31 : 0 ] in;

integer k;
integer i;
integer  mxm;

always @ (in or reset)
	begin
		if (reset)
			mxm = 32'h80000001;
		else 
			k=in;
		if (k>mxm)
			mxm <= k;
	end

endmodule
Testbench:
Code:
module max_val_tb;

wire [31:0] mxm;

reg reset,clk;
reg [31:0] Mem [0:3];

integer i,m;
integer input_data;

max_val uut (
			.mxm(mxm),
			.in(input_data),
			.reset(reset)
			);

initial $readmemh("D15.txt",Mem);

initial 
	begin
		reset = 1;
		#2 reset = 0;
	end

initial
	clk =0;

always
	#5 clk=~clk;

initial 
	i=0;

always @ (posedge clk)
	begin
		input_data = Mem[i];
		i = i+1;
		m=mxm;
		$monitor ("max = %d, input=%d", m, input_data);
	end

endmodule
 

Dear meher

Maybe you could solve another one of my neverending problems.
Im posting my code below. If possible, Please run it and see if it can be altered to function the way i want. My code isnt reading negative hex values. It only gives correct results for positive hex values. Can anything be done about it?

1. I have two arrays LIP and LSP. readmem will put memory values into LIP.

2. The code is supposed to read the four values from LIP and compare with the parameter T.

3. If greater than T, then move values to LSP.

4. If less than T, then leave it in LIP

5. The bit counters seem to function fine.

My code is

module test();

reg [31:0] Signbit_ctr;
reg [31:0] Bit_ctr0;
reg [31:0] Bit_ctr1;

reg[31:0] T=32'h00001000; //decimal 4096

integer i;
integer k;

reg [31:0] LIP [0:3];
reg [31:0] LSP [0:1023];


initial $readmemh("D16.txt",LIP);

initial
begin

Signbit_ctr = 0;
Bit_ctr0 = 0;
Bit_ctr1 = 0;

end


always @ (LIP)
begin
for(i=0;i<=3;i=i+1)

if (LIP >= T)

begin

LSP = LIP;

Bit_ctr1 = Bit_ctr1 + 1;
Signbit_ctr = Signbit_ctr + 1;

end
else
begin

Bit_ctr0 = Bit_ctr0 + 1;
$display("%d:%h",i,LSP);

end

end
endmodule

and the text file D16 is


12F2
FFFFFD3E
FFFFFF78
FF

Thankyou so much
 

Dear meher81
I need you help.
Im posting a code which u wrote for me a few months ago. Its a part of my encoder. It just wont synthesize. Maybe you can help.


The code is
module Log_max(v,n_var,T);

input [31:0]v;
output [31:0]n_var;
output reg [31:0] T=0;


wire [31:0] v;
reg [31:0]n_var;
reg [3:0] base = 2;

always @ (v)
n_var = CLogB2(v);

always@(*)
begin
T = base ** n_var;
end

//ceil of the log base 2
function integer CLogB2;
input [31:0] Depth;
integer i;
begin
i = Depth;
for(CLogB2 = 0; i > 1; CLogB2 = CLogB2 + 1)
i = i >> 1;
end
endfunction
endmodule

Testbench

module Log_max_tb;

// Inputs
reg [31:0] v;

// Outputs
wire [31:0] n_var;
wire [31:0] T;

// Instantiate the Unit Under Test (UUT)
Log_max uut (
.v(v),
.n_var(n_var),
.T(T)
);

initial begin
// Initialize Inputs
v = 32'h00000B43;


end

endmodule

It gives correct result but cannot synthesize. Please help
Thankyou
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top