how to have the vdhl code add text to itself - vhdl

While trying to see if I could come up with a way to make the number of outputs variable by setting a "generic" I came up with the following thought. The idea would be to have a routine in the VHDL code inside the "port" declaration such that the routine would add the text "output(X) : out std_logic_vector(bits-1 downto 0); inside the "port" declaration. Please note that (X) represents the number of the output ports, i.e. output1, output2, etc. The idea being that when the VHDL parser reads the code it would see the required number of outputs when compiled. Is this something that can be done?

If I understood you correctly, you want to do meta-programming and have a generic number of ports. That's not possible in VHDL. However, you can just use a multidimensional array for that:
-- declare array type VHDL-2008-style
-- put this in a package
type slv_array is array(natural range<>) of std_logic_vector;
entity test is
generic (
-- number of outputs, at least one output
num_outputs : positive := 1
);
port (
my_inputs : in std_logic_vector(1 downto 0);
my_outputs : out slv_array(num_outputs - 1 downto 0)(1 downto 0)
);
end entity test;
You would then be able to use the component like this:
comp0 : component test
generic map (
num_outputs => 1
)
port map (
my_inputs => "10",
my_outputs(0) => my_output0
);
comp1 : component test
generic map (
num_outputs => 2
)
port map (
my_inputs => "00",
my_outputs(0) => my_output1
my_outputs(1) => my_output2
);

Related

Can we write to two signals from a port map statement?

This is perhaps more of a hypothetical VHDL question as opposed to a real-life/case study question.
Say I have a component declaration as follows...
component my_comp is
port (
A : in std_logic;
--...other input/outputs
B : out std_logic_vector(9 downto 0)
);
end component my_comp;
And within the same entity containing my_comp i have the signals
signal my_comp_full_scale_output : std_logic_vector(9 downto 0);
signal my_comp_8_scale_output : std_logic_vector(7 downto 0);
Is there a way which I can assign these two signals both the value of B in the port map statement of the component instantiation? Something like this maybe...
my_comp_isnt : my_comp
port map (
A => some_signal,
-- other signal assignments
B => my_comp_full_scale_output,
B(9 downto 2) => my_comp_8_scale_output
);
Once again I stress that this is totally playing with VHDL's logic and I am not using this in any design!!! I do know that this can easily be done with an assignment of my_comp_full_scale_output to my_comp_8_scale_output outside of the component instantiation such as below and this is simply a sake of code for code's sake.
my_comp_isnt : my_comp
port map (
A => some_signal,
-- other signal assignments
B => my_comp_full_scale_output
);
my_comp_8_scale_output <= my_comp_full_scale_output(9 downto 2);
No.
1076-2008 - IEEE Standard VHDL Language Reference Manual states:
Each association element in an association list associates one
actual designator with the corresponding interface element in the
interface list of a subprogram declaration, component declaration,
entity declaration, block statement, or package.
So you can only map it once.

VHDL - How to Define Port Map of a component with a package in its entity?

I am trying to use packages to shift block of data within different components via top level entity.
I have defined a package with array as
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package my_array_pkg is
type my_array is array ( 0 to 9) of std_logic_vector(3 downto 0);
end my_array_pkg;
Then in top level entity I have declared my components as,
COMPONENT Array_Count is
Port ( C_1Hz : in std_logic;
reset : in std_logic;
digit : out my_array
);
end COMPONENT;
Now can someone help me about how to declare this "digit : out my_array" in the port map.
C2 : Array_Count
PORT MAP ( CLK1HZ, RESET, ????);
The array package needed to be updated in other component.
Thanks.
You need to "use" the package before the entity declaration :
use work.my_array_pkg.all;
or
library my_library;
use my_library.my_array_pkg.all;
to make the package contents visible.
Then you need to declare a signal of that type before you instantiate the component, for example:
signal my_digit : my_array;
and now connect the port to that signal
C2 : Array_Count
PORT MAP (
C_1Hz => CLK1HZ,
reset => RESET,
digit => my_digit);

How can I extract elements from a record using an integer reference in VHDL?

Firstly here is what I'm aiming to do, using made-up VHDL syntax...
type type_johns_record is
first_element : std_logic;
second_element: std_logic_vector(3 downto 0);
third_element : boolean;
end record;
....
....
for ii in johns_record'range loop
if johns_record.type_johns_record'val(ii) = .... then
exit;
end if;
end loop;
Hopefully you can see that I'm trying to reference the elements of a record using similar syntax to that which can be used to reference an enumerated type. This however (of course) does not work. Is there a similar syntax that will work? My solution at the moment is to use a record_info field and work using std_logic_vectors as shown below....
type type_johns_record is record
first_element : std_logic;
second_element : std_logic_vector(3 downto 0);
third_element : boolean;
record_info : type_integer_array(2 downto 0);
end record;
function type_johns_record2slv(d : type_johns_record) return std_logic_vector is
begin
return (d.first_element & d.second_element & bool2sl(d.third_element));
end function;
constant johns_record_zero : type_johns_record := (first_element => '0',
second_element => "0000",
third_element => false,
record_info => (1, 4, 1));
-- can be used with any type for which a record_info is known
function get_record_element(input : std_logic_vector; element_number : integer; record_info : type_integer_array) return std_logic_vector is
variable r : type_slv32_array(record_info'length-1 downto 0);
variable pos : integer := 0;
begin
for ii in record_info'range loop
r(ii)(record_info(ii)-1 downto 0) := input(pos+record_info(ii)-1 downto pos);
end loop;
return r(element_number)(record_info(element_number)-1 downto 0);
end function;
I can then use these functions (which are in a package) as follows...
for ii in johns_record.record_info'range loop
if get_record_element(type_johns_record2slv(johns_record), ii, johns_record.record_info) = conv_std_logic_vector(4, johns_record.record_info(ii)) then
exit;
end if;
end loop;
This really sucks and specifying the record_info is error prone and only marginally less time consuming that writing out individual element comparisons line by line. Please offer a better solution!!!
In the IEEE VHDL Standards group, there are actually two proposals relating to this:
http://www.eda.org/twiki/bin/view.cgi/P1076/RecordMemberAttribute
and
http://www.eda.org/twiki/bin/view.cgi/P1076/RecordIntrospection
This does not mean relax, someone else will address the issue. Instead, we need you to comment on it and/or propose additional use models (to help with justification). All of our work is done by volunteers - just like you - no memberships required for basic participation. Much of our work is done on the TWIKI and email reflector and all with VHDL background are welcome to participate. Drop me an email, I will get you setup - see my Stack Exchange profile for details.
To participate, start here: http://www.eda.org/twiki/bin/view.cgi/P1076/
Current proposals:
http://www.eda.org/twiki/bin/view.cgi/P1076/CollectedRequirements
Meeting information:
http://www.eda.org/twiki/bin/view.cgi/P1076/MeetingMinutes
If you'd like to shorten your implementation code slightly, you could write a custom function for each record type (which you already have to do to convert to slv; this would just be a bit longer) that returns the nth element, like:
function get_record_element(input : johns_record_type; element_number : natural) return std_logic_vector is
begin
case element_number is
when 0 =>
return to_slv(input.first_element);
when 1 =>
return to_slv(input.second_element);
...
end function;
...
if get_record_element(johns_record, 2) = ... then
where to_slv is just a set of helper functions to convert other types. Is that more or less tedious than writing a more generic function and using an extra record element?
Instead of a record, then an array may be used, where the index value are based on an enumerated type, and the array elements are a super-set of the required type. Declaration like:
type johns_elements_t is (FIRST, SECOND, THIRD);
subtype johns_type_t is std_logic_vector(3 downto 0); -- Super-set of required types
type johns_array_t is array (johns_elements_t) of johns_type_t;
signal johns_array : johns_array_t;
Use is then like:
for johns_index in johns_array'range loop
if johns_array(johns_index) = "0000" then
exit;
end if;
VHDL attributes can be used to convert the values in the enumerated type between natural, like for example:
for natural_index in 0 to johns_elements_t'pos(johns_elements_t'high) loop
if johns_array(johns_elements_t'val(natural_index)) = "0000" then
Access to elements must then take into account how the contents is used for each elements accessed by the values in the enumerated type, but that is the case anyway when using a record, but now where is no type checking in the compiler. Another use case is:
if johns_array(FIRST)(0) = '1' then -- Used as std_logic
johns_array(FIRST)(0) <= '0';
...
In synthesis, the tool is likely to remove the unused bits in elements where only a subset of the bits are used, so the final design is not larger.
Also, some synthesis tools (for example Altera Quartus II) does not accept functions that return variable length results like std_logic_vector, so a solution for synthesis should taken that into account, since a functions like get_record_element may result in an error.

Generate ports in VHDL?

Is there a way to generate port declarations in VHDL? I would like to do something similar to #IFDEF for debug signals out to pins for an oscope. That way I can quickly enable or disable debug logic. For example:
entity my_entity is
port (
debug_label: if debug_on = 1 generate
debug1: out;
end debug_label;
....
);
end component;
When I try something like this is doesn't work. Is there any way to make it work? Or an alternative way to do something similar?
The ports can't be conditional, but the length of for example a
std_logic_vector can be configurable through a generic, and the length may
even be 0, resulting in null range. An entity showing this is:
entity mdl is
generic(
DEBUG_LEN : natural := 0);
port(
...
debug_o : out std_logic_vector(DEBUG_LEN - 1 downto 0));
end entity;
You should run a test synthesis to see how the your selected synthesis tool
handles null range when assigning to pins.

I don't understand what's wrong with this VHDL code?

I have the following code:
entity wave_select is
port( address:in std_logic_vector(6 downto 0);
ws1: in std_logic;
ws0: in std_logic;
wave_out: out std_logic_vector(6 downto 0));
end wave_select;
architecture choose_arch of wave_select is
signal internal_sine:std_logic_vector(6 downto 0);
signal internal_tri:std_logic_vector(6 downto 0);
signal internal_sqr:std_logic_vector(6 downto 0);
begin
U0: entity sine_tbl port map(addr=>address, sine_val=>internal_sine);
U1: entity triangle_tbl port map(addr=>address, tri_val=>internal_tri);
U2: entity square_tbl port map(addr=>address, square_val=>internal_sqr);
process (std_logic_vector'(ws1, ws0))
begin
case ws_combo is
when "01" => wave_out<=internal_sine;
when "10" => wave_out<=internal_tri;
when "11" => wave_out<=internal_sqr;
when others =>wave_out<=(others => '-');
end case;
end process;
end choose_arch;`
Whenever I try to compile this, I get the following errors:
Identifier/keyword expected (for the process line)
Keyword end expected (for the when "10" line)
Design unit declaration expected (for the same line as keyword error)
FIXED THE QUESTION
As it stands right now, this has a number of problems, mostly with fairly basic syntax.
Although it seems likely you mean the combination of ws0 and ws1 to be treated as ws_combo, you haven't done anything to tell the synthesizer that, so it treats ws_combo as simply undefined.
At least as far as I know, you can't combine signals in the process sensitivity list like you've done. The sensitivity list is to tell what external signals this process responds to, not much else.
You don't have a definition of wave_out (unless it's also in your entity declaration).
You don't have definitions of internal_sine, internal_tri, or internal_sqr. Hard to guess what type they should be without knowing the type of wave_out.
As an interim idea of how this might turn out, I've fixed some of the syntax errors, added an entity declaration that declares ws0, ws1 and wave_out, then sets wave_out to values suitable to the type I've given it (in this case, just took binary input and produced Grey code output).
entity controller1 is
port (
ws1 : in std_logic;
ws0 : in std_logic;
wave_out : out std_logic_vector(1 downto 0)
);
end;
architecture whatever of controller1 is
begin
impl: process(ws0, ws1)
begin
case std_logic_vector'(ws1,ws0) is
when "01" => wave_out<="01";
when "10" => wave_out<="11";
when "11" => wave_out<="10";
when others =>wave_out<=(others => '-');
end case;
end process;
end whatever;
Of course, this also needs the typical library and using to get declarations for std_logic and std_logic_vector, but with those added the synthesizer seems to accept it. Of course, some other synthesizer (I'm checked it with Synplify) might find a problem I missed, but I think that probably covers at least most of the obvious problems.
What are you attempting to achieve with the std_logic_vector' in this line?
process (std_logic_vector'(ws1, ws0))
If you just change that for the more conventional
process (ws1, ws0)
I imagine it will help.
But I assume ws_combo is a signal like
ws_combo = ws1&ws0;
so
process (ws_combo)
would be better still.

Resources