Skip to content
Juan Gonzalez-Gomez edited this page Jan 18, 2022 · 139 revisions

Contents

Introduction

In this collection you will find blocks for working with wires and buses of different sizes. Use it in your digital circuits for opensource FPGAs created with icestudio. All the blocks in this collection are passive: There are no active components (gates, flip-flips, etc), but just simple operations with wires (joining, spliting, rearranging...)

These are examples of some blocks of this collection:

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 blocks for extracting bits from the Buses, adding wires to the Buses, reversing the wires in a bus, getting the sign bit, shifting right or left... All the operations are passive: they are implemented using only wires

Split: Extracting bits from a Bus

The Split blocks allow us to have access to the bits from an input Bus of N bits. It is easier to explain it by means of examples. In this picture the Split-1-3 block is shown:

The 4-bits input bus is divided into two sub-buses of sizes 1 and 3 bits. The 1-bit bus contains the most significant bit of the input Bus, and the 3-bits bus the less significant bits

This is another example: the Split-5-2 block. The 7-bits input bus is split into two sub-buses of 5 and 2 bits respectivelly

Other Split blocks have more than two outputs. For example, the Split 3-8-8 block has a 19-bits input bus that is split into three sub-buses of 3, 8 and 8 bits:

The Split blocks with the sufix -all mean that all the wires in the bus are accesible in their outputs. This is the 5-bits split-all block: There are 5 output wires

Example 1: Using the Bus-2-Split-all Block

This example is available on the File/Examples/03-Split/Alhmabra-II folder. The two buttons of the Alhambra-II board are shown on the LEDs 7 and 0 respectivelly. This functionality can be implemented in different ways. In this examples a 2-bits Bus Split-all block is used

The two buttons are read in a 2-bits Bus that is split into its two independent bits. The Most significant bit is shown on LED7 and the Less Significan Bit on the LED0

Example 2: Using the Split 1-4 block

In this example the Split-1-4 block is used for spliting a 5-bits constant into two sub-buses of sizes 1 and 4 bits. The MSB bit is shown on LED7 and the other 4 Less significant bits are shown on the LEDs 0,1,2 and 3

Implementation

As the Split blocks are foundamental, they all are implemented in Verilog (and not from other blocks), using assign statements

For example, the Split-1-4 block is implemented with the following verilog code, were i is the input bus and o0 and o1 the output buses:

assign o1 = i[4];
assign o0 = i[3:0];

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

Join: Grouping bits into a Bus

The Join blocks allow us to group together input buses to form a bigger output Bus. They are the opposite to the Split blocks. In this picture the Join-1-3 block is shown:

Another example: The Join-5-2 Block. Two input buses of sizes 5 and 2 bits respectivelly are joined into a 7-bits output bus

This is the Join-3-8-8 Block, the oposite of the Split-3-8-8. The three input buses of sizes 3, 8 and 8 bits are joined to form a 19-bits output bus

The sufix -all is used for joining all the input wires into a Bus. For example, the bus 5 join-all block has 5 wires as inputs and a 5-bits output bus

Example 3: Using the Bus-2-Join-all Block

This example is available on the File/Examples/04-Join/Alhmabra-II folder. The two buttons of the Alhambra-II board are inserted into a 2-bits bus and then shown on the LEDs 7 and 0. This functionality can be implemented in different ways. In this examples a 2-bits Bus Join-all block is used

Example 4: Using the Join-1-4 block

In this example the Join-1-4 block is used for joining together a 4-bits constant and the SW1 button into a 5-bits bus. This 5-bits output bus is displayed on 5 LEDs

Implementation

As the Join blocks are foundamental, they all are implemented in Verilog (and not from other blocks), using assign statements

For example, the Join-1-4 block is implemented with the following verilog code, were i0 and i1 are the input sub-bus and o is the output bus:

assign o = {i1, i0};

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

Wire/Bus: Auxiliary wires

Auxiliary wires are Blocks that act like a wire or a Bus. You can find them on the Wires menu. In this picture you can see the wire block along with the Bus-3 block

These two circuits just turn on a LED. In the first one the connection between the 1 constant bit and the LED is direct. In the second the wire block is used. But both circuito are equivalent. They do exactly the same, and consume exactly the same resources on the FPGA

So, if these circuits are equivalent, why using the wire/bus blocks?. For two main reasons:

  • Wiring simplification and fragmentation: Sometimes the wiring of our design could be complex and difficult for other to understand or modify. By means of the wire/bus blocks this wiring can be simplified and/or fragmented so that long wires are divided in different parts (and these parts can be deleted without having to draw again the whole wire). In this picture you can see an example in wich the constante 1 is connected to the LED, but the wire has been divided into three segments. These segments can be rewired and moved indepently, without affecting the others

  • Direct conection of an input label with an output label. The labels are used for connecting the blocks of our circuits without visible wires, making our design more clean. The labels can be connected only to blocks, but not between them. Sometimes we could need to connect an input label directly to an output label. It can be achieve by means of the wire/bus blocks. These two circuits are equivalent. A button is conected to a LED. In the first circuit, que connection is made using only the label xx. In the second, the label xx is connected to the label yy (for creating a kind of virtual wire) and then to the LED

Example 5: Connecting two buttons to two LEDs

In this example two buttons are connected to two LEDs by means of the Bus-2 block. Of course, this block is not necessary: the buttons can be connected directly to the LEDs. But this is just an example of use

Implementation

The wire and buses blocks are implemented in verilog using the assign statement:

assign o = i;

where o is the output wire/bus and i the input wire/bus

For example, in this picture the implementation of the Bus-2 block is shown:

Copy: Copying a wire N times

When a wire is conected to other, the bit on the first wire is also transmited on the second wire. For example, if we want to show the state of one button on 4 LEDs, all we need to do is to connect 4 wires from the button to each LED. The four wires carry the same bit

Instead of placing 4 independent wires, we can use the Copy-4 block:

Using this block, the previous circuit become this new one:

Example 6: Turning on 8 LEDs with one button

In this example a Copy-8 block is used for turning on the 8 LEDs when pressing the SW1 button

Implementation

The implementation is done by connecting the inputs with a Join block. For example, this is how the Copy-8 is implemented:

Sign: Getting the sign bit

The Most Signicant Bit of a signed number carries the sign bit: 0 means positivo, 1 means negative. This bit can be extracted easily by means of the Sign block. In this picture a Sign-int8 block is shown

The input is an 8 bits signed number. The output is the signed bit (the Most significant Bit). You can find more Sign blocks for diferent sizes of signed number: 2, 3, 4 bits.... on the Sign menu

Example 7: Showing the sign bit on a LED

In this example, the sign of an 8-bit number in displayed on the LED7

Implementation

The Sign block is implemented with a Split block which extracts the most significant bit and ignore the rest of the bits:

UINT: Extend unsigned int numbers

A given unsigned number of N bits is extended to a bigger size of N+K bits (K 0-bits are added as Most significant bits). For example, if the 2-bits number 11 is extended to 8 bits this is the result: the number 00000011. 6 zero-bits have been added to the left

In this example the input is a 2-bits number and the output the 8-bits extended number

Example 8: Showing the two buttons on 8 LEDs

The two buttons are grouped into a 2-bit number. This number is extended to 8 bits and shown on the LEDs

Implementation

This block is implemented using a Join block, for adding the necesary 0s as the Most significant bits

Reversal: Reversing the bits of a bus

The bits of the input number are mirrored. For example, the 4-bit number abcd is outputed as the dcba number

Example 9: Mirroring the bits of a number

In this example the bits of the number 1100 are reversal and shown on the LEDs. The number shown is 0011

Implementation

This is the implementation of the 4-bits reversal block:

Shift blocks

These are blocks for shifting the bits to the right or to the left. The two basic blocks just shift 1 bit. In this picture you can see the shift-left (SL1) and shift-right (SR1) blocks for 4-bits numbers:

Let's use this 4-bits number as an example: 1010 (Whish is 10 in decimal). When it is shifted 1 bit to the left and a 0 inserted as its Less significant bit (LSB), the 4-bits result is 0100. The previous MSB was 1

If the same number is shifted 1 bit to the right and a 0 inserted as it Most significant bit (MSB), the 4-bits result is 0101. The previous LSB was 0

Example 10: Shifting a 4-bits number to the right

In this example the 4-bit number 1100 is shifted 1 bit to the right (an a 0 inserted as the MSB). The result is displayed on the LEDs 0-3

Implementation

The implementation of the shift blocks is done using Split and Join blocks. This is the implementation for the 4-bits shift-right 1 block:

And this is the implementation for the 4-bits shift-left 1 block:

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:
    • xx-Index.ice: Collection indexes. 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

There are 3 Index files:

  • 00-Index.ice:

  • 01-Index.ice:

  • 02-Index.ice:

Creating new blocks

You can easily create new blocks from the current blocks. You can follow the instructions given for the icek collection, but applied to the modules of this collection. This is the summary of the steps to follow:

  1. Place a block similar to the one you would like to create
  2. Select the block and click on Edit/Copy (or press Ctrl-C)
  3. Click on Edit/Clone. It will create an indepent copy of the block
  4. Doble click on the new block for going inside it
  5. Click on the top-right lock for editing the block
  6. Change the new module, adding whatever you need
  7. Change the block description, version, name and icon. Click on Edit/Project information and change the data. For updating the icon you should first have the icon in SVG and then open it from the Project information window
  8. Finished. Click on OK and then on the lock. Your new block is ready!
  9. The NEW BLOCK IS NOT in the collection YET!

NOTE that this new block has not been saved into any collection yet. It is available for you to use in your circuits, or copy and paste to other circutis. If you want to save it into some folder, or into another collection, enter into the block again and click on File/Save as. Select the folder were you want to save it and click on OK. If it was saved in the block folder of another collection, it will be available the next time you run icestudio and open that collection. Or you can click on Tools/Collection/Reload and it will be available in that collection

Contributing to the collection

Contributions are welcome! 😀️

You can contribute in different manners:

  • Adding new blocks. Maybe you would like to add your split or join blocks adapted to your needs and share them with the community
  • Translating the collection to your language
  • Migrating the examples to more boards

These are the steps to follow for contributing:

  1. Fork the icewires 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 icewires collection is ONLY FOR PASSIVE BLOCKS related to wires. If you want to contribute with other type of blocks, do it in its corresponding collection (iceGate, iceMux, iceRegs....)