【问题标题】:How do I implement a Parametrizable Mux in SystemVerilog?如何在 SystemVerilog 中实现参数化 Mux?
【发布时间】:2015-11-07 07:50:44
【问题描述】:

我在使用 VCS 合成器的 System Verilog 中收到以下错误:

以下访问的索引数无效。 总线[i]

我基本上是在尝试做一个由接口组成的可参数化多路复用器,选择总线是单热的:

module myMux
    #(int unsigned WIDTH=3)
    (
        my_interface              bus[WIDTH-1:0],
        input  logic [WIDTH-1:0]  select,
        output logic [31:0]       out_data
    )
    always_comb begin
        out_data = 'x;
        for (int unsigned i=0; i < WIDTH; i++) begin
            if (select[i]) out_data = bus[i].in_data;
        end
    end
endmodule

我尝试了this answer here 中列出的不同方法(包括使用 |= ),但我总是遇到同样的错误。使用“genvar i”而不是 int 甚至无法编译。

如果我用 bus[0] 替换 bus[i],那么它会编译(但这不是我想要的)。 . .此外,用 for 语句中的数字(即 i

有什么想法吗?代码需要是可综合的。

【问题讨论】:

  • 另一件事。 . .如果我将接口更改为注册信号而不是它的工作原理(但这不是我想要的)。
  • 您的总线是声明为 [WIDTH-1:0] 还是应该是 bus[WIDTH]。此外,从代码中选择行似乎是单个位,应该是input select [WIDTH]。 genvar 解决方案必须有效,您可能犯了一些愚蠢的错误。
  • @shavill111 哦,当我将它复制到问题中时,这是一个错字。 Select 声明为 [WIDTH-1:0] 而 out_data 是 32 位总线。已在上述问题中更正。
  • 我尝试用最新版本的 VCS 编译,但这些行仍然出错,但这次是“bus[i].in_data。类型检查失败的原因:只有常量索引是这里支持。”还是不知道怎么做一个简单的带接口的MUX,不敢相信做不到。
  • 当我们没有为端口声明指定任何数据类型时,信号将默认为有线类型。所以,我们需要一个连续赋值语句......但是在第二种情况下,我们将数据类型指定为逻辑......所以连续赋值在那里不起作用......我们应该使用过程赋值。请在同一链接查看修改后的代码:edaplayground.com/x/LJ8

标签: system-verilog


【解决方案1】:

只能通过模拟常量(参数、genvar 或硬编码数字)访问阵列接口的实例。数据类型和设计元素都使用点名来访问受尊敬的成员或分层名称,但访问索引数组的规则不同。我能快速找到的最佳描述是 IEEE Std 1800-2012 § 23.6 分层名称和 § 23.7 成员选择和分层名称

这里有两种可能的解决方案:

三态解决方案:如果 select 为 0,则浮动,x 在具有多个冲突驱动程序的位上。

module myMux
    #(int unsigned WIDTH=3)
    (
        my_interface              bus[WIDTH-1:0],
        input  logic [WIDTH-1:0]  select,
        output wire  [31:0]       out_data
    );
  for (genvar i=0; i < WIDTH; i++) begin : loop
    assign out_data = select[i] ? bus[i].in_data : 'z;
  end
endmodule

优先级选择器:使用本地二维数组映射接口实例。这个map 可以在always 块中访问。如果您使用的是 FPGA,这是更好的解决方案,因为它不需要三态。

module myMux
    #(int unsigned WIDTH=3)
    (
        my_interface              bus[WIDTH-1:0],
        input  logic [WIDTH-1:0]  select,
        output logic [31:0]       out_data
    );
  logic [31:0] map [WIDTH];
  for (genvar i=0; i < WIDTH; i++) begin : loop
    assign map[i] = bus[i].in_data;
  end
  always_comb begin
    out_data = 'x;
    for(int unsigned i=0; i<WIDTH; i++) begin
      if (select[i]) out_data = map[i];
    end
  end
endmodule

【讨论】:

  • 对于第一个(三态解决方案),它仍然无法为我编译,因为我收到错误消息:“变量“out_data”由多个结构驱动程序驱动。”第二个,“优先级选择器”,为我编译,尽管我并不真正理解为什么首先需要地图。 . .所以我要批准这个答案。一个问题 。 . .合成时,会不会将其展平而没有优先级,还是会增加逻辑复杂度并尽量保持优先级?
  • 三态解决方案需要将out_data 声明为wire,而不是logic。它可能无法与 fpga 合成(有限数量的三态驱动程序)。对于优先级选择器,合成器可以保持优先级。如果select 保证是单热的,或者是编译指示(如果合成器支持它,请查看手册),或者可能是合成器选项中的设置,它可能会变平。
  • 谢谢!如果我按照您的方式将 out_data 更改为 wire,那么即使是第一个也可以编译。我什至可以将分配更改为 'x 而不是 'z。我认为逻辑(可以保持包括 z 和 x 在内的 4 种状态)可以在任何可以使用线的地方使用,但显然有一些微妙之处!
  • 'z 是浮动的(无驱动程序)。 'x 已被驱动,但具有未知/非法值。 wire 允许多个并发赋值(冲突的 0/1/X 赋值导致 X.Z 不与任何东西冲突),并且不能在 always 块中赋值。 logic & reg 在 always 块中分配,不能有多个并发分配。如果两个或多个 always 块分配相同的寄存器,则最后的分配获胜,并且不可综合。
猜你喜欢
  • 2017-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多