Skip to content
Juan Gonzalez-Gomez edited this page Apr 6, 2024 · 128 revisions

Contents

Introduction

In this collection you will find blocks for working with the FPGA pins. Use it in your digital circuits for opensource FPGAs created with icestudio. Some of the blocks in this collection depend on a particular FPGA family, others are generic. If you use the wrong block (a block that is for other FPGA) you will get an error message

These are examples of some blocks of this collection:

Notice that these blocks have a different color than usual. This is for hightlighting the fact that they are special blocks that depends on the type of FPGA, and should always be connected to an FPGA pin

FPGA IO Blocks

The FPGAs have some special blocks called PIOs (Programable Input/Outputs). These blocks are located near each of the FPGA pins and they are in charge of configuring each pin either as input or output. In addition, special features can be configured as well, like enabling the internal pull-ups

Each FPGA has its own specialized PIO blocks. Usually these blocks are placed and configured automatically by the Synthesis tool. But sometimes it is needed to place them manually and connect their ports to our circuit. That is the case when using bidirection pins

The iceIO collection contains the blocks for configuring the pins and using them, for the different FPGA families

Installation in Icestudio

Find information about collections and how to install them on this link: Installing the iceK collection in Icestudio. It was written for the iceK collection as an example. Use the repo of the icewires collection instead

Quick Download:

Using the collection

There are two types of blocks: one for configuring the pins as input or output, and other for enabling the internal pull-ups. All these blocks should always be conected directly to an FPGA pin (if not, you will get an error message). Also, these blocks only can be used for an FPGA family. They are not valid for all the FPGAs

InOut: Configuring a pin as input or output

The InOut block is used for configuring the FPGA pin as input or output. It can be found in the InOut Menu and the FPGA family submenu (ex. InOut/ICE40/InOut)

This block has 4 ports:

  • pin: It should be conected directly to an FPGA pin. If it is connected to something different than a pin an error message is displayed
  • oe: Output enable. This port is used for configuring the pin as input or output: 0: The pin is configured as input 1: The pin is configured as output
  • din: Input data. When the pin is configured as input, the data comming from the outside can be read from this port
  • dout: Output data. When the pin is configured as output, the bits written in this port are sent outside the FPGA

There is another block, InOut-right, that is exactly the same but the pin port is located on the right instead of on the left

Implementation

As the InOut blocks are foundamental, they all are implemented in Verilog. This verilog code is generic. The parameter N is used for chaging the number of data bits

//-- Generic InOut
//-- Number of data bits
localparam N = 1;

//-- Configuration as input:
//---- Read from pin --> din
assign din = oe ? {N{1'b0}}  : pin;

//-- Configuration as output
//-- din is always 0!
//-- dout --> pin
assign pin = oe ? dout : {N{1'bZ}};

Example 1: Using the InOut Block as input (ICE40 FPGA)

This example is available on the File/Examples/01-Input-Config/Alhmabra-II/01-button-LED menu. It is an example of the manually configuration of a pin as input, for the Alhambra-II ICE40 FPGA board

The SW1 button is displayed on the LED0

This is just an example on how to configure manually the pin as input using the InOut block. Usually this is done automatically by the Synthesizer

You can double click on the block for displaying its implementation:

Example 2: Using the InOut Block as output (ICE40 FPGA)

This example is available on the File/Examples/02-Output-Config/Alhmabra-II/01-blinking-LED menu. It is an example of the manually configuration of a pin as output, for the Alhambra-II ICE40 FPGA board

The LED0 is blinking at the rate of 1Hz

This is just an example on how to configure manually the pin as output using the InOut-right block. Usually this is done automatically by the Synthesizer

Example 3: Using the InOut Block as input/output (ICE40 FPGA)

This example is available on the File/Examples/03-InOut-test/Alhmabra-II/01-Inout-button-LED menu. It is an example of the manually configuration of a pin as input/output, for the Alhambra-II ICE40 FPGA board

The button SW2 is used for seting the configuration of the pin:

  • 0: Button not pressed. Input pin
  • 1: Button pressed. Output pin

An external wire should be used to connect the DO pin to the D1 or D2 pins. The former is for reading a button (input) and the later for writing on a LED (output)

Example 4: Using the InOut Block as input (ECP5 FPGA)

This example is available on the File/Examples/01-Input-Config/ULX3S-12F/01-button-LED menu. It is an example of the manually configuration of a pin as input, for the Radiona ULX3S-12F ECP5 FPGA board

The B1 button is displayed on the D1 LED

Example 5: Using the InOut Block as output (ECP5 FPGA)

This example is available on the File/Examples/02-Output-Config/ULX3S-12F/01-blinking-LED menu. It is an example of the manually configuration of a pin as output, for the Radiona ULX3S ECP5 FPGA board

The LED 0 is blinking

This is just an example on how to configure manually the pin as output using the InOut-right block. Usually this is done automatically by the Synthesizer

Example 6: Using the InOut Block as input/output (ECP5 FPGA)

This example is available on the File/Examples/03-InOut-test/ULX3S-12F/01-Inout-button-LED menu. It is an example of the manually configuration of a pin as input/output, for the Radiona ULX3S ECP5 FPGA board

The button B2 is used for seting the configuration of the pin:

  • 0: Button not pressed. Input pin
  • 1: Button pressed. Output pin

An external wire should be used to connect the GN0 pin to the GN1 or GN2 pins. The former is for reading a button (input) and the later for writing on a LED (output)

InOut: Multiple pins

For working with multiple pins we use the InOut-xN and ****InOut-right-xN blocks, where N is the number of bits. They contanin N InOut blocks in paralell

They look similar to the 1-bit version, except for the width of the Pin, din and dout ports In this picture you can see the 2-bits InOut blocks:

There are two implementations: In Verilog or by means of other blocks

Implementation 1: Verilog

It is the same implementation given above, but in the case of multple pins the parameter N should be change. For example, this is the verilog code corresponding to a 2-bits InOut block:

//-- Generic InOut
//-- Number of data bits
localparam N = 2;

//-- Configuration as input:
//---- Read from pin --> din
assign din = oe ? {N{1'b0}}  : pin;

//-- Configuration as output
//-- din is always 0!
//-- dout --> pin
assign pin = oe ? dout : {N{1'bZ}};

Implementation 2: Blocks

The Implementation of the InOut blocks for N bits is the same for all the FPGA families. In this picture the implementation of the 2-bits InOut blocks is shown

It consist of two InOut blocks placed in paralell

Example 7: Configuration of two input pins (ICE40 FPGA)

In this example, two input pins are configured manually as inputs. The state of the two buttons, SW1 and SW2 is shown on LEDs 0 and 1

Pull-up

In some FPGAs the PIO blocks can also be used for enabling the internal pull-ups when configured as inputs. In that cases we use the Pull-up blocks

In this picture the pull-up and Pull-up-x2 blocks are shown

The top parameter is used for configuring the pull-up. If it is set to 0, the pull-up is not active. If it is 1, the internal pull-up is enabled

The pin ports should always be connected directly to FPGA pins. If not, an error message will be displayed

ICE40

The PIO blocks of the ICE40 FPGA family have internal pull-ups that can be configured

Example 8: Testing one pull-up

In this example the internal pull-up is actived. The state of the D0 input pin is shown on LED0

Example 9: Testing two pull-ups

The two internal pull-ups of the D0 and D1 pines are enabled. The state of these pins are shown on the LEDs 0 and 1

Implementation

The pull-up for the ICE40 FPGA family is implemented in Verilog:

// 1-Pull up

//-- Place the IO block, configured as  
//-- input with pull-up
SB_IO
  #(
    .PIN_TYPE(6'b 1010_01),
    
    //-- The pull-up is activated or not
    //-- depeding on the ON parameter
    .PULLUP(ON)
    
  ) input_pin (

    //--- Input pin
    .PACKAGE_PIN(i),
    
    //-- Block output
    .D_IN_0(o),
    
    //-- Configured as input
    .OUTPUT_ENABLE(1'b0),
    
    //-- Not used
    .D_OUT_0(1'b0)
  );

You can double click on the block for displaying its implementation:

The arrays of N pull-ups are implemented placing N of this modules in paralell. In this figure it is shown the implementation of the pull-up-x02 block

Error messages

There are two different errors we can get when working with the Input/Output blocks. The first one is displayed when there is NO FPGA pin connected directly to the pin port. In this example the input pin is not connected directly to the InOut block, but though a NOT gate. This is incorrect

This is the error messages:

There are errors in the design...
ERROR: No wire found for port PACKAGE_PIN on destination cell

This error is displayed when you are using a board with an ICE40 FPGA but you have placed wrongly an InOut block for other Family (For example ECP5):

There are errors in the design...
ERROR: Module `\TRELLIS_IO' referenced in module
`\va91acb_v43ad2d' in cell  '\siod_out_bidir' is not part of the design

This other error is displayed when you are using a board with an ECP5 FPGA but you have placed wrongly an InOut block for other Family (For example ICE40):

There are errors in the design...
ERROR: Module `\SB_IO' referenced in module
`\v328169_v43ad2d' in cell `\tristate' is not part of the design

Translations

The collection can be translated to any language. Any translation is very welcome!! 😀️ If you want to translate it to your native languaje please follow these instructions: Translating the collection into your language. This instructions are for the iceK collection, but the translation procedure is the same for any other collection

Organization of the collection

The Organization of this collections is exactly the same than all the other collections. It consist of the following folders:

  • blocks: This is were the icestudio blocks are located, with all the elements of the collection, organized by subfolders
  • examples: Circuit examples ready to use in Icestudio. Inside this examples there are some special elements:
    • 00-Index.ice: Collection indexe. Here you will see some of the more important blocks that the collection contains
    • TESTs: This is used by the collection developer for testing the different blocks. Everytime a block is added, it should be tested somehow. That tests are in that folder. This is not likely for the standar user, so you can skip it
  • icons: Here you will find the SVG files for the icons used in the collection blocks. You can edit them or create new icons from them
    • block+icon: Some of the blocks in SVG, for using them in your documentations. These are some examples:
  • locale: Folder with the English texts and their translation into other languages
  • wiki: Images used in this wiki

This is the Index file:

  • 00-Index.ice:

Contributing to the collection

Contributions are welcome! 😀️

You can contribute in different manners:

  • Adding new blocks
  • Translating the collection to your language
  • Migrating the examples to more boards

These are the steps to follow for contributing:

  1. Fork the iceIO repo into your github account
  2. Clone it to your computer
  3. Install the collection as an external collection, so that you can access it from icestudio (See: Other uses: External collection)
  4. Create your own block (See Creating new blocks)
  5. Save it and click on Tools/Collection/Reload for using it and testing it
  6. Commit and push to your repo
  7. Emit a pull request

Important

  • The main language is English: Create all your blocks and examples in English (the English text should be inside de .ice files). Then translate it to your local language (if you like), following the instructions mentioned here: Translating the collection into your language
  • The iceIO collection is ONLY FOR BLOCKS RELATED TO FPGA PINS. If you want to contribute with other type of blocks, do it in its corresponding collection (iceGate, iceMux, iceRegs....)