2
\$\begingroup\$

I wrote a module in System Verilog, I need 32 modules, so I am using generate statement for instantiation.

The problem is that in every rising edge of clock I need to instantiate new values to the modules and then need to choose one of them (in the same posedge clock, depending on the outputs of the modules, in my case the min between all the module output).

How can I do that?

This is my current version of the code:

    genvar j; 
    generate 
        for (int j=0; j<32; j++)
         begin: module_instant_loop
            always @(posedge Clock)
               begin
                  MyUnit unit[j] (.A(TEST1[j],.B(TEST2[j]),.OUT(MYOUT[j]);
               end              
            end
         end
    endgenerate

And this is the code that I want to add:

for (int i=0; i<32; i++)
    begin
        if (MYOUT[i] < MINIMUM) MINIMUM=MYOUT[i];
        if (MYOUT[i] > MAXIMUM) MAXIMUM=MYOUT[i];
    end

How can I add the loop to my code?

\$\endgroup\$
1
  • \$\begingroup\$ You shouldn't have the int in the for loop inside the generate statement - j is already declared as a genvar. \$\endgroup\$ Commented Jun 1, 2015 at 0:25

1 Answer 1

3
\$\begingroup\$

You cannot instantiate a module instance inside an always block. You choices are to move the synchronous logic inside MyUnit or flop the output MyUnit at the same level.

Typically, you want to flop your final outputs. You may put some combinational logic after the flop, but be aware this can can make flop-to-flop timing across different modules harder to calculate.

So assuming MINIMUM and MAXIMUM are the values you want flopped, I would recommend the following logic:

always_comb begin
  // Set defaults
  next_MINIMUM = '1; // fill with all 1s
  next_MAXIMUM = '0; // fill with all 0s

  // Alternative default with the previous MIN/MAX values
  //next_MINIMUM = MINIMUM;
  //next_MAXIMUM = MAXIMUM;

  // Update MIN/MAX based on MYOUT
  foreach(MYOUT[idx]) begin // IEEE Std 1800-2012 12.7.3 The foreach-loop
    if (MYOUT[idx] < next_MINIMUM) next_MINIMUM=MYOUT[idx];
    if (MYOUT[idx] > next_MAXIMUM) next_MAXIMUM=MYOUT[idx];
  end
end

always_ff @(posedge clk) begin
  MINIMUM <= next_MINIMUM;
  MAXIMUM <= next_MAXIMUM;
end

It is a best practice to always assign a flop with non-blocking. Blocking assignments are needed to properly calculate the next value. Therefore, the intermediate signals next_*. When using SystemVerilog, it is recommend to use always_comb and always_ff instead of always (See IEEE Std 1800-2012 § 9.2.2.2.2 always_comb compared to always @*).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.