Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16597 Discussions

IO_OBUF polarity not matching RTL

Robert_H_Intel
Employee
1,843 Views

I am working on a design using an Agilex F-series part (AGFB014R24B2E3V) and am having issues with tri-stated outputs.  The RTL in question is:

assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'bz;

When I test my board, I found it to be inverted.  If I set lb_enable_dd high, it was hi-z, low gave me clk_fast on my TRIG[0] output.  When I opened the Technology Map View (post-fit) I noticed the IO_OBUF primitive had a inverter on the OE input that didn't seem to be compensated for in compile.

Robert_H_Intel_0-1645128008718.png

Things I have tried:

- Tested both 21.2 and 21.3 versions of the tools.

- Switching to a non-tristating output.  This works as expected, no polarity issues.

assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'b0;

- Tried generating the buffer using the GPIO Intel FPGA IP core from the library. 

trig_out trig_out (
   .din ({lb_rxclk_det[0], clk_fast, lb_enable_dd, clk_fast}),
   .oe ({4{lb_enable_dd}}), 
   .pad_out (TRIG[3:0]) 
);

Same inverter present on the IO_OBUF.  Even when I open the datasheet for that IP core it says OE should be active high.

Robert_H_Intel_2-1645128258306.png

Thoughts? 

0 Kudos
16 Replies
ShengN_Intel
Employee
1,832 Views

Hi,

 

Tri-state buffer can be either active high or active low. There are many types of it you can refer here. What I can guess is that IO_OBUF is most likely an active low tri-state buffer.

Moreover, --OE is active high-- you highlighted in manual don't very related to IO_OBUF mentioned above. That is for Data Interface Signals of gpio ip.

 

Best regards,
Sheng

p/s: If any answer from the community or Intel support are helpful, please feel free to give Kudos.

0 Kudos
Robert_H_Intel
Employee
1,824 Views

That doesn't change the fact that when I implement an active-high tri-state buffer (either with RTL or instantiating a GPIO IP block), the tools put in the IO_OBUF and the polarity of the OE is active-low, but that doesn't seem to be compensated for.

The behavior of my hardware is the opposite of what I have coded for the design and when I drive 0 instead of hi-Z in the "disabled" state the polarity is now correct.  I have never actually instantiated an IO_OBUF, that is just what the tools used during synthesis but it seems like they are not compensating for the active-low OE of that primitive.

So...

assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'bz;

lb_enable_dd = 0,  TRIG[0] = clk_fast  (observed on the HW, which is wrong, it should be hi-Z)

lb_enable_dd = 1, TRIG[0] = hi-Z (observed on the HW, which is wrong, it should be clk_fast)

 

assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'b0;

lb_enable_dd = 0,  TRIG[0] = 0  (observed on the HW, which is correct)

lb_enable_dd = 1, TRIG[0] = clk_fast (observed on the HW, which is correct)

 

Thanks

Rob

 

0 Kudos
ShengN_Intel
Employee
1,814 Views

Hi Rob,

 

In order to be in tri-state mode, you have to drive "hi-Z" instead of "0". Otherwise, it will be switched to a non-tristating output as you say before if you drive "0". Thus, driving "hi-Z" or "0" will result in two different modes.

In tri-state mode, IO_OBUF primitive comes originally with active-low OE internal settings. That is the primary internal logic function of IO_OBUF primitive which you cannot simply change it.

Btw, you can refer to here https://en.wikipedia.org/wiki/Three-state_logic as well for Three-state logic. (Many devices are controlled by an active-low input called OE (Output Enable) which dictates whether the outputs should be held in a high-impedance state or drive their respective loads (to either 0- or 1-level).)

 

Thanks.

Best regards,

Sheng

0 Kudos
Robert_H_Intel
Employee
1,808 Views

Yes, I understand driving 0 will instantiate a different buffer.  I am using that "version" to show that my logic is sound.

 

Let me put it more simply.  If my RTL contains this line in the top level, and TRIG[0] is defined as an output pin on the top-level design.

assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'bz;

 

And lb_enable_dd is "1", what would you expect on the output pin TRIG[0]?  I think it should be "clk_fast".

And if lb_enable_dd is "0", I would expect Hi-Z?  Does that sound correct?

 

If so, there is a problem in the way Quartus is synthesizing this statement.

 

I believe you that IO_OBUF has an active low OE input, I see that in the tech view.  However, why is there no inverter instantiated by the tools before the OE# input to match the logic defined in the RTL.  This is the issue.  What I am coding is not what I am getting, and I have confirmed this on the hardware as well.

 

0 Kudos
ShengN_Intel
Employee
1,799 Views

Hi Rob,

 

Can you provide a sample project with the problem for better viewing?

 

Thanks.

Best regards,
Sheng

0 Kudos
ShengN_Intel
Employee
1,784 Views

Hi Rob,

 

I further think about the problem you mentioned and found out should be no problem with both IO_OBUF primitive and RTL.

IO_OBUF primitive is designed to be active low OE means you have to use '0' instead of '1' to enable output in order to enable the clock.

So when using assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'bz;, an inverter is automatically added to make the RTL matches the IO_OBUF primitive design setting. If change to assign TRIG[0] = (lb_enable_dd) ? 1'bz : clk_fast;, I guess the inverter will most likely disappear.  The problem is IO_OBUF OE part there will change based on which RTL you are using to make sure '0' is used to enable output at last.

If you still insist to use '1' for triggering the clock, I think you have to additionally add a not gate or inverter in front of active low OE manually by yourself. O_OBUF primitive setting will not do that for you.

 

Thanks.

Best regards,
Sheng

0 Kudos
Robert_H_Intel
Employee
1,772 Views

"So when using assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'bz;, an inverter is automatically added to make the RTL matches the IO_OBUF primitive"

 

You seem to be missing the point.  The tools ARE NOT automatically adding this inverter, that is my whole issue!!!!!

0 Kudos
ShengN_Intel
Employee
1,763 Views

Hi Rob,

 

What I mean is assign TRIG[0] = (lb_enable_dd) ? clk_fast : 1'bz; represents the whole IO_OBUF primitive. For that assign, obviously '1' is needed to trigger the clk_fast. However, IO_OBUF primitive needs to function as active low OE means lb_enable_dd needs to be '0' at any point. For that assign, if lb_enable_dd is '0' 1'bz will be selected right? If like that IO_OBUF is not active low OE anymore. So an inverter is automatically added to compensate for that (first pic you share).

In order to use '1' for clk_fast triggering, you have to manually add a not gate or inverter. 

 

Best regards,
Sheng


0 Kudos
ShengN_Intel
Employee
1,751 Views

Hi Rob,

 

Do you have any further update or Should I consider that case to be closed?

 

Thanks,

Best regards,
Sheng

0 Kudos
Robert_H_Intel
Employee
1,709 Views

The problem still persists.  The Quartus synthesis is failing to add the required inverter in front of the IO_OBUF to match the logic in my RTL.

 

Inverting it on my end changes my intended logic (and would still likely be wrong on my end).

 

The issue appears to be in the tools, not my RTL, so I can't see a way that I can fix this on my end.

0 Kudos
ShengN_Intel
Employee
1,694 Views

Hi Rob,

 

Can you provide a sample file which duplicates the issue for better viewing? If that's a bug, I can reflect this to internal team with the reference file.

 

Thanks,

Best regards,
Sheng

0 Kudos
Robert_H_Intel
Employee
1,680 Views

Sure.  However, can you please be more specific as to which file(s) you want to look at?  I want to make sure I provide adequate information to look at.

 

Or do you mean create a very  small project that demonstrates the error?  I can do that too, will just take a bit more time.

0 Kudos
Robert_H_Intel
Employee
1,634 Views

I made a very simple new project.  The same device (AGFB014R24B2E3V).  This is the RTL.

module tri_test (

input logic clk1,
input logic clk2,

input logic en1,
input logic en2,

output logic out1,
output logic out2
);

assign out1 = (en1) ? clk1 : 1'bz;
assign out2 = (en2) ? clk2 : 1'b0;

endmodule

 

You can see that out1 "should" be clk1 if en1 is high, and Hi-Z if en1 is low.  You can also see the post-fit Technology Map Viewer shows the polarity implemented is wrong (there is no inverter added to compensate for the active-low OE on the IO_OBUF primitive).

The out2 circuit is the same logic, but without the tri-state (it just outputs 0 if en2 is low).

Robert_H_Intel_0-1646437680712.png

 

The whole project folder is now attached.

 

0 Kudos
ShengN_Intel
Employee
1,618 Views

Hi Rob,

 

You're absolutely right. Sorry for the confusion before. The post-fit Technology Map Viewer result is totally opposite of the RTL viewer and simulation. I noticed this problem still persists on version 21.3 and above.

I also found out a previous similar issue from KDB here. By right, the problem should be fixed beginning with version 21.3 but looks like it wasn't being solved thoroughly. 

At the mean time, I think you can invert the output enable signal in your RTL by using assign out1 = (!en1) ? clk1 : 1'bz;. By doing this, can temporarily get the correct output and post-fit Technology Map Viewer.

ShengN_Intel_0-1646490492467.png

I'll reflect this bug to internal team for further investigation.

 

Thanks,

Best regards,
Sheng

 

 

0 Kudos
Robert_H_Intel
Employee
1,548 Views

I am hesitant to simply invert the control to "work around" this bug since all it will take is a newer version of the tools (with the fix in place) and suddenly the polarity of the control signal will be wrong again (at a system level).  

If I am the one working on this new version that would be fine, but if it is someone else, they won't necessarily have the historical information to know what is happening.

 

At this point, I would just like to be kept in the loop on the fixes being made, and what release of the tools will contain the fix.  Also, if there is a pre-release patch that becomes available I would like to know about it.

Is there a way to get on a notification list or something?

0 Kudos
ShengN_Intel
Employee
1,491 Views

Hi Rob,


The internal team feedback is the problem will be planned in version 22.3. You may keep tracking the progress from here https://hsdes.intel.com/appstore/article/#/15010826170


Thanks,

Best regards,

Sheng


0 Kudos
Reply