toomanychushki
toomanychushki

Reputation: 149

Verilog part select in a genvar context

I am trying to multiplex the input for a filter module but I am having difficulty with the syntax. Can anyone help? I was thinking to do,

reg [y:0] MULTICHANNEL_INPUT;
wire [x:0] channelDataIn;
wire [1:0] channelNumberIn;

Filter XYZ (
...
.chan_in(channelNumberIn), 
.din(channelDataIn),             //[x:0] data in
...
);

always @ (*)
 case(channelNumberIn) 
   0:  assign channelDataIn = MULTICHANNEL_INPUT[x:0]
   1:  assign channelDataIn = MULTICHANNEL_INPUT[2x:x+1]
   ...
 endcase

This however does not compile. How should I be doing this?

Upvotes: 0

Views: 520

Answers (2)

nguthrie
nguthrie

Reputation: 2685

I am taking a guess at what you are trying to accomplish, but if you just want to grab part of a vector you can use an indexed part select

module test
 #(
   parameter x = 4,
   parameter y = 4*x
  )
  (
   input [y-1:0] MULTICHANNEL_INPUT,
   input [1:0] channelNumberIn,
   output [x-1:0] channelDataIn
  )

    assign channelDataIn = MULTICHANNEL_INPUT[x*channelNumberIn +: x];

endmodule

This can also be done with a case statement:

module test
 #(
   parameter x = 4,
   parameter y = 4*x
  )
  (
   input [y-1:0] MULTICHANNEL_INPUT,
   input [1:0] channelNumberIn,
   output reg [x-1:0] channelDataIn
  )

    always_comb begin
      case(channelNumberIn)
        2'd0: channelDataIn = MULTICHANNEL_INPUT[1*x-1:0*x];
        2'd1: channelDataIn = MULTICHANNEL_INPUT[2*x-1:1*x];
        2'd2: channelDataIn = MULTICHANNEL_INPUT[3*x-1:2*x];
        2'd3: channelDataIn = MULTICHANNEL_INPUT[4*x-1:3*x];
      endcase
    end

endmodule

Notice that I had to make the output a reg since it is driven inside an always block. However, this doesn't change anything. These two modules should synthesize to the same gates. I like the first solution better since it is less error prone: A typo in the second one could result in overlapping part selects.

Another option just for fun. I don't like this as much since it is not very clear what is happening and you run the risk of getting the dimensions backwards (I'm not sure I actually did it right here):

wire [3:0][x-1:0] input_2d;
assign input_2d = MULTICHANNEL_INPUT;
assign channelDataIn = input_2d[channelNumberIn];

Upvotes: 1

toomanychushki
toomanychushki

Reputation: 149

A simple approach to get an unregistered mux is to use continuous assignment

assign <wire1> = <2-bit_select> ? <value0> : <2-bit_select> ? <value1> : ... <value1>;

Upvotes: 0

Related Questions