Skip to content

Repository files navigation

eMMC Controller IP

FPGA IP core for Embedded MultiMediaCard (eMMC) interface controller.

Overview

Embedded Multi-Media Card (eMMC) is a type of non-volatile storage solution widely used in mobile devices, automotive systems, and embedded applications. It integrates NAND flash memory and a flash memory controller into a single package, providing a compact, cost-effective, and standardized storage interface.

The Lattice eMMC Controller IP is a soft IP block that implements the host-side JEDEC eMMC protocol, bridging an SoC's system bus to an external eMMC device over a 1/4/8-bit MMC interface. It manages the entire transaction lifecycle—command and response sequencing and data transfers. The IP provides memory-mapped control and status registers on standard APB interface, and AXI4 Manager interface for data transfer.

Features

  • JEDEC JESD84-B51A standard support
  • Data IO width: x1, x4, x8 support
  • AMBA AXI4 Manager bus interface for data transfer
  • AMBA APB bus interface for CSR access
  • eMMC clock frequencies up to 52 MHz, Single Data Rate
  • Programmable clock divider
  • Internal FIFO for data buffering (configurable depth)
  • Interrupt support
  • Optional IO primitive integration

Limitations / Not Yet Implemented

Higher data rate as well as DDR mode is currently not supported and may be added in the future.

FeatureStatusDescription
DDR ModeNot ImplementedDouble Data Rate transfers
HS200Not ImplementedHigh Speed 200 MB/s mode
HS400Not ImplementedHigh Speed 400 MB/s mode
Boot ModeNot ImplementedeMMC boot partition access

Current Maximum Speed: 52 MB/s (High Speed SDR mode)

Quick Facts

CategoryItemValue
IP RequirementsSupported FamiliesLAV-AT (Lattice Avant), LFCPNX (CertusPro-NX), LFD2NX (Certus-NX), LIFCL (CrossLink-NX), LFMXO5 (MachXO5-NX)
Supported User InterfaceAXI4 or AHBL (Data), APB (CSR)
Design Tool SupportMin Radiant Version2025.1
Min Propel Version2025.1
SynthesisSynopsys Synplify Pro for Lattice, Lattice Synthesis Engine
IP CoreVersion1.0.0
CategoryProcessors, Controllers and Peripherals

Resource Utilization

Sample resource utilization using LFMXO5-100T device with default configuration:

ResourceCount
Slices1,613
Registers1,417
LUTs1,877
EBR (Block RAM)2

Note: Resource utilization varies based on configuration parameters (FIFO depth, bus width, etc.)

Validation Status

Test TypeStatusDetails
RTL Simulation✓ PassedFunctional verification with eMMC device model
Hardware Testing✓ PassedBasic commands validated on Sentry DC-SCM Board with MachXO5D (XO5D)
STA Timing✓ MetStatic timing analysis passed at 100 MHz

User Interfaces

User InterfaceSupported ProtocolsDescription
CSR Interface (Subordinate)APBUsed to configure the IP core and control the IP to send eMMC commands. Register map is 1 KiB.
Data Interface (Manager)AXI4, AHBLUsed to move data blocks from local system memory to eMMC device or vice versa. 32-bit address, 32-bit data. Selectable via GUI.

Note: AHB-Lite (AHBL) data interface is available but not as extensively tested as AXI4. When using AHBL, the AXI4 ports are tied off internally.

Register Map

The eMMC Controller provides memory-mapped registers accessible via the APB interface. Register addresses are byte offsets (DWORD aligned).

Address Map Overview

OffsetRegisterAccessDescription
0x00IDRIP Identification (0x4C534343 = "LSCC")
0x04INT_ENAR/WInterrupt Enable
0x08CFG0R/WConfiguration 0 (clock, IO)
0x0CCFG1R/WConfiguration 1 (timeouts)
0x100INFO_STSRInformation Status
0x104INT_STSR/W1CInterrupt Status
0x108RSP_DAT0RResponse Data 0 (command index + status)
0x10CRSP_DAT1RResponse Data 1
0x110RSP_DAT2RResponse Data 2
0x114RSP_DAT3RResponse Data 3
0x118RSP_DAT4RResponse Data 4
0x200SOFT_RSTR/WSoft Reset Control
0x204INT_SETWInterrupt Set (debug)
0x208SRC_DST_ADDRR/WDMA Source/Destination Address
0x20CCTRL0R/WControl 0 (block size/count)
0x210CTRL1R/WControl 1 (command argument)
0x214CTRL2R/WControl 2 (command trigger)

CFG0 - Configuration Register 0 (Offset: 0x08)

BitFieldAccessDefaultDescription
[31:22]reservedRO0Reserved
[21:20]io_widthR/W0Data IO width: 0=x1, 2=x4, 3=x8
[19:18]reservedRO0Reserved
[17]ddr_modeR/W0DDR mode: 0=SDR, 1=DDR (requires EN_DDR_MODE)
[16]pp1_od0R/W0IO drive mode: 0=Open-Drain, 1=Push-Pull
[15:0]clk_divR/W*Clock divider. eMMC CLK = clk_i / (2 × clk_div). 0=divide by 1

* Default clk_div is calculated from system clock to achieve ~400 KHz initial eMMC clock.


CFG1 - Configuration Register 1 (Offset: 0x0C)

BitFieldAccessDefaultDescription
[31:24]reservedRO0Reserved
[23:16]dat_timeoutR/W0Data timeout in multiples of 32 eMMC clocks
[15:8]reservedRO0Reserved
[7:0]cmd_timeoutR/W0Command timeout in multiples of 32 eMMC clocks

Timeout calculation: timeout_cycles = 32 × (value + 1) eMMC clock cycles


INT_ENA - Interrupt Enable Register (Offset: 0x04)

BitFieldAccessDefaultDescription
[31:22]reservedRO0Reserved
[21]dat_timeoutR/W0Enable data timeout interrupt
[20]cmd_timeoutR/W0Enable command timeout interrupt
[19]bus_rd_errR/W0Enable bus read error interrupt
[18]bus_wr_errR/W0Enable bus write error interrupt
[17]dat_crc_errR/W0Enable data CRC error interrupt
[16]cmd_crc_errR/W0Enable command CRC error interrupt
[15:1]reservedRO0Reserved
[0]cmd_doneR/W0Enable command done interrupt

INT_STS - Interrupt Status Register (Offset: 0x104)

BitFieldAccessDefaultDescription
[31:22]reservedRO0Reserved
[21]dat_timeoutR/W1C0Data timeout occurred
[20]cmd_timeoutR/W1C0Command response timeout
[19]bus_rd_errR/W1C0AXI4 bus read error
[18]bus_wr_errR/W1C0AXI4 bus write error
[17]dat_crc_errR/W1C0Data CRC mismatch
[16]cmd_crc_errR/W1C0Command CRC mismatch
[15:1]reservedRO0Reserved
[0]cmd_doneR/W1C0Command completed successfully

R/W1C: Write 1 to clear the corresponding bit.


INFO_STS - Information Status Register (Offset: 0x100)

BitFieldAccessDefaultDescription
[31:24]debug_dat_oeRO-Data IO output enable (emmc_dat_oe_o)
[23:16]debug_dat_oRO-Data IO output (emmc_dat_o)
[15:8]debug_dat_iRO-Data IO input (emmc_dat_i)
[7]reservedRO0Reserved
[6]debug_cmd_oeRO-Command IO output enable
[5]debug_cmd_oRO-Command IO output
[4]debug_cmd_iRO-Command IO input
[3:1]reservedRO0Reserved
[0]emmc_busyRO0Controller busy: 0=Idle, 1=Transaction in progress

SOFT_RST - Soft Reset Register (Offset: 0x200)

BitFieldAccessDefaultDescription
[31:2]reservedRO0Reserved
[1]emmc_rstR/W0Assert eMMC device reset (emmc_rst_n_o)
[0]ip_core_rstR/W0Reset IP core logic (self-clearing)

SRC_DST_ADDR - Source/Destination Address Register (Offset: 0x208)

BitFieldAccessDefaultDescription
[31:0]addressR/W0System memory address for DMA transfers

CTRL0 - Control Register 0 (Offset: 0x20C)

BitFieldAccessDefaultDescription
[31:16]num_blocksR/W0Number of data blocks (0=no data, 1=1 block, etc.)
[15:4]reservedRO0Reserved
[3:0]block_lenR/W*Block length: 2^block_len bytes (9=512 bytes)

* Default block_len is log2(DEF_BLOCK_SIZE).


CTRL1 - Control Register 1 (Offset: 0x210)

BitFieldAccessDefaultDescription
[31:0]cmd_argR/W032-bit command argument

CTRL2 - Control Register 2 (Offset: 0x214)

BitFieldAccessDefaultDescription
[31:15]reservedRO0Reserved
[14:12]rsp_typR/W0Response type: 0=none, 1=R1, 2=R2, 3=R3, 4=R4, 5=R5
[11]send_stopR/W0Send CMD12 (stop) after data transfer
[10]send_deselectR/W0Send CMD7 deselect after command
[9]send_selectR/W0Send CMD7 select before command
[8]cmd_bootR/W0Boot mode command (not implemented)
[7]cmd_startW0Write 1 to trigger command (self-clearing)
[6]reservedRO0Reserved
[5:0]cmd_idxR/W0eMMC command index (0-63)

RSP_DAT0-4 - Response Data Registers (Offset: 0x108-0x118)

RegisterOffsetDescription
RSP_DAT00x108[5:0] Command index from response
RSP_DAT10x10CResponse bits [31:0]
RSP_DAT20x110Response bits [63:32]
RSP_DAT30x114Response bits [95:64]
RSP_DAT40x118Response bits [127:96]

For R2 (136-bit) responses, all RSP_DAT registers contain valid data. For shorter responses (R1, R3, etc.), only RSP_DAT0 and RSP_DAT1 are relevant.

Programming Sequence

Initialization

  1. De-assert reset (rst_n_i = 1) and wait at least 4 clock cycles
  2. Configure clock divider in CFG0 for ~400 KHz initial clock
  3. Set IO mode to Open-Drain (pp1_od0 = 0) and x1 width (io_width = 0)
  4. Assert emmc_rst_n_o via SOFT_RST if needed
  5. Send CMD0 (GO_IDLE_STATE) to reset the eMMC device
  6. Send CMD1 (SEND_OP_COND) repeatedly until device is ready
  7. Send CMD2 (ALL_SEND_CID) to get device CID
  8. Send CMD3 (SET_RELATIVE_ADDR) to assign RCA

Sending Commands

  1. Write command argument to CTRL1 (cmd_arg)
  2. Configure CTRL0 if data transfer is needed (num_blocks, block_len)
  3. Configure CTRL2 with command index and response type
  4. Write 1 to cmd_start bit in CTRL2 to trigger command
  5. Wait for cmd_done interrupt or poll INFO_STS[0] for busy status
  6. Read response from RSP_DAT registers if applicable
  7. Check INT_STS for any errors

Data Read Operation

  1. Configure SRC_DST_ADDR with destination memory address
  2. Set CTRL0: num_blocks and block_len
  3. Send CMD17 (READ_SINGLE_BLOCK) or CMD18 (READ_MULTIPLE_BLOCK)
  4. Wait for cmd_done interrupt
  5. Data is automatically transferred via AXI4 to the configured address

Data Write Operation

  1. Configure SRC_DST_ADDR with source memory address
  2. Set CTRL0: num_blocks and block_len
  3. Send CMD24 (WRITE_BLOCK) or CMD25 (WRITE_MULTIPLE_BLOCK)
  4. Wait for cmd_done interrupt
  5. Data is automatically transferred via AXI4 from the configured address

Switching to High Speed Mode

  1. Complete initialization sequence
  2. Send CMD6 (SWITCH) to set HS_TIMING in EXT_CSD
  3. Update CFG0 clock divider for higher frequency (up to 52 MHz)
  4. Set IO mode to Push-Pull (pp1_od0 = 1)
  5. Optionally switch to x4 or x8 bus width via CMD6

Clocking

The eMMC Controller IP has a single input clock operating at up to 200 MHz. The IP generates the eMMC clock using internal clock divider. The eMMC clock frequency depends on the divider setting (clk_div):

  • eMMC Clock = Input Clock, when clk_div = 0
  • eMMC Clock = Input Clock / (2 × clk_div), when clk_div ≥ 1

For example, if the input clock is 200 MHz and the divider setting is 2, then the eMMC clock frequency is 50 MHz.

Reset

The eMMC Controller IP provides:

  • Hardware Reset (rst_n_i) - Asynchronous active-low reset for the entire IP including CSR. Minimum pulse width is one clock cycle.
  • IP Core Reset - Soft reset that resets the eMMC Controller logic except the CSR block
  • eMMC Target Reset - Resets the target device through emmc_rst_n_o

After de-asserting reset, wait for at least four clock cycles before starting any transaction.

Directory Structure

emmc_controller/
├── rtl/ # RTL source files (12 files)
├── testbench/ # Testbench files
├── sim/ # Simulation scripts
├── doc/ # Documentation (introduction.html)
├── driver/ # C driver files
├── plugin/ # Tool plugins
├── example_design/ # Example Propel SoC project
├── constraints/ # IP level constraints
├── scripts/ # Release and utility scripts
├── hooks/ # Git hooks
├── metadata.xml # IP metadata
├── settings.xml # IP parameter settings
├── ports.xml # IP port definitions
├── rtl_params.xml # RTL parameters
├── bus_interface.xml # Bus interface definitions
├── memory_map.xml # Memory map definitions
├── address_space.xml # Address space definitions
├── IP Release Notes.md # Revision history
├── QUICKSTART.md # Getting started guide
└── README.md # This file

RTL Files

FileDescription
lscc_emmc_controller.vTop-level wrapper
emmc_top.vCore controller top
emmc_csr.vControl/Status registers (APB subordinate)
emmc_cmd_proc.vCommand processor
emmc_axi4_m.vAXI4 manager interface
emmc_ahbl_m.vAHB-Lite manager interface
emmc_apb_s.vAPB subordinate interface
emmc_fifo.vData FIFO
emmc_clkgen.vClock generator/divider
emmc_serdes.vSerializer/Deserializer
emmc_serdes_top.vSERDES top wrapper
emmc_iologic.vIO logic primitives

IP Configuration Parameters

The following parameters are configurable through the Radiant IP Catalog GUI. Default values are shown in bold.

User Interface

AttributeValuesDescription
CSR Interface (Target)APBMain interface to configure and control the IP registers (informational).
Enable Full CSR Address DecodingChecked, UncheckedIf enabled, register address is decoded using full 32-bit address. If disabled, only lower 10 bits are decoded. Disable for Propel-based designs where address space is automatically allocated.
Register Map: APB Base Address (32b Hex)0x00000000 – 0xFFFFFC00Starting address of register space (1 KiB aligned). Only editable when full address decoding is enabled.
Data Interface (Controller)AXI4, AHBLInterface used by IP to move data between eMMC device and system memory.
AXI4 Bus ID Width1 – 12Width of AXI4 transaction ID signals. Only visible when Data Interface is AXI4.
FIFO Depth512, 1024, 2048, 4096, 8192Depth of data interface FIFO in bytes. Options depend on maximum block size.
FIFO ImplementationLUT, EBR, HARD IPFIFO memory implementation type. Available options depend on device family.

Capabilities

AttributeValuesDescription
Enable Double Transfer RateUncheckedDDR mode support (not yet implemented, always disabled).
Max Number of Data LanesX1, X4, X8Maximum data IO width. X1=1-bit, X4=4-bit, X8=8-bit bidirectional data pins.
Minimum Block Size Supported (Bytes)256 – 16384, 512Minimum block size in bytes. Affects internal counter and register width.
Maximum Block Size Supported (Bytes)256 – 16384, 1024Maximum block size in bytes. Affects internal counter and register width.
Default Block Size (Bytes)512Default block size (informational, calculated from min block size).
Maximum Number of Blocks in Single Transfer3, 7, 15, 31, 63, ..., 65535Maximum blocks per read/write command. Affects internal counter and register width.
eMMC Maximum Speed (MBps)1 – 52Maximum device speed in MB/s. Affects clock frequency range and divider width.

Clock Configuration

AttributeValuesDescription
System Clock Frequency (MHz)2 – 200, 100System clock (clk_i) frequency. Range depends on eMMC maximum speed.
Internal Clock Frequency (MHz)(calculated)Same as system clock frequency (informational).
Minimum eMMC Clock Frequency (KHz)10 – 400Minimum eMMC clock frequency for initialization. Affects clock divider width.
Default eMMC Clock Pulse Width0 – varies, 125Default clock divider value. 0=same as clk_i, 1=divide by 2, 2=divide by 4, etc.
Default eMMC Clock Frequency (MHz)(calculated)Calculated as clk_i/(2×pulse_width) or clk_i if pulse_width=0 (informational).
Default eMMC Clock Period (ns)(calculated)Calculated from default eMMC clock frequency (informational).

IO Primitive

AttributeValuesDescription
Include IO PrimitiveChecked, UncheckedWhen enabled, eMMC command and data pins are bidirectional IO at top level (emmc_cmd_io, emmc_dat_io). When disabled, tristate control signals are exposed as separate ports (emmc_cmd_i/o/oe, emmc_dat_i/o/oe).

RTL Parameters

These parameters are passed to the Verilog module and are derived from the GUI settings above.

ParameterTypeDefaultDescription
DEVICE_FAMILYstring(auto)Target FPGA family (from device selection)
SIMULATIONint0Enable simulation mode
DATA_INTERFACEstring"AXI4"Data interface type ("AXI4" or "AHBL")
CSR_INTERFACEstring"APB"CSR interface type
CLKI_FREQreal100.0System clock frequency (MHz)
MAX_NUMLANEint8Maximum data lanes (1, 4, or 8)
DEF_BLOCK_SIZEint512Default block size (bytes)
MIN_BLOCK_SIZEint512Minimum block size (bytes)
MAX_BLOCK_SIZEint1024Maximum block size (bytes)
MAX_NUM_BLOCKint32Maximum blocks per transfer (gui_max_num_blk + 1)
FIFO_DEPTHint512FIFO depth in bytes
MEM_IMPLstring"HARD_IP"Memory implementation ("HARD_IP", "EBR", "LUT")
AXI4_TID_WIDTHint1AXI4 transaction ID width (1–12)
CLKDIV_WIDint(calc)Clock divider register width (calculated from clock settings)
SPI_SCKDIVint125Default clock divider value
USE_CLKDIV1int(calc)Enable divide-by-1 mode (1 if min divider is 0)
USE_IO_PRIMITIVEint1Include internal IO primitives (0 or 1)
EN_DDR_MODEint0Enable DDR mode (not implemented)
EN_FULLADDR_DECODEint0Enable full 32-bit address decoding
REG_BASE_ADDR32-bit32'h00000000Register block base address
TMR_WIDTHint8Timeout timer width (bits)

Port Descriptions

System Clock and Reset

SignalDirectionDescription
clk_iInputSystem clock. Maximum frequency is 200 MHz.
rst_n_iInputAsynchronous active-low reset. Minimum pulse width is one clock cycle. After de-asserting reset, wait at least 4 clock cycles before starting any transaction.

eMMC Interface

SignalDirectionWidthDescription
emmc_clk_oOutput1eMMC output clock. Generated by the IP, synchronous to command and data transfers. Idle state is low.
emmc_rst_n_oOutput1Asynchronous active-low reset to eMMC device. Controlled by programmable register. Default state is high.
emmc_dat_ds_iInput1Data strobe input from eMMC device (for HS400 mode - not yet implemented).

With Internal IO Primitives (USE_IO_PRIMITIVE=1):

SignalDirectionWidthDescription
emmc_cmd_ioInout1Bidirectional command channel. Open-drain for initialization, push-pull for fast transfers. Default state is tri-stated (device pull-up makes it high).
emmc_dat_ioInout[MAX_NUMLANE-1:0]Bidirectional data channels (DAT0-DAT7). Push-pull mode. Width depends on MAX_NUMLANE parameter (1, 4, or 8). Default state is tri-stated.

With External IO Primitives (USE_IO_PRIMITIVE=0):

SignalDirectionWidthDescription
emmc_cmd_iInput1Command input from external IO buffer
emmc_cmd_oOutput1Command output to external IO buffer. Default state is high.
emmc_cmd_oe_oOutput1Active-high command output enable. Default state is low.
emmc_dat_iInput[MAX_NUMLANE-1:0]Data input from external IO buffer
emmc_dat_oOutput[MAX_NUMLANE-1:0]Data output to external IO buffer. Default state is high.
emmc_dat_oe_oOutput[MAX_NUMLANE-1:0]Active-high data output enable. Default state is low.

Interrupt

SignalDirectionDescription
int_oOutputLevel-sensitive active-high interrupt. Asserts when any enabled interrupt status bit is set.

AXI4 Manager Interface (Data Transfer)

Write Address Channel:

SignalDirectionWidthDescription
m_axi4_awready_iInput1Write address ready
m_axi4_awvalid_oOutput1Write address valid
m_axi4_awid_oOutput[AXI4_TID_WIDTH-1:0]Write transaction ID
m_axi4_awaddr_oOutput32Write address (DWORD aligned)
m_axi4_awlen_oOutput8Burst length
m_axi4_awsize_oOutput3Burst size (fixed: 2 = 4 bytes)
m_axi4_awburst_oOutput2Burst type (fixed: 1 = INCR)
m_axi4_awprot_oOutput3Protection (tied to 0)

Write Data Channel:

SignalDirectionWidthDescription
m_axi4_wready_iInput1Write data ready
m_axi4_wvalid_oOutput1Write data valid
m_axi4_wdata_oOutput32Write data
m_axi4_wstrb_oOutput4Write strobes
m_axi4_wlast_oOutput1Last write data in burst

Write Response Channel:

SignalDirectionWidthDescription
m_axi4_bready_oOutput1Write response ready
m_axi4_bvalid_iInput1Write response valid
m_axi4_bid_iInput[AXI4_TID_WIDTH-1:0]Write response ID
m_axi4_bresp_iInput2Write response status

Read Address Channel:

SignalDirectionWidthDescription
m_axi4_arready_iInput1Read address ready
m_axi4_arvalid_oOutput1Read address valid
m_axi4_arid_oOutput[AXI4_TID_WIDTH-1:0]Read transaction ID
m_axi4_araddr_oOutput32Read address (DWORD aligned)
m_axi4_arlen_oOutput8Burst length
m_axi4_arsize_oOutput3Burst size (fixed: 2 = 4 bytes)
m_axi4_arburst_oOutput2Burst type (fixed: 1 = INCR)
m_axi4_arprot_oOutput3Protection (tied to 0)

Read Data Channel:

SignalDirectionWidthDescription
m_axi4_rready_oOutput1Read data ready
m_axi4_rvalid_iInput1Read data valid
m_axi4_rid_iInput[AXI4_TID_WIDTH-1:0]Read response ID
m_axi4_rdata_iInput32Read data
m_axi4_rresp_iInput2Read response status
m_axi4_rlast_iInput1Last read data in burst

AHB-Lite Manager Interface (Alternative Data Transfer)

SignalDirectionWidthDescription
m_ahbl_hsel_oOutput1AHB select
m_ahbl_haddr_oOutput32Address
m_ahbl_htrans_oOutput2Transfer type
m_ahbl_hwrite_oOutput1Write enable
m_ahbl_hsize_oOutput3Transfer size
m_ahbl_hburst_oOutput3Burst type
m_ahbl_hprot_oOutput4Protection
m_ahbl_hmastlock_oOutput1Locked transfer
m_ahbl_hwdata_oOutput32Write data
m_ahbl_hready_iInput1Transfer done
m_ahbl_hresp_iInput1Transfer response
m_ahbl_hrdata_iInput32Read data

Note: AHB-Lite interface is available in RTL but not fully validated.

APB Subordinate Interface (CSR Access)

SignalDirectionWidthDescription
s_apb_psel_iInput1APB select. Indicates target is selected for data transfer.
s_apb_penable_iInput1APB enable. Indicates second cycle of APB transfer.
s_apb_pwrite_iInput1APB write. 0=Read, 1=Write.
s_apb_paddr_iInput32APB address (DWORD aligned).
s_apb_pwdata_iInput32APB write data.
s_apb_prdata_oOutput32APB read data.
s_apb_pready_oOutput1APB ready. Indicates transfer completion.
s_apb_pslverr_oOutput1APB error response.

Getting Started

See QUICKSTART.md for step-by-step instructions.

Documentation

  • doc/introduction.html - IP introduction for Radiant catalog
  • This README contains the complete register map and usage information

References

  • JEDEC JESD84-B51A - Embedded Multi-Media Card (eMMC) Electrical Standard

Version

v1.0.0

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages