Is there anyway to generate a list using a for loop in verilog?


logic [NUM-1:0]  [31:0] data;
logic [3:0] addr, cmd, testvalue;
logic [(NUM/2+1)*32-1:0] list;

assign list = {addr, cmd,
              for ( i=0;i<NUM;i=i+2) begin

This is a bit of a nonsense example but just to get the point across about selecting and concatenating regular fixed intervals.


2 Answers 2


Since list is a reg, it cannot be continuously driven by data. But if we change it to wire, then we can create a continuous assignment with a generate block as follows:

module main
#(parameter NUM = 8);
    logic [NUM-1:0]  [31:0] data;
    wire [(NUM/2+1)*32-1:0] list;
    genvar i;
    for (i = 0; i < NUM ; i = i + 2) begin: genbit
        assign list[(i+1)*32-1 -: 32] = data[i];

If I understood correctly your intention, you want to "flatten" the data into a list of bits while taking every second data word, so the code above is using the bit selection syntax to assign chunks of 32 bits at a time. You might want to reverse the selection depending on "endianess" you want the data to be flatten with.

  • 2
    \$\begingroup\$ 'logic can be driven continuously using assign as well ... no problems ... \$\endgroup\$
    – Mitu Raj
    Jun 22, 2021 at 5:26
  • \$\begingroup\$ Thanks! I was toying around with that approach. I guess what I'm after is something that allows multiple items in "list" including slices of data without having to create temporary wires. Ex list = {addr, cmd, data[5:4], data[1:0], testvalue}; It would be nice to use a "for loop" to add in slices but it seems you can only loop over complete code ( terminated by ; ) versus sub portions of code. \$\endgroup\$
    – togaclad
    Jun 22, 2021 at 11:51
  • \$\begingroup\$ @Mitu my compiler is shouting at me when I do it.. \$\endgroup\$
    – Eugene Sh.
    Jun 22, 2021 at 12:26
  • \$\begingroup\$ That's weird. logic was meant to be a replacement to both wire and reg in Verilog-2009/SV, \$\endgroup\$
    – Mitu Raj
    Jun 22, 2021 at 13:33

First of all, you cannot do it in verilog the way you proposed. You need to have the loop setting those bits separately. The only slight problem in your case is to figure out correct offsetts and widths.

BTW, your decalaration of data logic [NUM-1:0] [31:0] data; does not correspond the proposed usage int the for loop. You need to swap the ranges. Also, size of the list is smaller than you need for the concat. If i am not mistaken, you should use (NUM-1)/2 to be precise. Check me :-).

I propose you use the following in order to simplify the code: use a separate temp variable for extracting elements form data and use it in the following concat. BTW, there is no need to use assign.

  logic [31:0] [NUM-1:0]  data; // << swap array ranges
  logic [3:0] addr, cmd, testvalue;
  logic [((NUM-1)/2)*32+$bits(addr)+$bits(cmd)+$bits(testvalue)-1:0] list; //<< fix the width

  logic [31:0][(NUM-1)/2-1:0] list_data;
  always_comb begin   
    for(int i = 0; i < NUM; i+=2)
      list_data[i/2] = data[i];
    list = {addr, cmd, list_data, testvalue};

or if you wish, yhou can use assign for logic

assign list = {addr, cmd, list_data, testvalue};

Another variation is to use functions. This one should be definied inside the module in order to see data. Or you can pass data as an argument.

  function logic [31:0][(NUM-1)/2-1:0] list_data();      
      for(int i = 0; i < NUM; i+=2)
        list_data[i/2] = data[i];
  assign // or always_comb
    list = {addr, cmd, list_data(), testvalue};

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.