= Register and fields

The field component is the lowest-level structural component in SystemRDL.
a register is defined as a set of one or more SystemRDL field instances that are atomically
accessible by software at a given address.

== Field types
There are two types of field that are defined in SystemRDL which are set base on software and hardware access type (Table 12 in SystemRDL 2.0 spec.).

Storage::
Implements flip-flops in VHDL DesyRDL entity. +
There are also two special purpose storage fields:
Counter:::: field which can be incremented or decremented, more in <<counter-properties>> section
Interrupt:::: affects also register which becomes an interrupt register, more in xref:expl_interrupts.adoc[] chapter.
Wire::
Implements wire/bus in VHDL DesyRDL entity.

NOTE: In principle wire register is only when HW can only write to the register or when register has constant - SW and HW can only read.

All registers and fields are accessible in VHDL over `t_addrmap_<addrmap_name>_in/out` record type.

----
addrmap_i/o.<REGISTER_NAME>.<field_name>.<property>
----

=== SW Read Only register fields (wire)

Example of wire type fields.

.SystemRDL
[source,qml]
----
// Automatic type and instance, auto address
reg {
    name = "Test register";
    desc = "Test register for testing read/writes from the hardware."
    default sw = r;
    default hw = w;
    field {} data[32];
} TEST;
----

.VHDL
[source,vhdl]
----
addrmap_i.TEST.data.data <= test_signal;
----

=== SW Read/Write register fields (storage)

Example of storage type register

.SystemRDL
[source,qml]
----
// Automatic type and instance
reg {
    name = "Test register";
    desc = "Test register for testing read/writes from  the software."
    default sw = rw;
    default hw = r;
    field {} field_a[16] = 0x000A;
    field {} field_b[16] = 0x000B;
} TEST @0x10;
----

.VHDL
[source,vhdl]
----
test_signal <= addrmap_o.TEST.field_a.data;
test_signal <= addrmap_o.TEST.field_b.data;
----

== Software access properties

Fields can have additional software properties which can be accessed in VHDL.
Supported properties from *Table 14* from SystemRDL 2.0 spec.

[cols="1s,5,1,1"]
|=================================================
| Property | Behavior/Application | Type | Dynamic

|swmod
| Assert when field is modified by software (written or read with a set or clear side effect)
| boolean
| Yes

|swacc
| Assert when field is software accessed.
| boolean
| Yes

|=================================================

IMPORTANT: To be able to use them they have to be added for the field in the RDL file. By default they are `false`.

.SystemRDL
[source,qml]
----
// added swmod and swacc propertied
reg {
    name = "Test register";
    desc = "Test register for testing read/writes from  the software."
    default sw = rw;
    default hw = r;
    default swacc=true;
    default swmod=true;
    field {} data[32] = 0x0000000A;
} TEST @0x10;
----

.VHDL
[source,vhdl]
----
test_swmod <= addrmap_o.TEST.data.swmod;
test_swacc <= addrmap_o.TEST.data.swacc;
----


== Hardware access properties

Fields can have additional hardware properties which can be accessed in VHDL.
Supported properties from *Table 18* from SystemRDL 2.0 spec.

[cols="1s,5,1,1"]
|=================================================
| Property | Behavior/Application | Type | Dynamic

|we
|Write-enable (active high).
|boolean
|Yes

|wel
|Write-enable (active low).
|boolean
|Yes

| hwclr
| Hardware clear. This field need not be declared as hardware-writable.
|boolean
|Yes

| hwset
| Hardware set. This field need not be declared as hardware-writable.
|boolean
|Yes
|=================================================

=== Write enable `we` example

Example with SW and HW write access. Register from HW is set when `we` flag is set to '1';

.SystemRDL
[source,qml]
----
reg {
    name = "Test register";
    desc = "Test register for testing read/writes from hardware."
    default sw = rw;
    default hw = rw;
    default we;
    field {} field_a[16] = 0x000A;
} TEST;
----


.VHDL
[source,vhdl]
----
addrmap_i.TEST.field_a.data <= test_signal;
addrmap_i.TEST.field_a.we   <= test_signal_we;
----

[#counter-properties]
== Counter properties

[cols="1s,5,1,1"]
|=================================================
| Property | Behavior/Application | Type | Dynamic

| counter
| Field implemented as a counter.
| boolean
| Yes

| incrvalue
| Increment counter by specified value. +
If set to 0 in rdl then possible to set from VHDL
| bit or reference
| Yes

| decrvalue
| Decrement counter by specified value. +
If set to 0 in rdl then possible to set from VHDL
| bit or reference
| Yes

| incr
|References the counter’s increment signal. Use to actually increment
the counter, i.e, the actual counter increment is controlled by another
component or signal (active high).
| reference
| Yes

| decr
|References the counter’s decrement signal. Use to actually decrement
the counter, i.e, the actual counter decrement is controlled by another
component or signal (active high).
| reference
| Yes
|=================================================

.SystemRDL
[source,qml]
----
reg { // counter register, sw and hw can read
    default sw = r;
    default hw = r;
    default hwclr = true; // clear signal
    field {counter;} error_cnt[16]; // default inc counter with incrvalue=1
    field {
        counter;
        incrwidth=2;
    } event_cnt[8]; // incrwidth
    field {
        counter;
        incrwidth=0;
    } set_cnt[8]; //dynamic value, if incrwidth > 0 then use field signal of width incrwidth
} COUNTERS ;
----

.VHDL
[source,vhdl]
----
addrmap_i.COUNTERS.error_cnt.incr    <= error_signal_edge;
addrmap_i.COUNTERS.event_cnt.incr    <= event_signal(0);
addrmap_i.COUNTERS.set_cnt.incrwidth <= std_logic_vector(to_unsigned(3,8));
addrmap_i.COUNTERS.set_cnt.incr      <= event;
addrmap_i.COUNTERS.error_cnt.hwclr   <= reset_error_cnt;
----

== Software side effects (atomic operations)

DesyRDL implements side effects of the software access. This allows for atomic operations on registers.

There are all side effects supported except `wuser` and `ruser`. From Table 15 and Table 16.

They are set over `onread` and `onwrite` property.

.Software read side-effect `onread` value
[cols="2s,7"]
|========================================
| onread property value | Behavior/Application

|rclr |All the bits of the field are cleared on read `(field = 0)`.
|rset |All the bits of the field are set on read `(field = all 1’s)`.
|========================================

.Software write function `onwrite` values
[cols="2s,7"]
|========================================
| onwrite property value | Behavior/Application

| woset | Bitwise write one to set `(field = field \| write_data)`.
| woclr | Bitwise write one to clear `(field = field & ~write_data)`.
| wot   | Bitwise write one to toggle `(field = field ^ write_data)`.
| wzs   | Bitwise write zero to set `(field = field \| ~write_data)`.
| wzc   | Bitwise write zero to clear `(field = field & write_data)`.
| wzt   | Bitwise write zero to toggle `(field = field ~^ write_data)`.
| wclr  | All bits of the field are cleared on write `(field = 0)`.
| wset  | All bits of the field are set on write `(field = all 1’s)`.
|========================================

NOTE: Values `rclr`, `rset`, `woset`, `woclr` can be used as properties which will imply `onread` or `onwrite` value. +
e.g. setting `default woclr;` is equalivant to `default onwrite=woclr;`

.SystemRDL
[source,qml]
----
reg {
    default sw = rw;
    default hw = r;
    // default woclr;
    default onwrite = woclr;
    default swmod=true;
    field {} data[32] = 0x0000000B;
} WOCLR ;
----