Module Hardcaml_xilinx.Memory_builder

A general-purpose means of representing memories. The Config.t type allows the user to configure the underlying memory implementations. Eg: Using URAM for bits 0-72, and BRAMs for bits 73-80. This module allows construction of memories in 1D or 2D Modes. See further documentation below.

module For_deriving : sig ... end
module Config : sig ... end

Configuration for the memory builder. See documentation below for elaboration about the purpose of configuration fields.

type 'a t
module Port_label : sig ... end
module Create (M : Hardcaml.Interface.S) : sig ... end
val read_latency : _ t -> Base.int

Returns the read latency of the memory, including possibly any combinational latency due to muxing.

val complete : _ t -> Base.unit

Must be called strictly after all set_{read/write}_ functions have been called. This assigns to the underlying instantiated memories, and asserts that the memory satisfies the config's requirements.

Straightforward 1D Memories

1-dimensional memories are laid out the way one would expect. A memory of depth d, with columns shared between URAM and BRAM will have the following layout:

| URAM | BRAM | | x0 | | x1 | | .... | | xd-1 | ------------------------

Read_port_1d does not implement Hardcaml.Interface.S, since the address and data are not necessarily known without a config. To get something one can use in Hardcaml interfaces, you'll have to specialize it with Specialize.

module type Widths_1d = sig ... end
module Read_port_1d : sig ... end

General purpose 1D read ports.

module Write_port_1d : sig ... end

General purpose 1D Write ports. Note that it is possible to write 'a Write_port_1d.M(Foo).t in type declarations in mlis.

val set_read_port_1d : 'data t -> Port_label.t -> Hardcaml.Signal.t Read_port_1d.t -> 'data

Assigns the read port for 1D memories. Raises a runtime exception when called on a non single dimensional memory.

val set_write_port_1d : 'data t -> Port_label.t -> ( Hardcaml.Signal.t, 'data ) Write_port_1d.t -> Base.unit

Similar to set_read_port_1d, but for write ports.

General-Purpose "2D" Memories

The more general-purporse memory builders can be used to construct memories with the layout H * V where every entry is B bits wide. One can read from any of the entires through the read ports. When writing, however, an entire horizontal index must be written to at once, namely x*, v. This is because the memory is represented using parallel columns of memories along the H axis.

Under the hood, this constructs a memory of depth V and width H * B using the underlying_memories constructs provided by the Config.t. When reading (h, v), the memory reads the underlying memory at index v, which returns H copies of the the data, and multiplexes them with h. For that reason, V must be a power of two, but H does not have to be.

Here's a possible underlying layout by using this memory builder, for H=3, V=8, implemented with 2 URAMs and 1 BRAMs.

| URAM | BRAM | BRAM | | x00 | x10 | x20 | | x01 | x11 | x21 | | x02 | x12 | x22 | | x03 | x13 | x23 | | x04 | x14 | x24 | | x05 | x15 | x25 | | x06 | x16 | x26 | | x07 | x17 | x27 | --------------------------------------

Since writes to a row are atomic, for a given v and d, all entries at x{0, 1, 2}d must be written to simultaneously.

Note that 1D memories are simply a special case of 2D memories where H = 1.

module type Widths_2d = sig ... end
module Read_port_2d : sig ... end

General-purpose Read Ports.

module Write_port_2d : sig ... end

General purpose write ports. Note that it is possible to write 'a Write_port_2d.M(Foo).t in type declarations in mlis

val set_write_port_2d : 'data t -> Port_label.t -> ( Hardcaml.Signal.t, 'data ) Write_port_2d.t -> Base.unit

Set the write port.

val set_read_port_2d : 'data t -> Port_label.t -> Hardcaml.Signal.t Read_port_2d.t -> 'data

Set the read port. This should only ever be called once.

module M (X : Base.T1) : sig ... end

Shorthand useful for writing Memory_builder.M(Foo).t