代码之家  ›  专栏  ›  技术社区  ›  distributed

“序列化”VHDL记录

  •  3
  • distributed  · 技术社区  · 15 年前

    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

    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 , X_WIDTH 出现 两次 在代码中,一旦与 y . 这很快就变得乏味了。如果通过添加其他字段来更改记录的定义,则必须同时更新序列化代码和(非常类似的)反序列化代码,而我可能会忘记这一点。当我删除字段时,至少编译器会抱怨。

    因此,这就引出了我的问题:是否有一种简单的、自动化的或至少是准自动化的方法将VHDL记录转换成 标准逻辑向量 不需要手动编写序列化/非序列化代码?对我来说,知道具体的编码并不重要,因为我在内部使用记录,而且最终的输出格式是明确指定的,将手动实现。

    6 回复  |  直到 15 年前
        1
  •  5
  •   Philippe    15 年前

    你就不能这样写吗:

    d <= pnt.x & pnt.y;
    
        2
  •  2
  •   Charles Steinkuehler    15 年前

    在你的情况下,比如:

    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值填充/剪裁为自然长度(即:可能将X和Y值调整为16或32位值)。unsigned type和resize函数对此很有效:

    slv(31 downto 16):=  std_logic_vector(resize(unsigned(pnt.x,16)));
    slv(15 downto  0):=  std_logic_vector(resize(unsigned(pnt.7,16)));
    
        3
  •  2
  •   Chiggs    15 年前

    虽然目前还没有正式的自动方式将记录转换成矢量(反之亦然),但这是一个非常常见的要求。你有两个选择:

    • 为每种记录类型定义自己的to-u向量和from-u向量函数( 乏味的
    • 自动生成包含上述类型转换的包( 困难/易出错 )

    单调和重复的任务会激励你编写脚本来生成代码,这表明了语言本身的缺陷。你可以用一个 积极作用 在IEEE工作组和 影响 这个 next version of the VHDL standard .

        4
  •  2
  •   Lincoln    14 年前

    摘自讨论 here

    对于大型记录,一种合理的方法是提前定义范围,如下所示:

    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;
    
        5
  •  1
  •   Smita    13 年前

    我准备了一个脚本,它自动生成 VHDL td_logic_vector 键入。

    此脚本的源发布为 PUBLIC DOMAIN alt.sources 小组。 你可以看到 http://groups.google.com/group/alt.sources/browse_frm/thread/53ea61208013e9d1 VHDL语言 用于在记录类型和 std_logic_vector " 如果您想从Google档案中解压档案,请记住选择“ show original Python 源头将被破坏。

        6
  •  0
  •   modimo    7 年前

    我又做了一次记录序列化的尝试。我相信我的方法更稳健一些。您仍然需要为每种记录类型创建函数,但不需要提及范围。

    假设您需要使用我的包序列化类型:

    type type_a is record
      a : std_logic_vector(15 downto 0);
      b : std_logic_vector(31 downto 0);
      c : std_logic_vector(7 downto 0);
      d : std_logic_vector(7 downto 0);
    end record type_a;
    
    constant type_a_width : integer := 64;
    

    use work.SERIALIZE_PKG.all;
    
    function serialize (
         input : type_a)
      return std_logic_vector is
      variable ser : serializer_t(type_a_width-1 downto 0);
      variable r   : std_logic_vector(type_a_width-1 downto 0);
    begin  -- function serialize_detectorCacheLine_t
      serialize_init(ser);
      serialize(ser, input.a);
      serialize(ser, input.b);
      serialize(ser, input.c);
      serialize(ser, input.d);
      r := serialize_get(ser);
      return r;
    end function serialize;
    
    
    function deserialize (
         input : std_logic_vector)
      return type_a is
      variable ser : serializer_t(type_a_width-1 downto 0);
      variable r   : type_a;
    begin  -- function serialize_detectorCacheLine_t
      ser := serialize_set(input);
      deserialize(ser, r.a);
      deserialize(ser, r.b);
      deserialize(ser, r.c);
      deserialize(ser, r.d);
      return r;
    end function deserialize;
    

    然后您可以在如下代码中使用它:

    signal type_a_ser       : std_logic_vector(type_a_width-1 downto 0)       := (others => '0');
    signal type_a_in        : type_a;
    signal type_a_out       : type_a;
    ....
    type_a_ser       <= serialize(type_a_in);
    type_a_out       <= deserialize(type_a_ser);
    

    我将我的代码和更复杂类型(嵌套记录等)的示例发布在: https://github.com/gitmodimo/vhdl-serialize

    推荐文章