user2286899
user2286899

Reputation: 11

Generate Block Compile Time If-Else Parameterized

I'm looking to be able to parametric some behavioral level Verilog using the generate block. The module is for a re-configurable readout and FIFO block, mainly so we can code this up one and just use a parameter at the top level.

Lets say we have:

always @(posedge write_out_clk or posedge RESETN)
 begin
   if (RESETN)          
    SENSE_ADDR <= 0;
   else if (enb[0] == 1)
        SENSE_ADDR <= 1;   // for example but may be some other wire/bus etc
   else if (enb[1] == 2)
        SENSE_ADDR <= 1;   // for example but may be some other wire/bus etc
   else
    SENSE_ADDR <= SENSE_ADDR;
   end
 end

This is behavioral so the specifics of implementation are left to the compiler with user given timing constraints etc. This works for 'n' else-if statements within the block if I hard code them, currently synthesis and simulation are both working for 16 statements.

My question however is how to parameterise this using generate? Clearly if 'n=8' its not too much of a big deal to hard code it. What if 'n=64' or 'n=128' etc. Seems a shame to hard code it if the rest of the module is fully parameterized using the generate for 'n'...

I have tried doing something like:

genvar elseif_generate;
generate
   for (elseif_generate=0; elseif_generate<FIFO_SUB_BLOCKS; elseif_generate=elseif_generate+1)
   begin: elseif_generate_logic
   always @(posedge write_out_clk or posedge RESETN)
    begin
    if (RESETN)
        SENSE_ADDR <= 0;
    else if (enb[elseif_generate] == 1)
        SENSE_ADDR <= some_wire[elseif_generate];
    else
        SENSE_ADDR <= SENSE_ADDR;
    end
   end
endgenerate

This however leads to Multi-source errors for the output wire 'SENSE_ADDR'. This leads me to the further question. Clearly a generate block is not suitable here but how would I go about implementing parameterised code replication for this block? Basically I want the functionality of the behavioral, hard coded if-else always block in a parameterised form...

Upvotes: 1

Views: 1364

Answers (2)

Greg
Greg

Reputation: 19104

You don not need a generate block. Add a combination always block to calculate next_SENSE_ADDR that will be flopped to SENSE_ADDR.

always @(posedge write_out_clk or posedge RESETN)
 begin
   if (RESETN)          
    SENSE_ADDR <= 0;
   else
    SENSE_ADDR <= next_SENSE_ADDR;
 end

integer idx;
always @* begin // @(SENSE_ADDR or enb or some_wire)
  next_SENSE_ADDR = SENSE_ADDR; // default, value if enb is all 0
  // count down because lsb has higher priority
  for ( idx=FIFO_SUB_BLOCKS-1; idx>=0; idx-- ) begin
    if ( enb[idx] )
      next_SENSE_ADDR = some_wire[idx];
  end
end

Upvotes: 1

Brian Magnuson
Brian Magnuson

Reputation: 1487

Does this serve your needs? No generate required.

module mux #(
        parameter WIDTH = 5,
        parameter NUM   = 2,
        parameter NUMLG = $clog2(NUM)
    ) (
        input [NUMLG -1:0] sel,
        input [WIDTH - 1:0] in [0:NUM-1],
        output [WIDTH - 1:0] out
    );

    assign out = in[sel];

endmodule

If your simulator doesn't support SystemVerilog that well you'll have to modify this to blow out the input array but the concept is the same.

Upvotes: 1

Related Questions