A memory controller is a digital logic block, either integrated into an SoC/MCU or implemented as a discrete chip, that manages the electrical signaling, timing, addressing, and protocol required to interface a processor or bus master with a specific type of memory (SRAM, DRAM, Flash, SDRAM, etc.). It translates generic read/write requests from the CPU or DMA into the precise command sequences and timing that the memory device requires.
In practice
In bare-metal embedded development, the memory controller most often appears as an on-chip peripheral that must be configured before external memory is usable. On STM32F4/F7/H7 parts, this is the Flexible Memory Controller (FMC) or its predecessor FSMC; on NXP i.MX RT parts it is the SEMC (Smart External Memory Controller); on many Xilinx/AMD and Intel/Altera FPGAs a Memory Interface Generator (MIG) or similar IP block is instantiated. Configuration typically involves setting bus width, address/data setup and hold times, CAS/RAS latency (for SDRAM), and chip-select mapping — all derived from the memory device datasheet. Misconfiguring these timing parameters is one of the most common causes of intermittent read errors or outright system failure when adding external RAM.
For SDRAM specifically, the controller must run a periodic auto-refresh cycle to prevent data loss. On MCUs with an integrated SDRAM controller (such as STM32F746 or STM32H743), the programmer configures the refresh rate register and the hardware issues refresh commands autonomously. On resource-constrained parts without such a controller, SDRAM is generally not viable and SRAM or pseudostatic RAM (PSRAM) is used instead because PSRAM hides the refresh requirement internally.
In FPGA-based designs, a soft or hard memory controller IP block is typically the largest and most timing-critical component added to a design. Hard memory controllers (present in certain Xilinx UltraScale and Intel Stratix/Arria device families, among others) can deliver high bandwidth and are designed to meet the timing requirements of standards such as DDR4 or LPDDR4, though achievable performance depends on the specific device family and speed grade. Soft controllers implemented in fabric logic are more timing-sensitive than hard controllers and may be limited in achievable data rate or supported memory types, though they are used for a range of interfaces including SRAM, Flash, and lower-speed SDRAM or DDR variants; they require careful constraint management. The EmbeddedRelated article "PicoBlaze - Program RAM Access for an Interactive Monitor" illustrates a simple FPGA-based RAM access scheme that depends on the underlying block RAM controller behavior of the target FPGA.
On many small 8-bit and 16-bit MCUs (such as simple PIC, AVR, or MSP430 variants) that have no external bus interface, there is effectively no configurable memory controller — Flash and SRAM are accessed through fixed internal buses with timing fully managed by hardware. Note that some devices in these families do include external memory interfaces or limited memory control configuration. The concept of an explicitly configurable memory controller becomes most relevant when an external memory bus or a specific memory technology (NOR Flash with CFI, NAND Flash, SDRAM) is introduced.
Learn this in FPGA Fundamentals
Frequently asked
What is the difference between a memory controller and a memory bus?
The memory bus is the set of physical signals (address lines, data lines, control lines such as RAS, CAS, WE, OE, CS) that connect the controller to the memory device. The memory controller is the logic block that drives those signals in the correct sequence and with the correct timing. You configure the controller; the bus is the wiring it controls.
Why do I need to configure timing registers in the memory controller? Can I just use the most conservative (slowest) settings?
You can use conservative settings and the interface will likely be functional, but you may leave significant performance on the table. More critically, some timing parameters have a minimum as well as a maximum — for
SDRAM, for example, tRAS (row active time) must not be too short or data will be corrupted, but tRC (row cycle time) also has a minimum that must be met. Always derive timing register values from the memory device datasheet, then verify the resulting waveforms match the device's AC specifications.
Does the memory controller affect execution speed when code runs from external RAM or Flash?
Yes, significantly. External memory access through a controller typically adds wait states relative to internal SRAM. On an STM32H7 running at 480 MHz accessing external
SDRAM via the FMC, latency is multiple CPU cycles per access. Code executing from external memory therefore runs slower than from internal Flash or tightly coupled memory (TCM). Most designs copy critical code sections or ISRs to internal SRAM at startup to avoid this penalty.
What is a PSRAM and how does it simplify the memory controller requirement?
PSRAM (pseudostatic RAM) is a memory device that presents an SRAM-like interface to the outside world while internally managing its own refresh, typically by integrating refresh control logic alongside a DRAM array (though implementations vary across vendors). Because refresh is handled internally, the memory controller does not need to issue periodic auto-refresh commands or handle the
SDRAM initialization sequence. This makes PSRAM usable with simple asynchronous SRAM controllers available on many mid-range MCUs, at the cost of somewhat higher latency and price compared to raw SDRAM of the same density.
On STM32 parts, what is the difference between FSMC and FMC?
FSMC (Flexible Static Memory Controller) is found on older STM32 families such as STM32F1, F2, and some F4 subfamilies, and supports NOR/PSRAM, NAND Flash, and PC Card interfaces but not
SDRAM. FMC (Flexible Memory Controller), introduced on STM32F42x/F43x and used on F7, H7, and others, adds SDRAM support and wider bus options while retaining the static memory interfaces. Register layouts differ enough that driver code written for FSMC usually requires modification before it works with FMC.
Differentiators vs similar concepts
A memory controller is sometimes confused with a memory management unit (MMU) or a memory protection unit (MPU). An MMU translates virtual addresses to physical addresses and enforces access permissions at the OS level; an MPU enforces region-level access permissions without virtual addressing. Neither the MMU nor the MPU deals with the electrical signaling or refresh timing of the memory device itself — those are the memory controller's responsibilities. The three blocks can all be present simultaneously on a complex SoC: the MMU/MPU operates at the logical level above the bus, and the memory controller operates at the physical level below it.