+ Post New Thread
Results 1 to 8 of 8
  1. #1
    Newbie level 3
    Points: 27, Level: 1

    Join Date
    Apr 2020
    Posts
    4
    Helped
    0 / 0
    Points
    27
    Level
    1

    VHDL: Default Record for generic type

    Hi,

    I am currently trying to implement the VHDL-2008 construct Generic Package. For this I have a generic type, which I want to initalize with a default record. Does anyone know if an if so how this is possible?
    I would like the colored part of the code to be similar even though it obviously does not work exactly like this.

    Code:

    Code:
    package GenericPkg is
      generic (
        type myType is record 
            myValue : integer ;
        end record ;
      ) ;
    
      ...
    
    end GenericPkg ;

    Thanks a lot!

    •   AltAdvertisement

        
       

  2. #2
    Advanced Member level 5
    Points: 38,675, Level: 48
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,983
    Helped
    2063 / 2063
    Points
    38,675
    Level
    48

    Re: VHDL: Default Record for generic type

    This is not how generic types work.

    a generic list can have a type as a generic. But internally you do not have any knowledge of that type. Hence you cannot get access to the default value, because it doesnt exist.

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    package record_pkg is
      type myType is record
        myValue : integer;
      end record;
    end package;
     
    package GenericPkg is
      generic (
        type some_type   -- the user will specify the type when the package is instantiated
      )
    end package GenericPkg;
     
    package MyNewPkg is new GenericPkg generic map (some_type => work.myType );



    •   AltAdvertisement

        
       

  3. #3
    Newbie level 3
    Points: 27, Level: 1

    Join Date
    Apr 2020
    Posts
    4
    Helped
    0 / 0
    Points
    27
    Level
    1

    Re: VHDL: Default Record for generic type

    I'm aware of that. I may have expressed myself a little unclearly.
    The passed record is generic but always contains a fixed attribute and optionally others. This fixed attribute must be accessed in the GenericPkg.The GenericPkg is also passed a function that returns the record data type. Unfortunately, due to backwards compatibility reasons, the function cannot be converted into a procedure with two outputs, one with the fixed attribute and one generic record without the fixed attribute. I was hoping that it would be possible to set a default type for the generic datatype and then access the fixed attribute in the GenericPkg.
    I had already expected that it probably wouldn't work, but I still wanted to draw on the collective knowledge of this forum before I stopped my efforts and instead chose a simpler but also suboptimal way for my specific case.



    •   AltAdvertisement

        
       

  4. #4
    Advanced Member level 5
    Points: 38,675, Level: 48
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,983
    Helped
    2063 / 2063
    Points
    38,675
    Level
    48

    Re: VHDL: Default Record for generic type

    I am still confused, particularly as the code in your original post is syntactically incorrect and makes little sense, as specifying a type in a generic is not generic (you cannot even supply a default for a generic type). It might be easiest to post the actual code?
    Other parts of your post make me think you're talking about unconstrained types rather than generic types? these are two different things.
    A generic type can still be assigned an unconstrained type, but you cannot use any array attributes of a generic type because you have no visibility of the type.

    There is a good discussion here as to why getting the initial value of a generic type is not possible:

    TL:DR - how can you have an INIT_VAL attribute for an unconstrained type?

    So, I think the answer you are looking for is that no, its not possible, but I suspect you are trying to do things in the wrong way.



  5. #5
    Newbie level 3
    Points: 27, Level: 1

    Join Date
    Apr 2020
    Posts
    4
    Helped
    0 / 0
    Points
    27
    Level
    1

    Re: VHDL: Default Record for generic type

    The actual code looks like this:

    Code:
    package GenericPkg is
      generic (
        type complex_data_type;
        function Match( A, B : complex_data_type ) return boolean;
        function Print( obj : complex_data_type ) return string;
      );
    
      procedure Check( A, B : in complex_data_type ); 
    end GenericPkg;
    
    package body GenericPkg is
      procedure Check( A, B : in complex_data_type ) is
        variable row : line;
      begin
        if not Match( A, B ) then
          write(row, Print(A));
          write(row, Print(B));
        end if;
      end procedure;
    end GenericPkg;
    
    
    package my_functions_pkg is
      function my_match ( A, B : my_complex_data_type ) return boolean;
      function my_print ( obj : my_complex_data_type ) return string;
    end my_functions_pkg;
    
    package body my_functions_pkg is
      function my_match ( A, B : my_complex_data_type ) return boolean is
      begin
         if(...) then
           return false;
         end if;
         return true;
      end function my_match
    
      function my_print ( obj : my_complex_data_type ) return string;
      begin
        return ("Informations stored in obj"...);
      end function my_print;
    end my_functions_pkg;
    
    package my_Pkg is new GenericPkg
      generic map (
        complex_data_type  => my_complex_data_type,
        Match              => my_match,
        Output             => my_print
      );
    But I want more information from the match function. If it is not matched I want to know what exactly it failed and display it in the print function.
    So I want to add an additional data_type as output of the match function and input of the print function to display more detailed info. But as functions can only have one output in VHDL, I have the possibility to store it in one record (but then i need to access the boolean value inside this record, which seems not to be possible) or I change the match function into a procedure with to outputs - the boolean and the information data type- this second way would work perfectly, but has been considered as too different from the previous version.



  6. #6
    Advanced Member level 5
    Points: 38,675, Level: 48
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,983
    Helped
    2063 / 2063
    Points
    38,675
    Level
    48

    Re: VHDL: Default Record for generic type

    Looks like you're trying to get more information out of the OSVVM Scoreboard package :)

    You can do what you want, as Ive done it. The trick is to compare everything as a string. Because you've already written a to_string function. so you can just compare the two results as strings char by char, giving you a char by char matching that you can then have reported in the log. What mine also does is allow you to put 'X' in the expected string to force a match with the actual value. This is useful when, for example, you have byte enables and you only want to check the "valid" bytes in the bus.

    So, here is what I do. First off, have a "match_string" function, that returns a string that comapres two strings char by char, and returns a string that has 'X' where there is a missmatch between the two string:

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    --------------------------------------------------------------------------------------------
    -- Takes 2 strings and produces another strings that marks missmatches
    --------------------------------------------------------------------------------------------
    function match_string(s1, s2          : string;
                          match_char      : character := ' ';
                          missmatch_char  : character := 'X';
                          s1_ignore       : string    := "";
                          s2_ignore       : string    := "" ) return string is
     
      variable ret      : string(s1'range);
      variable s1_local : string(s1'range) := s1;
      variable s2_local : string(s2'range) := s2;
    begin
      assert (s1'length = s2'length)
        report "match_string: S1 and S2 lengths must match" & LF
              & "S1 = " & s1 & LF
              & "S2 = " & s2
          severity FAILURE;
     
      for i in s1'range loop
        ----------------------------------------------------------------------------
        -- Force a match on ignore chars
        ----------------------------------------------------------------------------
        for j in s1_ignore'range loop
          s1_local(i) := s2_local(i) when s1_local(i) = s1_ignore(j);
        end loop;
     
        for j in s2_ignore'range loop
          s2_local(i) := s1_local(i) when s2_local(i) = s2_ignore(j);
        end loop;
     
        ret(i) := match_char when (s1_local(i) = s2_local(i)) else missmatch_char;
      end loop;
     
      return ret;
    end function match_string;

    then a procedure that does what you suggested - returns the matching string (with Xs in it) and whether it was a complete match or not

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    procedure match_string( constant s1, s2          :       string;
                            constant match_char      :       character := ' ';
                            constant missmatch_char  :       character := 'X';
                            constant s1_ignore       :       string    := "";
                            constant s2_ignore       :       string    := "";
     
                            variable match_str       : inout line;
                            variable matched         :   out boolean )   is
    begin
      DEALLOCATE(match_str);
      matched       := false;
      match_str     := new string'( match_string(s1, s2, match_char, missmatch_char, s1_ignore, s2_ignore) );
     
      -- return missmatch on any missmatch char
      for i in s1'range loop
        if match_str(i) = missmatch_char then return; end if;
      end loop;
     
      matched       := true;
    end procedure;

    then finally, the magic match_X_generic function that can take any data type so you can plug it directly to the scoreboard package of osvvm

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    function match_X_generic generic ( type data_t;
                                       function to_string(d : data_t) return string is <> )
                             parameter( act, exp    : data_t )
                             return boolean is
      variable matched    : boolean;
      variable match_str  : line;
    begin
      match_string( s1          => to_string(act),
                    s2          => to_string(exp),
                    s2_ignore   => "X-"          ,
                    match_str   => match_str     ,
                    matched     => matched        );
     
      if not matched then
        -- Dont Use Alert, as this will come in Scoreboard
        log(TBTOOLS_ALERT_ID, "act: " & to_string(act), ALWAYS);
        log(TBTOOLS_ALERT_ID, "exp: " & to_string(exp), ALWAYS);
        log(TBTOOLS_ALERT_ID, "     " & match_str.all , ALWAYS);
      end if;
     
      DEALLOCATE(match_str);
     
      return matched;
    end function match_X_generic;

    so then, in your log, you can get output like this every time the scoreboard performs a check:

    Code:
    %% Log   ALWAYS  in testbench_tools_pkg, act: tid: 0x00 tdata: 0x9B3EC00E13ECBA2E tuser: 0xXXXXA5420F6560 tkeep: 0xFF tlast: 0  at 5570 ns
    %% Log   ALWAYS  in testbench_tools_pkg, exp: tid: 0x00 tdata: 0xFFFFFFFFFFFFFFFF tuser: 0xXXXXA5420F6560 tkeep: 0xFF tlast: 0  at 5570 ns
    %% Log   ALWAYS  in testbench_tools_pkg,                         XXXXXXXXXXXXXXXX                                               at 5570 ns
    %% Alert ERROR   in Filtered Packet Checker,    Received: tid: 0x00 tdata: 0x9B3EC00E13ECBA2E tuser: 0xXXXXA5420F6560 tkeep: 0xFF tlast: 0    Expected: tid: 0x00 tdata: 0xFFFFFFFFFFFFFFFF tuser: 0xXXXXA5420F6560 tkeep: 0xFF tlast: 0    Item Number: 1 at 5570 ns
    Last edited by TrickyDicky; 4th April 2020 at 11:12.



  7. #7
    Newbie level 3
    Points: 27, Level: 1

    Join Date
    Apr 2020
    Posts
    4
    Helped
    0 / 0
    Points
    27
    Level
    1

    Re: VHDL: Default Record for generic type

    That's exactly what I want to do.
    And it looks like I can use some of your code for my case.
    But unfortunately I compare data packets with a length of up to 1500 bytes. So I do not want to output the whole data, but only the number of the first erroneous byte and the stored values in actual and expected.
    In my case I verify an packet-based network which routes the packet to the corresponding output stored in the address bits.
    I know that I could push and check each byte separately, but then it would become very chaotic if a hole packet would be routed to a wrong port.



    •   AltAdvertisement

        
       

  8. #8
    Advanced Member level 5
    Points: 38,675, Level: 48
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,983
    Helped
    2063 / 2063
    Points
    38,675
    Level
    48

    Re: VHDL: Default Record for generic type

    In my case, all packets are sent on an AXIS bus, and I generate whole ethernet packets and break them into AXIS transactions, and compare on the AXI bus. I do this because I have an AXIS interface I can send the packets to and do the checking for me. If I had N checkers (for each endpoint) I can check each packet transaction by transaction. But like you say you can copy some of my ideas if you want to check at a higher level.

    I hope you get what you need working. Am always willing to help.



--[[ ]]--