Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: cb053dc0118f
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: eb922f6ddce5
Choose a head ref
  • 4 commits
  • 14 files changed
  • 1 contributor

Commits on May 25, 2015

  1. Copy the full SHA
    0d2db23 View commit details
  2. Copy the full SHA
    c371629 View commit details
  3. litesata: add mirroring

    enjoy-digital committed May 25, 2015
    Copy the full SHA
    0d1a7b9 View commit details
  4. Copy the full SHA
    eb922f6 View commit details
4 changes: 3 additions & 1 deletion misoclib/mem/litesata/README
Original file line number Diff line number Diff line change
@@ -59,9 +59,11 @@ Core:
- Errors detection and reporting

Frontend:
- Configurable crossbar (simply use core.crossbar.get_port() to add a new port!)
- Configurable crossbar (simply declare your crossbar and use crossbar.get_port() to add a new port!)
- Ports arbitration transparent to the user
- Synthetizable BIST
- Striping module to segment data on multiple HDDs and increase write/read speed and capacity. (RAID0 equivalent)
- Mirroring module for data redundancy and increase read speeds. (RAID1 equivalent)

[> Possibles improvements
-------------------------
2 changes: 1 addition & 1 deletion misoclib/mem/litesata/core/link/__init__.py
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ def __init__(self, phy):

# inserter CONT and scrambled data between
# CONT and next primitive
cont = BufferizeEndpoints("source")(LiteSATACONTInserter(phy_description(32)))
cont = BufferizeEndpoints("sink")(LiteSATACONTInserter(phy_description(32)))
self.submodules += cont

# datas / primitives mux
198 changes: 148 additions & 50 deletions misoclib/mem/litesata/doc/source/docs/frontend/index.rst
Original file line number Diff line number Diff line change
@@ -1,93 +1,191 @@
.. _frontend-index:

========================
Frontend
Frontend interfaces
========================

Crossbar and user ports
=======================

LiteSATA provides a crossbar to let the user request the number of port he needs.
Ports are automatically arbitrated and dispatched to and from the core. In the
following example we create a core and get a port from the crossbar:

.. code-block:: python
self.submodules.sata_phy = LiteSATAPHY(platform.device,
platform.request("sata"),
"sata_gen2",
clk_freq)
self.submodules.sata = LiteSATA(self.sata_phy)
user_port = self.sata.crossbar.get_port()
Our user_port has 2 endpoints:
All frontend modules of LiteSATA share the same user interface based on packets.
An interface has 2 endpoints:

- A Sink used to send commands and write data.
- A Source used to receive commands acknowledges and receive read data.
- A Source used to receive commands acknowledges and read data.

Packets and user commands/responses are described in the next sections.

Packets description
===================

Sink and Source are packets with additional parameters. A packet has the following signals:

- stb: Strobe signal indicates that command or data is valid.
- sop: Start Of Packet signal indicates that current command or data is the first of the packet.
- eop: End Of Packet signal indicates that current command or data is the last of the packet.
- ack: Response from the endpoint indicates that core is able to accept our command or data.
- data: Current data of the packet.
- :code:`stb`: Strobe signal indicates that command or data is valid.
- :code:`sop`: Start Of Packet signal indicates that current command or data is the first of the packet.
- :code:`eop`: End Of Packet signal indicates that current command or data is the last of the packet.
- :code:`ack`: Response from the endpoint indicates that core is able to accept our command or data.
- :code:`data`: Current data of the packet.

.. figure:: packets.png
:scale: 30 %
:width: 50%
:align: center

An example of packet transaction between endpoints.

.. tip::

- When a packet only has a command or data, sop and eop must be set to 1 on the same clock cycle.
- A data is accepted when stb=1 and ack=1.
- When a packet only has a command or :code:`data`, :code:`sop` and :code:`eop` must be set to 1 on the same clock cycle.
- A :code:`data` is accepted when :code:`stb` =1 and :code:`ack` =1.

User Commands
=============

All HDD transfers are initiated using the Sink endpoint which has the following signals:
All transfers are initiated using the Sink endpoint which has the following signals:

- write: 1 bit signal indicates if we want to write data to the HDD.
- read: 1 bit signal indicaties if we want to read data from the HDD.
- identify: 1 bit signal indicates if command is an identify device command (use to get HDD informations).
- sector: 48 bits signal, the sector number we are going to write or read.
- count: 16 bits signal, the number of sectors we are going to write or read.
- data: 32 bits signal, the write data.
- :code:`write`: 1 bit signal indicates if we want to write data to the HDD.
- :code:`read`: 1 bit signal indicaties if we want to read data from the HDD.
- :code:`identify`: 1 bit signal indicates if command is an identify device command (use to get HDD informations).
- :code:`sector`: 48 bits signal, the sector number we are going to write or read.
- :code:`count`: 16 bits signal, the number of sectors we are going to write or read.
- :code:`data`: n x 32 bits signal, the write data. (n depends of the frontend module)

.. tip::

- write, read, identify, sector, count are parameters so remain constant for a packet duration.
- sector, count are ignored during an identify command.
- data is ignored during a read or identify command.
- :code:`write`, :code:`read`, :code:`identify`, :code:`sector`, :code:`count` are parameters so remain constant for a packet duration.
- :code:`sector`, :code:`count` are ignored during an :code:`identify` command.
- :code:`data` is ignored during a :code:`read` or :code:`identify` command.

User Responses
==============

HDD responses are obtained from the Source endpoint which has the following signals:
Responses are obtained from the Source endpoint which has the following signals:

- write: 1 bit signal indicates if command was a write.
- read: 1 bit signal indicaties if command was a read.
- identify: 1 bit signal indicates if command was an identify device command.
- last: 1 bit signal indicates if this is the last packet of the response. (A Response can be return in several packets)
- failed: 1 bit signal identicates if an error was detected in the response (CRC, FIS...)
- data: 32 bits signal, the read data
- :code:`write`: 1 bit signal indicates if command was a write.
- :code:`read`: 1 bit signal indicaties if command was a read.
- :code:`identify`: 1 bit signal indicates if command was an identify device command.
- :code:`last`: 1 bit signal indicates if this is the last packet of the response. (A response can be return in several packets)
- :code:`failed`: 1 bit signal identicates if an error was detected in the response (CRC, FIS...)
- :code:`data`: n x 32 bits signal, the read data. (n depends of the frontend module)

.. tip::

- write, read, identify, last are parameters so remain constant for a packet duration.
- data can be ignored in the case of a write or identify command.
- in case of a read command, read data packets are presented followed by an empty packet indicating the end of the transaction (last=1).
- :code:`write`, :code:`read`, :code:`identify`, :code:`last` are parameters so remain constant for a packet duration.
- :code:`data` can be ignored in the case of a :code:`write` or :code:`identify` command.
- in case of a :code:`read` command, read data packets are presented followed by an empty packet indicating the end of the transaction (last=1).

========================
Frontend modules
========================

LiteSATA provides a configurable and flexible frontend that can be used to:

- Provides any number of user ports.
- Generate any RAID configuration when used with multiple HDDs.

Crossbar
========

The crossbar let the user request any number of ports. It automatically arbitrate requests and dispatch responses to the corresponding ports.

The following example creates a crossbar and 2 user ports:

.. code-block:: python
self.submodules.sata_crossbar = LiteSATACrossbar(self.sata_core)
user_port0 = self.sata_crossbar.get_port()
user_port1 = self.sata_crossbar.get_port()
Striping
========

The striping module segment data so that data is stored on N different controllers. (RAID0 equivalent)

.. code-block:: python
+----> controller0 (dw)
port (N*dw) <----+----> controllerX (dw)
+----> controllerN (dw)
Characteristics:
- :code:`port`'s visible capacity = N x :code:`controller`'s visible capacity
- :code:`port`'s throughput = N x (slowest) :code:`controller`'s throughput

It can be used to increase capacity and writes/reads speed.

The following example creates a striping with 2 HDDs:

.. code-block:: python
self.submodules.sata_striping = LiteSATAStriping([self.sata_core0, self.sata_core1])
:code:`sata_striping`'s sink and source are the user interface.

Mirroring
=========

The mirroring module handles N controllers and provides N ports. (RAID1 equivalent)

Each port has its dedicated controller for reads:

.. code-block:: python
port0 <----> controller0
portX <----> controllerX
portN <----> controllerN
Writes are mirrored on each controller:

.. code-block:: python
(port0 write) | (portN write)
port0 ----------+----> controller0 | port0 (stalled) +-----> controller0
portX (stalled) +----> controllerX | portX (stalled) +-----> controllerX
portN (stalled) +----> controllerN | portN ----------+-----> controllerN
Writes have priority on reads. When a write is presented on one of the port, the module waits for all ongoing reads to finish and commute to write mode. Once all writes are serviced it returns to read mode.

Characteristics:
- :code:`port`'s visible capacity = :code:`controller`'s visible capacity
- total writes throughput = (slowest) :code:`controller`'s throughput
- total reads throughput = N x :code:`controller`'s throughput

It can be used for data redundancy and/or to increase total reads speed.

.. code-block:: python
self.submodules.sata_mirroring = LiteSATAMirroring([self.sata_core0, self.sata_core1])
:code:`sata_striping`'s ports[0] and ports[1] are the user interfaces.

Modules combinations
====================

Since all frontend modules share the same interface, it's easy to combine them together.

In the following code, we have 4 HDDs, do a striping with (0,1) and (2,3), a mirroring on top of that and then create a crossbar on the first port of our mirroring module:

.. code-block:: python
self.submodules.sata_striping0 = LiteSATAStriping([self.sata_core0, self.sata_core1])
self.submodules.sata_striping1 = LiteSATAStriping([self.sata_core2, self.sata_core3])
self.submodules.sata_mirroring = LiteSATAMirroring([self.sata_striping0, self.sata_striping1])
self.submodules.sata_crossbar = LiteSATACrossbar(self.sata_mirroring.ports[0])
self.user_port0 = self.sata_crossbar.get_port()
self.user_port1 = self.sata_crossbar.get_port()
This code provides the following user interfaces: :code:`self.user_port0`, :code:`self.user_port1` and :code:`self.sata_mirroring.ports[1]`.


Examples
========

A BIST_ (Data generator and checker) design is provided. It can be used to understand how to connect
your logic to the user_port provided by the crossbar. (See LiteSATABISTGenerator, LiteSATABISTChecker and LiteSATABISTIdentify)
Since it's probably easier to figure out how to use the frontend modules with real use cases, we provides example designs:

- A BIST_ (Data generator and checker) design that can be used to understand how to connect your logic to the user_port provided by the crossbar.

- A Striping_ design that can be used to understand how to connect couple 4 HDDs together in striping mode and do a BIST it.

- A Mirroring_ design that can be used to understand how to connect couple 4 HDDs together in Mirroring mode and do a BIST it.

.. _BIST: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/example_designs/targets/bist.py

.. _BIST: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/frontend/bist.py
.. _Striping: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/example_designs/targets/striping.py

.. _Mirroring: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/example_designs/targets/mirroring.py
4 changes: 3 additions & 1 deletion misoclib/mem/litesata/doc/source/docs/intro/about.rst
Original file line number Diff line number Diff line change
@@ -50,9 +50,11 @@ Core:
- Errors detection and reporting

Frontend:
- Configurable crossbar (simply use core.crossbar.get_port() to add a new port!)
- Configurable crossbar (simply declare your crossbar and use core.crossbar.get_port() to add a new port!)
- Ports arbitration transparent to the user
- Synthetizable BIST
- Striping module to segment data on multiple HDDs and increase write/read speed and capacity. (RAID0 equivalent)
- Mirroring module for data redundancy and increase read speeds. (RAID1 equivalent)


Possibles improvements
18 changes: 10 additions & 8 deletions misoclib/mem/litesata/doc/source/docs/simulation/index.rst
Original file line number Diff line number Diff line change
@@ -7,14 +7,16 @@ Simulation
.. note::
Please contribute to this document, or support us financially to write it.

Simulations are available in ./lib/sata/test:
- crc_tb
- scrambler_tb
- phy_datapath_tb
- link_tb
- command_tb
- bist_tb
Simulations are available in ./test:
- :code:`crc_tb`
- :code:`scrambler_tb`
- :code:`phy_datapath_tb`
- :code:`link_tb`
- :code:`command_tb`
- :code:`bist_tb`
- :code:`striping_tb`
- :code:`mirroring_tb`

Models for all the layers of SATA and a simplified HDD model are provided.
To run a simulation, go to ./test and run:
- make <simulation_name>
- :code:`make <simulation_name>`
6 changes: 3 additions & 3 deletions misoclib/mem/litesata/example_designs/targets/bist.py
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@
from misoclib.mem.litesata.frontend.bist import LiteSATABIST


class _CRG(Module):
class CRG(Module):
def __init__(self, platform):
self.clock_domains.cd_sys = ClockDomain()

@@ -54,7 +54,7 @@ def __init__(self, platform):
]


class BISTLeds(Module):
class StatusLeds(Module):
def __init__(self, platform, sata_phys):
for i, sata_phy in enumerate(sata_phys):
# 1Hz blinking leds (sata_rx and sata_tx clocks)
@@ -93,7 +93,7 @@ def __init__(self, platform):
)
self.add_cpu_or_bridge(UARTWishboneBridge(platform.request("serial"), clk_freq, baudrate=115200))
self.add_wb_master(self.cpu_or_bridge.wishbone)
self.submodules.crg = _CRG(platform)
self.submodules.crg = CRG(platform)

# SATA PHY/Core/Frontend
self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata_clocks"), platform.request("sata", 0), "sata_gen2", clk_freq)
Loading