Create matrix of instances in veriloga - verilog

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.

Related

Is $clog2 task supported in Verilog HDL?

When I used it in a program an error was generated ($clog2 is not supported). But I see our StackOverflowers using $clog2 task in their program. Please tell me how to use that.
$clog2 is not supported by Verilog. It is a SystemVerilog system task. Moreover, system tasks are not synthesizable.
However, you can make a function/macro which outputs the log bsae 2 value of a given number. Here are some of the examples of user defined implementation:
Using macro:
`define CLOG2(x) \
(x <= 2) ? 1 : \
(x <= 4) ? 2 : \
(x <= 8) ? 3 : \
(x <= 16) ? 4 : \
(x <= 32) ? 5 : \
(x <= 64) ? 6 : \
..etc, ..
(x <= 4294967296) ? 32 : \
-1
parameter MAX_VALUE = 42;
parameter MAX_WIDTH = `CLOG2(MAX_VALUE);
Using function:
function [31:0] log2;
input [31:0] value;
integer i;
reg [31:0] j;
begin
j = value - 1;
log2 = 0;
for (i = 0; i < 31; i = i + 1)
if (j[i]) log2 = i+1;
end
endfunction
initial
begin
$display("10 = %d", log2(10));
end
Both the above examples leads to synthesizable code. The user can extend this code as per the maximum bit width requirement.
So, you can either change the compiler to compile SystemVerilog code or implement the above function to make a user-defined log code.
$clog2is supported by Verilog, but only Verilog-2005 (IEEE Std 1364-2005). Since Verilog-2005 was released at the same time as IEEE's SystemVerilog, it is generally considered a SystemVerilog enhancement. Here are two source documenting $clog2 as a Verilog-2005 feature:
Sutherland HDL - Busting the Myth that SystemVerilog is only for Verification ยง 9.6 Expression size functions
Xilinx - Verilog $clog2 function implemented improperly
The Verilog-2005 was mostly an intermediate release for eventual merger of Verilog and SystemVerilog (which happened in IEEE Std 1800-2009). Some simulators may have not implanted Verilog-2005 as everything in it is included in SystemVerilog. If your simulator does not run Verilog-2005 by default, then refer to your manual which may included a option to enable it. Enabling SystemVerilog is another option, or user methods as described in sharvil111's solution.
Just wanted to point out that $clog2 is a synthesizable construct and can be handled by most tools. It does not become unsynthesizable simply because it is a system task.
For example, the following is a synthesizable statement:
logic [$clog2(WIDTH) - 1 : 0] addr;

How to prevent ISE compiler from optmizing away my array?

I'm new to Verilog, ISE, FPGAs. I'm trying to implement a simple design into an FPGA, but the entire design is being optimized away. It is basically an 2D array with some arbitrary values. Here is the code:
module top(
output reg out
);
integer i;
integer j;
reg [5:0] array [0:99][0:31];
initial begin
for(i=0;i<100;i=i+1) begin
for(j=0;j<32;j=j+1) begin
array[i][j] = j;
out = array[i][j];
end
end
end
endmodule
It passes XST Synthesis fine, but it fails MAP in the Implementation process. Two Errors are given:
ERROR:Map:116 - The design is empty. No processing will be done.
ERROR:Map:52 - Problem encountered processing RPMs.
The entire code is being optimized away in XST. Why? What am I doing wrong?
The reason your design is being synthesized away is because you have not described any logic in your module.
The only block in your design is an initial block which is typically not used in synthesis except in limited cases; the construct mainly used for testbenches in simulation (running the Verilog through ModelSim or another simluator).
What you want is to use always blocks or assign statements to describe logic for XST to synthesize into a netlist for the FPGA to emulate. As the module you provided has neither of these constructs, no netlist can be generated, thus nothing synthesized!
In your case, it is not entirely clear what logic you want to describe as the result of your module will always have out equal to 31. If you want out to cycle through the values 0 to 31, you'll need to add some sequential logic to implement that. Search around the net for some tutorials on digital design so you have the fundamentals down (combinational logic, gates, registers, etc). Then, think about what you want the design to do and map it to those components. Then, write the Verilog that describes that design.
EDIT IN LIGHT OF COMMENTS:
The reason you are get no LUT/FF usage on the report is because the FPGA doesn't need to use any resources (or none of those resources) to implement your module. As out is tied to constant 31, it will always have the value of 1, so the FPGA only needs to tie out to Vdd (NOTE that out is not 31 because it is only a 1-bit reg). The other array values are never used nor accesses, so the FPGA synthesized them away (ie, not output needs to know the value of array[0][1] as out is a constant and no other ports exist in the design). In order to preserve the array, you need only use it to drive some output somehow. Heres a basic example to show you:
module top( input [6:0] i_in, // Used to index the array like i
input [4:0] j_in, // Used to index the array like j
output reg [5:0] out // Note, out is now big enough to store all the bits in array
);
integer i;
integer j;
reg [5:0] array[0:99][0:31];
always #(*) begin
// Set up the array, not necessarily optimal, but it works
for (i = 0; i < 100; i = i + 1) begin
for (j = 0; j < 32; j = j + 1) begin
array[i][j] = j;
end
end
// Assign the output to value in the array at position i_in, j_in
out = array[i_in][j_in];
end
endmodule
If you connect the inputs i_in and j_in to switches or something and out to 6 LEDs, you should be able to index the array with the switches and get the output on the LEDs to confirm your design.

Verilog: Adding individual bits of a register (combinational logic, register width is parameterizable)

I am trying to come up with a way to add individual bits of a register.
eg, if regA = 111000 then regB = 3 (Sum of bits of regA).
1) Is there any synthesizable function/operator in Verilog or SystemVerilog which I can directly use to do this operation?
If not, then maybe the problem is a little interesting, especially because the operation has to be done in one clock cycle (pure combinational logic) and the register width is parameterizable.
2) In case there is no inbuilt Verilog or SystemVerilog operator then what can be done?
Thanks,
Ujjwal
Verilog (IEEE Std 1364-2001 or newer):
integer i;
always #* begin
B = WIDTH_LOG2'b0;
for (i=0; i<WIDTH; i=i+1)
B = B + A[i];
end
SystemVerilog (IEEE Std 1800-2005 or newer):
always_comb begin
B = '0; // fill 0
foreach(A[i])
B += A[i];
end
Both will synthesize to combination logic. No latches or flops.
SystemVerilog does have $countones(), but I'm unsure if it is synthesizable. Ff it is then: always_comb B = $countones(A)
You can try something like this. I am not exactly sure what it will synthesize to but it should work.
int i;
reg [`WIDTH-1:0] A;
reg [`WIDTH_LOG2:0] B;
B = 0;
for(i = 0; i < `WIDTH; i = i + 1)
begin
B = B + A[i];
end
Of course there are more complex ways that may have better performance, depending on on your tool flow and what is available, where you can create your own adders and cascade them in parallel reducing the size each step. Assuming the width was 32-bits, something like:
adder1bit_1(output1, A[31:24]);
adder1bit_2(output2, A[23:16]);
adder1bit_3(output3, A[15:8]);
adder1bit_4(output4, A[7:0]);
adder3bit_1(output5, output1, output2);
adder3bit_2(output6, output3, output4);
adder4bit(final_ouput, output5, output6);

Generate statement inside verilog task

I want to use generate statement inside a task. The following code is giving compile errors (iverilog).
task write_mem; //for generic use with 8, 16 and 32 bit mem writes
input [WIDTH-1:0] data;
input [WIDTH-1:0] addr;
output [WIDTH-1:0] MEM;
integer i;
begin
generate
genvar j;
for(j=0; j<i;j++)
MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
endgenerate
end
endtask // write_mem
I also tried putting generate just after the line integer i, but still its producing errors. Any thoughts?
EDIT: I also tried putting genvar declaration between begin and generate statement in the above code. Its still producing compiler errors
Thanks in advance,
Jay Aurabind
What you are trying is not possible - a generate region (generate..endgenerate block) is only allowed in the module description (aka "top level"), i.e. the same level where you have parameters, wires, always- and inital-regions, etc. (see Syntax 12-5 in the IEEE Std. 1364-2005). Within a task a generate region is e.g. as invalid as an assign statement.
However, you can use a non-generate for-loop in a task (this is also synthesizeable).
Either way, you can not count from 0 to i-1 in synthesizeable code as 'i' is not constant. Also note that j++ is not valid verilog, you must write j=j+1 instead. Finally you probably want to use a nonblocking assignment (<=) instead of a blocking assignment (=), but this depends on how you intent to use this task.
genvars should be defined before the generate statement:
genvar j;
generate
for(j=0; j<i;j++)
MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
endgenerate
Although your usage here does not look like it needs a generate statement a for loop would have done.
As pointed out by #CliffordVienna generate statements are for building hierarchy and wiring based on compile time constants. ie parameters can be changed for reusable code but are constant in a given simulation. Tasks do not contain hierarchy and therefore the use of a generate is invalid.
Any for loop that can be unrolled is synthesizable, some thing like:
task write_mem; //for generic use with 8, 16 and 32 bit mem writes
input [WIDTH-1:0] data;
input [WIDTH-1:0] addr;
output [WIDTH-1:0] mem;
integer i = WIDTH / 8; // CONSTANT
begin
for(j=0; j<i;j++) begin
mem[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
end
end
endtask // write_mem
Tasks are synthesizable as long as they do not contain any timing control, which yours does not. From the information given this should be synthesizable.
NB: I would separate data width and addr width, they might be the same now but you might want to move to 8 bit addressing and 16 bit data.

Logarithm in 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

Resources