Types

The language provides 5 base types and 2 composite types that can be used.

  • Base types : Bool, Bits, UInt for unsigned integers, SInt for signed integers, Enum.
  • Composite types : Bundle, Vec.

Those types and their usage (with examples) are explained hereafter.

Bool

This is the standard boolean type that correspond to a bit.

@TODO is there a any way / sense to assign values such as U or X, does it correspond in reality to std_logic ?

Declaration

The syntax to declare such as value is as follows:

Syntax Description Return
Bool or Bool() Create a Bool Bool
True Create a Bool assigned with true Bool
False Create a Bool assigned with false Bool
Bool(value : Boolean) Create a Bool assigned with a Scala Boolean Bool

Using this type into Spinal yields:

val myBool = Bool()
myBool := False         // := is the assignment operator
myBool := Bool(false)   // Use a Scala Boolean to create a literal

Operators

The following operators are available for the Bool type

Operator Description Return type
!x Logical NOT Bool
x && y Logical AND Bool
x || y Logical OR Bool
x ^ y Logical XOR Bool

The BitVector family - (Bits, UInt, SInt)

BitVector is a family of types for storing multiple bits of information in a single value. This type has three subtypes that can be used to model different behaviours: Bits do not convey any sign information whereas the UInt (unsigned integer) and SInt (signed integer) provide the required operations to compute correct results if signed / unsigned arithmetics is used.

Declaration syntax

@TODO mettre un lien sur syntaxe EBNF

Syntax (using EBNF syntax) Description Return
Bits/UInt/SInt [()] Create a BitVector, bit count is inferred Bits/UInt/SInt
Bits/UInt/SInt(x bit) Create a BitVector with x bit Bits/UInt/SInt
B/U/S(value : Int[,width : BitCount]) Create a BitVector assigned with ‘value’ Bits/UInt/SInt
B/U/S”[[size’]base]value” Create a BitVector assigned with ‘value’ Bits/UInt/SInt
B/U/S([x bit], element, …) Create a BitVector assigned with the value specified by elements (see bellow table) Bits/UInt/SInt

Elements could be defined as follows:

Element syntax Description
x : Int -> y : Boolean/Bool Set bit x with y
x : Range -> y : Boolean/Bool Set each bits in range x with y
x : Range -> y : T Set bits in range x with y
x : Range -> y : String Set bits in range x with y
The string format follow same rules than B/U/S”xyz” one
x : Range -> y : T Set bits in range x with y
default -> y : Boolean/Bool Set all floating bits y

You can define a Range values

Range syntax Description Width
(x downto y) [x:y] x >= y x-y+1
(x to y) [x:y] x <= y y-x+1
(x until y) [x:y[ x < y y-x
val myUInt = UInt(8 bit)
myUInt := U(2,8 bit)
myUInt := U(2)
myUInt := U"0000_0101"  // Base per default is binary => 5
myUInt := U"h1A"        // Base could be x (base 16)
                        //               h (base 16)
                        //               d (base 10)
                        //               o (base 8)
                        //               b (base 2)                       
myUInt := U"8'h1A"       
myUInt := 2             // You can use scala Int as literal value

myUInt := U(default -> true) // Assign myUInt with "11111111"
myUInt := U(myUInt.range -> true) // Assign myUInt with "11111111"
myUInt := U(7 -> true,default -> false) //Assign myUInt with "10000000"
myUInt := U((4 downto 1) -> true,default -> false) //Assign myUInt with "00011110"

Valid operators

Operator Description Return
~x Bitwise NOT T(w(x) bit)
x & y Bitwise AND T(max(w(x), w(y) bit)
x | y Bitwise OR T(max(w(x), w(y) bit)
x ^ y Bitwise XOR T(max(w(x), w(y) bit)
x(y) Readbit, y : Int/UInt Bool
x(hi,lo) Read bitfield, hi : Int, lo : Int T(hi-lo+1 bit)
x(offset,width) Read bitfield, offset: UInt, width: Int T(width bit)
x(y) := z Assign bit, y : Int/UInt Bool
x(hi,lo) := z Assign bitfield, hi : Int, lo : Int T(hi-lo+1 bit)
x(offset,width) := z Assign bitfield, offset: UInt, width: Int T(width bit)
x.toBools Cast into a array of Bool Vec(Bool,width(x))

Bits

Operator Description Return
x » y Logical shift right, y : Int T(w(x) - y bit)
x » y Logical shift right, y : UInt T(w(x) bit)
x « y Logical shift left, y : Int T(w(x) + y bit)
x « y Logical shift left, y : UInt T(w(x) + max(y) bit)
x.resize(y) Return a resized copy of x, filled with zero, y : Int T(y bit)

UInt, SInt

Operator Description Return
x + y Addition T(max(w(x), w(y) bit)
x - y Subtraction T(max(w(x), w(y) bit)
x * y Multiplication T(w(x) + w(y) bit)
x > y Greater than Bool
x >= y Greater than or equal Bool
x > y Less than Bool
x >= y Less than or equal Bool
x » y Arithmetic shift right, y : Int T(w(x) - y bit)
x » y Arithmetic shift right, y : UInt T(w(x) bit)
x « y Arithmetic shift left, y : Int T(w(x) + y bit)
x « y Arithmetic shift left, y : UInt T(w(x) + max(y) bit)
x.resize(y) Return an arithmetic resized copy of x, y : Int T(y bit)

Bool, Bits, UInt, SInt

Operator Description Return
x.asBool Binary cast in Bool, True if x bit 0 is set Bool)
x.asBits Binary cast in Bits Bits(w(x) bit)
x.asUInt Binary cast in UInt UInt(w(x) bit)
x.asSInt Binary cast in SInt SInt(w(x) bit)

Vec

Declaration Description
Vec(type : Data, size : Int) Create a vector of size time the given type
Vec(x,y,..) Create a vector where indexes point to given elements.
this construct support mixed element width
Operator Description Return
x(y) Read element y, y : Int/UInt T
x(y) := z Assign element y with z, y : Int/UInt  
val myVecOfSInt = Vec(SInt(8 bit),2)
myVecOfSInt(0) := 2
myVecOfSInt(1) := myVecOfSInt(0) + 3

val myVecOfMixedUInt = Vec(UInt(3 bit), UInt(5 bit), UInt(8 bit))

val x,y,z = UInt(8 bit)
val myVecOf_xyz_ref = Vec(x,y,z)
for(element <- myVecOf_xyz_ref){
  element := 0   //Assign x,y,z with the value 0
}
myVecOf_xyz_ref(1) := 3    //Assign y with the value 3

###Bundle ```scala case class RGB(channelWidth : Int) extends Bundle{ val red = UInt(channelWidth bit) val green = UInt(channelWidth bit) val blue = UInt(channelWidth bit)

def isBlack : Bool = red === 0 && green === 0 && blue === 0 def isWhite : Bool = { val max = U((channelWidth-1 downto 0) -> True) return red === max && green === max && blue === max } }

case class VGA(channelWidth : Int) extends Bundle{ val hsync = Bool val vsync = Bool val color = RGB(channelWidth) }

val vgaIn = VGA(8) //Create a RGB instance val vgaOut = VGA(8) vgaOut := vgaIn //Assign the whole bundle vgaOut.color.green := 0 //Fix the green to zero ```

Enum

TODO ```scala object UartCtrlTxState extends SpinalEnum { val sIdle, sStart, sData, sParity, sStop = newElement() }

import UartCtrlTxState._ val stateNext = UartCtrlTxState() stateNext := sIdle ```

Data (Bool, Bits, UInt, SInt, Enum, Bundle, Vec)

Operator Description Return
x === y Equality Bool
x =/= y Inequality Bool
x.getWidth Return bitcount Int
x ## y Concatenate, x->high, y->low Bits(width(x) + width(y) bit)
Cat(x) Concatenate list, first element on lsb, x : Array[Data] Bits(sumOfWidth bit)
Mux(cond,x,y) if cond ? x : y T(max(w(x), w(y) bit)
x.asBits Cast in Bits Bits(width(x) bit)
x.assignFromBits(bits) Assign from Bits  
x.assignFromBits(bits,hi,lo) Assign bitfield, hi : Int, lo : Int T(hi-lo+1 bit)
x.assignFromBits(bits,offset,width) Assign bitfield, offset: UInt, width: Int T(width bit)
x.getZero Get equivalent type assigned with zero T

Register

Creating register is very different than VHDL/Verilog.

Syntax Description
Reg(type : Data) Register of the given type
RegInit(value : Data) Register with the given value when a reset occur
RegNext(value : Data) Register that sample the given value each cycle

You can also set the reset value of a register by calling the init(value : Data) function ```scala val counter = Reg(UInt(4 bit)) init(0) //Register of 4 bit initialized with 0 counter := counter + 1

val counter = RegInit(U”0000”) counter := counter + 1

val registerStage = RegNext(counter) //counter delayed by one cycle ```

Tags: