Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
8 years ago

Registers in I/O cells

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?

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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?).