diff --git a/source/SpinalHDL/Examples/index.rst b/source/SpinalHDL/Examples/index.rst index a7c7320c31b..dbb892f8d84 100644 --- a/source/SpinalHDL/Examples/index.rst +++ b/source/SpinalHDL/Examples/index.rst @@ -15,9 +15,6 @@ Examples .. _example_introduction: -Introduction -============ - Examples are split into three kinds: * Simple examples that could be used to get used to the basics of SpinalHDL. diff --git a/source/SpinalHDL/Formal verification/index.rst b/source/SpinalHDL/Formal verification/index.rst index dd3523fe5d0..490c78dd814 100644 --- a/source/SpinalHDL/Formal verification/index.rst +++ b/source/SpinalHDL/Formal verification/index.rst @@ -37,7 +37,7 @@ Installing requirements To install the Symbi-Yosys, you have a few options. You can fetch a precompiled package at: - https://github.com/YosysHQ/oss-cad-suite-build/releases -- https://github.com/YosysHQ/fpga-toolchain/releases +- https://github.com/YosysHQ/fpga-toolchain/releases (EOL - superseded by oss-cad-suite) Or you can compile things from scratch : @@ -59,10 +59,10 @@ Here is an example of a simple counter and the corresponding formal testbench. import spinal.core._ //Here is our DUT - class LimitedCounter extends Component{ + class LimitedCounter extends Component { //The value register will always be between [2:10] val value = Reg(UInt(4 bits)) init(2) - when(value < 10){ + when(value < 10) { value := value + 1 } } @@ -94,9 +94,9 @@ If you want you can embed formal statements directly into the DUT: .. code-block:: scala - class LimitedCounterEmbedded extends Component{ + class LimitedCounterEmbedded extends Component { val value = Reg(UInt(4 bits)) init(2) - when(value < 10){ + when(value < 10) { value := value + 1 } @@ -124,11 +124,11 @@ but you can also use the formal `anyseq`, `anyconst`, `allseq`, `allconst` state .. code-block:: scala - class LimitedCounterInc extends Component{ + class LimitedCounterInc extends Component { //Only increment the value when the inc input is set val inc = in Bool() val value = Reg(UInt(4 bits)) init(2) - when(inc && value < 10){ + when(inc && value < 10) { value := value + 1 } } @@ -160,7 +160,7 @@ For instance we can check that the value is counting up (if not already at 10): // Check that the value is incrementing. // hasPast is used to ensure that the past(dut.value) had at least one sampling out of reset - when(pastValid() && past(dut.value) =/= 10){ + when(pastValid() && past(dut.value) =/= 10) { assert(dut.value === past(dut.value) + 1) } }) @@ -172,7 +172,7 @@ Here is an example where we want to prevent the value ``1`` from ever being pres .. code-block:: scala - class DutWithRam extends Component{ + class DutWithRam extends Component { val ram = Mem.fill(4)(UInt(8 bits)) val write = slave(ram.writePort) val read = slave(ram.readAsyncPort) @@ -186,13 +186,13 @@ Here is an example where we want to prevent the value ``1`` from ever being pres assumeInitial(ClockDomain.current.isResetActive) // assume that no word in the ram has the value 1 - for(i <- 0 until dut.ram.wordCount){ + for(i <- 0 until dut.ram.wordCount) { assumeInitial(dut.ram(i) =/= 1) } // Allow the write anything but value 1 in the ram anyseq(dut.write) - clockDomain.withoutReset(){ //As the memory write can occur during reset, we need to ensure the assume apply there too + clockDomain.withoutReset() { //As the memory write can occur during reset, we need to ensure the assume apply there too assume(dut.write.data =/= 1) } @@ -215,7 +215,7 @@ If you want to keep your assertion enabled during reset you can do: .. code-block:: scala - ClockDomain.current.withoutReset(){ + ClockDomain.current.withoutReset() { assert(wuff === 0) } @@ -244,7 +244,7 @@ If you have a Mem in your design, and you want to check its content, you can do .. code-block:: scala // Manual access - for(i <- 0 until dut.ram.wordCount){ + for(i <- 0 until dut.ram.wordCount) { assumeInitial(dut.ram(i) =/= X) //No occurence of the word X } @@ -294,10 +294,10 @@ Formal primitives - Return True when ``that`` transitioned from True to False * - ``changed(that : Bool)`` - Bool - - Return True when ``that`` current value changed between comparred to the last cycle + - Return True when ``that`` current value changed between compared to the last cycle * - ``stable(that : Bool)`` - Bool - - Return True when ``that`` current value didn't changed between comparred to the last cycle + - Return True when ``that`` current value didn't changed between compared to the last cycle * - ``initstate()`` - Bool - Return True the first cycle @@ -306,13 +306,13 @@ Formal primitives - Returns True when the past value is valid (False on the first cycle). Recommended to be used with each application of ``past``, ``rose``, ``fell``, ``changed`` and ``stable``. * - ``pastValidAfterReset()`` - Bool - - Simliar to ``pastValid``, where only difference is that this would take reset into account. Can be understand as ``pastValid & past(!reset)``. + - Simliar to ``pastValid``, where only difference is that this would take reset into account. Can be understood as ``pastValid & past(!reset)``. Note that you can use the init statement on past: .. code-block:: scala - when(past(enable) init(False)){ ... } + when(past(enable) init(False)) { ... } diff --git a/source/SpinalHDL/Libraries/Com/usb_device.rst b/source/SpinalHDL/Libraries/Com/usb_device.rst index f163a4ece01..5cc04e06849 100644 --- a/source/SpinalHDL/Libraries/Com/usb_device.rst +++ b/source/SpinalHDL/Libraries/Com/usb_device.rst @@ -1,8 +1,10 @@ USB device -============ +========== -There is a USB device controller in the SpinalHDL library. In a few bullet points it can be resumed to : +Here exists a USB device controller in the SpinalHDL library. + +A few bullet points to summarise support: - Implemented to allow a CPU to configure and manage the endpoints - A internal ram which store the endpoints states and transactions descriptors @@ -27,23 +29,23 @@ Deployments : Architecture --------------- +------------ The controller is composed of : - A few control registers - A internal ram used to store the endpoint status, the transfer descriptors and the endpoint 0 SETUP data. -A linked list of descriptors for each endpoint in order to handle of the USB IN/OUT transactions and data. +A linked list of descriptors for each endpoint in order to handle the USB IN/OUT transactions and data. The endpoint 0 manage the IN/OUT transactions like all the other endpoints but has some additional hardware to manage the SETUP transactions : - Its linked list is cleared on each setup transactions -- The data of the SETUP transaction are stored in a fixed location (SETUP_DATA) +- The data from the SETUP transaction is stored in a fixed location (SETUP_DATA) - It has a specific interrupt flag for SETUP transactions Registers --------------- +--------- Note that all registers and memories of the controller are only accessible in 32 bits word access, bytes access isn't supported. @@ -79,36 +81,37 @@ finalise the SET_ADDRESS sequance. The controller will then automaticaly turn on INTERRUPT (0xFF08) ********************** -All bits of this register can be cleared by writing '1' in them. - -+--------------+------+-----------+------------------------------------------------------------------+ -| Name | Type | Bits | Description | -+==============+======+===========+==================================================================+ -| endpoints | RC | 15-0 | Raised when a enpoint generate a interrupt | -+--------------+------+-----------+------------------------------------------------------------------+ -| reset | RC | 16 | Raised when a USB reset appeared | -+--------------+------+-----------+------------------------------------------------------------------+ -| ep0Setup | RC | 17 | Raised when endpoint 0 receive a setup transaction | -+--------------+------+-----------+------------------------------------------------------------------+ -| suspend | RC | 18 | Raised when a USB suspend appeared | -+--------------+------+-----------+------------------------------------------------------------------+ -| resume | RC | 19 | Raised when a USB resume appeared | -+--------------+------+-----------+------------------------------------------------------------------+ -| disconnect | RC | 20 | Raised when a USB disconnect appeared | -+--------------+------+-----------+------------------------------------------------------------------+ +Individual bits of this register can be cleared by writing '1' in them. +Reading this register returns the current interrupt status. + ++--------------+-------+-----------+------------------------------------------------------------------+ +| Name | Type | Bits | Description | ++==============+=======+===========+==================================================================+ +| endpoints | W1C | 15-0 | Raised when an endpoint generates an interrupt | ++--------------+-------+-----------+------------------------------------------------------------------+ +| reset | W1C | 16 | Raised when a USB reset occurs | ++--------------+-------+-----------+------------------------------------------------------------------+ +| ep0Setup | W1C | 17 | Raised when endpoint 0 receives a setup transaction | ++--------------+-------+-----------+------------------------------------------------------------------+ +| suspend | W1C | 18 | Raised when a USB suspend occurs | ++--------------+-------+-----------+------------------------------------------------------------------+ +| resume | W1C | 19 | Raised when a USB resume occurs | ++--------------+-------+-----------+------------------------------------------------------------------+ +| disconnect | W1C | 20 | Raised when a USB disconnect occurs | ++--------------+-------+-----------+------------------------------------------------------------------+ HALT (0xFF0C) ********************** -This register allow to place a single enpoint in a dormant state in order to ensure atomicity of CPU operations, allowing to do things as read/modify/write on the endpoint registers and descriptors. -The peripheral will return NAK if the given endpoint is addressed by the usb host. +This register allows placement of a single endpoint into a dormant state in order to ensure atomicity of CPU operations, allowing to do things as read/modify/write on the endpoint registers and descriptors. +The peripheral will return NAK if the given endpoint is addressed by the usb host while halt is enabled and the endpoint is enabled. +-------------------------+------+-----------+------------------------------------------------------------------+ | Name | Type | Bits | Description | +=========================+======+===========+==================================================================+ | endpointId | WO | 3-0 | The endpoint you want to put in sleep | +-------------------------+------+-----------+------------------------------------------------------------------+ -| enable | WO | 4 | | +| enable | WO | 4 | When set halt is active, when clear endpoint is unhalted. | +-------------------------+------+-----------+------------------------------------------------------------------+ | effective | RO | 5 | After setting the enable, you need to wait for this bit to be | | enable | | | set by the hardware itself to ensure atomicity | @@ -168,7 +171,7 @@ To get a endpoint responsive you need : - Set its enable flag to 1 Then the there is a few cases : -- Either you have the stall or nack flag set, and so, the controller will always responde with the corresponding responses +- Either you have the stall or nack flag set, and so, the controller will always respond with the corresponding responses - Either, for EP0 setup request, the controller will not use descriptors, but will instead write the data into the SETUP_DATA register, and ACK - Either you have a empty linked list (head==0) in which case it will answer NACK - Either you have at least one descriptor pointed by head, in which case it will execute it and ACK if all was going smooth @@ -176,12 +179,12 @@ Then the there is a few cases : SETUP_DATA (0x0040 - 0x0047) ********************************* -When endpoint 0 receive a SETUP transaction, the data of the transaction will be stored at that place. +When endpoint 0 receives a SETUP transaction, the data of the transaction will be stored in this location. Descriptors ----------------------------- +----------- -Descriptors allows to specify how a endpoint need to handle the data phase of IN/OUT transactions. +Descriptors allows to specify how an endpoint needs to handle the data phase of IN/OUT transactions. They are stored in the internal ram, can be linked together via their linked lists and need to be aligned on 16 bytes boundaries +-------------------+------+-----------+------------------------------------------------------------------+ @@ -191,33 +194,33 @@ They are stored in the internal ram, can be linked together via their linked lis +-------------------+------+-----------+------------------------------------------------------------------+ | code | 0 | 19-16 | 0xF => in progress, 0x0 => success | +-------------------+------+-----------+------------------------------------------------------------------+ -| next | 1 | 15-4 | Point the the next descriptor | +| next | 1 | 15-4 | Pointer to the next descriptor | | | | | 0 => nothing, byte address = this << 4 | +-------------------+------+-----------+------------------------------------------------------------------+ | length | 1 | 31-16 | Number of bytes allocated for the data field | +-------------------+------+-----------+------------------------------------------------------------------+ | direction | 2 | 16 | '0' => OUT, '1' => IN | +-------------------+------+-----------+------------------------------------------------------------------+ -| interrupt | 2 | 17 | If set, the completion of the descriptor will generate a | +| interrupt | 2 | 17 | If set, the completion of the descriptor will generate an | | | | | interrupt. | +-------------------+------+-----------+------------------------------------------------------------------+ -| completionOnFull | 2 | 18 | Normaly, a descriptor completion only occure when a USB transfer | +| completionOnFull | 2 | 18 | Normally, a descriptor completion only occurs when a USB transfer| | | | | is smaller than the maxPacketSize. But if this field is set, | | | | | then when the descriptor become full is also a considered | | | | | as a completion event. (offset == length) | +-------------------+------+-----------+------------------------------------------------------------------+ | data1OnCompletion | 2 | 19 | force the endpoint dataPhase to DATA1 on the completion of the | -| | | | descriptoo | +| | | | descriptor | +-------------------+------+-----------+------------------------------------------------------------------+ | data | ... | ... | | +-------------------+------+-----------+------------------------------------------------------------------+ -Note, if the controller receive a frame where the IN/OUT does not match the descriptor IN/OUT, the frame will be ignored. +Note, if the controller receives a frame where the IN/OUT does not match the descriptor IN/OUT, the frame will be ignored. -Also, to initialise a descriptor, the CPU should set the code field to 0xF +Also, to initialise a descriptor, the CPU should set the code field to 0xF Usage --------------- +----- .. code-block:: scala diff --git a/source/SpinalHDL/Libraries/Com/usb_ohci.rst b/source/SpinalHDL/Libraries/Com/usb_ohci.rst index 6587e371d4a..6fd04a987f2 100644 --- a/source/SpinalHDL/Libraries/Com/usb_ohci.rst +++ b/source/SpinalHDL/Libraries/Com/usb_ohci.rst @@ -1,17 +1,19 @@ USB OHCI -============ +======== -There is a USB OHCi controller (host) in the SpinalHDL library. In a few bullet points it can be resumed to : +Here exists a USB OHCi controller (host) in the SpinalHDL library. + +A few bullet points to summarise support: - It follow the `OpenHCI Open Host Controller Interface Specification for USB` specification (OHCI). -- It is compatible with the upstream linux / uboot OHCI drivers already. (there is also a OHCI driver on tinyUSB) -- This provide USB host full speed and low speed capabilities (12Mbps and 1.5Mbps) +- It is compatible with the upstream linux / uboot OHCI drivers already. (there is also an OHCI driver on tinyUSB) +- This provides USB host full speed and low speed capabilities (12Mbps and 1.5Mbps) - Tested on linux and uboot - One controller can host multiple ports (up to 16) - Bmb memory interface for DMA accesses - Bmb memory interace for the configuration -- Require a clock for the internal phy which is a multiple of 12 Mhz at least 48 Mhz +- Requires a clock for the internal phy which is a multiple of 12 Mhz at least 48 Mhz - The controller frequency is not restricted - No external phy required @@ -26,7 +28,7 @@ Limitations : - Some USB hub (had one so far) do not like having a full speed host with low speed devices attached. - Some modern devices will not work on USB full speed (ex : Gbps ethernet adapter) -- Require memory coherency with the CPU (or the cpu need to flush his data cache in the driver) +- Require memory coherency with the CPU (or the cpu need to be able to flush its data cache in the driver) Deployments : @@ -71,7 +73,7 @@ Usage val management = phy.io.management.toIo } - object UsbHostGen extends App{ + object UsbHostGen extends App { val p = UsbOhciParameter( noPowerSwitching = true, powerSwitchingMode = true, diff --git a/source/SpinalHDL/Libraries/EDA/altera/qsysify.rst b/source/SpinalHDL/Libraries/EDA/altera/qsysify.rst index 0ae64bcbd5e..dfaae8fa368 100644 --- a/source/SpinalHDL/Libraries/EDA/altera/qsysify.rst +++ b/source/SpinalHDL/Libraries/EDA/altera/qsysify.rst @@ -18,8 +18,8 @@ In the case of a UART controller : .. code-block:: scala - case class AvalonMMUartCtrl(...) extends Component{ - val io = new Bundle{ + case class AvalonMMUartCtrl(...) extends Component { + val io = new Bundle { val bus = slave(AvalonMM(AvalonMMUartCtrl.getAvalonMMConfig)) val uart = master(Uart()) } @@ -31,7 +31,7 @@ The following ``main`` will generate the Verilog and the QSys TCL script with i .. code-block:: scala - object AvalonMMUartCtrl{ + object AvalonMMUartCtrl { def main(args: Array[String]) { //Generate the Verilog val toplevel = SpinalVerilog(AvalonMMUartCtrl(UartCtrlMemoryMappedConfig(...))).toplevel diff --git a/source/SpinalHDL/Libraries/Graphics/colors.rst b/source/SpinalHDL/Libraries/Graphics/colors.rst index e81e81f2dfa..4826c517a9c 100644 --- a/source/SpinalHDL/Libraries/Graphics/colors.rst +++ b/source/SpinalHDL/Libraries/Graphics/colors.rst @@ -9,11 +9,11 @@ You can use an Rgb bundle to model colors in hardware. This Rgb bundle take as p .. code-block:: scala - case class RgbConfig(rWidth : Int,gWidth : Int,bWidth : Int){ + case class RgbConfig(rWidth : Int,gWidth : Int,bWidth : Int) { def getWidth = rWidth + gWidth + bWidth } - case class Rgb(c: RgbConfig) extends Bundle{ + case class Rgb(c: RgbConfig) extends Bundle { val r = UInt(c.rWidth bits) val g = UInt(c.gWidth bits) val b = UInt(c.bWidth bits) diff --git a/source/SpinalHDL/Libraries/Graphics/vga.rst b/source/SpinalHDL/Libraries/Graphics/vga.rst index 88d66d5b4a2..08b23a1b7c8 100644 --- a/source/SpinalHDL/Libraries/Graphics/vga.rst +++ b/source/SpinalHDL/Libraries/Graphics/vga.rst @@ -11,7 +11,7 @@ An VGA bus definition is available via the Vga bundle. .. code-block:: scala - case class Vga (rgbConfig: RgbConfig) extends Bundle with IMasterSlave{ + case class Vga (rgbConfig: RgbConfig) extends Bundle with IMasterSlave { val vSync = Bool() val hSync = Bool() @@ -46,7 +46,7 @@ VGA timings could be modeled in hardware by using an VgaTimings bundle : VGA controller -------------- -An VGA controller is available. It's definition is the following : +An VGA controller is available. Its definition is the following : .. code-block:: scala diff --git a/source/SpinalHDL/Libraries/IO/readableOpenDrain.rst b/source/SpinalHDL/Libraries/IO/readableOpenDrain.rst index 378d3b7c636..31c59bd3934 100644 --- a/source/SpinalHDL/Libraries/IO/readableOpenDrain.rst +++ b/source/SpinalHDL/Libraries/IO/readableOpenDrain.rst @@ -6,7 +6,7 @@ The ReadableOpenDrain bundle is defined as following : .. code-block:: scala - case class ReadableOpenDrain[T<: Data](dataType : HardType[T]) extends Bundle with IMasterSlave{ + case class ReadableOpenDrain[T<: Data](dataType : HardType[T]) extends Bundle with IMasterSlave { val write,read : T = dataType() override def asMaster(): Unit = { @@ -21,11 +21,11 @@ There is an example of usage : .. code-block:: scala - val io = new Bundle{ + val io = new Bundle { val dataBus = master(ReadableOpenDrain(Bits(32 bits))) } io.dataBus.write := 0x12345678 - when(io.dataBus.read === 42){ + when(io.dataBus.read === 42) { } diff --git a/source/SpinalHDL/Libraries/IO/tristate.rst b/source/SpinalHDL/Libraries/IO/tristate.rst index 7cd8ebfa680..6d9fec861b3 100644 --- a/source/SpinalHDL/Libraries/IO/tristate.rst +++ b/source/SpinalHDL/Libraries/IO/tristate.rst @@ -3,7 +3,7 @@ TriState ======== -Tri-state signals are weird to handle in many cases: +Tri-state signals are difficult to handle in many cases: * They are not really kind of digital things * And except for IO, they aren't used for digital design @@ -25,7 +25,7 @@ The TriState bundle is defined as following : .. code-block:: scala - case class TriState[T <: Data](dataType : HardType[T]) extends Bundle with IMasterSlave{ + case class TriState[T <: Data](dataType : HardType[T]) extends Bundle with IMasterSlave { val read,write : T = dataType() val writeEnable = Bool() @@ -42,13 +42,13 @@ There is an example of usage: .. code-block:: scala - val io = new Bundle{ + val io = new Bundle { val dataBus = master(TriState(Bits(32 bits))) } io.dataBus.writeEnable := True io.dataBus.write := 0x12345678 - when(io.dataBus.read === 42){ + when(io.dataBus.read === 42) { } @@ -61,7 +61,7 @@ It is defined as following : .. code-block:: scala - case class TriStateArray(width : BitCount) extends Bundle with IMasterSlave{ + case class TriStateArray(width : BitCount) extends Bundle with IMasterSlave { val read,write,writeEnable = Bits(width) override def asMaster(): Unit = { @@ -76,12 +76,12 @@ There is an example of usage : .. code-block:: scala - val io = new Bundle{ + val io = new Bundle { val dataBus = master(TriStateArray(32 bits) } io.dataBus.writeEnable := 0x87654321 io.dataBus.write := 0x12345678 - when(io.dataBus.read === 42){ + when(io.dataBus.read === 42) { } diff --git a/source/SpinalHDL/Libraries/binarySystem.rst b/source/SpinalHDL/Libraries/binarySystem.rst index f9a0bec47fe..3a3f270ee91 100644 --- a/source/SpinalHDL/Libraries/binarySystem.rst +++ b/source/SpinalHDL/Libraries/binarySystem.rst @@ -171,7 +171,7 @@ Int/Long/BigInt to Binary-List $: BigInt("123451118", 10).toBinInts List(0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1) -align to fix width +align to a fixed width .. code-block:: scala @@ -179,7 +179,7 @@ align to fix width $: 39.toBinInts() List(1, 1, 1, 0, 0, 1) - $: 39.toBinInts(8) // align to 8 bit fill with 0 + $: 39.toBinInts(8) // align to 8 bit zero filled at MSB List(1, 1, 1, 0, 0, 1, 0, 0) diff --git a/source/SpinalHDL/Libraries/bus_slave_factory.rst b/source/SpinalHDL/Libraries/bus_slave_factory.rst index a066d9b6d42..3903c6707ac 100644 --- a/source/SpinalHDL/Libraries/bus_slave_factory.rst +++ b/source/SpinalHDL/Libraries/bus_slave_factory.rst @@ -18,8 +18,8 @@ You can find more documentation about the internal implementation of the ``BusSl Functionality ------------- -| Currently there is three implementation of the ``BusSlaveFactory`` tool : APB3, AXI-lite 3 and Avalon. -| Each implementation of that tool take as argument one instance of the corresponding bus and then offer following functions to map your hardware into the memory mapping : +| There are many implementations of the ``BusSlaveFactory`` tool : AHB3-lite, APB3, APB4, AvalonMM, AXI-lite 3, AXI4, BMB, Wishbone and PipelinedMemoryBus. +| Each implementation of that tool take as an argument one instance of the corresponding bus and then offers the following functions to map your hardware into the memory mapping : .. list-table:: :header-rows: 1 diff --git a/source/SpinalHDL/Libraries/fiber.rst b/source/SpinalHDL/Libraries/fiber.rst index 5171533ecc7..c957894b3f3 100644 --- a/source/SpinalHDL/Libraries/fiber.rst +++ b/source/SpinalHDL/Libraries/fiber.rst @@ -6,26 +6,29 @@ Fiber framework ==================== +.. warning:: + This framework is not expected to be used for general RTL generation and targets large system + design management and code generation. It is currently used as toplevel integration tool in SaxonSoC. + Currently in developpement. The Fiber to run the hardware elaboration in a out of order manner, a bit similarly to Makefile, where you can define rules and dependencies which will then be solved when you run a make command. It is very similar to the Scala Future feature. -Such framework complexify simple things but provide some strong feature for complex cases : +Using this framework can complicate simple things but provide some strong features for complex cases : -- You can define things before even knowing all their requirements, ex : instanciating a interruption controller, before knowing how many lines of interrupt you need +- You can define things before even knowing all their requirements, ex : + instantiating a interruption controller, before knowing how many interrupt signal lines you need - Abstract/lazy/partial SoC architecture definition allowing the creation of SoC template for further specialisations -- Automatic requirements negotiation between multiple agents in a decentralized way, ex : between masters and slaves of a memory bus +- Automatic requirement negotiation between multiple agents in a decentralized way, ex : between masters and slaves of a memory bus The framework is mainly composed of : -- Handle[T], which can be used later to store a value of type T. -- handle.load which allow to set the value of a handle (will reschedule all tasks waiting on it) -- handle.get, which return the value of the given handle. Will block the task execution if that handle isn't loaded yet -- Handle{ code }, which fork a new task which will execute the given code. The result of that code will be loaded into the Handle -- soon(handle), which allow the current task to announce that soon it will load that handle with a value (used to track which handle will - +- ``Handle[T]``, which can be used later to store a value of type ``T``. +- ``handle.load`` which allow to set the value of a handle (will reschedule all tasks waiting on it) +- ``handle.get``, which return the value of the given handle. Will block the task execution if that handle isn't loaded yet +- ``Handle{ /*code*/ }``, which fork a new task which will execute the given code. The result of that code will be loaded into the Handle +- ``soon(handle)``, which allows the current task to announce that it will load ``handle`` with a value (used for scheduling) -Warning, this is realy not usual RTL description and aim large system generation. It is currently used as toplevel integration tool in SaxonSoC. Simple dummy example -------------------- diff --git a/source/SpinalHDL/Libraries/fsm.rst b/source/SpinalHDL/Libraries/fsm.rst index 1c43af18dd4..be70d6ec9a8 100644 --- a/source/SpinalHDL/Libraries/fsm.rst +++ b/source/SpinalHDL/Libraries/fsm.rst @@ -29,7 +29,7 @@ Style A: } val fsm = new StateMachine { - val counter = Reg(UInt(8 bits)) init (0) + val counter = Reg(UInt(8 bits)) init(0) io.result := False val stateA : State = new State with EntryPoint { @@ -62,12 +62,12 @@ Style B: val result = out Bool() } - val fsm = new StateMachine{ + val fsm = new StateMachine { val stateA = new State with EntryPoint val stateB = new State val stateC = new State - val counter = Reg(UInt(8 bits)) init (0) + val counter = Reg(UInt(8 bits)) init(0) io.result := False stateA @@ -235,7 +235,7 @@ Each of them provides the following functions to define the logic associated to StateDelay ^^^^^^^^^^ -``StateDelay`` allows to create a state which waits for a fixed number of cycles before executing statments in ``whenCompleted {...}``. The preferred way to use it is: +``StateDelay`` allows you to create a state which waits for a fixed number of cycles before executing statements in ``whenCompleted {...}``. The preferred way to use it is: .. code-block:: scala @@ -254,7 +254,7 @@ It can also be written in one line: StateFsm ^^^^^^^^ -``StateFsm`` allow to describe a state containing a nested state machine. When the nested state machine is done (exited), statments in ``whenCompleted { ... }`` are executed. +``StateFsm`` allows you to describe a state containing a nested state machine. When the nested state machine is done (exited), statements in ``whenCompleted { ... }`` are executed. There is an example of StateFsm definition : @@ -268,7 +268,7 @@ There is an example of StateFsm definition : } def internalFsm() = new StateMachine { - val counter = Reg(UInt(8 bits)) init (0) + val counter = Reg(UInt(8 bits)) init(0) val stateA : State = new State with EntryPoint { whenIsActive { @@ -292,14 +292,14 @@ In the example above, ``exit()`` makes the state machine jump to the boot state StateParallelFsm ^^^^^^^^^^^^^^^^ -``StateParallelFsm`` allows to handle multiple nested state machines. When all nested state machine are done, statments in ``whenCompleted { ... }`` are executed. +``StateParallelFsm`` allows you to handle multiple nested state machines. When all nested state machine are done, statements in ``whenCompleted { ... }`` are executed. Example: .. code-block:: scala val stateD = new StateParallelFsm (internalFsmA(), internalFsmB()) { - whenCompleted{ + whenCompleted { goto(stateE) } } diff --git a/source/SpinalHDL/Libraries/regIf.rst b/source/SpinalHDL/Libraries/regIf.rst index 50c8669b964..9fff129d406 100644 --- a/source/SpinalHDL/Libraries/regIf.rst +++ b/source/SpinalHDL/Libraries/regIf.rst @@ -5,7 +5,7 @@ RegIf Register Interface Builder - Automatic address, fields allocation and conflict detection -- 28 Register Access types(Covering the 25 types defined by the UVM standard) +- 28 Register Access types (Covering the 25 types defined by the UVM standard) - Automatic documentation generation Automatic allocation @@ -15,8 +15,8 @@ Automatic address allocation .. code:: scala - class RegBankExample extends Component{ - val io = new Bundle{ + class RegBankExample extends Component { + val io = new Bundle { apb = Apb3(Apb3Config(16,32)) } val busif = Apb3BusInterface(io.apb,(0x0000, 100 Byte) @@ -51,7 +51,7 @@ Automatic fileds allocation .. image:: /asset/image/regif/field-auto-allocate.gif -confilict detection +conflict detection .. code:: scala @@ -145,7 +145,7 @@ Attention, please don't forget to drive it. .. code:: scala - val io = new Bundle{ + val io = new Bundle { val cnt = in UInt(8 bit) } @@ -238,7 +238,7 @@ CSTM is only used to generate software interfaces, and does not generate actual val reg = Reg(Bits(16 bit)) init 0 REG.registerAtOnlyReadLogic(0, reg, CSTM("BMRW"), resetValue = 0, "custom field") - when(busif.dowrite){ + when(busif.dowrite) { reg := reg & ~busif.writeData(31 downto 16) | busif.writeData(15 downto 0) & busif.writeData(31 downto 16) } @@ -278,7 +278,7 @@ withStrb Typical Example =============== -Batch creat REG-Address and fields register +Batch create REG-Address and fields register .. code:: scala @@ -292,7 +292,7 @@ Batch creat REG-Address and fields register } val busif = Apb3BusInterface(io.apb, (0x000, 100 Byte), regPre = "AP") - (0 to 9).map{ i => + (0 to 9).map { i => //here use setName give REG uniq name for Docs usage val REG = busif.newReg(doc = s"Register${i}").setName(s"REG${i}") val real = REG.field(SInt(8 bit), AccessType.RW, 0, "Complex real") @@ -365,14 +365,14 @@ Manual writing interruption this is a very tedious and repetitive work, a better way is to use the "factory" paradigm to auto-generate the documentation for each signal. -now th InterruptFactory can do that. +now the InterruptFactory can do that. -Easy Way creat interruption: +Easy Way create interruption: .. code:: scala class EasyInterrupt extends Component { - val io = new Bundle{ + val io = new Bundle { val apb = slave(Apb3(Apb3Config(16,32))) val a, b, c, d, e = in Bool() } @@ -432,24 +432,24 @@ SpinalUsage: Spinal Factory -------------- -=================================================================================== =========================================================== +=================================================================================== ============================================================ BusInterface method Description -=================================================================================== =========================================================== -``InterruptFactory(regNamePre: String, triggers: Bool*)`` creat RAW/FORCE/MASK/STATUS for pulse event -``InterruptFactoryNoForce(regNamePre: String, triggers: Bool*)`` creat RAW/MASK/STATUS for pulse event -``InterruptFactory(regNamePre: String, triggers: Bool*)`` creat MASK/STATUS for level_int merge -``InterruptFactoryAt(addrOffset: Int, regNamePre: String, triggers: Bool*)`` creat RAW/FORCE/MASK/STATUS for pulse event at addrOffset -``InterruptFactoryNoForceAt(addrOffset: Int, regNamePre: String, triggers: Bool*)`` creat RAW/MASK/STATUS for pulse event at addrOffset -``InterruptFactoryAt(addrOffset: Int, regNamePre: String, triggers: Bool*)`` creat MASK/STATUS for level_int merge at addrOffset -=================================================================================== =========================================================== +=================================================================================== ============================================================ +``InterruptFactory(regNamePre: String, triggers: Bool*)`` create RAW/FORCE/MASK/STATUS for pulse event +``InterruptFactoryNoForce(regNamePre: String, triggers: Bool*)`` create RAW/MASK/STATUS for pulse event +``InterruptFactory(regNamePre: String, triggers: Bool*)`` create MASK/STATUS for level_int merge +``InterruptFactoryAt(addrOffset: Int, regNamePre: String, triggers: Bool*)`` create RAW/FORCE/MASK/STATUS for pulse event at addrOffset +``InterruptFactoryNoForceAt(addrOffset: Int, regNamePre: String, triggers: Bool*)`` create RAW/MASK/STATUS for pulse event at addrOffset +``InterruptFactoryAt(addrOffset: Int, regNamePre: String, triggers: Bool*)`` create MASK/STATUS for level_int merge at addrOffset +=================================================================================== ============================================================ Example ------- .. code:: scala - class RegFileIntrExample extends Component{ - val io = new Bundle{ + class RegFileIntrExample extends Component { + val io = new Bundle { val apb = slave(Apb3(Apb3Config(16,32))) val int_pulse0, int_pulse1, int_pulse2, int_pulse3 = in Bool() val int_level0, int_level1, int_level2 = in Bool() @@ -508,7 +508,7 @@ BusIfVistor give access BusIf.RegInsts to do what you want // lib/src/main/scala/lib/bus/regif/BusIfVistor.scala - trait BusIfVisitor { + trait BusIfVisitor { def begin(busDataWidth : Int) : Unit def visit(descr : FifoDescr) : Unit def visit(descr : RegDescr) : Unit diff --git a/source/SpinalHDL/Libraries/stream.rst b/source/SpinalHDL/Libraries/stream.rst index 4ddefecd608..10317bdaa4d 100644 --- a/source/SpinalHDL/Libraries/stream.rst +++ b/source/SpinalHDL/Libraries/stream.rst @@ -176,7 +176,7 @@ The following code will create this logic : .. code-block:: scala - case class RGB(channelWidth : Int) extends Bundle{ + case class RGB(channelWidth : Int) extends Bundle { val red = UInt(channelWidth bits) val green = UInt(channelWidth bits) val blue = UInt(channelWidth bits) @@ -459,7 +459,7 @@ When you have multiple Streams and you want to arbitrate them to drive a single StreamJoin ^^^^^^^^^^ -This utile takes multiple input streams and wait until all of them fire before letting all of them through. +This utility takes multiple input streams and waits until all of them fire `valid` before letting all of them through by providing `ready`. .. code-block:: scala diff --git a/source/SpinalHDL/Libraries/utils.rst b/source/SpinalHDL/Libraries/utils.rst index 189c159e1e9..f89c60754f9 100644 --- a/source/SpinalHDL/Libraries/utils.rst +++ b/source/SpinalHDL/Libraries/utils.rst @@ -163,7 +163,7 @@ There is an example of different syntaxes which could be used with the Counter t .. code-block:: scala val timeout = Timeout(10 ms) //Timeout who tick after 10 ms - when(timeout){ //Check if the timeout has tick + when(timeout) { //Check if the timeout has tick timeout.clear() //Ask the timeout to clear its flag } @@ -178,7 +178,7 @@ The ResetCtrl provide some utilities to manage resets. asyncAssertSyncDeassert ~~~~~~~~~~~~~~~~~~~~~~~ -You can filter an asynchronous reset by using an asynchronously asserted synchronously deaserted logic. To do it you can use the ``ResetCtrl.asyncAssertSyncDeassert`` function which will return you the filtred value. +You can filter an asynchronous reset by using an asynchronously asserted synchronously deaserted logic. To do it you can use the ``ResetCtrl.asyncAssertSyncDeassert`` function which will return you the filtered value. .. list-table:: :header-rows: 1 @@ -204,7 +204,7 @@ You can filter an asynchronous reset by using an asynchronously asserted synchro - Number of register stages used to avoid metastability (default=2) -There is also an ``ResetCtrl.asyncAssertSyncDeassertDrive`` version of tool which directly assign the ``clockDomain`` reset with the filtred value. +There is also an ``ResetCtrl.asyncAssertSyncDeassertDrive`` version of tool which directly assign the ``clockDomain`` reset with the filtered value. Special utilities ----------------- @@ -218,6 +218,6 @@ Special utilities - Description * - LatencyAnalysis(paths : Node*) - Int - - | Return the shortest path,in therm of cycle, that travel through all nodes, + - | Return the shortest path, in terms of cycles, that travel through all nodes, | from the first one to the last one diff --git a/source/SpinalHDL/Other language features/scope_property.rst b/source/SpinalHDL/Other language features/scope_property.rst index 7c398819eb8..2059a5000dd 100644 --- a/source/SpinalHDL/Other language features/scope_property.rst +++ b/source/SpinalHDL/Other language features/scope_property.rst @@ -3,7 +3,7 @@ ScopeProperty ================== -A scope property is a thing which can store values localy to the current thread. Its API can be used to set/get that value, but also to apply modification to the value for a portion of the execution in a stack manner. +A scope property is a thing which can store values locally to the current thread. Its API can be used to set/get that value, but also to apply modification to the value for a portion of the execution in a stack manner. In other words it is a alternative to global variable, scala implicit, ThreadLocal. @@ -16,12 +16,12 @@ In other words it is a alternative to global variable, scala implicit, ThreadLoc object Xlen extends ScopeProperty[Int] - object ScopePropertyMiaou extends App{ + object ScopePropertyMiaou extends App { Xlen.set(1) println(Xlen.get) //1 - Xlen(2){ + Xlen(2) { println(Xlen.get) //2 - Xlen(3){ + Xlen(3) { println(Xlen.get) //3 Xlen.set(4) println(Xlen.get) //4 diff --git a/source/SpinalHDL/Other language features/stub.rst b/source/SpinalHDL/Other language features/stub.rst index 3d37c7d6bd9..688f24589aa 100644 --- a/source/SpinalHDL/Other language features/stub.rst +++ b/source/SpinalHDL/Other language features/stub.rst @@ -2,18 +2,18 @@ Stub ====== -You can emtpy an Component Hierarchy as stub: +You can empty an Component Hierarchy as stub: .. code-block:: scala - class SubSysModule extends Component{ - val io = new Bundle{ + class SubSysModule extends Component { + val io = new Bundle { val dx = slave(Stream(Bits(32 bits))) val dy = master(Stream(Bits(32 bits))) } io.dy <-< io.dx } - class TopLevle extends Component { + class TopLevel extends Component { val dut = new SubSysModule().stub //instance an SubSysModule as empty stub } @@ -40,17 +40,17 @@ It will generate the following Verilog code for example: endmodule -You can also emtpy the top Compoent +You can also empty the top Component .. code-block:: scala SpinalVerilog(new Pinsec(500 MHz).stub) -what `stub` do +What does `stub` do ? -* first walk all the component and find out clock ,then keep clock -* remove all children component -* reomove all assignment and logic we dont wan't +* first walk all the components and find out clock, then keep clock +* then remove all children component +* then remove all assignment and logic we dont want * tile 0 to output port diff --git a/source/SpinalHDL/Other language features/utils.rst b/source/SpinalHDL/Other language features/utils.rst index cf93bf53b8d..71e2f48646a 100644 --- a/source/SpinalHDL/Other language features/utils.rst +++ b/source/SpinalHDL/Other language features/utils.rst @@ -72,7 +72,7 @@ For example: .. code-block:: scala def plusOne(value : UInt) : UInt = { - // Will recreate a UInt with the same width than ``value`` + // Will provide new instance of a UInt with the same width as ``value`` val temp = cloneOf(value) temp := value + 1 return temp @@ -86,6 +86,20 @@ You can get more information about how hardware data types are managed on the :r .. note:: If you use the ``cloneOf`` function on a ``Bundle``, this ``Bundle`` should be a ``case class`` or should override the clone function internally. +.. code-block:: scala + + // An example of a regular 'class' with 'override def clone()' function + class MyBundle(ppp : Int) extends Bundle { + val a = UInt(ppp bits) + override def clone = new MyBundle(ppp) + } + val x = new MyBundle(3) + val typeDef = HardType(new MyBundle(3)) + val y = typeDef() + + cloneOf(x) // Need clone method, else it errors + cloneOf(y) // Is ok + Passing a datatype as construction parameter -------------------------------------------- @@ -153,12 +167,12 @@ SpinalHDL has a dedicated syntax to define frequency and time values: .. code-block:: scala - val frequency = 100 MHz - val timeoutLimit = 3 ms - val period = 100 us + val frequency = 100 MHz // infers type TimeNumber + val timeoutLimit = 3 ms // infers type HertzNumber + val period = 100 us // infers type TimeNumber - val periodCycles = frequency * period - val timeoutCycles = frequency * timeoutLimit + val periodCycles = frequency * period // infers type BigDecimal + val timeoutCycles = frequency * timeoutLimit // infers type BigDecimal | For time definitions you can use following postfixes to get a ``TimeNumber``: | ``fs``, ``ps``, ``ns``, ``us``, ``ms``, ``sec``, ``mn``, ``hr`` @@ -175,8 +189,8 @@ SpinalHDL allows the definition of integer numbers using binary prefix notation .. code-block:: scala - val memSize = 512 MiB - val dpRamSize = 4 KiB + val memSize = 512 MiB // infers type BigInt + val dpRamSize = 4 KiB // infers type BigInt The following binary prefix notations are available: diff --git a/source/SpinalHDL/Simulation/bootstraps.rst b/source/SpinalHDL/Simulation/bootstraps.rst index 58ff13cc976..212fb5aad51 100644 --- a/source/SpinalHDL/Simulation/bootstraps.rst +++ b/source/SpinalHDL/Simulation/bootstraps.rst @@ -156,7 +156,9 @@ Note is it equivalent to: simThread.suspend() // Avoid the "doSim" completion } -Note that by default, the simulation files will be placed into the ``simWorkspace/xxx`` folders. You can override the simWorkspace location by setting the ``SPINALSIM_WORKSPACE`` environnement variable. +.. _env_SPINALSIM_WORKSPACE: + +Note that by default, the simulation files will be placed into the ``simWorkspace/xxx`` folders. You can override the simWorkspace location by setting the ``SPINALSIM_WORKSPACE`` environment variable. Running multiple tests on the same hardware ------------------------------------------- diff --git a/source/SpinalHDL/Simulation/clock.rst b/source/SpinalHDL/Simulation/clock.rst index 70ac36d3f2a..ab594d0bda4 100644 --- a/source/SpinalHDL/Simulation/clock.rst +++ b/source/SpinalHDL/Simulation/clock.rst @@ -13,7 +13,7 @@ Below is a list of ``ClockDomain`` stimulation functions: * - ClockDomain stimulus functions - Description * - ``forkStimulus(period)`` - - Fork a simulation process to generate the clockdomain stimulus (clock, reset, softReset, clockEnable signals) + - Fork a simulation process to generate the ClockDomain stimulus (clock, reset, softReset, clockEnable signals) * - ``forkSimSpeedPrinter(printPeriod)`` - Fork a simulation process which will periodically print the simulation speed in kilo-cycles per real time second. ``printPeriod`` is in realtime seconds * - ``clockToggle()`` @@ -67,7 +67,7 @@ Below is a list of ``ClockDomain`` utilities that you can use to wait for a give .. warning:: - All the functionalities of the wait API can only be called from inside of a thread, and not from a callback. + All the functionality of the wait API can only be called directly from inside a thread, and not from a callback executed via the Callback API. .. _sim_clock_threadless: diff --git a/source/SpinalHDL/Simulation/index.rst b/source/SpinalHDL/Simulation/index.rst index c0ba93e787e..3c9ef8e987a 100644 --- a/source/SpinalHDL/Simulation/index.rst +++ b/source/SpinalHDL/Simulation/index.rst @@ -6,10 +6,11 @@ As always, you can use your standard simulation tools to simulate the VHDL/Veril To be able to simulate user-defined components, SpinalHDL uses external HDL simulators as backend. Currently, four simulators are supported: -- `Verilator `_ +- `Verilator `_ - `GHDL `_ **(experimental, since SpinalHDL 1.4.1)** -- `Icarus Verilog `_ **(experimental, since SpinalHDL 1.4.1)** +- `Icarus Verilog `_ **(experimental, since SpinalHDL 1.4.1)** - `VCS `_ **(experimental, since SpinalHDL 1.7.0)** +- `XSim `_ **(experimental, since SpinalHDL 1.7.0)** With external HDL simulators it is possible to directly test the generated HDL sources without increasing the SpinalHDL codebase complexity. diff --git a/source/SpinalHDL/Simulation/install/Verilator.rst b/source/SpinalHDL/Simulation/install/Verilator.rst index 329fa324a26..393a205d7e9 100644 --- a/source/SpinalHDL/Simulation/install/Verilator.rst +++ b/source/SpinalHDL/Simulation/install/Verilator.rst @@ -5,6 +5,14 @@ Setup and installation of Verilator SpinalSim + Verilator is supported on both Linux and Windows platforms. +It is recommended that v4.218 is the oldest Verilator version to use. While it maybe +possible to use older verilator versions, some optional and Scala source dependent +features that SpinalHDL can use (such as Verilog ``$urandom`` support) may not be supported +by older Verilator versions and will cause an error when trying to simulate. + +Ideally the latest v4.xxx and v5.xxx is well supported and bug reports should be opened +with any issues you have. + Scala ^^^^^ @@ -33,9 +41,9 @@ You will also need a recent version of Verilator installed : unsetenv VERILATOR_ROOT # For csh; ignore error if on bash unset VERILATOR_ROOT # For bash cd verilator - git pull # Make sure we're up-to-date - git checkout v4.218 - autoconf # Create ./configure script + git pull # Make sure we're up-to-date + git checkout v4.218 # Can use newer v4.228 and v5.xxx + autoconf # Create ./configure script ./configure make -j$(nproc) sudo make install @@ -87,7 +95,7 @@ From source unset VERILATOR_ROOT cd verilator git pull - git checkout v4.040 + git checkout v4.218 # Can use newer v4.228 and v5.xxx autoconf ./configure export CPLUS_INCLUDE_PATH=/usr/include:$CPLUS_INCLUDE_PATH diff --git a/source/SpinalHDL/Simulation/signal.rst b/source/SpinalHDL/Simulation/signal.rst index 375e74d6c01..cb5e359451f 100644 --- a/source/SpinalHDL/Simulation/signal.rst +++ b/source/SpinalHDL/Simulation/signal.rst @@ -88,7 +88,7 @@ Or you can add it later, after having instantiated your toplevel for the simulat def main(args: Array[String]) { SimConfig.compile { val dut = new TopLevel - dut.counter.simPublic() + dut.counter.simPublic() // Call simPublic() here dut }.doSim{dut => dut.clockDomain.forkStimulus(10) diff --git a/source/SpinalHDL/Simulation/simulator_specifics.rst b/source/SpinalHDL/Simulation/simulator_specifics.rst index d33ce4daf86..56b9a9f7431 100644 --- a/source/SpinalHDL/Simulation/simulator_specifics.rst +++ b/source/SpinalHDL/Simulation/simulator_specifics.rst @@ -6,7 +6,7 @@ How SpinalHDL simulates the hardware with Verilator backend =========================================================== 1. Behind the scenes, SpinalHDL generates a Verilog equivalent hardware model of the DUT and then uses Verilator to convert it to a C++ cycle-accurate model. -2. The C++ model is compiled into a shared object (.so), which is bound to Scala via JNR-FFI. +2. The C++ model is compiled into a shared object (.so), which is bound to Scala via JNI-FFI. 3. The native Verilator API is abstracted by providing a simulation multi-threaded API. **Advantages:** @@ -17,7 +17,7 @@ How SpinalHDL simulates the hardware with Verilator backend * Verilator accepts only synthesizable Verilog/System Verilog code. Therefore special care has to be taken when simulating Verilog blackbox components that may have non-synthesizable statements. * VHDL blackboxes cannot be simulated. -* The simulation boot process is slow due to the necessity to compile and link the generated C++ model +* The simulation boot process is slow due to the necessity to compile and link the generated C++ model. Some support to incrementally compile and link exists which can provide speedups for subsequent simulations after building the first. How SpinalHDL simulates the hardware with GHDL/Icarus Verilog backend ===================================================================== diff --git a/source/SpinalHDL/Structuring/parametrization.rst b/source/SpinalHDL/Structuring/parametrization.rst index b6a64b3bd88..6e209b4c7b3 100644 --- a/source/SpinalHDL/Structuring/parametrization.rst +++ b/source/SpinalHDL/Structuring/parametrization.rst @@ -84,7 +84,7 @@ Here is an example of class parameters You can also use global variable defined in Scala objects (companion object pattern). -A ``ScopeProperty`` can also be used for configuration. +A :ref:`ScopeProperty ` can also be used for configuration. Optional hardware ------------------------------------------