-
Notifications
You must be signed in to change notification settings - Fork 0
Home
- Introduction
- Installation in Icestudio
- Registers
- TestBenches
- Generation Scripts
- Translations
- Organization of the collection
- Contributing to the collection
In this collection you will find Registers. Use these blocks in your digital circuits for opensource FPGAs created with 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 iceFF collection instead
- Download the ZIP file from the latest release
- ...or get the ZIP file with the latest changes from the main branch: iceRegs.zip
The Registers store N-bits of information during a period of time. There are two main flavours: System Registers and standard registers, with or without reset input
The system register (Sys-Reg) captures the N-bits input data on every clock cycle. Therefore, this component is all the time reading information, at the system clock frecuency (very fast)
The input data at a given cycle n is captured on the rising edge of the system clock and output at the cycle n+1. Its N-bits initial value, (the value at cycle 0) can be set as a parameter. Its default value is 0
This is the Truth table
input (cycle n) | output (cycle n+1) |
---|---|
d | d |
Where d is a N-bits data
Because the System register captures data at cycle n and output it at cycle n+1, it its said that it "Delays" the data 1 cycle
The system registers can be implemented in two diffent ways: Using DFF blocks or directly in Verilog
An N-bits system register is implemented with N DFFs in paralell. As an example, let's examine the 2-bits Sys-reg:
It is composed of two DFFs, one for the storing the least significant bit, b0 and the other for the most significant bit, b1. As it is a 2-bits register, there are 2 parameters, one for each bit
The block is called sys-reg-dff-2-bits. The dff means that this system registers is implemented using DFF blocks
All the N-bits system registers can be implemented in this way, but if we want them to be initialized with a value different than zero, it is difficult to use them, as the initial value should be given in binary. Imagine that we want a 32-bit register to store initially the value 0xFFFF. We have to assign to 1 their 32 parameters!
Currently there is no way in Icestudio to generate inputs for the parameters, other than assigning individual values. Therefore, this implementation is rarely used (Just for educational purposes, for showing graphically how we can build registers)
Although the system registers are composed of N DFFs, they can also be considered fundamental components: Units that store a single data. We use the register for building higher level components, like counters and so on
They can be directly (and easily) be implemented in Verilog:
This is the verilog code:
//-- Generic System register
//-- Number of bits
localparam N = 2;
//-- Initial value
reg [N-1:0] qi = INI;
always @(posedge clk)
qi <= d;
//-- Connect the register with the
//-- output
assign q = qi;
It is a generic register with one parameter: N. Just changing this parameter is enough for creating a system register of a different size
In this example a data stream of two values is generated. The values are 2
and 1
, both can be represented with only 2-bits (values 10 and 01 in binary). The value 2 is generated at cycle 0 and the value 1 at cycle 1
In this chronogram is shown the data stream. It initially (at cycle 0) has the value of 2. In the next cycle it changes to 1 (and it remains unchaged until the circuit is reset)
This circuit is implemented using a 2-bit system register with an initial value of 2. The input is connected to the constant 1, so that it will capture this new value in the next cycle
The complete example also includes a 2-bit data LEDOSCOPE, so that we can capture the values at cycles 0 and 1, and show them on the LEDs (one sample at a time)
It initially shows the sample 0 (value 2). When the button is pressed, it shows the sample 1 (value 1). If the botton is pressed again it will shown the sample 0 again
We see the final value in LEDs 0 and 1. As the data stream changes very fast (at the system clock rate of speed) we cannot see how the LEDs changes, so we only see the final value (1). But we can see the two values on the LEDs connected to the LEDOSCOPE (in pins D0 and D1)
We can also use a Logica analyzer but it is easier with the LEDOSCOPE
A stream of four 8-bits values: 0x80, 0x20, 0x08 and 0x02 is generated. These values are written on the cycles 0 to 3. This is the chronogram:
This circuit is implemented using three 8-bit system register with the initial values of 0x80, 0x20 and 0x08. They are connected in cascade. The final stable value is implemented with a constant (0x02), that is connected to the system register on the left
These four values are captured by the LEDOSCOPE and displayed on the LEDs. Initially the sample 0 (taken at cycle 0) is shown. When the button is pressed, the next sample is displayed. After the sample 3, it shows again the sample 0
We see the final value in LEDs 0 to 7. As the data stream changes very fast (at the system clock rate of speed) we cannot see how the LEDs changes, so we only see the final value (0x02). But we can see the four values on the LEDs connected to the LEDOSCOPE (in pins from D0 to D3)
We can also use a Logica analyzer but it is easier with the LEDOSCOPE
The System register with reset (Sys-Reg-rst) works exactly the same as the Sys-Reg: it captures the input data on every clock cycle. But it includes the rst
input for setting the register to its initial value (The one set in their Init top parameter)
This is the table that defines how this register works. The rst input has priority over the data input. When rst is 1, the output is always the initial value (regardless of the input data d)
rst | d (cycle n) | output (cycle n+1) |
---|---|---|
0 | d | d |
1 | d | Initial value |
The system register with input reset
is implemented with a system register and a N-bit 2-1 Multiplexer. While the reset input (rst) is not active (0), the Sys-Reg is capturing the input data (d). When the reset input is active, the initial value is captured.
Notice that the priority is on the rst
pin, as it is used for selecting the multiplexer. No matter what value is in d if the rst input is 1
This is the implementation of a 2-bits System register with reset:
The system register with reset can be implemented directly in verilog as follows:
This is the verilog code:
//-- Generic System register
//-- with reset
//-- Number of bits
localparam N = 2;
//-- Initial value
reg [N-1:0] qi = INI;
always @(posedge clk)
begin
//-- Reset: Capture the initial
//-- value
if (rst == 1'b1)
qi <= INI;
//-- No reset: Capture the input
else
qi <= d;
end
//-- Connect the register with the
//-- output
assign q = qi;
Notice the N
parameter. This implementation correspond to a generic system register with reset. Change this vale to increase/decrease the number of bits
If we connect an 8-bit constant (0xAA) to the input of a system register (with an initial value of 0x55), what we get is a sequence of two values: 0x55 and 0xAA
But now, if we use a system register with reset, and we activate its reset input in cycle 1, the result is that this sequence is repeated in the next cycle:
This is the example circuit:
The standard Register has two inputs: data
(d) and load
. It only captures the input when load
is active (1). If load
is 0, the input is ignored and the register does not change its value
Its behaviour is described on this table:
load | d | output (next cycle) | Description |
---|---|---|---|
0 | data | No change | The Register does not change its value |
1 | data | data | The data is captured |
Notice that the Register behaves as a System register when load
is 1.
The system Register let's us to store information only for one cycle. In the next cycle a new value will be captured (the sys-reg is capturing all the time). With the standard register we can retain the information all the time we want. It only changes when load
is 1
The pulse symbol on the load
input means that the Register will capture one data per 1-cycle pulse. If you apply a 2-cycles pulse, the DFF will perform two consecutives captures (on two consecutive cycles)
A Register with the load input connected to the 1 constant it is equivalent to a System register (Sys-Reg): It will capture the input on every system clock cycle
The N-bit Register is implemented with an N-bit system register and an N-bit 2-1 Multiplexer. While the load
input (rst) is not active (0), the Sys-Reg is capturing its own value, so there is no change. When load
is 1, the input data is captured.
Although the system registers are composed of N DFFs, they can also be considered fundamental components: Units that store a single data. We use the register for building higher level components, like counters and so on
The register with load
input can be directly (and easily) implemented in Verilog:
This is the verilog code:
//-- Generic register
//-- Number of bits
localparam N = 8;
//-- Initial value
reg [N-1:0] qi = INI;
always @(posedge clk)
//-- The value is load only if
//-- load is 1
if (load == 1'b1)
qi <= d;
//-- Connect the register with the
//-- output
assign q = qi;
This is the classic example of displaying a number on the LEDs. Initially, the value 0xAA is shown. When the SW1 button is pressed, the register captures a 0x55, and the value is shown on the LEDs
The Register with reset and load (Reg-rst) works exactly the same as the Register with load, but it includes the rst
input (with priority over load) for setting the register to its initial value
This is the table that defines how this register works. The rst
input has priority over the load
input. When rst is 1, the output is always the initial value
rst | load | d (cycle n) | output (cycle n+1) |
---|---|---|---|
0 | 0 | data | no change |
0 | 1 | data | data |
1 | x | x | Initial value |
The Reg-rst is implemented with a system register with reset (sys-reg-rst) and a N-bit 2-1 Multiplexer. While the load
input is not active (0), the Sys-Reg-rst is capturing its own value, so there is no change. When load
is 1, the input data is captured. When the rst
input is set to 1, the register changes to its initial value. The rst
has priority over load
The register with reset and load
input can be directly (and easily) implemented in Verilog:
This is the verilog code:
//-- Generic register with reset
//-- Number of bits
localparam N = 8;
//-- Initial value
reg [N-1:0] qi = INI;
always @(posedge clk)
begin
//-- Reset has the priority
if (rst == 1'b1)
qi <= INI;
else
//-- The value is load only if
//-- load is 1
if (load == 1'b1)
qi <= d;
//-- In any other case the reg
//-- keeps its value
end
//-- Connect the register with the
//-- output
assign q = qi;
This is the classic example of displaying a number on the LEDs. Initially, the value 0xAA is shown. When the SW1
button is pressed, the register captures a 0x55, and the value is shown on the LEDs. If the SW2
is pressed, the register is reset and its initial value (0xAA) is displayed again
The circuits used for testing all que components of this collection can be found on this collection:
- IceRegs-TB: Testbenches for the Registers. It is intended for developers, not for final users
All the component of this collection have been created from templates by python scripts Each family of registers has its on Template and Generation script:
Block identifier | Template | Python Script | |
---|---|---|---|
System registers | Sys-reg |
Template-Sys-reg.ice |
generate-sys-reg.py |
System registers with reset | Sys-reg-rst |
Template-Sys-reg-rst.ice |
generate-sys-reg-rst.py |
Registers | Reg |
Template-Reg.ice |
generate-reg.py |
Registers with reset | Reg-rst |
Template-Reg-rst.ice |
generate-reg-rst.py |
In this example it is shown how the System registers from 2 to 32 bits are created from the template
This is the command line that should be executed within the Template
folder:
obijuan@Hoth:~/Develop/Icestudio-collections/iceRegs/Templates
$ python3 generate-sys-reg.py
This is the result:
If you need to modify the registers, open the corresponding template with Icestudio, edit the component (typically changing its verilog code) and save it
Then, you should generate the new registers with the corresponding script
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
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 index. Here you will see some of the more important blocks that the collection contains
-
-
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:
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:
- Fork the iceRegs repo into your github account
- Clone it to your computer
- Install the collection as an external collection, so that you can access it from icestudio (See: Other uses: External collection)
- Create your own block
- Save it and click on Tools/Collection/Reload for using it and testing it
- Commit and push to your repo
- Emit a pull request
-
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 iceRegs collection is ONLY FOR REGISTERS. If you want to contribute with other type of blocks, do it in its corresponding collection (iceK, iceGates, iceRegs, iceCoders, iceFF...)