I want to make my integer type signal range depend on output of some procedure i.e. something like this
procedure blah( signal A : in std_logic_vector(0 to 1); signal B : inout integer)
Begin
Case A is
When "00" => B <= 215;
When "01" => B <= 300;
When others => B <= 105;
end case;
End;
Next I want to use output from this procedure to define signal range of say type integer
Blah(A,myrange);
Signal myint: inout integer range 0 to myrange/23;
The difficulity is I can not use procedure in declaration of architecture, is there any way to define variable range for integer or is there a way to define integer range within architecture part after begin statement
As explained in the comments you cannot have a variable range for integer type. VHDL is a Hardware Description Language. On a pure hardware point of view, what would an integer type with variable range mean? Suppose you use the myint
signal as an input of an adder. If its type changes during the lifetime of your hardware, it means that you have some dynamic silicon too. Some transistors would appear suddenly when the type range increases, and they would vanish when the type range decreases. It does not really make sense, does it?
So, if you understand this constraint, you must also understand that there is no need for varying signals to define your type. What you need is plain constant values that can be computed statically at the beginning of the simulation or logic synthesis. Two possibilities here:
First case: this A
input that you use to compute the range is really an input of your design that can change during the lifetime of your hardware (switches of your board, for instance). Then, you must dimension your type to the worst case (300/23
), such that it is always sufficient, even when A
takes the worst case value "01"
:
signal myint: integer range 0 to 300 / 23;
Note: there is no mode specification for internal signal declarations, no inout
. Internal signals can always be assigned and read. It is entity ports, for instance, that have a mode (in
, out
...) constraining how they can be used.
Second case: this A
value is constant during the lifetime of your hardware. To make the point very clear, it means that if you decide to program an FPGA or to manufacture an Integrated Circuit (IC) with your design, you will fix the value of A
before programming the FPGA or manufacturing the IC and the hardware will work only with this value. No way to change it afterwards without re-programming the FPGA or manufacturing another IC.
Then, if you are in this case, it would be much better to declare it as a generic parameter than as an input port or an internal signal. This is exactly what generic parameters are intended for. And, as explained in the comments, you cannot use a procedure here, but you can use a function. As your procedure has only one output, a function also does the job:
entity foo is
generic(A: std_logic_vector(0 to 1));
port(...);
end entity foo;
architecture rtl of foo is
function blah(val: in std_logic_vector(0 to 1)) return integer is
begin
case val is
when "00" => return 215;
when "01" => return 300;
when others => return 105;
end case;
end function blah;
signal myint: integer range 0 to blah(A) / 23;
If you really also need this procedure during operations (for a completely different purpose than declaring types), you can even use the function to define the procedure:
procedure blah(signal A: in std_logic_vector(0 to 1); signal B: out integer) is
begin
B <= blah(A);
end procedure blah;
Note that I changed the mode of B
to out
instead of inout
because... it is only used as an output by your procedure, never as an input.