2017-03-15 19 views
0

レコード型の入出力を想定したFIFOを想定すると、fifoラッパーの入出力のレコード型と実際のFIFOのstd_logic_vectorの間のマッピングを処理する簡単な方法がありますか?VHDL/FPGAのFIFOとの間でレコードを簡単に読み書きする方法はありますか?

+0

これを正しく理解しているとすれば、入力/出力用のレコードをFIFOに使用することに決めました。レコードを入力として受け取り、std_logic_vectorを返す関数を使用してもかまいません。 –

+0

仮定は正しいです。これらの関数が簡略化されていて、サンプルの答えに書かれているものよりもエラーが起こりにくい例がありますか? – FritzDC

+0

例を追加しますが、そのエラーが発生しにくいということについてはわかりません。あなたがそれをより良く判断できると思います。 –

答えて

0

私がこれまでに出てくることができました最も簡単な方法です、次のように:まず

一定の範囲宣言整理する機能パッケージ:

library ieee; 
use ieee.std_logic_1164.all; 
package Fun_pck is 
    function fLenAtTopOf(a : natural; b: std_logic_vector) return natural; 
    function fTopOf(b : std_logic_vector) return natural; 
end package Fun_pck; 
package body Fun_pck is 
    function fLenAtTopOf(a : natural; b: std_logic_vector) return natural is 
    begin 
    return a+b'left; 
    end function fLenAtTopOf; 
    function fTopOf(b: std_logic_vector) return natural is 
    begin 
    return b'left+1; 
    end function fTopOf; 
end package body Fun_pck; 

次に、2つのパッケージが含まれヘルパーFIFOの定義:

library ieee; 
use ieee.std_logic_1164.all; 
use work.Fun_pck.all; 

package ExampleFifo_pck_private is 

-- This package is 'private', i.e. only meant to be seen by the package and 
-- entity in this file. This is so that the elements will not have a name 
-- clash. As they are top-level constants that would be a likely problem. 
-- Fifo element constants. 
    type width_array is array (integer range <>) of integer; 
    constant cElementWidths : width_array(0 to 2) := (4, 8, 1); 

    constant cFifoElement0 : std_logic_vector(cElementWidths(0)-1 downto 0) := (others => '0'); 
    constant cFifoElement1 : std_logic_vector(
    fLenAtTopOf(cElementWidths(1), cFifoElement0) downto 
    fTopOf(cFifoElement0)) := (others => '0'); 
    constant cFifoElement2 : std_logic_vector(
    fLenAtTopOf(cElementWidths(2), cFifoElement1) downto 
    fTopOf(cFifoElement1)) := (others => '0'); 

-- General Form: 
--constant cFifoElementN : std_logic_vector(
-- fLenAtTopOf(cElementWidths(N), cFifoElement[N-1]) downto 
-- fTopOf(cFifoElement[N-1])) := (others => '0'); 
end package ExampleFifo_pck_private; 

library ieee; 
use ieee.std_logic_1164.all; 
use work.Fun_pck.all; 
use work.ExampleFifo_pck_private.all; 

-- Fifo item type 
    type tExampleFifoData is record 
    A : std_logic_vector(cFifoElement0'length-1 downto 0); 
    B : std_logic_vector(cFifoElement1'length-1 downto 0); 
    C : std_logic_vector(cFifoElement2'length-1 downto 0); 
    end record tExampleFifoData; 

-- Reset constant 
    constant cResetExampleFifoData : tExampleFifoData := (
    A => cFifoElement0, 
    B => cFifoElement1, 
    C => cFifoElement2 
    ); 
-- Length Constant 
    constant cExampleFifoWidth : integer := fTopOf(cFifoElement2); 
    -- Data array type 
    type tExampleFifoData_Array is array (natural range<>) of tExampleFifoData; 
end package ExampleFifo_pck; 

およびFIFOモジュールをラップ最終的エンティティ/アーキテクチャのペア、この場合のザイリンクスXPM:

library ieee; 
    use ieee.std_logic_1164.all; 
    use work.ExampleFifo_pck.all; 
    use work.ExampleFifo_pck_private.all; 

    library xpm; 
    use xpm.vcomponents.all; 

    entity ExampleFifo is 
     port (
     iWrClk  : in std_logic; 
     iRst  : in std_logic; 
     iWrEn  : in std_logic; 
     iWrData  : in tExampleFifoData; 
     oWrFull  : out std_logic; 
     oWrProgFull : out std_logic; 
     iRdClk  : in std_logic; 
     iRdEn  : in std_logic; 
     oRdData  : out tExampleFifoData; 
     oRdEmpty : out std_logic 
     ); 
    end entity ExampleFifo; 

    architecture RTL of ExampleFifo is 

    -- Internal vector signals 
     signal sWrData : std_logic_vector(cExampleFifoWidth-1 downto 0) := (others => '0'); 
     signal sRdData : std_logic_vector(cExampleFifoWidth-1 downto 0) := (others => '0'); 

    begin 

     sWrData(cFifoElement0'range) <= iWrData.A; 
     sWrData(cFifoElement1'range) <= iWrData.B; 
     sWrData(cFifoElement2'range) <= iWrData.C; 

     oRdData.A <= sRdData(cFifoElement0'range); 
     oRdData.B <= sRdData(cFifoElement1'range); 
     oRdData.C <= sRdData(cFifoElement2'range); 

     x_fifo : xpm_fifo_async 
     generic map (
      -- check: 
      FIFO_MEMORY_TYPE => "distributed", --string; "auto", "block", or "distributed"; 
      ECC_MODE   => "no_ecc",  --string; "no_ecc" or "en_ecc"; 
      -- check: 
      RELATED_CLOCKS  => 0,    --positive integer; 0 or 1 
      -- check: 
      FIFO_WRITE_DEPTH => 32,    --positive integer 
      -- modify: 
      WRITE_DATA_WIDTH => cExampleFifoWidth, --positive integer 
      WR_DATA_COUNT_WIDTH => 1,    --positive integer 
      -- check: 
      PROG_FULL_THRESH => 27,    --positive integer 
      FULL_RESET_VALUE => 0,    --positive integer; 0 or 1; 
      read_mode   => "fwft",   --string; "std" or "fwft"; 
      FIFO_READ_LATENCY => 0,    --positive integer; 
      -- modify: 
      READ_DATA_WIDTH  => cExampleFifoWidth,   --positive integer 
      RD_DATA_COUNT_WIDTH => 1,    --positive integer 
      PROG_EMPTY_THRESH => 10,    --positive integer 
      DOUT_RESET_VALUE => "0",   --string 
      CDC_SYNC_STAGES  => 2,    --positive integer 
      WAKEUP_TIME   => 0    --positive integer; 0 or 2; 
     ) 
     port map (
      sleep   => '0', 
      rst   => iRst, 
      wr_clk  => iWrClk, 
      wr_en   => iWrEn, 
      din   => sWrData, 
      full   => oWrFull, 
      overflow  => open, 
      wr_rst_busy => open, 
      rd_clk  => iRdClk, 
      rd_en   => iRdEn, 
      dout   => sRdData, 
      empty   => oRdEmpty, 
      underflow  => open, 
      rd_rst_busy => open, 
      prog_full  => oWrProgFull, 
      wr_data_count => open, 
      prog_empty => open, 
      rd_data_count => open, 
      injectsbiterr => '0', 
      injectdbiterr => '0', 
      sbiterr  => open, 
      dbiterr  => open 
     ); 
    end architecture RTL; 

これは少し問題ですが、fifoを宣言するのはかなり管理しやすいです。それぞれのfifoは依然としてパッケージとエンティティの独自のバージョンを必要とします。当然のことながら、それらは単一のファイルに存在することができます。

は、このトラブルの後、FIFOの実際の使用は非常に簡単です:

簡潔にすること
library ieee; 
use ieee.std_logic_1164.all; 
use work.ExampleFifo_pck.all; 

entity tb is 
end entity tb; 

architecture sim of tb is 
    signal iWrClk  : std_logic := '1'; 
    signal iRst  : std_logic := '0'; 
    signal sWrEn  : std_logic := '0'; 
    signal sWrData  : tExampleFifoData; 
    signal sWrFull  : std_logic; 
    signal sWrProgFull : std_logic; 
    signal iRdClk  : std_logic := '1'; 
    signal sRdEn  : std_logic := '0'; 
    signal sRdData  : tExampleFifoData; 
    signal sRdEmpty : std_logic; 

    signal sTestIn : tExampleFifoData  := cResetExampleFifoData; 
    signal sTestOut : tExampleFifoData; 
    constant tests : tExampleFifoData_Array(0 to 1) := 
    (0 => (x"E", x"A7", "1"), 1 => (x"7", x"AC", "0")); 
begin 

    iWrClk <= not iWrClk after 5 ns; 
    iRdClk <= not iRdClk after 7.2 ns; 

    ExFifo : entity work.ExampleFifo 
    port map (
     iWrClk  => iWrClk, 
     iRst  => iRst, 
     iWrEn  => sWrEn, 
     iWrData  => sTestIn, 
     oWrFull  => sWrFull, 
     oWrProgFull => sWrProgFull, 
     iRdClk  => iRdClk, 
     iRdEn  => sRdEn, 
     oRdData  => sTestOut, 
     oRdEmpty => sRdEmpty 
    ); 

    wr : process is 
    begin 
    iRst <= '1'; 
    for i in 0 to 5 loop 
     wait until rising_edge(iWrClk);  
    end loop; 
    iRst <= '0'; 
    wait for 150 ns; 
    for i in 0 to 1 loop 
     wait for 15 ns; 
     wait until rising_edge(iWrClk); 
     sTestIn <= tests(i); 
     sWrEn <= '1'; 
     wait until rising_edge(iWrClk); 
     sWrEn <= '0'; 
     wait until rising_edge(iWrClk); 
    end loop; 
    wait; 
    end process wr; 

    rd : process is 
    begin 
    wait until rising_edge(iRdClk); 
    sRdEn <= '0'; 
    if(sRdEmpty = '0' ans sRdEn <= '0') then 
     sRdEn <= '1'; 
    end if; 
    end process rd; 

end architecture sim; 
0

...

-- items within fifo 
constant c_items : integer := 8; 
constant c_width : integer := 
(-- ADD NEW ITEMS HERE 
    c_CWidth + 
    c_BWidth + 
    c_AWidth 
); 
type t_intVector is array (natural range <>) of integer; 
constant c_start : t_intVector(c_items downto 0) := 
(-- INSERT/MODIFY FOR NEW ITEMS 
    0+c_AWidth+c_BWidth+c_CWidth, -- end 
    0+c_AWidth+c_BWidth,   -- C 
    0+c_AWidth,     -- B 
    0        -- A 
); 

-- MODIFY FOR ADDITIONAL ITEMS 
procedure f_writeToFifo(
    signal o_f : out std_logic_vector; 
      i_A :  unsigned; 
      i_B :  unsigned; 
      i_C :  unsigned) is 
begin 
    o_f <= i_C & 
      i_B & 
      i_A; 
end procedure f_writeToFifo; 

type t_data is record 
    A : unsigned(c_AWidth-1 downto 0); 
    B : unsigned(c_BWidth-1 downto 0); 
    C : unsigned(c_CWidth-1 downto 0); 
end record; 

function f_readA(i_f : std_logic_vector) return unsigned is begin return unsigned(i_f(c_start(3)-1 downto c_start(2))); end function f_readA; 
function f_readB(i_f : std_logic_vector) return unsigned is begin return unsigned(i_f(c_start(2)-1 downto c_start(1))); end function f_readB; 
function f_readC(i_f : std_logic_vector) return unsigned is begin return unsigned(i_f(c_start(1)-1 downto c_start(0))); end function f_readC; 
function f_read (i_f : std_logic_vector) return t_data is begin 
    return (C => f_readC(i_f), 
      B => f_readB(i_f), 
      A => f_readA(i_f)); 
end function f_read; 

リスト/位置/アイテムの作成を無視します。プロシージャ/レコード/関数は、私が強調しようとしているものです。

1

提示されているように、パッケージ内の会話を非表示にすることができます。したがって、FIFOインターフェイスとレコード間の2つの機能があります。

Rob Gaddi(IEEE WG for VHDLの副議長)は、一度レコードタイプとの間でstd_logic_vectorsを素早くパッキングしアンパックするための一連のヘルパープロシージャを提示しました。 彼のproposed pack and unpack subprogramsを参照してください。

ワーキンググループは、このような問題の解決方法について長い議論を重ねてきました。 3つの可能性があります。

  • VHDLはエンティティ宣言のジェネリック型をサポートしています。したがって、VHDL-2008に準拠した合成ツールは、任意のタイプ*)をFIFO要素として受け入れる汎用FIFOを作成することができます。
  • VHDL-2017は、少なくともレコードからの会話をstd_logic_vectorに解決することができるreflection APIを追加します。私は逆の道を実装する方法を考えています。
  • レコード要素を反復する直接的解決策は未だ見出されておらず、次のリビジョン(VHDL-2020)

*)任意の合成スカラ、アレイまたはレコードタイプに遅延されます。

関連する問題