Logarithm in Verilog - verilog

I've a statement in verilog looking like integer level = log(N) (Where N is a parameter and level is to be determined) But I understand I cannot do complex math statements in verilog, so I'm wondering if there is an alternative solution to the above problem?
Any feedback appreciated!

If it is a logarithm base 2 you are trying to do, you can use the built-in function $clog2().

The answer to ADDRESS WIDTH from RAM DEPTH describes a couple ways to evaluate constant logarithms in this situation.

Verilog has functions for natural logarithm ($ln()), decadic logarithm ($log10()) and ceiling of binary logarithm ($clog2()). In constant expressions they should be synthesizable, but actual support by tools varies.
The following is synthesizable Verilog code:
module test(output [31:0] a, b, c);
assign a = 1000 * $ln(123);
assign b = 1000 * $log10(123);
assign c = 1000 * $clog2(123);
endmodule
E.g. after RTL synthesis with Yosys (e.g. yosys -p 'prep; write_verilog -noattr' test.v):
module test(a, b, c);
output [31:0] a;
output [31:0] b;
output [31:0] c;
assign a = 32'd4812;
assign b = 32'd2090;
assign c = 32'd7000;
endmodule

But I understand I cannot do complex math statements in Verilog
Verilog is first and foremost a hardware description language. What hardware log(N) statement is describing? Modern FPGAs consist of LUTs, flops, small embedded memories, simple DSPs that implement MAC (multiply-accumulate) primitives. log(N) and other complex math statements cannot be mapped directly into those primitives. The same goes with ASICs.
By analogy, log(N) doesn't get executed by a processor. It calls a bunch of lower-level assembly instructions to do so. Those assembly instructions are part of the log(N) library (C, C++, etc.)
To be able to synthesize log(N) for ASIC/FPGA it requires an instance of a log(N) IP core.

I like to think of (logarithm base n of value) as answering the question "How many base n digits do I need to represent 'value' independent numbers?" (Keeping in mind that 0 counts as a number)
Thinking of it that way, you can implement your own log base 2 in SystemVerilog:
function bit [31:0] log_base_2 (bit [31:0] log_input);
bit [31:0] input_copy;
bit [31:0] log_out = 0;
input_copy = log_input;
while(input_copy > 0)begin
input_copy = input_copy >> 1;
log_out = log_out + 1;
end
log_out = log_out - 1;
if(log_input != (1 << log_out))
log_out = log_out + 1;
return log_out;
endfunction

Related

Can't figure out the correct amount of bits for an output

Well, my task is to create a n(n is a multiple of 4) bit cla (carry lookahead adder) using 4 bit cla and multiplexers. Specifically, I have to implement the following:
The part that is in brackets has to be repeated as many times as need for the parameter n that is given. My Question is: how should I define the wires r,t and c?
At first I thought the following:
wire [3n/4-3-1:0] c; // without considering the first wire that comes out of the right most cla4
wire [n - 4 - 1:0] r,t;
This does indeed work for n>4 (8,12,16...) but there is an obvious problem when n=4 ([-1:0]).
Is there a way I can get around this? One simple solution would be to have these wires be more bits that needed, but I am stuck trying to think of another solution.
Try this.
localparam M = (N>4) ? (3*N)/4 - 3 : 1;
localparam L = (N>4) ? N-4 : 1;
wire [M-1:0] c;
wire [L-1:0] r,t;

Create matrix of instances in veriloga

Is it possible do create an crossbararray of memristormodules with two for loops in veriloga? I have the following code but it does not work:
module variable_crossbar(I, V);
`define size 4
output [`size:1] I;
electrical [`size:1] I;
input [`size:1] V;
electrical [`size:1] V;
genvar i,j;
analog begin
for(i = 1; i < `size; i = i + 1) begin
for(j = 1; j <= `size; j = j + 1) begin
JART_VCM_2 mem_'j'_'i' ( V[j] , I[i] ); //memristormodulefile is included
end
end
end
endmodule
Verilog-A is not a standard by itself. It is described in Appendix C of the Verilog-AMS LRM (which you provided a link to).
Verilog-AMS was standardized based on the pre-existing implementation. As such, it is a set of analog extensions mixed with IEEE 1364-2004 Verilog, and a tiny bit of IEEE 1800 SystemVerilog (the string type). Verilog-AMS standardization was all done at Accellera. Normally Accellera standards feed into IEEE standards, but this proved to be problematic since by the time the possibility of IEEE standardization arose, IEEE 1364 Verilog was superseded by IEEE 1800 SystemVerilog. IEEE does not normally allow standards based on other superseded standards. There has been work on upgrading to SystemVerilog-AMS but this is a mammoth task and has not yet borne any fruit.
Verilog-A and Verilog-AMS should support generate and genvar.
From what I can tell pure Verilog-A does not support instantiating modules with generate loops. Verilog-AMS, a superset language of Verilog-A, does.
Verilog-A and Verilog-AMS are frequently referred to interchangeable in my research. From what I can tell, the original Verilog-A was derived from Verilog (IEEE1364-1995) syntax; adding analog features (Ex: electrical, V(), etc.) and removing digital features (reg, always, etc.). The latest version of Verilog-AMS merged Verilog (IEEE1364-2005) with Verilog-A, supporting both syntax and features in one language. Oddly, Verilog-AMS LRM explicitly refers to IEEE1364-2005, buts does not mention Verilog-A despite using the same analog syntax. Maybe they are near identical competing languages, or maybe there is some trademark issue over the names, or some other convoluted reason I couldn't figure out in the time I allocated to look up Verilog-A and Verilog-AMS.
With Verilog-AMS you can use the Verilog approach to instantiating modules with generate loops. Note the you cannot use the index in the instance name. It is recommenced to name the generate blocks (loop_i,loop_j in this example). Also not it is recommened to use parameter instead of `define to prevent polluting the global space.
module variable_crossbar(I, V);
parameter SIZE 4; // `define are global space and assigned by compile order
output [SIZE:1] I;
electrical [SIZE:1] I;
input [SIZE:1] V;
electrical [SIZE:1] V;
genvar i,j;
generate
for(i = 1; i < SIZE; i = i + 1) begin : loop_i
for(j = 1; j <= SIZE; j = j + 1) begin : loop_j
JART_VCM_2 mem ( V[j] , I[i] ); //memristormodulefile is included
end
end
endgenerate
endmodule
Again, from what I can tell pure Verilog-A does not support instantiating modules with generate loops. So hopefully what you really mean is Verilog-AMS. And hopefully your simulator supports the the features.

Determine whether a binary number is of power of two in verilog code

I am trying to determine whether a binary number is of power of two (in other words, is it of one-hot encoding).
I found a method to do so, but it is for integer.
Could anyone help to transform the method for usage with binary number in verilog ?
There's nothing wrong with your codeā€”it's limitations of the tool you are using.
Verilator requires code with inputs and outputs so it can be stimulated and results displayed.
It also doesn't like performing logical operators on multi-bit operands.
module is_power_of_two(output reg f);
reg [7:0];
initial begin
#1 v = 8'b11110000;
#1;
end
always #(*) f = v != 0 && !((v & v - 1) != 0);
endmodule

Is there a mandate for the variable to be of data type "integer" for arithmetic operations "+" and "-"?

Following is the code for finding factorial of a number. If I declare "i" as "register", the output (z) remains 1, irrespective of the input. If it is declared as "integer", I get the proper result. Why is it so? Please explain.
module Factorial_calc(n, z);
input [5:0] n;
output reg [64:0] z;
reg i;
// integer i;
always #(n)
begin
i=0;
z=1;
while(i<n)
begin
i=i+1;
z=i*z;
end
end
endmodule
Because your integer is 32 bits wide and your reg is only one bit wide. Your simulation should not finish for most values of n, let alone produce a result.
HDL is not like any other programming language. Beware that even if your code simulates it does not mean it will work in hardware. In your case it will not synthesize. You value of n is undefined at compile time.
Last be not least do NOT use x or z for variables, They are too easily confused with 'x or 'z.

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.

Resources