如何将记录写入内存并在VHDL中恢复?

时间:2017-03-12 07:57:08

标签: vhdl

在VHDL伪代码中,我想要实现的是:

type tTest is record
    A : std_logic_vector(3 downto 0);
    B : std_logic_vector(7 downto 0);
    C : std_logic_vector(0 downto 0);
end record tTest;
. . . 
signal sTestIn       : tTest;
signal sMemWrData    : std_logic_vector(fRecordLen(tTest)-1 downto 0);
signal sMemRdData    : std_logic_vector(fRecordLen(tTest)-1 downto 0);
signal sTestOut      : tTest;
. . .
sMemWrData <= fRecordToVector(sTestIn);
-- At some point sMemRdData gets the data in sMemWrData...
sTestOut <= fVectorToRecord(sMemRdData);

fRecordLen是一个虚函数,它直接从类型和fRecordToVector返回记录的聚合长度,fVectorToRecord有望自我解释。目标是可合成的代码,不会产生任何额外的逻辑。我发布我当前的解决方案作为进一步澄清操作的答案。然而,这是非常尴尬的方法,由于锅炉板代码的数量,我不认为它是一个可行的解决方案。

我知道record introspection proposal但是没有屏住呼吸,即使提出的方法看起来也很麻烦。

我已经放弃了对完全通用解决方案的希望,因此一些让步超出了可接受范围。例如,只允许记录中的std_logic_vectors并使用多个函数/过程调用。但是,避免任何必须根据每个记录进行手动或外部脚本调整的样板代码是很好的。

此外,如果存在任何可以直接输入/输出记录并实现相同的Verilog / SystemVerilog包装器,则非常欢迎指针。

2 个答案:

答案 0 :(得分:1)

将数据从矢量(线性数组)转换为记录的一种方法是使用聚合。

library ieee;
use ieee.std_logic_1164.all;

package TestPck is
    subtype A is std_logic_vector (12 downto 9);
    subtype B is std_logic_vector  (8 downto 1);
    subtype C is std_logic_vector  (0 downto 0);
    constant ABC_len: natural := A'length + B'length + C'length;
    type tTest is record
        A:  std_logic_vector (A'RANGE);
        B:  std_logic_vector (B'RANGE);
        C:  std_logic_vector (C'RANGE);
    end record tTest;
    type tTests is array (natural range <>) of tTest;
end package TestPck;

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

entity tb is
end entity tb;

architecture sim of tb is
    signal sTestIn:        tTest;
    signal sMemWrData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sMemRdData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sTestOut:       tTest;
    constant tests:        tTests (0 to 1) :=  
             (0 => (x"E", x"A7", "1"), 1 => (x"7", x"AC", "0"));
begin
    sMemWrData <= sTestIn.A & sTestIn.B & sTestIn.C;
    sMemRdData <= sMemWrData after 5 ns;
    sTestOut <= 
        tTest'(sMemRdData(A'range), sMemRdData(B'range), SMemRdData(C'range));
process is
    begin
        wait for 10 ns;
        sTestIn <= tests(0);
        wait for 10 ns;
        sTestIn <= tests(1);
        wait for 10 ns;
        wait;
    end process;
end architecture sim;

限定表达式将聚合定义为具有位置关联的tTest记录值,该关联分配给记录类型sTestOut。

这就是:

tb.png

因此,您可以使用串联来组合向量值(或-2008中的聚合),并使用聚合作为限定表达式将sMemRdData传输到sTestOut。

如果您没有计划声明A,B或C子类型的对象,可以将它们声明为整数子类型:

library ieee;
use ieee.std_logic_1164.all;

package TestPck is
    subtype A is natural range 12 downto 9;
    subtype B is natural range  8 downto 1;
    subtype C is natural range  0 downto 0;
    constant ABC_len: natural := A'left + 1;
    type tTest is record
        A:  std_logic_vector (A);
        B:  std_logic_vector (B);
        C:  std_logic_vector (C);
    end record tTest;
    type tTests is array (natural range <>) of tTest;
end package TestPck;

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

entity tb is
end entity tb;

architecture sim of tb is
    signal sTestIn:        tTest;
    signal sMemWrData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sMemRdData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sTestOut:       tTest;
    constant tests:        tTests (0 to 1) :=  
             (0 => (x"E", x"A7", "1"), 1 => (x"7", x"AC", "0"));
begin
    sMemWrData <= sTestIn.A & sTestIn.B & sTestIn.C;
    sMemRdData <= sMemWrData after 5 ns;
    sTestOut <= 
        tTest'(sMemRdData(A), sMemRdData(B), SMemRdData(C));
process is
    begin
        wait for 10 ns;
        sTestIn <= tests(0);
        wait for 10 ns;
        sTestIn <= tests(1);
        wait for 10 ns;
        wait;
    end process;
end architecture sim;

这可能更容易阅读。它会产生相同的波形。

答案 1 :(得分:0)

这是实现所要求的一种方式。缺点/改进的想法在评论中。

library ieee;
use ieee.std_logic_1164.all;
package TestPck is
    type tTest is record
        A : std_logic_vector(3 downto 0);
        B : std_logic_vector(7 downto 0);
        C : std_logic_vector(0 downto 0);
    end record tTest;
    procedure pSliceToFrom (
        signal vec_to   : out   std_logic_vector;
        signal vec_from : in    std_logic_vector;
        position        : inout integer
    );
end package TestPck;

package body TestPck is
  procedure pSliceToFrom (
    signal vec_to   : out   std_logic_vector;
    signal vec_from : in    std_logic_vector;
    position        : inout integer
    ) is
  begin
    vec_to   <= vec_from(position-1 downto position-vec_to'length);
    position := position-vec_to'length;
  end pSliceToFrom;
end package body TestPck;

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

entity tb is
end entity tb;

architecture sim of tb is
  signal sTestIn       : tTest;
  -- How to create this constant in the package, 
  -- i.e. without needing the signal?
  constant cTestLength : integer := sTestIn.A'length + sTestIn.B'length + sTestIn.C'length;
  signal sMemWrData    : std_logic_vector(cTestLength-1 downto 0);
  signal sMemRdData    : std_logic_vector(cTestLength-1 downto 0);
  signal sTestOut      : tTest;
begin
  -- How to make this without needing to know what 
  -- is inside tTest?
  sMemWrData <= sTestIn.A & sTestIn.B & sTestIn.C;
  -- Memory, Fifo, communication link, doesn't matter...
  sMemRdData <= sMemWrData after 5 ns;
  -- How to get the data back without needing this
  -- process (and the procedure)?
  slice_data_to_item : process (all) is
    variable vPosition : integer := 0;
  begin
    vPosition := cTestLength;
    pSliceToFrom(sTestOut.A, sMemRdData, vPosition);
    pSliceToFrom(sTestOut.B, sMemRdData, vPosition);
    pSliceToFrom(sTestOut.C, sMemRdData, vPosition);
  end process slice_data_to_item;

process is
    begin
        wait for 10 ns;
        sTestIn <= (x"E", x"A7", "1");
        wait for 10 ns;
        sTestIn <= (x"7", x"AC", "0");
        wait;
    end process;
end architecture sim;