Rich Maes
Rich Maes

Reputation: 1222

Parameterizing a casex statement in verilog

Consider the following function which I would like to parameterize. I have created some parameters to set a width of the input and a corresponding width parameter for the output.

parameter SELECT_WIDTH = 6;
parameter PRIENC_WIDTH = $clog2(SELECT_WIDTH+1);


function [PRIENC_WIDTH-1:0] prienc6;
 input [SELECT_WIDTH-1:0] select;
 reg   [PRIENC_WIDTH-1:0] out;
 begin
   casex(select)
     6'b000001: out = 3'b101;  // Is it possible to parameterize the case statement with generate
     6'b00001x: out = 3'b100;
     6'b0001xx: out = 3'b011; 
     6'b001xxx: out = 3'b010; 
     6'b01xxxx: out = 3'b001; 
     6'b1xxxxx: out = 3'b000; 
   endcase
   prienc6 = out ;
 end
end function

Obviously, the casex statement cases will not expand as written.
So I tried the following, which didn't compile correctly indicating unexpected generate found.

function [PRIENC_WIDTH-1:0] prienc_n;
 input [SELECT_WIDTH-1:0] select;
 reg   [PRIENC_WIDTH-1:0] out;
 begin
   genvar gv_j;
   casex(select)
      for (gv_j = 0; gv_j < SELECT_WIDTH; gv_j = gv_j + 1)
         begin
           {{(SELECT_WIDTH-1)-gv_j{1'b0}},1'b1,{gv_j{1'bx}}} : out = (SELECT_WIDTH-1)-gv_j;
         end
   endcase
   prienc_n = out ;
 end
end function

I have been able to get the correct behavior using parameterized if's, but it seems like I should be able to parameterize that casex statement. Any thoughts on how to do this? I guess what I will try next is to wrap the casex in the generate loop and create 6 casex statements, each with only one state.

Upvotes: 0

Views: 973

Answers (1)

dave_59
dave_59

Reputation: 42673

Since you tagged this question with SystemVerilog, I'll show you how to do this without a case statement or generate

function logic [PRIENC_WIDTH-1:0] prienc_n(
 input [SELECT_WIDTH-1:0] select);
 for (int j = 0; j < SELECT_WIDTH; j++) begin
   if (select[SELECT_WIDTH-1]) return j;
   select <<=1;
 end
 // if no 1 found
 return ('x); // you did not specify this case
endfunction

If you need to stay in Verilog, it will need an intermediate variable

   function reg [PRIENC_WIDTH-1:0] prienc_n(
     input [SELECT_WIDTH-1:0] select);
     reg   [PRIENC_WIDTH-1:0] out;
     integer j;
     begin
       out = {PRIENC_WIDTH{1'bx}}; // what should be returned if no 1 found
       for (j = 0; j < SELECT_WIDTH; j = j + 1) begin
         if (select[SELECT_WIDTH-1]) begin 
                                       out = j;
                                       select = 0;
                                     end
         select = select << 1;
     end
     prienc_n = out;
    end
    endfunction

Upvotes: 2

Related Questions