Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document mem sim api #217

Merged
merged 2 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package spinaldoc.libraries.sequential_logic

import spinal.core._
import spinal.lib._
import spinal.core.sim._

import scala.language.postfixOps

case class MemoryExample() extends Component {
val wordCount = 64
val io = new Bundle {
val address = in port UInt(log2Up(wordCount) bit)
val i = in port Bits(8 bit)
val o = out port Bits(8 bit)
val we = in port Bool()
}

val mem = Mem(Bits(8 bit), wordCount=wordCount)
io.o := mem(io.address)
when(io.we) {
mem(io.address) := io.i
}
}
// end case class MemoryExample

object MemorySim extends App {
SimConfig.withVcdWave.compile {
val d = MemoryExample()
// make memory accessible during simulation
d.mem.simPublic()
d
}.doSim("example") { dut =>
dut.io.we #= false
dut.clockDomain.forkStimulus(10)
dut.clockDomain.waitSampling(2)

// do a write
dut.io.we #= true
dut.io.address #= 10
dut.io.i #= 0xaf
dut.clockDomain.waitSampling(2)
// check written data is there
assert(dut.mem.getBigInt(10) == 0xaf)

dut.io.we #= false
dut.clockDomain.waitSampling(1)

// set some data in memory
dut.mem.setBigInt(15, 0xfe)
// do a read to check if it's there
dut.io.address #= 15
dut.clockDomain.waitSampling(1)
assert(dut.io.o.toBigInt == 0xfe)
}
}

4 changes: 2 additions & 2 deletions source/SpinalHDL/Sequential logic/memory.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
RAM/ROM
=======
RAM/ROM Memory
==============

To create a memory in SpinalHDL, the ``Mem`` class should be used.
It allows you to define a memory and add read and write ports to it.
Expand Down
86 changes: 58 additions & 28 deletions source/SpinalHDL/Simulation/signal.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,6 @@ Each interface signal of the toplevel can be read and written from Scala:
dut.io.a #= BigInt("0123456789ABCDEF", 16)
println(dut.io.b.toInt)


.. _simulation_of_memory:

Load and Store of Memory in Simulation
--------------------------------------

It is possible to modify the contents of ``Mem`` hardware interface
components in simulation. The `data` argument should be a word-width
value with the `address` being the word-address within.

There is no API to convert address and/or individual data bits into
units other than the natural word size.

There is no API to mark any memory location with simulation `X` (undefined)
state.

.. list-table::
:header-rows: 1
:widths: 3 5

* - Syntax
- Description
* - ``Mem.getBigInt(address: Long): BigInt``
- Read a word from simulator at the word-address.
* - ``Mem.setBigInt(address: Long, data: BigInt)``
- Write a word to simulator at the word-address.


Accessing signals inside the component's hierarchy
--------------------------------------------------

Expand Down Expand Up @@ -129,3 +101,61 @@ Or you can add it later, after having instantiated your toplevel for the simulat
}
}


.. _simulation_of_memory:

Load and Store of Memory in Simulation
--------------------------------------

It is possible to modify the contents of ``Mem`` hardware interface
components in simulation. The `data` argument should be a word-width
value with the `address` being the word-address within.

There is no API to convert address and/or individual data bits into
units other than the natural word size.

There is no API to mark any memory location with simulation `X` (undefined)
state.

.. list-table::
:header-rows: 1
:widths: 1 1

* - Syntax
- Description
* - ``Mem.getBigInt(address: Long): BigInt``
- Read a word from simulator at the word-address.
* - ``Mem.setBigInt(address: Long, data: BigInt)``
- Write a word to simulator at the word-address.

Using this simple example using a memory:

.. literalinclude:: /../examples/src/main/scala/spinaldoc/sequential_logic/memory_sim.scala
:language: scala
:start-at: case class MemoryExample
:end-before: // end case class MemoryExample

Setting up the simulation we make the memory accessible:

.. literalinclude:: /../examples/src/main/scala/spinaldoc/sequential_logic/memory_sim.scala
:language: scala
:start-at: SimConfig
:end-at: doSim

We can read data during simulation, but have to take care that the data is already available (might be
a cycle late due to simulation event ordering):

.. literalinclude:: /../examples/src/main/scala/spinaldoc/sequential_logic/memory_sim.scala
:language: scala
:start-at: // do a write
:end-at: assert(dut.mem

And can write to memory like so:

.. literalinclude:: /../examples/src/main/scala/spinaldoc/sequential_logic/memory_sim.scala
:language: scala
:start-at: // set some data in memory
:end-at: assert(dut.io

Care has to be taken that due to event ordering in simulation e.g. the read depicted above has to be delayed
to when the value is actually available in the memory.
33 changes: 0 additions & 33 deletions source/SpinalHDL/miscelenea/core/core_components.rst
Original file line number Diff line number Diff line change
Expand Up @@ -444,39 +444,6 @@ There is a small component and a ``main`` that generate the corresponding VHDL.
}
}

Memory
------

.. list-table::
:header-rows: 1
:widths: 2 1

* - Syntax
- Description
* - Mem(type : Data,size : Int)
- Create a RAM
* - Mem(type : Data,initialContent : Array[Data])
- Create a ROM


.. list-table::
:header-rows: 1
:widths: 3 2 1

* - Syntax
- Description
- Return
* - mem(x)
- Asynchronous read
- T
* - mem(x) := y
- Synchronous write
-
* - mem.readSync(address,enable)
- Synchronous read
- T


Instantiate VHDL and Verilog IP
-------------------------------

Expand Down