@@ 0,0 1,155 @@
+# SPI peripheral
+
+The spi perihperal made here is mainly meant to be used as a peripheral for
+a microcontroller. But it can be used as standalone in fpga, with driving
+logic. Its interface of reception and transmission should be quite a standard
+way - there are valid and ready signals.
+
+Currently master is supported only. The maximum speed to drive the peripheral
+at is `f_clk / 2`, where clk is the input clock frequency. The clk is used
+as the clock throughout the design, no clock domain crossing is introduced.
+
+## Design structure
+
+The blocks in the design are quite simple.
+
+There is `spi_peripheral` that wraps `spi_masterslave`.
+The `spi_masterslave` is meant to hold both slave and master
+controllers. Currently only master controller is implemented.
+
+Apart from that, there is `spi_clkgen` that generates the clock,
+dividing by selected divider. `spi_clkmon` for monitoring the clock,
+as a slave. Then `shift_register` for transmitting and receiving the data.
+Lastly, there is `reg`, as a register for transmitting the data from shift
+register at correct shifting edge.
+
+## Inputs/Outputs
+
+### SPI peripheral
+
+For each spi signal (miso, mosi, sck, csn) there are two outputs and
+one input. One output, \_t, is for making the pin high impedance,
+\_o is the current output of the pin, valid only if \_t is high.
+The \_i is the pin value.
+
+For writing `waddress_i` specifies the address, `wdata_i` is the data to write,
+`write_i` says when to write the data into the address.
+
+For reading, `raddress_i` specifies the address to read from,
+`rdata_i` says the data read on the address. `read_i` says that
+read from an address is performed. The data appear immediately,
+but `read_i` should be asserted, to say the data are read, as
+there are side effects even on reading, specifically in the DATA
+register. A read will empty the rx buffer.
+
+The peripheral also has an interrupt, that is an or from the
+status register, for unmasked status fields.
+
+### SPI masterslave
+
+The master slave also has i/o for spi, same as the peripheral.
+Other inputs and outputs map to what is described in the registers
+below.
+
+## Verification
+
+For verification, cocotb has been used. Cocotb is a Python framework
+for co-simulation, supporting various simulators like ModelSim,
+Vivado simulator or open-source GHDL.
+
+There are numerous tests for the spi_masterslave as well as
+spi_peripheral that uses the registers for transmitting and receiving data.
+
+## Memory mapped peripheral
+
+The peripheral has 4 registers,
+
+: Peripheral registers
+
++----------+---------+---------------------------------------------------+
+| Register | Address | Description |
++==========+=========+===================================================+
+| CTRL | 0 | Control register |
++----------+---------+---------------------------------------------------+
+| INTMASK | 1 | Interrupt masks |
++----------+---------+---------------------------------------------------+
+| STATUS | 2 | Status of the peripheral |
++----------+---------+---------------------------------------------------+
+| DATA | 2 | Received data on read, transmit data on write |
++----------+---------+---------------------------------------------------+
+
+
+: CTRL register fields
+
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Field | Off | Len | Description |
++======================+=====+=====+==================================================================================================================================================================================+
+| EN | 0 | 1 | Enable the peripheral. If disabled, the peripheral won't function and the outputs will be high impedance |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| MASTER | 1 | 1 | Whether to turn on master mode (currently only master supported) |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| TX EN | 2 | 1 | Enable transmission. If disabled, mosi is high impedance. To transmit, you still write to data register |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| RX EN | 3 | 1 | Enable reception. If disabled, no data are filled to rx buffer. |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| CLOCK POL | 4 | 1 | Clock polarity of the clock when not transmitting. |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| CLOCK PHA | 5 | 1 | Phase of the clock, if 0, first edge is sampling, second is shifting. The edge type depends on clock polarity. For clock polarity 0, clock phase 0 means sampling on rising edge |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| LSBFRST | 6 | 1 | What bit to send first, lsb if high |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| SIZE | 10 | 1 | The size of data to select, selected through generic, default is 0 for 8, 1 for 16 |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| DIV | 20 | 3 | The divisor of spi clock. Selected through generic. Default is `clk frequency / 2**(DIV_SEL + 1)` |
++----------------------+-----+-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+If a field in INTMASK register is set to '1', when the corresponding
+field in STATUS register goes high, an interrupt will be fired.
+
+: INTMASK register fields
+
++-----------------+--------+--------+--------------------------+
+| Field | Offset | Length | Description |
++=================+========+========+==========================+
+| RX BUFFER FULL | 0 | 1 | Mask for rx buffer full |
++-----------------+--------+--------+--------------------------+
+| TX BUFFER EMPTY | 1 | 1 | Mask for tx buffer empty |
++-----------------+--------+--------+--------------------------+
+
+: STATUS register fields
+
++-----------------+--------+--------+--------------------------------------------------------------------------+
+| Field | Offset | Length | Description |
++=================+========+========+==========================================================================+
+| RX BUFFER FULL | 0 | 1 | The receive buffer is full, data can be received via DATA register |
++-----------------+--------+--------+--------------------------------------------------------------------------+
+| TX BUFFER EMPTY | 1 | 1 | The transmit buffer is empty, data can be transmitted by writing to DATA |
++-----------------+--------+--------+--------------------------------------------------------------------------+
+| BUSY | 3 | 1 | The peripheral is currently busy transmitting or receiving |
++-----------------+--------+--------+--------------------------------------------------------------------------+
+| LOST RX DATA | 4 | 1 | Data has been lost, since they weren't read in time |
++-----------------+--------+--------+--------------------------------------------------------------------------+
+
+DATA register fields:
+The data register size is based on the format specified in CTRL
+register. If you write to the register, the data will be transmitted,
+if you read, the received data are read. Data can be transmitted
+only if TX_BUFFER\_EMPTY. Data can be received only if
+RX\_BUFFER\_FULL.
+
+## Demonstration
+
+To test the peripheral, Zynq has been used. This repository contains
+both Vivado and Vitis projects. As a demonstration, the Zynq is used
+as an spi master. It has a counter and sends numbers to the slave,
+incrementing by one every second. On STM Nucleo board, a slave has
+been made. This slave receives the number and shows it on a seven
+segment display on Funduino board.
+
+## Project structure
+
+- `hdl_spi/src` - VHDL code describing the spi peripheral itself
+- `hdl_spi/tests` - tests in Python, utilizing cocotb for co-simulation
+- `vivado` - Vivado project, with AXI peripheral wrapper for spi peripheral, for Zynq Z20
+- `vitis` - Vitis projects, utilizing the project from vivado as a platform
+- `stm_spi_funduino` - spi slave on Nucleo, using Funduino board for displaying the numbers