Can I call functions inside PORT MAPs? - vhdl

Can I call functions like:
label1: component_name PORT MAP (x AND y, b SSL 3, output);
In VHDL?
I searched a lot until I decided to post here, and also read the VHDL manual, but it doesn't say you can't. Although it doesn't show it's possible either.
I'm on macOS right now, so I can't test it.
EDIT: I'm using Altera Quartus 16.0
Thanks in advance!

It will depend a lot on the compiler unfortunately.
As a relevent aside, expressions such as
x and y
are treated differently from function calls
and_fn(x,y)
I have successfully used code with fully qualified associations, and function calls rather than expressions, such as:
label1: component_name
port map(
a => and_fn(x,y),
b => myfunc(),
c => output
);
The definitive document is the Language Reference Manual, but the point is moot - try it in your toolset, support and compliance varies.

Related

How to ignore one or more output bus pins for a module instantiation

I want to ignore one or more bits in an array argument for a module in SystemVerilog.
module x(in a, out [0:3] z);
...
endmodule
module tb;
logic my_a;
logic [1:3] my_z;
// I want to stop having to do this next line:
logic ignore_this_bit;
x myx(.a(my_a), .z({ignore_this_bit, my_z}));
endmodule
What is the proper syntax to do this? I have been doing it just as shown above with a declaration of ignore_this_bit and simply never connecting to that net. But it seems there should be a simpler way. Something like just using a comma and no variable name in the arguments for the module instantiation or maybe using something like 1'bX instead of an output argument bit, or something like that.
Is this affected by the fact that I am using big-endian bit ordering for the vectors here? (I hate it, but I am building code for an old CPU that uses that ordering and it's way easier to match my code to the existing than to fix it.)
This is a hard concept to search for, and I have tried. Does anyone have expertise that can help me know how to do this "the right way"? Thanks.
There is no special way in verilog for ignoring bits of the output. So, your way of using concat with an unneeded variable is a good way for doing it ({ignore_this_bit, my_z}). Naming of this variable is important for readability reasons.
It is not affected by the range description order. It looks like you are ignoring the left-most bit. And the bits are always ordered in the same way, no matter how you describe the range:
bits: 0011
[3:0]: 3 0
[0:3]: 0 3
concat: {ign, 0, 1, 1};
The other way around is to use a variable big enough to connect to the output and then use its bits:
logic [1:3] my_z;
logic [0:3] their_z;
x myx(.a(my_a), .z(their_z));
assign my_z = their_z[1:3];
You should not need to do anything here. This should just work truncating the MSB z[0]
x myx(.a(my_a), .z(my_z));
Think of an output port as an implicit continuous assignment
assign my_z = myx.z;
But if the MSB is not the bit you want to ignore, there is no simple solution. You might want to look at the net alias feature.

Updating VHDL generic map values in execution

Probably an easy one, but has been a while since I've dabbled in VHDL, but I'm trying to figure out how to properly change generic values of a sub-component after instantiation, when an event happens. Some pseudo code is below that jumps to the point:
U1: PARITY
generic map (N => 8)
port map (A => DATA_BYTE,
ODD => PARITY_BYTE);
....
process(Some_button_click)
begin
// Change generic map value for N (integer) in PARITY to 10 //
end process;
I'm not in front of the code, but I've tried using 'shared variables' to no avail.... any help is greatly appreciated as this has been strangely hard to google.
I understand what you want to do, but as far as I understand generics are mean to be used only to make components reusable and flexible. It does not make sense to change a constant value at run time. My suggestion is that if you need to change the value you better use a signal port

Halide::Expr' is not contextually convertible to 'bool' -- Storing values of functions in variables

I am new to using Halide and I am playing around with implementing algorithms first. I am trying to write a function which, depending on the value of the 8 pixels around it, either skips to the next pixel or does some processing and then moves on to the next pixel. When trying to write this I get the following compiler error:
84:5: error: value of type 'Halide::Expr' is not contextually convertible to 'bool'
if(input(x,y) > 0)
I have done all the tutorials and have seen that the select function is an option, but is there a way to either compare the values of a function or store them somewhere?
I also may be thinking about this problem wrong or might not be implementing it with the right "Halide mindset", so any suggestions would be great. Thank you in advance for everything!
The underlying issue here is that, although they are syntactically interleaved, and Halide code is constructed by running C++ code, Halide code is not C++ code and vice versa. Halide code is entirely defined by the Halide::* data structures you build up inside Funcs. if is a C control flow construct; you can use it to conditionally build different Halide programs, but you can't use it inside the logic of the Halide program (inside an Expr/Func). select is to Halide (an Expr which conditionally evaluates to one of two values) as if/else is to C (a statement which conditionally executes one of two sub-statements).
Rest assured, you're hardly alone in having this confusion early on. I want to write a tutorial specifically addressing how to think about staged programming inside Halide.
Until then, the short, "how do I do what I want" answer is as you suspected and as Khouri pointed out: use a select.
Since you've provided no code other than the one line, I'm assuming input is a Func and both x and y are Vars. If so, the result of input(x,y) is an Expr that you cannot evaluate with an if, as the error message indicates.
For the scenario that you describe, you might have something like this:
Var x, y;
Func input; input(x,y) = ...;
Func output; output(x,y) = select
// examine surrounding values
( input(x-1,y-1) > 0
&& input(x+0,y-1) > 0
&& ...
&& input(x+1,y+1) > 0
// true case
, ( input(x-1,y-1)
+ input(x+0,y-1)
+ ...
+ input(x+1,y+1)
) / 8
// false case
, input(x,y)
);
Working in Halide definitely requires a different mindset. You have to think in a more mathematical form. That is, a statement of a(x,y) = b(x,y) will be enforced for all cases of x and y.
Algorithm and scheduling should be separate, although the algorithm may need to be tweaked to allow for better scheduling.

SystemVerilog data type map to VHDL

my problem is that I have an int_array generic in a VHDL entity and I want to set it from my SV tb. Which is the correct SV data type to do it? I tried several possibilities but no one of them was correct.
Thanks in advance.
It's not possible to say exactly. Because the interface between VHDL and SystemVerilog isn't specified in any way, it's up to the simulator vendors to implement it in whatever way they see fit. You'll have to ask your EDA vendor if what you want is possible and if so, which data type you need to use.
Since you didn't provide any code, I'll just have to speculate that you had to define your array type before using it as a generic (as otherwise it doesn't compile):
package my_types_pkg is
type my_array_t is array (0 to 2) of integer range 0 to 255;
end package my_types_pkg;
This is probably how your DUT looks like:
entity dut is
generic (
int_array : my_array_t
);
end dut;
architecture dummy of dut is
begin
end dummy;
Because we've had to define a new type there, Questa requires us to import the type definition into the SystemVerilog world. This is where it gets proprietary. The way Mentor Graphics chose to do this is by compiling the VHDL package with the -mixedsvvh switch:
vcom -mixedsvvh dut.vhd
It's essential that the type is defined inside a VHDL package otherwise it won't get exported. Inside your SystemVerilog file you can just define a localparam of the my_array_t type and use that for your instantiation:
module top;
localparam my_types_pkg::my_array_t my_array = '{ 1, 2, 3 };
dut #(my_array) dut_inst();
endmodule // top
In the code above my_types_pkg is the package defined in VHDL, which was exported to SV with the -mixedsvvh switch.
Now comes the sad part. This doesn't work for me. Even though the types match, vsim still complains that the generic isn't valid. This answer should help you get started, though (what to search for in the docs, for example). Also try taking this case to Mentor Graphics support.

Can custom types be used in port declaration?

I am preparing for an exam by going through some old ones. One of the questions is:
Write the synthesizable behavioral VHDL code that implements the synchronous FSM in fig...
The FSM has one input, called request, that is of enumeration type with values (r1, r2, r3)...
That makes me want to write this code:
entity fsm is
port ( clk : in std_logic;
request : in my_enum_type
);
end fsm;
And somewhere have a:
type my_enum_type is (r1, r2, r3);
somewhere (I have tried right befor the port declaration and right after the architecture declaration).
But I can't seem to get that to work.
Can I have custom types as inputs or outputs like that?
Yes you can, and I regard it as best practice - it means least work, best understanding, easiest maintenance, and cleanest design.
The trick is to declare the types common to your whole design in a package (I usually call it "Common" :-) and add use work.Common.all before the entity declaration AND in every customer of that entity. More specialised components can have appropriate names, of course!
For example:
package Common is -- untested...
type my_enum_type is (r1, r2, r3);
-- (optional) useful tools
function to_slv (e : my_enum_type) return std_logic_vector;
function to_enum (s : std_logic_vector(my_enum'length downto 0))
return my_enum_type;
end Common;
package body Common is
-- subprogram bodies here
end Common;
Now when you add a value to the enumeration, you ONLY modify "Common" and rebuild the design, while those who follow conventional guidelines are still trying to identify every port and signal where they have to increase the range of their "std_logic_vector" by 1.
Works really well for bus interfaces too, where a record in each direction hides all the individual bus and handshaking signals.
You WILL have to fight brain-dead tools like Xilinx "automatic testbench generator" which will helpfully translate ALL your port types - integer or boolean as well as custom - into std_logic(_vector) and then fail to compile. Just translate them back again.
You can still make a case that at the very top level, all the external FPGA pins should still be std_logic based. And if you ever need to simulate a post-synthesis version of your design, then you will either need to live with std_logic_vector ports, or add a simple wrapper to convert from one form to the other.

Resources