There is a reg variable containing huge data array. This variable is declared and initialized inside a module.
I created a function inside the Verilog module to access this external data. Surprisingly, I am able to do so without any trouble.
So, is there any reason I should pass the values as input to the function when it can just access the external variables?
Here is a code example to show what I mean
module TestModule (
input clock,
output Out
);
// Variable declared outside the function
reg [7:0] externalVariable [10:0];
// Function declaration
function [7:0] myFunction;
input arg;
begin
myFunction = externalVariable[arg];
end
endfunction
always @(posedge clock) begin
// Assign a value to the external variable
Out <= myFunction(1);
end
endmodule
I simulated the above example and it works. But why?
If you're talking about Verilog, the scope rules are defined in 1364-2005 12.7. SystemVerilog may have made some minor changes, but probably not, since that would break stuff. The rules state that
If an identifier is referenced directly (without a hierarchical path) within a task, function, named block, or generate block, it shall be declared either within the task, function, named block, or generate block locally or within a module, task, function, named block, or generate block that is higher in the same branch of the name tree that contains the task, function, named block, or generate block.
So, within the function, you can directly reference something declared in the enclosing module.
Should you do this? Up to you. If you have any programming background, you would probably rather die first. Functions are meant to encapsulate functionality; pulling in arbitrary stuff from outside breaks this. It also makes the function 'impure', which isn't a concept in Verilog, but is probably the reason that you can't do fancy compile-time stuff in Verilog (things like pre-calculating filter coefficients, for example, which is common in Other HDLs, and has been for decades). SystemVerilog has added a concept of pure functions, so maybe they fixed that.
Interestingly, if you use a hierarchical identifier, you can access anything you want, anywhere. Again, whether this is good or bad is up to you, but don't do it in synthesisable code. It can be fantastically useful in testbenches, and I make extensive use of it in code which is compiled down to produce Verilog. Interestingly, the inability to use hierarchical identifiers like this in An Other HDL was always a major flaw, and took years to fix.