Verilog: Cross module reference for pure functions - verilog

Are pure (only accessing input regs) functions synthesizable when they are accessed as a cross module reference?
Example:
// a module with functions inside
module functions;
function fn1;
input reg i;
fn1 = i;
endfunction
endmodule
// must be synthesizable vvv
module consumer(input i, output o);
functions fns();
assign o = fns.fn1(i);
endmodule

It's perfectly synthesizable because a pure function gets in-lined into the combinatorial logic inside the the calling module. There are no cross-module reference to any signals after that. But many synthesis tools haven chosen not to handle any kind of cross-module reference, even if the hierarchy gets flattened.
In SystemVerilog you would define a function inside a package and then import the package into your module. Any synthesis tools that supports the most basic SystemVerilog constructs also supports this.

It's not possible in Verilog. (yes, that's the complete answer ffs)

Related

Continus assignment to verilog module instance

Is it possible to use assign keyword with module instances?
Lets assume I have a module logarithm which works as it's intended. In some other module, I want to have: A = log(B) + log(C).
Is there any efficient way other than the following to do so?
wire [3:0] logB;
wire [3:0] logC;
Logarithm log(logB, B);
Logarithm log(logC, C);
assign A = logB + logC;
And is it known as a gate-level design or a data-flow one?
If it is not data-flow, would you please present a data-flow alternative to this code?
Well your assign keyword in the code is not working on module instances. Rather, it is working on the outputs of those module instances.
The way you are assigning to A should help you get the desired output provided you have set its width accordingly. And it is a data flow representation
There is one mistake in your given lines of code though. You can not use the same instance name log for both the instantiations of the module Logarithm. They have to be unique.

Using Outputs From Two Other Module (Verilog)

I have a quick question.
How can I use the outputs of two other modules with a new module?
Example:
module test1(ans, X, Y)
output ans;
input X, Y;
do stuff
endmodule
module test2(ans2, X, Y)
output ans2;
input X, Y;
do stuff
endmodule
module result(final_ans, ans, ans2) <------- this is what I mean.
do stuff
endmodule
How would I go about this? How do I call the other two modules?
Thank you for the help.
You do not call modules. You instance modules. Verilog is not like normal programming languages, it is a hardware simulation language. If you stick to a subset of the language and you use that in the right way that language can also be converted to real hardware. That latter is called RTL (Register Transfer Language). I strongly suggest you find some existing Verilog code examples and study how people use it.
Thus what you do is you make an instance of each module and you connect
signals to the inputs and outputs. Compare it to placing an IC on a board and soldering wires to it. But then all in software.
test1 instance_of_test1 (
.X(signal_into_X),
.Y(signal_into_Y),
.ans(signal_outof_ans)
);
Then you can use the signals coming out of test1 and test2 to go into result:
result instance_of_result (
.ans(signal_outof_ans),
.ans2(signal_outof_ans2),
.final_ans(signal_outof_final_ans)
);
Just as a side note:
The example I use also shows that naming conventions using the port direction is general a bad idea. Signals come out of one module and go into another. Thus the name signal_outof_ans is fine for the module test1 but it is wrong for the module result as there it goes into the module. Here I wanted to emphasize what happens at the level of module test1. (I also know that some companies even prescribe it as the preferred coding style so I am waiting for the flak to arrive on this). In my own code I would never use this. So here is the correct way to code:
wire ans,ans2;
test1 instance_of_test1 (
.X(X),
.Y(Y),
.ans(ans)
);
...
...
result instance_of_result (
.ans(ans),
.ans2(ans2),
.final_ans(final_ans)
);

Instantiate vector of custom modules in Verilog with additional parameters

I have a custom module in Verilog that takes several inputs and a few parameters.
module modA (
input inp1, input inp2, ... output out);
parameter my_addr;
...
endmodule
For various reasons associated with the specific hardware that I'm using, I need to create many instances of this module, each time with a different parameter (because my_addr corresponds to a specific location in memory that I am then accessing from the host). Moreover, I would like an easy way to access all of the outputs. I thought of doing something like
wire [9:0] outputs;
modA #(.my_addr) all_modA[9:0](.inp1(inp1), .inp2(inp2), .out(outputs));
So then I would have a vector of elements of all_modA, and the nth element of outputs would correspond to the nth instantiation of modA. That sounds like it would work well, except I need to pass a unique address to each instantiation. When I was just doing one instantiation at a time, it was quite easy to just define a parameter, but I don't see how I could pass a unique identifier each time.
Is there any way to accomplish this? The problem is, if I use a for loop, then I don't see how I can instantiate each modA with a unique identifier. If I don't use a for loop, then I'm not sure how to add a unique identifier.
You can use a generate block over here. Generate blocks are evaluated during elaboration of the design. They do not execute at simulation time and the result is determined before the simulation begins. Therefore, all expressions in generate schemes shall be constant expressions, deterministic at elaboration time.
Give different values to my_addr according to the requirement. Also, you can apply some label identifier to begin-end block. This as an optional feature for generate blocks, but very highly recommended. By doing so, a unique hierarchical path can be seen to every instance of modA is different for each module.
For your code, I have created a testbench that instantiates the module with changing value of my_addr and outputs bus driving the out signal.
module modA #(parameter int my_addr) (input inp1, input inp2,output out);
initial $display("%m: %d",my_addr);
endmodule
module top();
wire [9:0] outputs;
genvar i; // generate iterator
generate
for(i=0;i<9;i++) begin: some_identifier
// my_addr = i+1 for every module
modA #(.my_addr(i+1)) all_modA(.inp1(inp1), .inp2(inp2), .out(outputs[i])); // Multiple modules
end
endgenerate
endmodule
For more information, refer to IEEE 1800-2012 Section 27. Similar questions can be found here and here.

SystemVerilog error 10748

I am using SystemVerilog to handle a 3-dimensional array. My code is as follows.
module sub_bytes();
reg [7:0] word_stream_reg [0:1][0:1]= '{'{8'hFF,8'hA4},'{8'h50,8'hC6}};
reg [7:0] test = word_stream_reg[0][1][7:0];
endmodule
I get this error:
Error (10748): Verilog HDL error at sub_bytes.v(6): expression in variable declaration assignment to test must be constant
I spent about 4 hours but could not find the reason for this error. I would be grateful if anyone could assist me in this.
Even if some tools allow it, it is a very bad programming practice to initialize a static variable with a another static variable. This is refereed to the "static initialization fiasco" in many programming languages. Outside of a procedural context, there is no defined ordering of static initializers.
Assigning a constant value to a variable does not make that variable a constant. It's still a variable as far as the compiler is concerned.
What you probably want to do is use a parameter instead of a variable.
parameter logic [7:0] word_stream_reg [0:1][0:1]= '{'{8'hFF,8'hA4},'{8'h50,8'hC6}};
Note: Since you are using SystemVerilog, use logic instead of reg.
As #Qui say referencing another variable for initialisation does not work with some simulators.
Why not use:
reg [7:0] word_stream_reg [0:1][0:1]= '{'{8'hFF,8'hA4},'{8'h50,8'hC6}};
wire [7:0] test = word_stream_reg[0][1][7:0];

Can we have an array of custom modules?

Can we have an array of instances for a custom module?
For example: we can have input [15:0] a; - this creates a bus. Can we do same thing for custom modules, i.e. DFF [15:0] d;, where DFF is a custom module?
Here I intend to create 16 instances of the DFF module.
Verilog arrays of instances were added in Verilog-1995 (IEEE 1364-1995). They can be used with gates, user-defined primitives, and modules. Generates, which are more powerful but also more complex, were added in Verilog-2001.
Here is an example array of module instances:
DFF d[15:0] (clk, DFF_i, DFF_o);
For each port connection, if the size matches that of the formal parameter then it is connected to every instance. Otherwise each instance is connected to a part-select (or bit-select) of the expression.
it is not possible to do this directly (update: now after mark4o's answer I know that there is a way), but what you can do is using the generate statement to create multiple instances of your custom module and hook them up to your signals. Should look something like this:
wire DFF_i[15:0];
wire DFF_o[15:0];
generate
genvar i;
for (i=0; i<15; i=i+1) begin : dff
custom i_custom(
.clk(clk)
,.input(DFF_i[i])
,.output(DFF_o[i])
);
end
endgenerate
Otherwise there are probably some possibility during synthesis to use the correct custom modules, but I'm not an expert there.
Cheers,
Daniel

Resources