如何模拟C++;VHDL-2008或以上版本的课程 VC++有一种方法,用VHDL函数和VHDL记录来模拟C++类中的数据封装特性吗?我在诸如“c”之类的语言中多次看到过这种类型的事情,但在VHDL中很少看到

如何模拟C++;VHDL-2008或以上版本的课程 VC++有一种方法,用VHDL函数和VHDL记录来模拟C++类中的数据封装特性吗?我在诸如“c”之类的语言中多次看到过这种类型的事情,但在VHDL中很少看到,vhdl,Vhdl,具体地说,我想将所有类数据公开给类的每个方法,只是为了保持简单 C++示例: class item_t { public: uint32_t addr; uint32_t data; bool valid; }; class keeper_t { public: item_t data[100]; void put(uint32_t addr, uint32_t data);

具体地说,我想将所有类数据公开给类的每个方法,只是为了保持简单

C++示例:

class item_t {
   public:
       uint32_t addr;
       uint32_t data;
       bool     valid;
};

class keeper_t {
    public:
        item_t data[100];
        void     put(uint32_t addr, uint32_t data);
        uint32_t get(uint32_t addr);
};
关于如何用VHDL模拟上述代码,我的想法是创建一个记录来保存类数据,并在每次将其传递到每个函数中以保存类的状态。我在VHDL中使用这种技术的问题是,如何修改传递到函数中的“类”数据结构?在向调用进程返回结构时,VHDL确实非常有限。例如:

library ieee;
use ieee.std_logic_1164.all;

--------------------------------------------------
package ADT is

  constant A_OK        :integer := 0;
  constant max_keepers :natural := 100;

  type keeper_item_t is record
    addr     :std_logic_vector(31 downto 0);
    data     :std_logic_vector(31 downto 0);
    valid    :std_logic;
  end record;  

  type keeper_t is array (0 to max_keepers) of keeper_item_t;

  function keeper_new return keeper_t;
  function keeper_add(signal k :inout keeper_t) return integer;
  function keeper_get(signal k :inout keeper_t; signal kitem: out keeper_item_t) return integer;

end package ADT;

--------------------------------------------------
package body ADT is

  function keeper_new return keeper_t is
      variable rkeeper :keeper_t;
  begin
      rkeeper(0).addr  <= X"AABBCCDD";
      rkeeper(0).data  <= X"10101010";
      rkeeper(0).valid <= '0';
      return rkeeper;
  end function;

  function keeper_add(signal k :inout keeper_t) return integer is
  begin
      k(0).addr  <= X"12345678";
      k(0).data  <= X"BEEF1234";
      k(0).valid <= '1';
      return A_OK;
  end function;

  function keeper_get(signal k :inout keeper_t; signal kitem: out keeper_item_t) return integer is
    variable kitem: keeper_item_t;
  begin
      kitem := k(0);
      return A_OK;
  end function;

end package body;

--------------------------------------------------
entity testbench is
end entity;

--------------------------------------------------
architecture sim of testbench is
begin

process
    variable kp :keeper_t;
    variable ki :keeper_item_t;
    variable ok :integer;
begin
        kp := keeper_new;   
    ok := keeper_put(kp);
    ki := keeper_get(kp);       
    wait;
end process;

end architecture;
为了解决这个问题,我想我需要传入一个VHDL“访问指针”,而不是keeper\t结构本身。如果我这样做,那么我将向函数传递一个只读指针,该指针反过来指向可以修改的实际数据结构

    type Keeper_Ptr_t is access keeper_t;

    --Dereferencing a VHDL Access Type: The suffix .all is 
    --  used to de-reference a pointer, i.e. it gives 
    --  you the thing pointed to by the pointer.
因此,我也尝试了使用访问类型的方法:

library ieee;
use ieee.std_logic_1164.all;

--------------------------------------------------
package ADT is

  constant A_OK        :integer := 0;
  constant max_keepers :natural := 100;

  type keeper_item_t is record
    addr     :std_logic_vector(31 downto 0);
    data     :std_logic_vector(31 downto 0);
    valid    :std_logic;
  end record;  

  type keeper_t is array (0 to max_keepers) of keeper_item_t;

  type keeper_ptr_t is access keeper_t;

  function keeper_new return keeper_t;
  function keeper_add(kp: keeper_ptr_t) return integer;
  function keeper_get(kp: keeper_ptr_t) return keeper_item_t;

end package ADT;

--------------------------------------------------
package body ADT is

  function keeper_new return keeper_t is
      variable rkeeper :keeper_t;
  begin
      rkeeper(0).addr  <= X"AABBCCDD";
      rkeeper(0).data  <= X"10101010";
      rkeeper(0).valid <= '0';
      return rkeeper;
  end function;

  function keeper_add(kp: keeper_ptr_t) return integer is
  begin
      kp.all(0).addr  <= X"12345678";
      kp.all(0).data  <= X"BEEF1234";
      kp.all(0).valid <= '1';
      return A_OK;
  end function;

  function keeper_get(kp: keeper_ptr_t) return keeper_item_t is
  begin
      return kp.all(0);
  end function;

end package body;

--------------------------------------------------
entity testbench is
end entity;

--------------------------------------------------
architecture sim of testbench is
begin

process
    variable kp :keeper_t;
    variable ki :keeper_item_t;
    variable ok :integer;
begin
    kp := keeper_new;   
    ok := keeper_put(kp);
    ki := keeper_get(kp);       
    wait;
end process;

end architecture;
这是可能的

我从中学到:

(1) 将记录的访问指针作为“变量”类型传递到过程中。不要将函数用于类方法

(2) 使用“inpure function”为“class”创建新方法,使用“new”关键字返回新分配的记录


您还需要查看vhdl 2002中的受保护类型。它们类似于类,因为它们可以具有成员函数和带有内部变量的过程。vhdl 2008中存在一些限制,例如无法传递入/出访问类型,orc有它们的数组(两者在vhdl 2019中都已修复)。但仍然完全有可能构建队列或随机数据包生成器之类的东西

Type pt is protected
  Procedure add_one;
  Function get_val return integer;
End protected pt;

Type pt is protected body
  Variable x : integer;

  Procedure add_one is
  Begin
   X := x + 1;
  End  procedure;

  Function get_val return integer is
  Begin
    Return x;
  End function get_val;
End protected body pt;

.....

Process
  Variable ptv : pt;
Begin
  Ptv.add_one;
  Ptv.add_one;

  Report to_string(ptv.get_val);
  Wait;
End process;
OSVVM是一个很好的例子,它广泛使用了受保护的类型(以及2008年的一般特性)

我从中学到:

(1) 将记录的访问指针作为“变量”传递到过程中 类型。不要将函数用于类方法

(2) 使用“不纯函数”为“类”创建新方法, 使用“new”关键字返回新分配的记录

你可以做得更好。已实现的引用的行为类似于指针,但都是常量。对于常量,您可以执行的操作没有限制。您可以将它们与函数一起使用,您可以从它们构建数组,您可以在没有任何约束的情况下共享它们,您可以将它们放在泛型中等等。一个例子是使用基本
整数向量ptr\t
类型构建的。它可以作为如何构建自己类型的示例。还有其他基于相同原理构建的数据类型,如和

VHDL-2019将修复受保护类型的一些问题,但它们不如常量灵活。VUnit中的引用甚至可以与VHDL-93一起使用

你读了更多关于它的内容


免责声明:我是作者之一。

使用VHDL和访问指针模拟类的另一个示例:

-- Behavorial Fifo for use in testbench
--------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

--------------------------------------------------
package pkg_simfifo is
    subtype uint32_t is unsigned(31 downto 0);

    constant max_simfifos :natural := 100;

    type simfifo_item_t is record
       addr     :std_logic_vector(31 downto 0);
       data     :std_logic_vector(31 downto 0);
       valid    :std_logic;
    end record;  

    type simfifo_array_t is array (0 to max_simfifos) of simfifo_item_t;

    type simfifo_class_t is record
        karray :simfifo_array_t;
        count  :integer;
    end record;

    type simfifo_ptr_t is access simfifo_class_t;

    impure function simfifo_new return simfifo_ptr_t;

    procedure simfifo_purge(
        variable that :inout  simfifo_ptr_t
    );

    -- Push Onto Fifo
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     std_logic_vector(31 downto 0);
                 data :in     std_logic_vector(31 downto 0);        
        variable ok   :out    std_logic
    );
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     unsigned(31 downto 0);
                 data :in     unsigned(31 downto 0);
        variable ok   :out    std_logic
    );

    -- Pop from Fifo
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    );
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    );

    -- Peak without Popping
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    );

    -- Peak without Popping
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    );

    procedure simfifo_get_count(
        variable that  :inout  simfifo_ptr_t; 
                 count :out    integer
    );

end package;

--------------------------------------------------
package body pkg_simfifo is

    impure function simfifo_new return simfifo_ptr_t is
        variable that : simfifo_ptr_t;
    begin
        that := new simfifo_class_t;
        simfifo_purge(that);        
        return that;
    end function;

    procedure simfifo_purge(
        variable that   :inout  simfifo_ptr_t
    ) is
    begin        
        that.all.count := 0;                

        for i in 0 to max_simfifos loop
            that.all.karray(0).addr  := (others => '0');
            that.all.karray(0).data  := (others => 'X');
            that.all.karray(0).valid := '0';
        end loop;

    end procedure;

    -- Push Onto Fifo
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     std_logic_vector(31 downto 0);
                 data :in     std_logic_vector(31 downto 0);        
        variable ok   :out    std_logic
    ) is  
        variable i    :integer;
    begin

        --insert address at end of array
        if (that.all.count < max_simfifos) then
             i := that.all.count;
            that.all.karray(i).addr  := addr;
            that.all.karray(i).data  := data;
            that.all.karray(i).valid := '1';
            that.all.count := that.all.count + 1;
            ok := '1';
            return;
        end if;

        -- no more space in array
        ok := '0';
        return;        
    end procedure;

    -- Push Onto Fifo
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     unsigned(31 downto 0);
                 data :in     unsigned(31 downto 0);
        variable ok   :out    std_logic
    ) is
        variable slv_addr :std_logic_vector(31 downto 0);
        variable slv_data :std_logic_vector(31 downto 0);        
    begin
        simfifo_push(
            that, 
            std_logic_vector(addr),
            std_logic_vector(data),
            ok
        );
        return;        
    end procedure;


    -- Pop from Fifo
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    ) is
    begin
        addr   := that.all.karray(0).addr;
        data   := that.all.karray(0).data;
        valid  := that.all.karray(0).valid;

        -- Shift Down
        for i in 0 to max_simfifos-1 loop
            --report "max_simfifos" & integer'image(max_simfifos) & " i:" & integer'image(i) & " i+1:" & integer'image(i+1);
            that.all.karray(i) := that.all.karray(i+1);
            if (that.all.karray(i+1).valid = '0') then
                exit;
            end if;            
        end loop;
        that.all.karray(max_simfifos-1).valid := '0';
        that.all.karray(max_simfifos-1).data  := (others => 'X');
        that.all.karray(max_simfifos-1).addr  := (others => 'X');


        if (that.all.count /= 0) then
            that.all.count := that.all.count - 1;
        end if;

    end procedure;

    -- Pop from Fifo
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    ) is
        variable slv_addr :std_logic_vector(31 downto 0);
        variable slv_data :std_logic_vector(31 downto 0);
    begin
        simfifo_pop(
            that,
            slv_addr,
            slv_data,
            valid
        );

        addr := unsigned(slv_addr);    
        data := unsigned(slv_data);
    end procedure;

    -- Peek from Fifo
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    ) is
    begin
        addr   := that.all.karray(0).addr;
        data   := that.all.karray(0).data;
        valid  := that.all.karray(0).valid;
    end procedure;

    -- Pop from Fifo
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    ) is
        variable slv_addr :std_logic_vector(31 downto 0);
        variable slv_data :std_logic_vector(31 downto 0);
    begin
        simfifo_peek(
            that,
            slv_addr,
            slv_data,
            valid
        );

        addr := unsigned(slv_addr);
        data := unsigned(slv_addr);
    end procedure;

    -- Peek from Fif    
    procedure simfifo_get_count(
        variable that  :inout  simfifo_ptr_t; 
                 count :out    integer
    ) is
    begin
        count := that.all.count;
    end procedure;

end package body;

--library ieee;
--use ieee.std_logic_1164.all;
--use work.pkg_simfifo.all;
--
----------------------------------------------------
--entity testbench is
--end entity;
--
----------------------------------------------------
--architecture sim of testbench is
--begin
--
--process
--  variable that   :simfifo_ptr_t;
--    variable wvalid :std_logic;
--    variable raddr  :std_logic_vector(31 downto 0);
--    variable rdata  :std_logic_vector(31 downto 0);
--    variable rvalid :std_logic;
--begin
--    that := simfifo_new;
--    
--    simfifo_push  (that, X"10102323", X"AAAABBBB", wvalid);
--    simfifo_push  (that, X"10102334", X"EEEECCCC", wvalid);
--    
--    simfifo_pop   (that, raddr, rdata, rvalid);        
--    report "pop: " & to_hstring(rdata);
--    
--    simfifo_pop   (that, raddr, rdata, rvalid);        
--    report "pop: " & to_hstring(rdata);
--    
--    simfifo_pop   (that, raddr, rdata, rvalid);        
--    report "pop: " & to_hstring(rdata);
--    
--    wait;
--end process;
--
--end architecture;

——用于测试台的行为Fifo
--------------------------------------------------
图书馆ieee;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
--------------------------------------------------
包装箱simfifo为
子类型uint32_t无符号(31到0);
常数max_simfifos:natural:=100;
输入simfifo\u项目为记录
地址:标准逻辑向量(31到0);
数据:标准逻辑向量(31到0);
有效:标准逻辑;
结束记录;
类型simfifo_array_t是simfifo_项的数组(0到最大simfifos);
类型simfifo\u class\u t为记录
karray:simfifo_阵列;
计数:整数;
结束记录;
类型simfifo_ptr_t是访问simfifo_类;
不纯函数simfifo\u新返回simfifo\u ptr\t;
程序simfifo_清除(
变量:inout simfifo\u ptr\t
);
--推动先进先出
程序simfifo_push(
变量为:inout simfifo\u ptr\t;
地址:标准逻辑向量(31向下至0);
数据:标准逻辑向量(31到0);
变量ok:输出标准逻辑
);
程序simfifo_push(
变量为:inout simfifo\u ptr\t;
地址:无符号(31到0);
数据:无符号(31到0);
变量ok:输出标准逻辑
);
--先进先出
程序simfifo_pop(
变量为:inout simfifo\u ptr\t;
变量addr:out标准逻辑向量(31向下至0);
变量数据:输出标准逻辑向量(31到0);
变量有效:out std_逻辑
);
程序simfifo_pop(
变量为:inout simfifo\u ptr\t;
变量addr:out无符号(31到0);
变量数据:输出无符号(31到0);
变量有效:out std_逻辑
);
--峰无爆裂
程序simfifo_peek(
变量为:inout simfifo\u ptr\t;
变量addr:out标准逻辑向量(31向下至0);
变量数据:输出标准逻辑向量(31到0);
变量有效:out std_逻辑
);
--峰无爆裂
程序simfifo_peek(
变量为:inout simfifo\u ptr\t;
变量addr:out无符号(31到0);
变量数据:输出无符号(31到0);
变量有效:out std_逻辑
);
程序simfifo\u get\u计数(
变量为:inout simfifo\u ptr\t;
计数:输出整数
);
端包装;
--------------------------------------------------
包装体组件simfifo为
不纯函数simfifo_新返回simfifo_ptr_t为
变量为:simfifo_ptr_t;
开始
即:=新的simfifo\u类;
simfifo_purge(即:;
归还;
末端功能;

library ieee;
use ieee.std_logic_1164.all;

--------------------------------------------------
package ADT is

  constant A_OK        :integer := 0;
  constant max_keepers :natural := 100;

  type keeper_item_t is record
    addr     :std_logic_vector(31 downto 0);
    data     :std_logic_vector(31 downto 0);
    valid    :std_logic;
  end record;  

  type keeper_t is array (0 to max_keepers) of keeper_item_t;

  type keeper_ptr_t is access keeper_t;

  impure function keeper_new return keeper_ptr_t;
  procedure keeper_add(variable kp: inout keeper_ptr_t);
  procedure keeper_get(variable kp: inout keeper_ptr_t; variable item: out keeper_item_t);

end package ADT;

--------------------------------------------------
package body ADT is

    impure function keeper_new return keeper_ptr_t is
        variable kp : keeper_ptr_t;
    begin
        kp := new keeper_t;
        kp.all(0).addr  := X"AABBCCDD";
        kp.all(0).data  := X"10101010";
        kp.all(0).valid := '0';
        return kp;
    end function;

    procedure keeper_add(variable kp: inout keeper_ptr_t) is
    begin
        kp.all(0).addr  := X"12345678";
        kp.all(0).data  := X"BEEF1234";
        kp.all(0).valid := '1';
    end procedure;

    procedure keeper_get(variable kp: inout keeper_ptr_t; variable item: out keeper_item_t) is
    begin
        item := kp.all(0);
    end procedure;

end package body;

use work.ADT.all;

--------------------------------------------------
entity testbench is
end entity;

--------------------------------------------------
architecture sim of testbench is
begin

process
    variable km :keeper_t;
    variable kp :keeper_ptr_t;
    variable ki :keeper_item_t;
    variable ok :integer;
begin
    kp := keeper_new;
    keeper_add(kp);
    keeper_get(kp, ki);     
    wait;
end process;

end architecture;

Type pt is protected
  Procedure add_one;
  Function get_val return integer;
End protected pt;

Type pt is protected body
  Variable x : integer;

  Procedure add_one is
  Begin
   X := x + 1;
  End  procedure;

  Function get_val return integer is
  Begin
    Return x;
  End function get_val;
End protected body pt;

.....

Process
  Variable ptv : pt;
Begin
  Ptv.add_one;
  Ptv.add_one;

  Report to_string(ptv.get_val);
  Wait;
End process;
-- Behavorial Fifo for use in testbench
--------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

--------------------------------------------------
package pkg_simfifo is
    subtype uint32_t is unsigned(31 downto 0);

    constant max_simfifos :natural := 100;

    type simfifo_item_t is record
       addr     :std_logic_vector(31 downto 0);
       data     :std_logic_vector(31 downto 0);
       valid    :std_logic;
    end record;  

    type simfifo_array_t is array (0 to max_simfifos) of simfifo_item_t;

    type simfifo_class_t is record
        karray :simfifo_array_t;
        count  :integer;
    end record;

    type simfifo_ptr_t is access simfifo_class_t;

    impure function simfifo_new return simfifo_ptr_t;

    procedure simfifo_purge(
        variable that :inout  simfifo_ptr_t
    );

    -- Push Onto Fifo
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     std_logic_vector(31 downto 0);
                 data :in     std_logic_vector(31 downto 0);        
        variable ok   :out    std_logic
    );
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     unsigned(31 downto 0);
                 data :in     unsigned(31 downto 0);
        variable ok   :out    std_logic
    );

    -- Pop from Fifo
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    );
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    );

    -- Peak without Popping
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    );

    -- Peak without Popping
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    );

    procedure simfifo_get_count(
        variable that  :inout  simfifo_ptr_t; 
                 count :out    integer
    );

end package;

--------------------------------------------------
package body pkg_simfifo is

    impure function simfifo_new return simfifo_ptr_t is
        variable that : simfifo_ptr_t;
    begin
        that := new simfifo_class_t;
        simfifo_purge(that);        
        return that;
    end function;

    procedure simfifo_purge(
        variable that   :inout  simfifo_ptr_t
    ) is
    begin        
        that.all.count := 0;                

        for i in 0 to max_simfifos loop
            that.all.karray(0).addr  := (others => '0');
            that.all.karray(0).data  := (others => 'X');
            that.all.karray(0).valid := '0';
        end loop;

    end procedure;

    -- Push Onto Fifo
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     std_logic_vector(31 downto 0);
                 data :in     std_logic_vector(31 downto 0);        
        variable ok   :out    std_logic
    ) is  
        variable i    :integer;
    begin

        --insert address at end of array
        if (that.all.count < max_simfifos) then
             i := that.all.count;
            that.all.karray(i).addr  := addr;
            that.all.karray(i).data  := data;
            that.all.karray(i).valid := '1';
            that.all.count := that.all.count + 1;
            ok := '1';
            return;
        end if;

        -- no more space in array
        ok := '0';
        return;        
    end procedure;

    -- Push Onto Fifo
    procedure simfifo_push(
        variable that :inout  simfifo_ptr_t;
                 addr :in     unsigned(31 downto 0);
                 data :in     unsigned(31 downto 0);
        variable ok   :out    std_logic
    ) is
        variable slv_addr :std_logic_vector(31 downto 0);
        variable slv_data :std_logic_vector(31 downto 0);        
    begin
        simfifo_push(
            that, 
            std_logic_vector(addr),
            std_logic_vector(data),
            ok
        );
        return;        
    end procedure;


    -- Pop from Fifo
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    ) is
    begin
        addr   := that.all.karray(0).addr;
        data   := that.all.karray(0).data;
        valid  := that.all.karray(0).valid;

        -- Shift Down
        for i in 0 to max_simfifos-1 loop
            --report "max_simfifos" & integer'image(max_simfifos) & " i:" & integer'image(i) & " i+1:" & integer'image(i+1);
            that.all.karray(i) := that.all.karray(i+1);
            if (that.all.karray(i+1).valid = '0') then
                exit;
            end if;            
        end loop;
        that.all.karray(max_simfifos-1).valid := '0';
        that.all.karray(max_simfifos-1).data  := (others => 'X');
        that.all.karray(max_simfifos-1).addr  := (others => 'X');


        if (that.all.count /= 0) then
            that.all.count := that.all.count - 1;
        end if;

    end procedure;

    -- Pop from Fifo
    procedure simfifo_pop(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    ) is
        variable slv_addr :std_logic_vector(31 downto 0);
        variable slv_data :std_logic_vector(31 downto 0);
    begin
        simfifo_pop(
            that,
            slv_addr,
            slv_data,
            valid
        );

        addr := unsigned(slv_addr);    
        data := unsigned(slv_data);
    end procedure;

    -- Peek from Fifo
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    std_logic_vector(31 downto 0);
        variable data  :out    std_logic_vector(31 downto 0);
        variable valid :out    std_logic
    ) is
    begin
        addr   := that.all.karray(0).addr;
        data   := that.all.karray(0).data;
        valid  := that.all.karray(0).valid;
    end procedure;

    -- Pop from Fifo
    procedure simfifo_peek(
        variable that  :inout  simfifo_ptr_t; 
        variable addr  :out    unsigned(31 downto 0);
        variable data  :out    unsigned(31 downto 0);
        variable valid :out    std_logic
    ) is
        variable slv_addr :std_logic_vector(31 downto 0);
        variable slv_data :std_logic_vector(31 downto 0);
    begin
        simfifo_peek(
            that,
            slv_addr,
            slv_data,
            valid
        );

        addr := unsigned(slv_addr);
        data := unsigned(slv_addr);
    end procedure;

    -- Peek from Fif    
    procedure simfifo_get_count(
        variable that  :inout  simfifo_ptr_t; 
                 count :out    integer
    ) is
    begin
        count := that.all.count;
    end procedure;

end package body;

--library ieee;
--use ieee.std_logic_1164.all;
--use work.pkg_simfifo.all;
--
----------------------------------------------------
--entity testbench is
--end entity;
--
----------------------------------------------------
--architecture sim of testbench is
--begin
--
--process
--  variable that   :simfifo_ptr_t;
--    variable wvalid :std_logic;
--    variable raddr  :std_logic_vector(31 downto 0);
--    variable rdata  :std_logic_vector(31 downto 0);
--    variable rvalid :std_logic;
--begin
--    that := simfifo_new;
--    
--    simfifo_push  (that, X"10102323", X"AAAABBBB", wvalid);
--    simfifo_push  (that, X"10102334", X"EEEECCCC", wvalid);
--    
--    simfifo_pop   (that, raddr, rdata, rvalid);        
--    report "pop: " & to_hstring(rdata);
--    
--    simfifo_pop   (that, raddr, rdata, rvalid);        
--    report "pop: " & to_hstring(rdata);
--    
--    simfifo_pop   (that, raddr, rdata, rvalid);        
--    report "pop: " & to_hstring(rdata);
--    
--    wait;
--end process;
--
--end architecture;