Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Having trouble assigning signals of interfaces to regs within for loop #1418

Closed
veripoolbot opened this issue Apr 12, 2019 · 6 comments
Closed
Labels
resolution: wontfix Closed; work won't continue on an issue or pull request

Comments

@veripoolbot
Copy link
Contributor


Author Name: Junyi Xie
Original Redmine Issue: 1418 from https://www.veripool.org


Hi Wilson,

I experienced errors when I tried to assign signals of an interfaces array to 2-d regs.
Attached are example files which can generate the errors below:

%Error: interface_for_loop_tb.sv:32: Expecting expression to be constant, but variable isn't const: i
%Error: interface_for_loop_tb.sv:32: Could not expand constant selection inside dotted reference: i
%Error: interface_for_loop_tb.sv:33: Expecting expression to be constant, but variable isn't const: i
%Error: interface_for_loop_tb.sv:33: Could not expand constant selection inside dotted reference: i

Appreciate your help.

Regards,
Junyi Xie

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2019-04-12T20:35:52Z


Verilator currently requires interface (or cell) references must be statically unrolled. This is currently a fairly fundamental assumption that is unlikely to be improved in the near term (so not leaving this bug open).

To work around it move your for loop to become a generate loop outside the always.

And thanks for your good bug report, that makes it a lot easier to help.

     for (genvar i = 0; i < 2; i++)
     begin
         always_comb
         begin
             buffer_a[i] = in_intfs[i].a;
             buffer_b[i] = in_intfs[i].b;
         end
     end

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Junyi Xie
Original Date: 2019-04-12T20:54:53Z


This is reasonable.
Thanks for the quick reply by the way!

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Junyi Xie
Original Date: 2019-04-15T14:26:34Z


Hi Wilson,
We come across a Xilinx page that suggests having for loop inside always_comb helps to save runtime.

https://www.xilinx.com/support/answers/55302.html

This might be interesting for your investigation.

We will for now use the style you recommended though.

Thanks!

@veripoolbot veripoolbot added the resolution: wontfix Closed; work won't continue on an issue or pull request label Dec 22, 2019
@mmatzev
Copy link

mmatzev commented Feb 7, 2021

Hi,

I guess I have a similar problem.

I want to select the next action based on a array of interfaces.

always_comb
begin
    // default values
    req_buffer_in.receiver  = IDLE; // do nothing
    req_buffer_in.client_id = '0;
    
    // check higest prio requests
    for( integer i = 0; i < NB_CLIENTS; i++) begin
        if (cfg_addr_stream[i].valid) begin 
            req_buffer_in.receiver  = CFG;
            req_buffer_in.client_id = i;
        end
    end

NB_CLIENTS is a parameter in this design. Therefore, I would expect that this for-loop can be easily unrolled an the interface with the highest number is selected.

Unfortunately, I get the error message:

%Error: hwac_manager_obi.sv:99:29: Expecting expression to be constant, but variable isn't const: 'i'
                                 : ... In instance hwac_top.i_hwac_manager.i_hwac_manager_obi
   99 |         if (cfg_addr_stream[i].valid) begin 
      |                             ^
%Error: hwac_manager_obi.sv:99:28: Could not expand constant selection inside dotted reference: 'i'
                                 : ... In instance hwac_top.i_hwac_manager.i_hwac_manager_obi
   99 |         if (cfg_addr_stream[i].valid) begin 
      |                            ^

The first message points with ^ to the i, while the second message points to the [ bracket.

I don't see why unrolling does not work here?

Regards,

@wsnyder
Copy link
Member

wsnyder commented Feb 7, 2021

You didn't indicate what cfg_addr_stream is. Regardless this would probably work

always_comb begin
  // default values
  req_buffer_in.receiver = IDLE; // do nothing
  req_buffer_in.client_id = '0;
end

for( integer i = 0; i < NB_CLIENTS; i++) begin
  always_comb begin
    if (cfg_addr_stream[i].valid) begin 
        req_buffer_in.receiver  = CFG;
        req_buffer_in.client_id = i;
    end
end

Note, in the future please avoiding posting to old closed issues for new questions, otherwise your question will likely get lost.

@mmatzev
Copy link

mmatzev commented Feb 8, 2021

Dear,

cfg_addr_stream is an interface for a FIFO stream containing the valid signal.

The basic idea of placing the code block in one always_comb is to force the synthesis to build-up a solution, which generates the IDLE state if none of the .valid signals is high. Your code has actually two always blocks, which drive the same signal and the order is not really defined, if I understood it right.

Getting the original code running would be nice, nevertheless there is a work-around by converting the .valid signals of the interface into a logic array and then it should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution: wontfix Closed; work won't continue on an issue or pull request
Projects
None yet
Development

No branches or pull requests

3 participants