【问题标题】:VHDL type conversion for array of arrays in neural network神经网络中数组数组的 VHDL 类型转换
【发布时间】:2016-12-01 20:28:54
【问题描述】:

我正在使用由 David Aledo 开发的前馈神经网络(请参阅 OpenCores 项目 Artificial Neural Network (ANN)),并且在代码生成的实例中初始化 RAM 数组时遇到了问题。

代码生成神经网络层作为实例。这些实例中的每一个都具有与层权重矩阵相关联的块 RAM。此 RAM 在代码中表示为 std_logic_vector 数组的数组,如下所示:

type ramd_type is array (NumN-1 downto 0) of std_logic_vector(NbitW -1 downto 0);
type layer_ram is array (NumIn-1 downto 0) of ramd_type;

其中NumNNumIN 是依赖于层的,NbitW 是常量。

我想要做的是用一个常数来初始化这个 RAM。为此,我创建了一个包含以下内容的包:

type ramd_type0 is array (33 downto 0) of std_logic_vector(NbitW-1 downto 0);
type layer_ram0 is array (26 downto 0) of ramd_type0;
type ramd_type1 is array (4  downto 0) of std_logic_vector(NbitW-1 downto 0);
type layer_ram1 is array (33 downto 0) of ramd_type1;
type ramd_type2 is array (0  downto 0) of std_logic_vector(NbitW-1 downto 0);
type layer_ram2 is array (4  downto 0) of ramd_type2;

constant w0 : layer_ram0 := (others => (others => (others => '0')));
constant w1 : layer_ram1 := (others => (others => (others => '0')));
constant w2 : layer_ram2 := (others => (others => (others => '0')));

在层实体中,我声明了选择与层号通用 Lnum 相适应的常量的函数:

function w_init(LNum : natural) return layer_ram is
begin
  if LNum = 0 then
    return layer_ram(w0);
  elsif LNum = 1 then
    return layer_ram(w1);
  elsif LNum = 2 then
    return layer_ram(w2);
  else
    return layer_ram(w2);
  end if;
end w_init;

layer_ram 的定义如上。

使用 GHDL 分析时出现以下错误:

不允许在不密切相关的类型之间进行转换

在 Modelsim 中我得到了这个:

work.wb_init.layer_ram0 到 layer_ram 的非法类型转换(数组元素类型不同)。

我知道问题在于,根据模拟器,layer_ramlayer_ram0 并不密切相关,这是因为数组元素具有不同的类型 ramdramd0。对我来说,这似乎违反了 1993 年的标准,该标准规定数组类型在以下情况下密切相关:

--对于每个索引位置,索引类型要么相同,要么密切相关;

我说的对吗?如何在不将 layer_ram 类型更改为 std_logic_vectors 数组的情况下使用常量初始化这些数组?


编辑:

可以在此处查看重现我的问题的最小工作示例:https://gist.github.com/jstefanowicz/e4f43a822cf5dd46c2668bfffa33c66c

library ieee;
use ieee.std_logic_1164.all;

library work;
package wb_init is

    constant NbitW : natural := 18;

    type ramd_type0 is array (1 downto 0) of std_logic_vector(NbitW-1 downto 0);
    type ramd_type1 is array (2  downto 0) of std_logic_vector(NbitW-1 downto 0);

    type layer_ram0 is array (3 downto 0) of ramd_type0;
    type layer_ram1 is array (4 downto 0) of ramd_type1;

    constant w0 : layer_ram0 := (others => (others => (others => '0')));
    constant w1 : layer_ram1 := (others => (others => (others => '0')));

end wb_init ;

--- test_gen:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

library work;
use work.wb_init.all;

entity test_gen is

   generic
   (
      LNum    : natural ;  
      NumN    : natural := 8; 
      NumIn   : natural := 8   
   );

   port
   (
      inputs  : in std_logic_vector(NbitW-1 downto 0);
      outputs : out std_logic_vector(NbitW-1 downto 0) 
   );

end test_gen;

architecture beh of test_gen is

  type ramd_type is array (NumN-1 downto 0) of std_logic_vector(NbitW-1 downto 0); 
  type layer_ram is array (NumIn-1 downto 0) of ramd_type;

  function w_init(LNum : natural) return layer_ram is
  begin
   if LNum = 0 then
     return layer_ram(w0);
   elsif LNum = 1 then
     return layer_ram(w1);
   else
     return layer_ram(w1);
   end if;
  end w_init;

  signal lram  : layer_ram := w_init(LNum); 

begin
  outputs<= inputs;
end beh;

--- test_gen_tb:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

library work;
use work.wb_init.all;

entity test_gen_tb is
end test_gen_tb;

architecture beh of test_gen_tb is

component test_gen is
  generic
  (
     LNum    : natural := 0; 
     NumN    : natural := 64;
     NumIn   : natural := 8  
  );

  port
  (
     inputs  : in std_logic_vector(NbitW-1 downto 0);
     outputs : out std_logic_vector(NbitW-1 downto 0) 
  );

  end component;
  type gen_ar is array (1 downto 0) of natural;
  signal NumN_ar : gen_ar := (2,3);
  signal NumIn_ar : gen_ar := (4,5);
  signal inputs,outputs : std_logic_vector(NbitW-1 downto 0);


begin

  test_gen_inst:
  for i in 0 to 1 generate
  test_gen
  generic map (
    LNum  => i,
    NumN  => NumN_ar(i),
    NumIn => NumIn_ar(i)
  )
  port map (
    inputs  => inputs,
    outputs => outputs
  );  
  end generate;

end beh;

【问题讨论】:

  • 问题是元素类型不同,一种元素类型为 ramd_type,另一种元素类型为 ramd_type0,都是数组类型。您没有显示常量 NumN 的值。如果没有更多信息(Minimal, Complete and Verifiable Example),目前还不清楚纠正措施是什么。还要注意 w0、w1 和 w2 的维度是不同的。您的 w_init 函数可能想要三个函数,或者您只是在做一些程序错误。
  • NumN 不是常量而是泛型。该函数根据通用 LNum 返回不同的数组大小。当 LNum = 0 时,NumN 和 NumIn 等于 w0 维度,依此类推。重点是我想根据通用值初始化可以具有不同维度的数组数组。
  • IEEE Std 1076-2008 6.5.6.1 通用接口列表完全由接口常量声明、接口类型声明、接口子程序声明和接口包声明组成。 NumN` 是接口常量,保留字常量是可选的(6.5.2)。您的工具链是否支持接口类型声明 (6.5.3)?
  • 另外,因为这些没有出现在实体接口列表中,所以只使用本地声明,并使它们始终依赖于泛型常量。
  • 我担心我的工具链不会和通过接口传递的类型一起去。至于另一个选项,我已经尝试使用权重矩阵在本地声明的常量,但问题如下。如果我将 w0 声明为 3x3 数组,将 w1 声明为 5x3 数组,两者都具有类型 layer_ram(数组维度取决于泛型),那么我在编译期间会遇到绑定检查失败。我还尝试将权重矩阵 agregates 直接传递给函数 w_gen 的返回值(带有类型转换),但我得到了错误,说 agregates 不能是类型转换操作数。

标签: initialization neural-network type-conversion vhdl


【解决方案1】:

我终于设法通过在函数winit 中逐个元素地分配它来初始化数组数组。这是上面发布的最小示例的修复:(https://gist.github.com/jstefanowicz/abad35de9b0a930033e54ed0deeed771)

library ieee;
use ieee.std_logic_1164.all;

library work;
package wb_init is

    constant NbitW : natural := 18;

    type ramd_type0 is array (1 downto 0) of std_logic_vector(NbitW-1 downto 0);
    type ramd_type1 is array (2  downto 0) of std_logic_vector(NbitW-1 downto 0);

    type layer_ram0 is array (3 downto 0) of ramd_type0;
    type layer_ram1 is array (4 downto 0) of ramd_type1;

    constant w0 : layer_ram0 := (others => (others =>(others =>'0')));
    constant w1 : layer_ram1 := (others => (others =>(others =>'0')));

end wb_init ;

--- test_gen:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

library work;
use work.wb_init.all;

entity test_gen is

   generic
   (
      LNum    : natural ;  
      NumN    : natural ; 
      NumIn   : natural    
   );

   port
   (
      inputs  : in std_logic_vector(17 downto 0);
      outputs : out std_logic_vector(17 downto 0) 
   );

end test_gen;

architecture beh of test_gen is


  type ramd_type is array (NumN-1 downto 0) of std_logic_vector(17 downto 0); 
  type layer_ram is array (NumIn-1 downto 0) of ramd_type;


  function w_init(LNum : natural) return layer_ram is
    variable tmp_arr : layer_ram ;
  begin
    if LNum = 0 then
      for i in 0 to NumIn-1 loop
        for j in 0 to NumN-1 loop
           tmp_arr(i)(j) := w0(i)(j);
        end loop;
     end loop;
    elsif LNum = 1 then
      for i in 0 to NumIn-1 loop
        for j in 0 to NumN-1 loop
           tmp_arr(i)(j) := w1(i)(j);
        end loop;
      end loop;
    else
      for i in 0 to NumIn-1 loop
        for j in 0 to NumN-1 loop
           tmp_arr(i)(j) := (others => '0');
        end loop;
      end loop;
    end if;

    return tmp_arr ;
  end w_init;

  signal lram  : layer_ram := w_init(LNum); 

begin
  outputs<= inputs;
end beh;

--- test_gen_tb:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

--library work;
--use work.wb_init.all;

entity test_gen_tb is
end test_gen_tb;

architecture beh of test_gen_tb is

component test_gen is
  generic
  (
     LNum    : natural ; 
     NumN    : natural ;
     NumIn   : natural   
  );

  port
  (
     inputs  : in std_logic_vector(17 downto 0);
     outputs : out std_logic_vector(17 downto 0) 
  );

  end component;
  type gen_ar is array (1 downto 0) of natural;
  signal NumN_ar : gen_ar := (3,2);
  signal NumIn_ar : gen_ar := (5,4);
  signal inputs,outputs : std_logic_vector(17 downto 0);

begin

  test_gen_inst:
  for i in 0 to 1 generate
  tg:test_gen
  generic map (
    LNum  => i,
    NumN  => NumN_ar(i),
    NumIn => NumIn_ar(i)
  )
  port map (
    inputs  => inputs,
    outputs => outputs
  );  
  end generate;

end beh;

【讨论】:

    猜你喜欢
    • 2018-06-12
    • 1970-01-01
    • 2014-01-15
    • 2020-08-01
    • 2022-01-18
    • 1970-01-01
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多