Generics in VHDL -- Starting with VHDL-2008, VHDL has added support for generics,
-- which are similar to type parameters in other languages.
library IEEE ;
use IEEE.STD_LOGIC_1164. ALL ;
use IEEE.NUMERIC_STD. ALL ;
-- As an example of a generic function, SlicesIndex takes
-- an array of any type and an element of that type and returns
-- the index of the first occurrence of v in s, or -1 if not present.
-- Note that VHDL doesn't have a direct equivalent to Go's 'comparable'
-- constraint, so we'll use a generic function for comparison.
entity SlicesIndex is
generic (
type T ;
function "=" ( a , b : T ) return boolean
);
port (
s : in T_ARRAY ;
v : in T ;
result : out integer
);
end SlicesIndex ;
architecture Behavioral of SlicesIndex is
begin
process ( s , v )
begin
result <= - 1 ;
for i in s 'range loop
if s ( i ) = v then
result <= i ;
exit ;
end if ;
end loop ;
end process ;
end Behavioral ;
-- As an example of a generic type, List is a
-- singly-linked list with values of any type.
package List_pkg is
generic ( type T );
type List ;
type List_ptr is access List ;
type List is record
value : T ;
next : List_ptr ;
end record ;
procedure Push ( lst : inout List_ptr ; v : in T );
function AllElements ( lst : List_ptr ) return T_ARRAY ;
end package List_pkg ;
package body List_pkg is
procedure Push ( lst : inout List_ptr ; v : in T ) is
variable new_node : List_ptr ;
begin
new_node := new List '( value => v , next => null );
if lst = null then
lst := new_node ;
else
new_node . next := lst ;
lst := new_node ;
end if ;
end procedure ;
function AllElements ( lst : List_ptr ) return T_ARRAY is
variable result : T_ARRAY ( 0 to 999 ); -- Assuming max 1000 elements
variable i : integer := 0 ;
variable current : List_ptr := lst ;
begin
while current /= null loop
result ( i ) := current . value ;
i := i + 1 ;
current := current . next ;
end loop ;
return result ( 0 to i - 1 );
end function ;
end package body List_pkg ;
-- Main testbench
entity testbench is
end testbench ;
architecture behavior of testbench is
type string_array is array ( natural range <> ) of string ( 1 to 3 );
constant s : string_array := ( "foo" , "bar" , "zoo" );
function string_eq ( a , b : string ) return boolean is
begin
return a = b ;
end function ;
-- Instantiate SlicesIndex
component SlicesIndex is
generic (
type T ;
function "=" ( a , b : T ) return boolean
);
port (
s : in T_ARRAY ;
v : in T ;
result : out integer
);
end component ;
signal index_result : integer ;
-- Instantiate List
package IntList_pkg is new List_pkg generic map ( T => integer );
use IntList_pkg. all ;
signal lst : List_ptr := null ;
begin
-- Test SlicesIndex
index_inst : SlicesIndex
generic map ( T => string ( 1 to 3 ), "=" => string_eq )
port map ( s => s , v => "zoo" , result => index_result );
process
begin
wait for 10 ns ;
report "index of zoo: " & integer 'image ( index_result );
-- Test List
Push ( lst , 10 );
Push ( lst , 13 );
Push ( lst , 23 );
wait for 10 ns ;
report "list: " & integer 'image ( AllElements ( lst )( 0 )) & " " &
integer 'image ( AllElements ( lst )( 1 )) & " " &
integer 'image ( AllElements ( lst )( 2 ));
wait ;
end process ;
end behavior ;
This VHDL code demonstrates concepts similar to generics in Go. The SlicesIndex
function is implemented as a generic entity, and the List
is implemented as a generic package. The main testbench shows how to use these generic components.
Note that VHDL’s type system and generics work differently from Go’s, so some adaptations were necessary. For example, VHDL doesn’t have a built-in concept of “comparable” types, so we pass in a comparison function instead. Also, VHDL doesn’t have dynamic memory allocation, so the linked list implementation uses access types (pointers) instead.
To run this VHDL code, you would typically use a VHDL simulator like ModelSim or GHDL. The process of compiling and running VHDL code varies depending on the tool used, but generally involves compiling the code and then running a simulation.