3

レコード メンバーのベクトル長を示すために定数に依存する次の型定義があるとします。

type point_t is record
    x: std_logic_vector(X_WIDTH-1 downto 0);
    y: std_logic_vector(Y_WIDTH-1 downto 0); 
end record;

std_logic_vectorこれらの種類のレコードをs に変換して、たとえば FIFO に入れたいと思います。現在、次のコードを使用しています。

PROCEDURE encodepoint(signal pnt: in point_t;
                      signal d: out std_logic_vector(POINT_ENC_WIDTH-1 downto 0)) is
    variable top: integer := 0;
begin
    top := X_WIDTH-1;
    d(top downto 0) <= pnt.x;

    top := top + Y_WIDTH;
    d(top downto top-X_WIDTH+1) <= sl.y;

    d(d'left downto top+1) <= (others => '0');
end;

このコードは多くの点で最適ではありません。たとえば、POINT_ENC_WIDTH を、dシリアル化されたレコード全体を保持できる十分な大きさの値に常に正しく設定する必要があります。非常に機械的な作業を行うのはプログラマーに依存しています。たとえば、レコードのすべてのメンバーについて、xはコード内に2 回X_WIDTH表示されます。1 回は直接関連して、もう 1 回は次のメンバー. これはすぐに退屈になります。フィールドを追加してレコードの定義を変更すると、シリアル化コードと (非常によく似た) 逆シリアル化コードの両方を更新する必要があり、これを忘れてしまう可能性があります。フィールドを削除すると、少なくともコンパイラは文句を言います。xy

したがって、これは私の質問につながります:std_logic_vector手動で書かれたシリアル化/非シリアル化コードに頼ることなく、VHDL レコードを s に変換する簡単な、自動化された、または少なくとも準自動化された方法はありますか? 私はレコードを内部で使用しており、最終的な出力形式は明確に指定されており、手動で実装されるため、特定のエンコーディングを知ることは重要ではありません。

4

6 に答える 6

6

次のように書けないでしょうか。

d <= pnt.x & pnt.y;
于 2010-10-21T12:07:43.620 に答える
3

現在、レコードをベクターに (およびその逆に) 変換する公式の自動化された方法はありませんが、これは非常に一般的な要件です。次の 2 つのオプションがあります。

  • すべてのレコード タイプに対して独自の to_vector および from_vector 関数を定義します (面倒です) 。
  • 上記の型変換を含むパッケージを自動生成する (難しい/エラーが発生しやすい)

コードを生成するためのスクリプトを作成する動機となる退屈で反復的なタスクは、言語自体に欠陥があることを示しています。IEEE ワーキング グループで積極的な役割を果たし、VHDL 標準の次のバージョンに影響を与えることで、これを変えることができます。

于 2011-06-27T09:18:30.940 に答える
2

ここの議論から取られた

大規模なレコードでこれを行う合理的な方法の 1 つは、次のように事前に範囲を定義することです。

type t_SPI_DATA_PORT is record
  Data_Size_Minus1: std_ulogic_vector(31 downto 28);
  Done: std_ulogic_vector(27 downto 27);
  Rx_Wait_Timeout: std_ulogic_vector(26 downto 26);
  Rx_Wait_On_Miso: std_ulogic_vector(25 downto 25);
  Sclk_Select: std_ulogic_vector(24 downto 24);
  Reserved: std_ulogic_vector(23 downto 20);
  Hold_Cs: std_ulogic_vector(19 downto 19);
  Cpha: std_ulogic_vector(18 downto 17);
  Cpol: std_ulogic_vector(16 downto 16);
  Data: std_ulogic_vector(15 downto 0);
end record;

次に、変換関数は次のようになります。

function To_Std_ULogic_Vector(L : t_SPI_DATA_PORT) return
  std_ulogic_vector is
    variable RetVal: std_ulogic_vector(31 downto 0);
  begin

    RetVal := (others => '0');
    RetVal(L.Data_Size_Minus1'range) := L.Data_Size_Minus1;
    RetVal(L.Done'range) := L.Done;
    RetVal(L.Rx_Wait_Timeout'range) := L.Rx_Wait_Timeout;
    RetVal(L.Sclk_Select'range) := L.Sclk_Select;
    RetVal(L.Reserved'range) := L.Reserved;
    RetVal(L.Rx_Wait_On_Miso'range) := L.Rx_Wait_On_Miso;
    RetVal(L.Hold_Cs'range) := L.Hold_Cs;
    RetVal(L.Cpha'range) := L.Cpha;
    RetVal(L.Cpol'range) := L.Cpol;
    RetVal(L.Data'range) := L.Data;

    return(RetVal);
end To_Std_ULogic_Vector;

function From_Std_ULogic_Vector(L : std_ulogic_vector) return
  t_SPI_DATA_PORT is
    variable RetVal: t_SPI_DATA_PORT;
    variable Lx: std_ulogic_vector(L'length - 1 downto 0);
  begin
    Lx := L;    
    RetVal.Data_Size_Minus1 := Lx(RetVal.Data_Size_Minus1'range);
    RetVal.Done := Lx(RetVal.Done'range);
    RetVal.Rx_Wait_Timeout := Lx(RetVal.Rx_Wait_Timeout'range);
    RetVal.Sclk_Select := Lx(RetVal.Sclk_Select'range);
    RetVal.Reserved := Lx(RetVal.Reserved'range);
    RetVal.Rx_Wait_On_Miso := Lx(RetVal.Rx_Wait_On_Miso'range);
    RetVal.Hold_Cs := Lx(RetVal.Hold_Cs'range);
    RetVal.Cpha := Lx(RetVal.Cpha'range);
    RetVal.Cpol := Lx(RetVal.Cpol'range);
    RetVal.Data := Lx(RetVal.Data'range);

    return(RetVal);
end From_Std_ULogic_Vector;
于 2012-03-05T18:08:43.950 に答える
2

私は通常、レコードと一緒にパッケージで変換関数を定義します。

あなたの場合、次のようなものです:

function point2slv (pnt : point_t) return std_logic_vector is
    variable slv : std_logic_vector(X_WIDTH + Y_WIDTH - 1 downto 0);
begin
    slv :=  pnt.x & pnt.y;
    return slv;
end;

function slv2point (slv : std_logic_vector) return point_t is
    variable pnt : point_t;
begin
    pnt.x     := slv(X_WIDTH + Y_WIDTH - 1 downto Y_WIDTH);
    pnt.y     := slv(Y_WIDTH - 1 downto  0);
    return pnt;
end;

注: 何をしようとしているのかによって、事前に定義されたサイズを片側または反対側に使用したり、変換関数を使用して自然な長さにパディング/クリップしたりすることができます (つまり、X と Y の値を 16 に合わせることができます)。または 32 ビット値)。unsigned 型とサイズ変更関数は、これに適しています。

slv(31 downto 16):=  std_logic_vector(resize(unsigned(pnt.x,16)));
slv(15 downto  0):=  std_logic_vector(resize(unsigned(pnt.7,16)));
于 2010-10-21T13:19:38.893 に答える
1

VHDLユーザー定義レコード型と s 型の間の変換用のパッケージを自動的に生成するスクリプトを用意しましたtd_logic_vector

このスクリプトのソースはPUBLIC DOMAINalt.sourcesグループとして公開されています。http://groups.google.com/group/alt.sources/browse_frm/thread/53ea61208013e9d1を参照するか、トピック「VHDLレコード タイプとの間の変換用のパッケージを生成するスクリプト」を探してくださいstd_logic_vector。 Google アーカイブ。「show original」オプションを忘れずに選択してください。そうしないと、Pythonソースのインデントが破損します。

于 2012-03-19T18:19:08.047 に答える