Skip to content
Juan Gonzalez-Gomez edited this page Feb 16, 2023 · 124 revisions

Contents

Introduction

In this collection you will find Registers. Use these blocks in your digital circuits for opensource FPGAs created with icestudio

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 iceFF collection instead

Quick Download:

  • Download the ZIP file from the latest release (TODO: Add link)
  • ...or get the ZIP file with the latest changes from the main branch: iceRegs.zip (TODO: Add link)

Registers

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

System registers

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

Implementation 1: DFFs

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)

Implementation 2: Verilog

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] q = INI;

always @(posedge clk)
  q <= d;

It is a generic register with one parameter: N. Just changing this parameter is enough for creating a system register of a different size

Example 1: Stream of two values

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

Example 2: Stream of four 8-bit values

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

System registers with reset

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

Implementation with blocks

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:

Verilog implementation

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] q = INI;

always @(posedge clk)
begin

  //-- Reset: Capture the initial
  //-- value
  if (rst == 1'b1)
    q <= INI;
    
  //-- No reset: Capture the input
  else
    q <= d;
end

Notice the N parameter. This implementation correspond to a generic system register with reset. Change this vale to increase/decrease the number of bits

Example 3: Stream of two 8-bit values with reset

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:

Registers with load input

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

Implementation 1: Blocks

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.

Implementation 2: Verilog

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] q = INI;

always @(posedge clk)

  //-- The value is load only if  
  //-- load is 1
  if (load == 1'b1)
    q <= d;

Example 4: Showing information on the LEDs

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

Registers with reset and load input

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

Implementation 1: Blocks

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

Implementation 2: Verilog

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] q = INI;

always @(posedge clk)
begin

  //-- Reset has the priority
  if (rst == 1'b1)
    q <= INI;
    
  else
    //-- The value is load only if  
    //-- load is 1
    if (load == 1'b1)
      q <= d;

  //-- In any other case the reg
  //-- keeps its value
end

Example 5: Showing information on the LEDs

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

Draft


Collections

Clone this wiki locally