How do I implement a Parametrizable Mux in SystemVerilog?

一个人想着一个人 提交于 2019-12-04 06:10:10

问题


I am getting the following error in System Verilog with VCS synthesizer:

The following access has an invalid number of indices. bus[i]

I am basically trying to do a parametrizable mux made of interfaces, with the select bus being one-hot:

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

I tried the different methods outlined in this answer here (including using |= ) but I always get the same error. Using a "genvar i" instead of an int does not even compile.

If I replace bus[i] with bus[0], then it compiles (but it is not what I want) . . . also, replacing WIDTH with a number in the for statement (ie i < 1) gives me the same error even though it is less than the value of WIDTH.

Any ideas? the code needs to be synthesizable.


回答1:


Accessing an instances of an arrayed interface can only be accessed via a simulation constant (parameter, genvar, or hard-coded number). Data types and design elements both use dotted names to access there respected member or hierarchical-name, but the rules for accessing index arrays are different. Best description I can quickly find is in IEEE Std 1800-2012 § 23.6 Hierarchical names and § 23.7 Member selects and hierarchical names.

Here are two possible solutions:

Tri-state solution: floating if select is 0, x on the bit with multiple conflicting drivers.

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

Priority selector: using a local 2D array to map the interface instances. This map can be accessed in an always block. If you are on FPGA, this is the better solution as it doesn't need tri-state.

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


来源:https://stackoverflow.com/questions/33580513/how-do-i-implement-a-parametrizable-mux-in-systemverilog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!