【问题标题】:Generics in hardware description language硬件描述语言中的泛型
【发布时间】:2013-12-03 23:23:14
【问题描述】:

我对高清描述语言相当陌生。我发现改变我的 C-ish 编程技能有点困难,我正在寻找一些指导来帮助我解决以下问题。

我想实现一棵完整的树,它的内部节点与其叶子不同。 叶子的数量是 generic(假设有 2^k 个叶子所以树可以是满的)

每个内部节点都是由简单的组合电路组成的组件。

叶子与时钟同步,并连接到下一个叶子(破坏树结构 - 形成类似移位寄存器的东西)

这意味着我的设计必须有一个根据叶子数量连接的通用组件数

虽然这可以在基于 C 的语言中以递归方式立即解决。我无法掌握用 HDL 解决它的想法,因为这种通用形式不同于 n 位输入信号...

我的实现必须是synthesizable,所以SystemVerilog不能在这方面大放异彩:(

是否可以在保持我的代码可综合性的同时实现所描述的问题? 任何人都可以指导我抛出这个或指向我关于这个主题的一个很好的参考吗?

【问题讨论】:

    标签: generics hardware vhdl verilog hdl


    【解决方案1】:

    您可以用 VHDL 编写递归算法,该算法在细化期间执行,然后通过 generate 语句定义要综合的硬件结构。你几乎可以在 Verilog 中做到这一点,它自 2001 年以来就具有自动功能,但它们并不是全自动的,而且我认为我在 Verilog 中没有看到任何可用的此类事情的可综合示例。

    发布一些伪 C,以便我们可以看到您想要的内容。

    编辑 请参阅this paper:它描述了 VHDL 中胖树结构的递归生成。这完全由递归组件实例化处理,而不是使用递归算法来预定义结构。

    【讨论】:

    • 这篇论文太酷了,看看那些被金字塔攻击的蜘蛛! =D
    【解决方案2】:

    您可能想了解如何在 VHDL 中使用 generate 语句。将 generate 语句与 for 语句一起使用将根据需要生成尽可能多的组件。

    要求在构建 FPGA 时知道叶子的总数。您不能动态创建叶子。

    【讨论】:

    • Verilog 也有生成
    【解决方案3】:

    我将尝试提供一个答案,允许您构建一个通用树,而无需递归,仅基于在编译时作为通用提供的树高度。代码本身对我来说看起来有点棘手。然而,解决方案背后的原则是直截了当的。以下是解决方案的概要:

    • 假设您的节点将被放置在一个网格上,尺寸为 V=TREE_HEIGHT+1 和 H=2**TREE_HEIGHT(请参见下面的 ASCII-gram)。然后,您所需要的只是一种算法,用节点填充网格,并建立正确的输入和输出连接。
    • 要将树的一个级别连接到下一个级别,您可以使用大小为 TREE_HEIGHT x 2**TREE_HEIGHT 的二维数组(请参见下面代码示例中的第 63 行)。
    • 要实例化节点,请使用两个嵌套循环(VHDL 中的for-generate,参见第 68-69 行)。您不会填充所有节点;对于 depth=i 处的给定行,只需要 2**(i-1) 个节点(第 71 行)。
    • 您可以为内部节点和叶节点实例化不同的实体。只需检查 i 的当前值是否等于 TREE_HEIGHT(第 74 和 84 行)。
    • 最后,您只需要连接树的各个层。算术有点棘手,但一旦你做对了,你就完成了(第 78-80 行)。
    • 依靠您的综合工具移除未使用的电线。

    以下是 HEIGHT=2 的“网格”的糟糕演绎:

                 j = 1           j = 2           j = 3           j = 4      
           +---------------+---------------+---------------+---------------+
    i = 1  | Root Node     |    (empty)    |    (empty)    |    (empty)    |
           +---------------+---------------+---------------+---------------+
    i = 2  | Internal Node | Internal Node |    (empty)    |    (empty)    |
           +---------------+---------------+---------------+---------------+
    i = 3  | Internal Node | Internal Node | Internal Node | Internal Node |
           +---------------+---------------+---------------+---------------+
    

    代码示例如下:

    /*  1 */  package tree_types_pkg is
    /*  2 */      -- define a data type for the input and output values at each node
    /*  3 */      subtype tree_data_type is integer range 0 to 255;
    /*  4 */      -- define a vector type to propagate the output of a tree level to the next
    /*  5 */      type layer_to_layer_channel_type is array (natural range <>) of tree_data_type;
    /*  6 */  end;
    /*  7 */  --------------------------------------------------------------------------------
    /*  8 */  use work.tree_types_pkg.all;
    /*  9 */
    /* 10 */  entity internal_node is
    /* 11 */      generic (
    /* 12 */          TREE_HEIGHT: integer := 3
    /* 13 */      );
    /* 14 */      port (
    /* 15 */          x: in integer range 1 to 2**TREE_HEIGHT;
    /* 16 */          y: in integer range 1 to TREE_HEIGHT;
    /* 17 */          input: in tree_data_type;
    /* 18 */          output_left: out tree_data_type;
    /* 19 */          output_right: out tree_data_type
    /* 20 */      );
    /* 21 */  end;
    /* 22 */
    /* 23 */  architecture rtl of internal_node is begin
    /* 24 */      -- perform some calculation at the node
    /* 25 */      output_left <= input + x * y;
    /* 26 */      output_right <= input - x * y;
    /* 27 */  end;
    /* 28 */  --------------------------------------------------------------------------------
    /* 29 */  use work.tree_types_pkg.all;
    /* 20 */
    /* 31 */  entity leaf_node is
    /* 32 */      generic (
    /* 33 */          TREE_HEIGHT: integer := 3
    /* 34 */      );
    /* 35 */      port (
    /* 36 */          x: in integer range 1 to 2**TREE_HEIGHT;
    /* 37 */          y: in integer range 1 to TREE_HEIGHT;
    /* 38 */          input: in tree_data_type;
    /* 39 */          output: out tree_data_type
    /* 30 */      );
    /* 41 */  end;
    /* 42 */
    /* 43 */  architecture rtl of leaf_node is begin
    /* 44 */      -- perform some calculation at the node
    /* 45 */      output <= input + x * y;
    /* 46 */  end;
    /* 47 */  --------------------------------------------------------------------------------
    /* 48 */  use work.tree_types_pkg.all;
    /* 49 */
    /* 50 */  entity dirtybit_binary_tree is
    /* 51 */      generic (
    /* 52 */          TREE_HEIGHT: integer := 4
    /* 53 */      );
    /* 54 */      port (
    /* 55 */          tree_input: in tree_data_type;
    /* 56 */          tree_outputs: out layer_to_layer_channel_type(1 to 2**TREE_HEIGHT)
    /* 57 */      );
    /* 58 */  end;
    /* 59 */
    /* 60 */  architecture behavior of dirtybit_binary_tree is
    /* 61 */      constant LEAF_NODES_COUNT: integer := 2**TREE_HEIGHT;
    /* 62 */      type channel_array_type is array (natural range <>) of layer_to_layer_channel_type;
    /* 63 */      signal connections: channel_array_type(1 to TREE_HEIGHT)(1 to LEAF_NODES_COUNT);
    /* 64 */  begin
    /* 65 */
    /* 66 */      connections(1)(1) <= tree_input;
    /* 67 */
    /* 68 */      grid_y: for i in 1 to TREE_HEIGHT generate
    /* 69 */          grid_x: for j in 1 to LEAF_NODES_COUNT generate
    /* 70 */
    /* 71 */              instantiate_nodes: if j <= 2**(i-1) generate
    /* 72 */
    /* 73 */                  internal_nodes: if (i /= TREE_HEIGHT) generate
    /* 74 */                      internal_node: entity work.internal_node 
    /* 75 */                          generic map (TREE_HEIGHT => TREE_HEIGHT)
    /* 76 */                          port map (
    /* 77 */                              x => j,
    /* 78 */                              y => i,
    /* 79 */                              input        => connections(i)(j),
    /* 80 */                              output_left  => connections(i+1)((j-1)*i+1),
    /* 81 */                              output_right => connections(i+1)((j-1)*i+2)
    /* 82 */                          );
    /* 83 */                  end generate;
    /* 84 */
    /* 85 */                  leaf_nodes: if (i = TREE_HEIGHT) generate
    /* 86 */                      leaf_node: entity work.leaf_node 
    /* 87 */                          generic map (TREE_HEIGHT => TREE_HEIGHT)
    /* 88 */                          port map (
    /* 89 */                              x => j,
    /* 90 */                              y => i,
    /* 91 */                              input  => connections(i)(j),
    /* 92 */                              output => tree_outputs(j)
    /* 93 */                          );
    /* 94 */                  end generate;
    /* 95 */
    /* 96 */              end generate;
    /* 97 */
    /* 98 */          end generate;
    /* 99 */      end generate;
    /* 100 */
    /* 101 */ end;
    

    最后,这是合成电路在 Quartus 12.1(RTL 查看器)上的样子:

    【讨论】:

      【解决方案4】:

      Verilog(或 VHDL)generate 语句可用于创建可扩展系统,但隐含的硬件数量在编译时是固定的。您不能即时更改有多少硬件。 Verilog 的链接生成onetwo

      简短的例子,将多根电线连接到逆变器

      parameter DATA_W = 4;
      parameter DEPTH  = 8;
      
      wire [DATA_W-1:0] data   [0:DEPTH-1];
      wire [DATA_W-1:0] data_n [0:DEPTH-1];
      
      genvar index;  
      generate  
        for (index=0; index < DEPTH; index=index+1) begin: gen_code_label  
          inv #(
            .WIDTH  ( DATA_W        ) 
          ) inv_i0 (  
            .rx     ( data[index]   ), // input  
            .tx     ( data_n[index] ), // output   
          );  
        end  
      endgenerate 
      

      我发现有时会产生一些难以理解的问题,尤其是如果用于连接大量硬件时,它们还会引入另一个层次结构,这通常是不受欢迎的。

      对于可扩展的模板代码,我使用 erb (ruby),使用 gem ruby-it
      免责声明我编写 gem 是为了让这更容易。

      另一个question showing use of erb

      【讨论】:

        【解决方案5】:

        递归在 HDL 中不起作用是没有原因的。 VHDL 的 generate 语句可以非常愉快地用于递归地实例化实体。请记住,您需要知道在编译时递归的深度,因为硬件是预先创建的。但这实际上与确保您在软件上下文中有足够的堆栈空间并没有太大不同——它只是强制执行的,而不是隐含的(如果你弄错了,可以选择令人兴奋的堆栈粉碎错误:)

        【讨论】:

          猜你喜欢
          • 2021-11-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-08
          • 2010-09-24
          • 2019-08-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多