..

RAM

Clocks

Time can be a rather abstract concept, and engineering requires a concrete method of timekeeping.

The clock is a sophisticated component. Below is the exact, rigorous process of making a computer clock:

1. Acquire a Magical Quartz Crystal

[quartz_crystals.png]

2. Apply an electrical charge to the crystal

This makes the crystal vibrate at an incredibly consistent rate.

3. Turn the vibration into an electrical signal

The implementation is left as an exercise for the reader

4. ???

5. Stable, Repeating Signal

[clock_cycle.png]

Each cycle consists of 1 high section and 1 low section.
The time required for one cycle is called the clock’s period (T).
The number of cycles that occur within one second is the clock’s frequency (f).
If there are 100 cycles per second, the clock has a frequency of 100, a.k.a 100Hz (Hertz).

Set-Reset Flip-Flop

Now that we can keep time, we also want to store and update data values at specific moments

The simplest flip flop consists of two NOR gates. It has two inputs and two outputs. The value of Q will always be opposite to Q’. If the set bit is 1, the output of Q will be 1 (and hence Q’=0). If the reset=1, then Q=0. Finally if both input bits are 0, then the outputs remain as they previously were. Having both set and reset bits as 1 simultaneously will break the circuit, and is not allowed.

[s_r_latch.png]

In all of our previous circuits, the outputs solely depend on the input values. These logic circuits are called combinatorial logic circuits.

However, we observe that circuit above is slightly peculiar. Some of the inputs of the NOR gates are connected to the output values of the circuit.

This means that aside from the input values set and reset, the new output of the circuit depends on the current output. This notion of current and new makes the circuit sequential.

It’s slightly confusing trying to figure out its logic at first, but we can break it down into pieces.

Recall the truth table for a single NOR gate

a b out
0 0 1
0 1 0
1 0 0
1 1 0

Consider an example where set = 1 and reset = 0. Assume the current outputs are Q = 0 and Q’ = 1.

  1. The upper NOR gate receives reset = 0 and Q’ = 1, so its new output becomes 0.
  2. The lower NOR gate, with inputs set = 1 and Q = 0, also outputs 0.
  3. Now, with the updated conditions, the upper NOR gate’s inputs become reset = 0 and the new value of Q’ = 0, which causes its output to change to 1.

The inputs to the lower NOR gate are now set=1 and new_Q=1, but this does not change the output, and new_Q’ remains at 0.

The circuit is at a stable state, and the final outputs are new_Q=1 and new_Q’=0.

The other possible configurations follow a similar pattern, and the truth table for the S-R Flip Flop is as follows:

set reset Q Q'
0 0 retain current value retain current value
1 0 1 0
0 1 0 1
1 1 this is not allowed

Level-triggered Data Flip-Flop

The Set-Reset Flip-flop allows us to edit the value of the output, but this only half the battle won. Remember that we want to introduce the time into the circuit. Having the outputs change together with a clock gives us the ability to synchronize changes across many logic circuits within a computer.

The first improvement to our circuit involves the addition of a third input: Load.

[load_sr_flipflop.png]

The load input acts as the gatekeeper to set and reset. By connecting them with a layer of And gates, without load’s approval (load=1) neither set nor reset is allowed to affect the circuit’s outputs.

The next improvement would be to simplify the set and reset inputs into a single input: Data.

![[data_flip_flop.png]] To convince ourselves that this will work, we can consider all possible scenarios:

  1. set=1 and reset=0 is now simplified into data=1
  2. set=0 and reset=1 is now data=0
  3. how can we represent set=0 and reset=0? We can’t. One of the inputs will always be inverted thanks to the Not gate. But this doesn’t really matter. Before, this input configuration will cause the outputs Q and Q’ to remain the same. Now we can achieve the same result my simply setting load=0.
  4. set=1 and reset=1 was strictly forbidden before, and thanks again to the Not gate, it is simply impossible now.

What we have on hand is a flip-flop that takes a data input, and is effected according to the level (1 or 0) or the load input: Level-triggered D-type Flip flop.

Unfortunately this flip-flop has a flaw. Consider the following scenario:

We want to add numbers together and keep a running count of the current total.

Suppose that we have an adder and a flip flop that can store more than 1-bit values. (We actually have made such adders, and it’s easy to apply extend the flip-flop to multiple bits by copy pasting the configuration in parallel).

[infinite_loop.png]

We would operate the circuit by quickly preparing the first value into manual input while the Clk value is 0. When Clk turns to 1, the output of the adder (first value) should be loaded into our flip-flop, and its output goes around and becomes the second input to the adder. During the next iteration of Clk=0 key in the next number into manual input to be added with our first number, giving us the new sum.

Can you spot the problem? The first number is going to added into the flip-flop more than once. In fact, it’s going to to be added a lot more times than once, adding for the entirety of the time Clk remains high (1), as many times as propagation delay will allow it. [repeated_adding.png]

How do we fix this?
Can we reduce the clock period down to the time that only one single add will occur?
Unreliable.
Should we get someone with insane reaction time to manually operate the clock values?
Unaffordable.

Edge-triggered Flip-Flop

What if the addition only occurred during the instant which the clk turns from 0 to 1? (or 1 to 0). This would remove duplicate operations. This transition is referred to as the edge. [one_bit_time_graph.png]

To achieve this, we use two-stages of Level-triggered flip-flops. [edge_triggered_impl.png]

The circuit may seem daunting, but you just have to understand a few key components.

Notice how the Clk acts as the load input for both stages. Crucially, however, the load input to the first stage is inverted. This configuration means that when Clk=0, data will be loaded into the first stage, but blocked from entering the second stage.

When Clk turns to 1, then the data is allowed to be loaded into the second section, and flows through to the final outputs.

Just like that, the edge-triggered mechanism has been implemented. The data is already on standby while clk is still 0, and the moment it turns to 1 the data floods through and is reflected on the output. However, thanks to the inversion of the Not gate, the data is prevented from immediately being loaded back into the first stage, hence avoiding infinite loops.

1-bit memory

The previous flip-flops are only able to store 1 bit of information. For the rest of the chapter, we will focus on scaling up the amount of data we can keep.

First, we simplify the representation of our data flip flops to: [DFF.png] Notice we’ll use Load as the input where Clk normally goes. We do this to control when we make the writes into memory, instead of being at the mercy of the clock’s eternal high and low cycles.

Register

A register behaves in the same way as our 1-bit memory, just with more bits. Registers come in various sizes: 8, 16, 32, 64 bits etc…here we will implement a 16-bit register.

[register.png]

[register_impl.png]

One load bit governs them all.

RAM

Random Access Memory (RAM), is the name of a memory component that supports quick read and writes. To take our first step into RAM, we will use an assemblage of registers with logic gates from previous chapters.

As we continue to increase our memory size, we will naturally require more logic gates. However, one property we wish to maintain is the ability to read and load data from our memory quickly. From all the aforementioned logic circuits, most of them reflect their outputs almost instantly, with the edge triggered flip flops being the most time consuming, requiring one cycle for the load operation to be completed.

What this means is that while registers (which are a group of flip flops), can be scaled in parallel. We must try not to use any more registers sequentially, and build RAM is combinatorial logic such that any delay is minimized.

RAM8

[ram_8.png] Our first baby RAM will be comprised of 8 registers. Its inputs are:

  1. 16-bit data in
  2. load bit
  3. 3-bit address

It’s output will be a 16-bit data out. Perhaps a peculiar point would be the fact that 16-bit data in is much smaller than the whole 8 * 16 = 128 bits of memory in this RAM. This is because we won’t be overwriting the entire RAM during each load operation, but rather a single register.

Then the new address input becomes a bit more obvious. This input allows us to specify which register. Specifically, which register to write when load is asserted, and which register to read when load is not asserted.

Why three bits?

bit1 bit2 bit3 register number
0 0 0 1
0 0 1 2
0 1 0 3
0 1 1 4
1 0 0 5
1 0 1 6
1 1 0 7
1 1 1 8

Because three bits have 8 possible states. n bits have 2n states.

Here is the implementation of an 8-register RAM.

[ram_8_impl.png]

The data input is piped to every register, but the load bit is demultiplexed, selected by the address input. This ensures that if load is asserted, then only the selected register will receive the load bit and be overwritten.

The same address input is as part of the selector in an multiplexer for the output. Notice that if load was asserted, the new value will reflected as the output.

RAM64

Let’s do one more example of scaling RAM even further: 64 registers. [ram_64.png]

64 registers require 6 address bits (26 = 64). The implementation is trivial. [ram_64_impl.png]

The diagram is starting to get messy, but the general idea is straightforward. The first three address bits are used to select which RAM8, and the next three address bits are used to select which register within that RAM8.

more and more and

It’s easy to see how this fractal architecture can scale memory from 64 registers to 512, 4K (212 ), 16K etc… We simply repeat the demultiplexing and multiplexing process.

In this chapter we went through computer clocks, started from a simple S-R flip flop and worked our way up to RAM.

to be continued.

© 2025 Xavier Goh