Tuesday, April 1, 2025

Entry 19: Memory Address Register (MAR) and Memory Data Register (MDR)

So, in entry 18 we designed SixteenByFourRam:

This chip is "asynchronous", it has no clock. Therefore, it does not seem right to connect the data bus directly to D and the address directly to A - we cannot be certain that the busses hold the values we need when we need them. 

I investigated this issue further, and it seems that a Memory Address Register (MAR) and a Memory Data Register (MDR) are used to address this particular problem.

Memory Address Register (MAR) and a Memory Data Register (MDR)

So I asked Grok "I am thinking about adding a Memory Address Register and a Memory Data Register to my setup. Can you tell me what these are?":

Adding a Memory Address Register (MAR) and a Memory Data Register (MDR) to your setup is a brilliant next step! These are critical components in computer architecture, including microprocessors like the 8085, and they’ll enhance your 16x4 SRAM system by providing dedicated storage for addresses and data during memory operations. Let’s break down what they are, how they work, and how to integrate them into your current asynchronous design with no clock signal (using D latches).


What Are MAR and MDR?

1. Memory Address Register (MAR)

  • Purpose: Holds the address of the memory location that the RAM wants to access (read from or write to).
  • Function: Acts as a buffer between the address bus and the memory. When you want to access a specific location (e.g., 0010 in your 16x4 RAM), the MAR stores that address temporarily so the memory can use it to select the right row.
  • Size: Matches the address bus width. In your setup, it’s 4 bits (A0–A3) to handle 16 locations.

2. Memory Data Register (MDR)

  • Purpose: Holds the data being read from or written to memory. It serves as a temporary storage for data moving between the CPU/registers and memory.
  • Function: Buffers data on the data bus. When writing, it holds the data to be stored; when reading, it captures the data from memory before it’s used elsewhere (e.g., loaded into a register).
  • Size: Matches the data bus width. In your setup, it’s 4 bits (D0–D3).

Why Add MAR and MDR?

  • Separation of Concerns: MAR isolates address handling from data handling, making your system more organized and scalable, like a real CPU.
  • Improved Control: They allow you to stage memory operations—set the address, then handle the data—reducing bus contention and simplifying timing.
  • Simulation of Real Systems: MAR and MDR are standard in architectures, so adding them brings your setup closer to a modern CPU.

So, the MAR and the MDR are four bit registers, and we can use "FourBitRegister" (see entry 15):

Summary

This is how I understand the connections between RAM, MDR, MAR, and the busses:

  • An address on the address bus can be loaded into MAR, through the D pins, by setting Load = 1. MAR then loads the data on the rising edge of the clock.
  • Data on the data bus can be loaded into MDR, through its D pins, by setting its Load = 1 (also on the rising edge).
  • RAM continuously takes its address from MAR and its data from MDR (no clock).
  • When RAM Load = 1, data on D is stored at address D.
  • When RAM Write = 1, RAM writes the content att address A onto the data bus as well as the address bus. 
  • MAR and MDR can also write to the address bus / data bus by setting its Write = 1.

ACEL connections:

  //Define chips
  auto* ram = new SixteenByFourRam((char*)("SRAM"));
  auto* mdr = new FourBitRegister((char*)("MDR"));
  auto* mar = new FourBitRegister((char*)("MAR"));
  auto* dataBus = new BusLineFour((char*)("Data Bus"));
  auto* addressBus = new BusLineFour((char*)("Address Bus"));


  //Add all chips to be emulated here
  Chip* chips[] = {
    ram, mdr, mar, dataBus, addressBus
  };

  //Add all connections here
  ConnectionBase* connections[] = {
    new ConnectionFour(addressBus->W, mar->D),
    new ConnectionFour(dataBus->W, mdr->D),
    new ConnectionFour(mar->Q, ram->A),
    new ConnectionFour(mdr->Q, ram->D),
    new ConnectionFour(ram->W, addressBus->X),
    new ConnectionFour(ram->W, dataBus->X),
    new ConnectionFour(mar->W, addressBus->X),
    new ConnectionFour(mdr->W, dataBus->X),
  };

We also need to connect the control pins. But first, I need to figure out where to put DIP switches in all of this so that we can program the RAM... in entry 20.


No comments:

Post a Comment