cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
1,211 Views
Registered: ‎01-17-2020

Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Hello, 

We have come across a simulation / synthesis mismatch in the codebase of the OpenTitan project (https://docs.opentitan.org/).

In particular, Vivado seems to remove the following submodule under certain circumstances:

https://github.com/lowRISC/opentitan/blob/master/hw/ip/rv_plic/rtl/rv_plic_target.sv

This is the tracking issue with some more background: 

https://github.com/lowRISC/opentitan/issues/1355

It seems like the root cause for this behavior are ternary statements within nested generate loops. We have isolated a standalone test case for this - see attached files. The "working.sv" module is synthesized correctly whereas the "not_working.sv" module triggers this behavior.

The code runs fine with other tools like Verilator, VCS, AscentLint, JG and DC.

We are using Vivado 2018.3, but the problem persists when moving to Vivado 2019.2.

FPGA target: ​xc7a200tsbg484-1

Best regards,
Michael

1 Solution

Accepted Solutions
Highlighted
Xilinx Employee
Xilinx Employee
1,128 Views
Registered: ‎06-14-2018

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Hi @schaffner ,

This is an issue, will file internal ticket to get it fixed.

You have workaround of not using ternary operator, alternately you can apply attribute keep = true on is_tree signal.

is_tree is signal that gets optimized incorrectly.

Thanks,

Ajay

View solution in original post

11 Replies
Highlighted
Xilinx Employee
Xilinx Employee
1,129 Views
Registered: ‎06-14-2018

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Hi @schaffner ,

This is an issue, will file internal ticket to get it fixed.

You have workaround of not using ternary operator, alternately you can apply attribute keep = true on is_tree signal.

is_tree is signal that gets optimized incorrectly.

Thanks,

Ajay

View solution in original post

Highlighted
Visitor
Visitor
1,094 Views
Registered: ‎01-17-2020

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Thanks for your quick reply, @apetley.

I have removed the ternary statements in the current version of the module. 

Best regards,
Michael

0 Kudos
Highlighted
Scholar
Scholar
1,084 Views
Registered: ‎09-16-2009

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

@apetley 

Can we clarify the conditions that cause the bug?  

i.e. is using the verilog ternary operator always unsafe with Vivado?

Or. is it unsafe when used under a generate loop?

Or is it unsage when used under a generate loop, at some level > 1?

Is this bug specific to 2018.3, or does it exist in 2019.1, and 2019.2 as well?

Thanks,

Mark

Highlighted
Xilinx Employee
Xilinx Employee
1,028 Views
Registered: ‎06-14-2018

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Hi @markcurry ,

This is not general bug and is specific to this case where more than one conditions are to be satisfied for exposing this bug. If you observe it has to be in for generate and then two if condition. The ternary operator has to be in else part of the second if. 

One more thing, sel is ANDing of two signals here, is_tree[c0] and is_tree[c1]. For bug to reproduce those are necessary to be part of ternary operator.

end else begin : gen_nodes
logic sel; // local helper variable
assign sel = (is_tree[c0] & is_tree[c1]);// ? 1'b1 :
assign is_tree[pa] = (sel) ? is_tree[c1] : is_tree[c0];
end : gen_nodes

i.e. is using the verilog ternary operator always unsafe with Vivado?

=> No 

Or. is it unsafe when used under a generate loop?

=> No

Or is it unsage when used under a generate loop, at some level > 1?

=> No

Is this bug specific to 2018.3, or does it exist in 2019.1, and 2019.2 as well?

Yes, hence file internal ticket to get it fixed. (to record here for future reference #1052575)

Thanks,

Ajay

0 Kudos
Highlighted
Scholar
Scholar
1,013 Views
Registered: ‎09-16-2009

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

@apetley wrote:

 

This is not general bug and is specific to this case where more than one conditions are to be satisfied for exposing this bug. If you observe it has to be in for generate and then two if condition. The ternary operator has to be in else part of the second if. 

One more thing, sel is ANDing of two signals here, is_tree[c0] and is_tree[c1]. For bug to reproduce those are necessary to be part of ternary operator.


Trying to rephrase to make sure I understand what to search for within my codebase.  The bug is triggered by a set of NESTED ternary operators, within a generate loop.  The First ternary statement must also include and AND condition.  The second ternary must include the result of the first ternary in the FALSE condition of the ternary.

wire foo, bar, baz, qux; 
wire condition1, condition2;
generate if( some_generate_condition ) begin : gen_cond assign condition1 = (foo & bar) ? 1'b1 : 1'b0; assign condition2 = baz ? qux : condition1; end endgenerate

The above code would trigger the Vivado bug on condition2?  

This bug is a quite serious bug in Vivado and calls for an Answer Record, IMHO.  I'm trying as we speak to come up with some way of searching my codebase for the condition that trigger it.  It's important that these sorts of details are explictly stated in order to help your customers determine whether or not they may be effected.

Regards,

Mark

0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
998 Views
Registered: ‎06-14-2018

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Hi @markcurry ,

Below testcase closely mimics original issue however doesnt reproduce testcase. This is not general issue. T

here are still some conditions which are not satisfied to reproduce issue.

module top(in1,in2,clk,out);
input [7:0] in1,in2,clk;
output reg [7:0] out;

wire [7:0] w1;
wire condition1, condition2;
wire foo;

generate

for (genvar i = 0; i < 7; i++) begin: for_gen
if( 2>1 )
begin : gen_cond1
if (1>2) begin : gen_cond2
assign w1[i] = in1[i];
end : gen_cond2
else begin
assign condition1 = w1[i] & w1[i];
assign foo = condition1 ? w1[i] : w1[i];
end
end : gen_cond1
end : for_gen
endgenerate


always@(posedge clk)
begin
out = foo;
end

endmodule

 

Thanks,

Ajay

0 Kudos
Highlighted
Scholar
Scholar
989 Views
Registered: ‎09-16-2009

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Ajay,

Stating "this is not a general issue" is not helpful.  This is a Vivado tool bug - a very serious one - simulation / synthesis mismatches are probably the worst bug an FPGA tool can generate.  We need to concretely list the conditions on which this bug triggers the Vivado errant behaviour, so that your customers can determine if the conditions neccesary to trigger the bug are in our code base.  The trigger conditions may seem rare to you, but there's no way Xilinx can determine if these rare conditions are in a customer's code base.  We must determine this ourselves.  Hence my request for an AR to be generated by Xilinx to help us achieve this.

Back to my question, does my example trigger the errant conditions or not?  By your reply, I'm guessing "no".  Your new example now includes nested generate if conditionals, but only ONE ternary operator.  So, again, it's not clear what are the conditions to trigger the bug?  My new guess at the bug trigger requirements:

  1. Nested conditional generate if conditionals
  2. The inner generate if conditional takes the else conditional clause
  3. The else clause contains more than one statement
    1. The first statement "condition1" in your example must include an "AND" operation (only an "AND" operator or any logic operation?)
    2. The second statement must include a ternary operator with 'condition1' being the selection operand of the ternary

Does this summarize what I should be searching for in my code base?  For the first conditional, if I assigning it procedurally will I still trigger the bug i.e.

always_comb
  condition1 = bar & baz;
assign foo = condition1 ? qux : fred;

Would this trigger the bug as well?  (Assuming this code is in "else" generate if clause of a nested conditional)

Thanks,

Mark

Highlighted
Xilinx Employee
Xilinx Employee
919 Views
Registered: ‎06-14-2018

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Hi @markcurry 

always_comb
  condition1 = bar & baz;
assign foo = condition1 ? qux : fred;

 Above code will not trigger bug.

Did some more analysis and following are my findings.

 

Capture.JPG 

I have tried to be comprehensive as much as I can. Any change in above will not trigger bug scenario. 

For instance if,

  • assign w1[0] = in1[0]; will not trigger bug scenario
  • assign condition1 = in2[0]; will not trigger bug scenario

If assign statements are replaced under procedural block (always) , there is no issue.

Said that bug will be fixed in future release.

Regards,

Ajay

0 Kudos
Highlighted
Visitor
Visitor
888 Views
Registered: ‎01-17-2020

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Ajay, Mark,

I reduced my testcase even further, and I can say that the following constructs do not trigger the bug:

  • localparams inside generate statements
  • if/else generate statement inside nested loops
  • locally defined helper signal " sel"
  • register at the output
  • AND operator in select statement

In fact, I can reproduce this error with the reduced test case attached below.
Note that "tree2" is not required to trigger the bug, but to prevent the logic optimizer from optimizing the reduction tree to a simple passthrough function.

module not_working #(
  parameter int N_SOURCE = 32
) (
  input [N_SOURCE-1:0] in1,
  input [N_SOURCE-1:0] in2,
  output logic         out
);

  localparam int unsigned N_LEVELS = $clog2(N_SOURCE);
  logic [2**(N_LEVELS+1)-2:0] tree1;
  logic [2**(N_LEVELS+1)-2:0] tree2;
  assign tree1[(2**N_LEVELS)-1 +: N_SOURCE] = in1;
  assign tree2[(2**N_LEVELS)-1 +: N_SOURCE] = in2;

  for (genvar level = 0; level < N_LEVELS; level++) begin : gen_tree
    for (genvar offset = 0; offset < 2**level; offset++) begin : gen_level
      // not working:
      assign tree1[(2**level)-1 + offset]  = (tree1[(2**(level+1))-1 + 2*offset] ^
                                              tree1[(2**(level+1))-1 + 2*offset + 1]) ? tree1[(2**(level+1))-1 + 2*offset + 1]
                                                                                      : tree1[(2**(level+1))-1 + 2*offset];
      assign tree2[(2**level)-1 + offset]  = (tree1[(2**(level+1))-1 + 2*offset] ^
                                              tree1[(2**(level+1))-1 + 2*offset + 1]) ? tree2[(2**(level+1))-1 + 2*offset + 1]
                                                                                      : tree2[(2**(level+1))-1 + 2*offset];
      // working:
      // assign tree1[(2**level)-1 + offset]  = ( (tree1[(2**(level+1))-1 + 2*offset] ^ tree1[(2**(level+1))-1 + 2*offset + 1]) & tree1[(2**(level+1))-1 + 2*offset + 1]) |
      //                                        (!(tree1[(2**(level+1))-1 + 2*offset] ^ tree1[(2**(level+1))-1 + 2*offset + 1]) & tree1[(2**(level+1))-1 + 2*offset]);
      // assign tree2[(2**level)-1 + offset]  = ( (tree1[(2**(level+1))-1 + 2*offset] ^ tree1[(2**(level+1))-1 + 2*offset + 1]) & tree2[(2**(level+1))-1 + 2*offset + 1]) |
      //                                        (!(tree1[(2**(level+1))-1 + 2*offset] ^ tree1[(2**(level+1))-1 + 2*offset + 1]) & tree2[(2**(level+1))-1 + 2*offset]);
     end : gen_level
  end : gen_tree

  assign out = tree2[0];

endmodule

 

Highlighted
Scholar
Scholar
866 Views
Registered: ‎09-16-2009

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Thanks for simplifying the testcase.  I know that sort of the thing takes quite a bit of futzing with the tools to accomplish.

Having said that I'm now even more worried about this Vivado bug.  Your new example shows some fairly straightforward logic, without much special at all. Just a single ternary operator inside a nested generate. (Perhaps also something to do with the indexing using the nested iterators?)

The bug conditions are NOT well understood at all nor, it appears to me, rare.  If this logic does indeed trigger the Vivado bug, then there's a very high probability of something like it appearing in our code base.

Regards,

Mark

0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
715 Views
Registered: ‎06-14-2018

Re: Simulation / Synthesis Mismatch with Vivado 2018.3

Jump to solution

Hi @markcurry , @schaffner ,

Have forwarded this to team to include as an AR.

Thanks,

Ajay 

0 Kudos