.. role:: raw-html-m2r(raw) :format: html Component and hierarchy ======================= Introduction ------------ Like in VHDL and Verilog, you can define components that can be used to build a design hierarchy. However, in SpinalHDL, you don't need to bind their ports at instantiation .. code-block:: scala class AdderCell extends Component { //Declaring all in/out in an io Bundle is probably a good practice val io = new Bundle { val a, b, cin = in Bool val sum, cout = out Bool } //Do some logic io.sum := io.a ^ io.b ^ io.cin io.cout := (io.a & io.b) | (io.a & io.cin) | (io.b & io.cin) } class Adder(width: Int) extends Component { ... //Create 2 AdderCell val cell0 = new AdderCell val cell1 = new AdderCell cell1.io.cin := cell0.io.cout //Connect cout of cell0 to cin of cell1 // Another example which create an array of ArrayCell val cellArray = Array.fill(width)(new AdderCell) cellArray(1).io.cin := cellArray(0).io.cout //Connect cout of cell(0) to cin of cell(1) ... } .. tip:: | val io = new Bundle{ ... } : | Declaring all inputs and outputs in a Bundle named `io` is probably a good pratice. If you call your bundle `io`, Spinal will check that all elements are defined as input or output. Input / output definition ------------------------- The syntax to define inputs and outputs is the following: .. list-table:: :header-rows: 1 :widths: 2 3 1 * - Syntax - Description - Return * - in/out Bool - Create an input/output Bool - Bool * - in/out Bits/UInt/SInt[(x bit)] - Create an input/output of the corresponding type - T * - in/out(T) - | For all other data types, you should add the brackets around it. | Sorry this is a Scala limitation. - T * - master/slave(T) - | This syntax is provided by the spinal.lib. T should extend IMasterSlave : | Some documentation is available :ref:`here ` - T There are some rules to follow with component interconnection: * Components can only read output and input signals of child components * Components can read their own output port values (unlike VHDL) .. tip:: If for some reason, you need to read signals from far away in the hierarchy (debug, temporal patch) you can do it by using the value returned by `some.where.else.theSignal.pull()`. Pruned signals -------------- SpinalHDL only generates things which are required to drive the outputs of your top level entity (directly or indirectly). All other signals (the useless ones) are removed from the RTL generation and are inserted into a list of pruned signals. You can get this list via the ``printPruned`` and the ``printPrunedIo`` function on the generated ``SpinalReport``. .. code-block:: scala class TopLevel extends Component { val io = new Bundle{ val a,b = in UInt(8 bits) val result = out UInt(8 bits) } io.result := io.a + io.b val unusedSignal = UInt(8 bits) val unusedSignal2 = UInt(8 bits) unusedSignal2 := unusedSignal } object Main{ def main(args: Array[String]) { SpinalVhdl(new TopLevel).printPruned() //This will report : // [Warning] Unused wire detected : toplevel/unusedSignal : UInt[8 bits] // [Warning] Unused wire detected : toplevel/unusedSignal2 : UInt[8 bits] } } If you want to keep a pruned signal into the generated RTL for debug reasons, you can use the ``keep`` function of that signal: .. code-block:: scala class TopLevel extends Component { val io = new Bundle{ val a,b = in UInt(8 bits) val result = out UInt(8 bits) } io.result := io.a + io.b val unusedSignal = UInt(8 bits) val unusedSignal2 = UInt(8 bits).keep() unusedSignal := 0 unusedSignal2 := unusedSignal } object Main{ def main(args: Array[String]) { SpinalVhdl(new TopLevel).printPruned() //This will report nothing } } Generic(VHDL) / Parameter(Verilog) ---------------------------------- If you want to parameterize your component, you can give parameters to the constructor of the component as follows: .. code-block:: scala class MyAdder(width: BitCount) extends Component { val io = new Bundle{ val a,b = in UInt(width) val result = out UInt(width) } io.result := io.a + io.b } object Main{ def main(args: Array[String]) { SpinalVhdl(new MyAdder(32 bits)) } } I you have several parameters, it is a good practice to give a specific configuration class as follows: .. code-block:: scala case class MySocConfig(axiFrequency : HertzNumber, onChipRamSize : BigInt, cpu : RiscCoreConfig, iCache : InstructionCacheConfig) class MySoc(config: MySocConfig) extends Component { ... } .. raw:: html