Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
Announcements
Intel Support hours are Monday-Fridays, 8am-5pm PST, except Holidays. Thanks to our community members who provide support during our down time or before we get to your questions. We appreciate you!

Need Forum Guidance? Click here
Search our FPGA Knowledge Articles here.

Registers in I/O cells

Altera_Forum
Honored Contributor I
1,584 Views

Most Altera families have register(s) in the I/O cells. Obviously if I want full control of the plumbing I can instantiate the 'GPIO Lite' IP core and do everything explicitly, but I thought that for simple cases the tools would spot a signal coming in on a pin going straight to a register and use the register in the I/O rather than using up an LE. 

 

However, with my current design it isn't doing that - the fitter resource report says "I/O registers 0/863 (0%)", and looking at the Technology Map viewer I can see my signals coming in through an "IO_IBUF" and then getting latched in a LE. 

 

I'm currently working with MAX10 and Quartus Prime 17.0.2 Lite edition (design in VHDL), but I thought I'd seen this working in earlier projects (with Cyclone2/3 and much older versions of Quartus). 

 

Am I missing a setting somewhere, or does this feature not exist?
0 Kudos
4 Replies
Altera_Forum
Honored Contributor I
434 Views

If I remember correctly, there is no input register in the IO cell, but a direct connection from the IO cell to the LAB, which is almost as fast. On the output side there should be a 2 registers, because doing DDIO interfaces in the LAB is far too slow(the mux after the registers becomes a LUT to route through and it gets ugly)

Altera_Forum
Honored Contributor I
434 Views

Hmm. 

 

According to the manual it certainly has registers ("Max 10 General Purpose I/O user guide", figure 2-1, and in fact I've just checked the old Cyclone III documentation and that has an almost identical diagram of the I/O structure there). 

 

That diagram shows a total of 3 registers - one for input, one for output, and one for OE. However, the description says: 

 

Each IOE contains one input register, two output registers and two output-enable (OE) registers. 

  • The two output registers and two OE registers are used for DDR applications 

  • You can use the input registers for fast setup times and output registers for fast clock-to-output times 

  • You can use the OE registers for fast clock-to-output enable times 

 

 

 

That total of 5 registers matches up with the resource summary from compiling my project - where I am using "0 out of 863 I/O registers" on a device with 178 I/O pins (5 registers per pin would be 890, but some of the pins are shared config pins and are input-only).
Altera_Forum
Honored Contributor I
434 Views

It all depends on your timing constraints and if you are using the "Fast I/O register" assignments. Using the registers in the I/O is not always good (and not regularly done by the Fitter) because it's possible to fail hold timing on the I/O to the upstream or downstream device. If you want to force the use of the I/O registers, use a Fast Input or Fast Output register assignment in the Assignment Editor.

Altera_Forum
Honored Contributor I
434 Views

Thanks. Enabling "fast input register" for one of my buses certainly got usage of the corresponding number "i/o registers" in the fitter summary, though it's not clear from the netlist viewers whether I had actually got what I had in mind. 

 

So, I gave up on that and decided to do it explicitly with the "Altera GPIO Lite" megafunction. In the megawizard there's not many options exposed: in particular, the clock enable isn't made available. However, the VHDL it generates has all sorts of features: 

 

component altera_gpio_lite is generic ( PIN_TYPE : string := "output"; SIZE : integer := 4; REGISTER_MODE : string := "bypass"; BUFFER_TYPE : string := "single-ended" ; ASYNC_MODE : string := "none"; SYNC_MODE : string := "none"; BUS_HOLD : string := "false"; OPEN_DRAIN_OUTPUT : string := "false"; ENABLE_OE_PORT : string := "false"; ENABLE_NSLEEP_PORT : string := "false"; ENABLE_CLOCK_ENA_PORT : string := "false"; SET_REGISTER_OUTPUTS_HIGH : string := "false"; INVERT_OUTPUT : string := "false"; INVERT_INPUT_CLOCK : string := "false"; USE_ONE_REG_TO_DRIVE_OE : string := "false"; USE_DDIO_REG_TO_DRIVE_OE : string := "false"; USE_ADVANCED_DDR_FEATURES : string := "false"; USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY : string := "false"; ENABLE_OE_HALF_CYCLE_DELAY : string := "true"; INVERT_CLKDIV_INPUT_CLOCK : string := "false"; ENABLE_PHASE_INVERT_CTRL_PORT : string := "false"; ENABLE_HR_CLOCK : string := "false"; INVERT_OUTPUT_CLOCK : string := "false"; INVERT_OE_INCLOCK : string := "false"; ENABLE_PHASE_DETECTOR_FOR_CK : string := "false" ); port ( inclock : in std_logic := 'X'; dout : out std_logic_vector(7 downto 0); pad_in : in std_logic_vector(7 downto 0) := (others => 'X'); inclocken : in std_logic := 'X'; fr_clock : out std_logic_vector(7 downto 0); hr_clock : out std_logic; invert_hr_clock : in std_logic := 'X'; outclock : in std_logic := 'X'; outclocken : in std_logic := 'X'; phy_mem_clock : in std_logic := 'X'; mimic_clock : out std_logic_vector(7 downto 0); din : in std_logic_vector(7 downto 0) := (others => 'X'); pad_io : inout std_logic_vector(7 downto 0) := (others => 'X'); pad_io_b : inout std_logic_vector(7 downto 0) := (others => 'X'); pad_in_b : in std_logic_vector(7 downto 0) := (others => 'X'); pad_out : out std_logic_vector(7 downto 0); pad_out_b : out std_logic_vector(7 downto 0); aset : in std_logic := 'X'; aclr : in std_logic := 'X'; sclr : in std_logic := 'X'; nsleep : in std_logic_vector(7 downto 0) := (others => 'X'); oe : in std_logic_vector(7 downto 0) := (others => 'X') ); end component altera_gpio_lite;  

 

 

I then tried instantating this by hand in my VHDL, setting "ENABLE_CLOCK_ENA_PORT" to "true", "REGISTER_MODE" to "single-register" and wiring up the relevant ports. 

 

This again gave sensible resource usage reports when compiled, but looking at the netlist viewer it seemed to have ignored my clock enable. 

 

 

So I am reluctantly concluding that this stuff is half-baked (at least in respect of Max10) - not clear whether the deficiencies lie in the tools, the documentation (describing features that don't exist), or the silicon (tools disabled because features don't work?).
Reply