Over the past year, I’ve been documenting the design process of an 8-bit CPU in Logisim. With the design work mostly complete, it is time to start getting ready to build this thing for real! With that goal in mind, I spent the last week completely rebuilding the CPU design using NMOS logic built with transistors in Logisim!
*https://www.youtube.com/watch?v=BS8HeMWX2sU
**https://300.ya.ru/summary
таймкоды
00:00:00 Введение
- Майк объясняет, как превратить логическую схему процессора в реальную электрическую цепь с транзисторами.
- Он использовал Logisim для моделирования схем на NMOS-транзисторах.
00:01:30 Цели моделирования
- Моделирование помогает проверить работоспособность конструкции перед физической сборкой.
- Позволяет протестировать аппаратные оптимизации, например, асинхронные адресные регистры и регистр команд.
00:02:30 Преобразование АЛУ
- Майк начал с АЛУ, используя элементы И-НЕ и исключающее ИЛИ-НЕ.
- Заменил элемент И на И-НЕ, а элемент ИЛИ-НЕ — на элемент ИЛИ, что сэкономило транзисторы.
- Применял похожие приёмы для создания XOR-вентиля и мультиплексора.
00:04:25 Регистры и шины
- Создал SR-защёлки, триггеры типа «ведущий-ведомый» и аккумулятор.
- Подключил аккумулятор к шине через вентили И-НЕ с открытым коллектором.
- Добавил 4-битный регистр для флагов АЛУ и два адресных регистра.
- Использовал вторую шину для экономии транзисторов.
00:05:25 Счётчик команд и указатель стека
- Счётчик команд включает схему инкрементатора из модифицированных элементов X NOR.
- Указатель стека может увеличивать и уменьшать значение, используя логику упреждающего переноса.
- Регистр команд идентичен адресным регистрам.
00:06:19 Асинхронный регистр и счётчик шагов
- Асинхронный регистр передаёт значение в декодер кода операции АЛУ и декодер команд.
- Счётчик шагов похож на счётчик команд, но меньше и проще.
- Декодер команд — точная копия логической схемы.
00:07:19 Отключение управляющих сигналов
- Управляющие сигналы отключаются при высоком тактовом сигнале для предотвращения состояния гонки.
- Это предотвращает загрузку неверных данных в регистры.
- Схема загрузки копирует содержимое ПЗУ в ОЗУ.
00:08:17 Триггер переполнения стека
- Добавлен триггер для определения переполнения стека.
- При переполнении стека загорается индикатор.
- Устройства ввода-вывода реализованы с помощью логических элементов.
00:09:14 Проблемы с Logisim и их решение
- Logisim выдаёт ошибку из-за колебаний в схеме.
- Решение: установить максимальное значение «Итерации до стабилизации» и флажок «Добавить шум к задержкам компонентов».
- Сброс схемы и симуляция помогают устранить колебания.
00:10:06 Запуск программы
- Программа Pi computing загружается в ОЗУ и запускается.
- Программа работает медленнее, чем версия LogicGate.
- Выводятся первые пять цифр числа «Пи».
00:11:09 Будущие планы
- Переход к проектированию физической схемы.
- Результаты опроса указывают на предпочтение сборки на печатной плате.
- Схема загружена на GitHub для экспериментов.
In this video
Timeline
Chapters
Transcript
0:00
How do you go from a logic diagram to an
0:02
actual circuit? Stay tuned because today
0:06
we’ll be going over how I turned this
0:08
CPU logic diagram into an actual circuit
0:10
with transistors.
0:13
0:20
0:25
0:30
Hello everyone. My name is Mike and
0:33
you’re watching Polymath Unlimited.
0:36
Those of you who have been following me
0:37
for a while will know that over the past
0:39
year or so, I’ve been documenting the
0:41
design work of an 8-bit CPU in Logisim.
0:45
The goal of this project has always been
0:47
to build this CPU out of real
0:48
transistors. At some point,
0:51
with the design work pretty much done,
0:53
there’s only so much more we can do in
0:54
Logisim before we get to work trying to
0:57
accomplish this goal.
0:59
However, there is one more thing we can
1:01
do in Logisim that will be a huge help
1:03
to us for the physical build.
1:06
Right at the very beginning of this
1:07
project, I made an episode detailing how
1:09
to build logic gates out of physical
1:11
transistors.
1:12
It turns out Logisim has a very handy
1:14
transistor component that makes it very
1:16
straightforward to simulate NOS
1:18
circuits. Ever since I discovered this
1:21
feature though, the question I’ve always
1:22
had was, can you make a whole CPU from
1:25
transistors in Logisim? Turns out yes,
1:28
you can. Over the past week, I have
1:31
painstakingly reconstructed the entire
1:33
logic diagram for the Chameleon CPU into
1:36
transistorized NMOS in Logisim.
1:39
I did this for a couple of reasons.
1:41
Firstly, it is freaking cool. I mean,
1:44
just look at this. You can’t tell me
1:46
that it’s not satisfying to be able to
1:48
physically see almost 2,000 transistors
1:51
all working together to run an actual
1:53
program.
1:55
Secondly, building the NMOS circuitry in
1:57
Logisim will help verify the design
1:59
before I actually build anything for
2:01
real. It would be a shame to go through
2:03
all that work building a bunch of
2:05
physical circuitry only to find out that
2:07
it doesn’t work at the end. Simulating
2:09
the CPU at the transistor level in
2:11
Logisim will help avoid that. And
2:14
finally, building this NMOS version of
2:16
the CPU allowed me to test out some
2:18
hardware optimizations I’ve been
2:19
planning on implementing. For example,
2:22
the address registers and the
2:23
instruction register are now
2:25
asynchronous, meaning they can be built
2:26
using simpler circuitry than a
2:28
synchronous register. I used a similar
2:31
technique for building most of the
2:32
registers in my Sublex CPU that I built
2:34
last summer. I’ll put a link to the
2:36
video I made about that processor in the
2:38
description if you’re interested.
2:41
Anyway, how did I manage to convert the
2:43
entire CPU diagram into transistors?
2:47
Well, just like we did when we were
2:48
designing the CPU’s logic, I started
2:51
with the ALU.
2:53
If we zoom in on the ALOU and compare it
2:55
side by side with the logic gate version
2:57
we built earlier, it should be fairly
2:59
straightforward to see how it was done.
3:02
We can see the NAND and XNOR gates that
3:05
are responsible for enabling the A
3:06
operand and inverting the B operand
3:08
respectively. We can also see the
3:11
chameleon gate which is responsible for
3:13
both selecting and performing a given
3:14
ALOU operation. The only difference here
3:17
is I changed the AND gate to a NANDgate
3:20
and I changed the NOR gate into an
3:22
ORgate which allowed me to change the
3:24
final NOR into an AND. This allowed me
3:26
to simply connect the outputs of the two
3:28
gates together instead of explicitly
3:30
building the final ANDgate which saved
3:32
me a lot of transistors.
3:34
I used some similar tricks when building
3:36
the final XOR gate multiplexer
3:38
combination which handles carry inputs
3:40
and bit shifting for each AO slice. I
3:43
also used the same trick when building
3:45
the AOU’s carry look ahead unit.
3:48
Taking a look at the ALOU flag
3:49
generators, we can also see the NOR gate
3:52
responsible for zero detection, the
3:54
multiplexer responsible for carry
3:56
detection, and the XNOR gate responsible
3:58
for overflow detection.
4:01
It was then a simple matter of just
4:02
hooking together a bunch of NAND gates
4:04
to form the ALOU’s operation decoder.
4:08
Once the ALOU was built and I had
4:10
verified that all of the AOU operations
4:12
were behaving correctly, it was time to
4:14
start building the registers. I started
4:16
by building a simple transistor-based SR
4:19
latch. Adding one more transistor allows
4:22
the set and reset inputs to be
4:23
selectively enabled.
4:26
Connecting two of these together with a
4:27
clock and inverted clock signal creates
4:29
a master slave flip-flop.
4:32
Adding eight of these flip-flops to the
4:33
circuit allowed me to make the
4:35
accumulator. I allowed the accumulator
4:37
to output to the bus by connecting it
4:39
with some open grain NAND gates. I also
4:42
built another 4-bit register to store
4:44
the ALU flags very similarly to how I
4:46
built the accumulator.
4:48
Then I added the two address registers
4:50
each built of some single gated SR
4:52
latches since they didn’t need to be
4:54
synchronous. Instead of building
4:56
Dlatches, which would have required one
4:58
additional transistor per latch, I
5:00
decided to save some transistors by
5:01
adding a second bus, which simply always
5:03
took the inverted value of the data bus.
5:06
I also created the address bus the same
5:09
way as the data bus and allow the
5:10
address registers to output the address
5:12
bus through some more open drain nan
5:14
gates.
5:16
The program counter is pretty similar to
5:18
the accumulator. The only difference is
5:20
that it has an incrementer circuit built
5:22
in to allow it to count through the
5:24
address space.
5:25
This incrementer was made from some
5:27
modified XNOR gates, allowing me to
5:29
incorporate a full carry look ahead unit
5:31
for bothtes of the program counter and a
5:33
surprisingly small amount of
5:34
transistors.
5:36
I also added an additional transistor to
5:38
each latch in the program counter to
5:40
enable me to hook it up to a reset
5:42
signal. The program counter can output
5:45
to both the data bus and the address bus
5:47
through more open drain logic.
5:50
The stack pointer is very similar to the
5:52
program counter, but it has a circuit
5:54
that can both increment and decrement,
5:56
meaning that it needs an extra xorgate
5:58
to handle the decrementing.
6:00
I also added some carry look ahead logic
6:02
to help speed up the incrementer
6:04
decreter circuit. However, due to the
6:07
way I inverted some logic elements, I
6:09
was able to build the carry look ahead
6:10
logic using orgates instead of and
6:12
gates.
6:14
The instruction register is basically
6:16
identical from the address registers.
6:19
It is simply an asynchronous register
6:21
with its value being sent to both the
6:23
ALU’s op code decoder and the
6:25
instruction decoder.
6:27
The step counter is very similar to the
6:29
program counter just smaller and with
6:31
some simplifications due to some program
6:33
counter features that it doesn’t need.
6:35
Its output also goes to the instruction
6:37
decoder.
6:39
The instruction decoder is more or less
6:41
a faithful reproduction of the logic
6:43
diagram. I figured I didn’t want to try
6:45
to mess with this circuit too much since
6:47
it works and it was already pretty well
6:49
optimized to begin with. The most
6:51
notable difference between this NOS
6:53
version and the original logic diagram
6:55
is that some control signals get
6:56
disabled when the clock is high. This is
6:59
because I made some registers
7:00
asynchronous in this version. If I
7:03
didn’t disable the control signals
7:04
related to these registers when the
7:05
clock is high, then there would have
7:07
been a risk of running into race
7:08
conditions.
7:10
This is because immediately after the
7:12
leading edge of the clock signal, many
7:14
signals in the CPU will still be
7:15
stabilizing and will therefore not
7:17
contain correct values. If some of these
7:20
incorrect values accidentally cause an
7:22
asynchronous registered input enabled
7:24
signal to go high, then garbage data
7:26
might be loaded into that register,
7:28
which would corrupt the entire execution
7:29
sequence.
7:31
Disabling the input enabled signals for
7:33
such registers while the clock is high
7:35
is a simple but effective method to
7:36
eliminate that possibility. I already
7:39
did this anyway in the original logic
7:41
diagram for the RAM’s read and write
7:43
signals since the RAM is also
7:45
asynchronous. So, it was a fairly
7:47
straightforward thing to add more such
7:49
logic here to protect the new
7:50
asynchronous registers.
7:52
The boot circuit is also more or less a
7:54
faithful reproduction of the original
7:56
logic diagram. Two latches determine
7:59
whether the CPU is in boot mode or run
8:01
mode. When in boot mode, the CPU simply
8:04
copies the contents of ROM into RAM, and
8:07
the CPU can be placed into boot mode by
8:09
pressing the boot button. The CPU can
8:12
also be reset or be taken out of boot
8:14
mode prematurely by pressing the reset
8:16
button.
8:18
One thing that I did add here that was
8:19
not in the original logic diagram was
8:21
this latch that detects stack overflows.
8:24
If the stack pointer ever counts down
8:26
below zero or if it ever counts up above
8:29
55, then the latch will change state and
8:32
the stack overflow indicator will turn
8:34
on. I figured this would be a useful
8:37
thing to have moving forward, especially
8:38
on the physical build since it will
8:40
allow us to detect stack overflows very
8:42
easily.
8:44
The one area where I cheated a bit and
8:46
used pre-built logic gates instead of
8:47
transistors, was in the IO devices.
8:50
I did this mainly because I’m not
8:52
necessarily planning on building these
8:54
IO devices completely from scratch like
8:55
the rest of the CPU. They only need to
8:58
be mapped to certain memory locations.
9:00
So, these gates handle that effectively.
9:03
With the CPU finished, let’s try running
9:05
an actual program on it. Unfortunately,
9:08
this is a bit less straightforward to do
9:10
here than it was in the original logic
9:12
only implementation.
9:14
For some reason, something about the
9:16
transistor component makes it so that
9:17
Logism freaks out when the circuit first
9:19
opens. is due to oscillations.
9:22
I suspect this happens because of the
9:23
latches we are using. They simply
9:25
oscillate between states rapidly without
9:27
settling into a definite state.
9:30
Since many of the latches are not hooked
9:32
up to a reset signal, there is really no
9:34
easy way to break out of these
9:35
oscillations. Luckily, I was able to
9:38
come up with a fairly straightforward
9:39
workound. When we open up the circuit,
9:42
we’ll go to project options. Then we’ll
9:45
set iterations until oscillation as high
9:46
as it will go. Then check the add noise
9:49
to component delays box.
9:52
Now we can reset the circuit by pressing
9:54
controlr. Then while holding the reset
9:57
button down in the circuit, we enable
9:58
the simulation by pressing control E.
10:01
This will make it so that all of the
10:02
latches connected to the reset signal
10:04
get placed in a definite state. Many of
10:07
the other latches will still be
10:08
oscillating though. But since we have
10:09
added noise to the component delays, we
10:11
can simply reenable the simulation by
10:13
pressing control E again. Some latches
10:16
will still be oscillating, but there
10:17
should be less than the four. Now, we
10:19
can simply keep pressing control E until
10:21
all of the latches have settled into
10:23
definite states. I have found that if we
10:26
keep the noise enabled, then some
10:27
aspects of our CPU’s timing will get
10:29
thrown off. So, after all latches have
10:31
settled, we’ll go back to project
10:33
options and reset them to the default
10:35
settings.
10:38
Now, we can copy a program into our
10:39
CPU’s ROM. I’ve simply copied the Pi
10:42
computing program we wrote a couple of
10:44
weeks ago. If we press boot, wait for
10:47
the program to load into RAM, and then
10:49
press reset [music] once it has, we
10:51
should see that the program runs just
10:53
fine. It does run a bit slower than the
10:55
logic game version. [music] Turns out
10:56
that Logisim runs into some bottlenecks
10:58
when trying to handle almost 2,000
11:00
transistors on the same circuit. But if
11:02
we run the program for a while, we
11:04
should see the first five digits of pi
11:06
[music] get printed to the console.
11:10
Well, we’re at a really exciting point
11:11
in the project with this new Logisim
11:14
circuit. We are ready to start actually
11:15
designing the physical circuitry.
11:18
Earlier this week, I put out a poll so
11:20
that you guys could help me decide which
11:21
approach to take during the [music]
11:22
physical build. And the results of that
11:24
poll seem to indicate that you guys
11:26
would prefer a PCB build. So, we’ll get
11:29
started designing some PCBs in Keycad
11:31
soon. Until then, feel free to play
11:33
around with this circuit. I’ve uploaded
11:36
it to my GitHub and I’ll leave a link to
11:37
that in the description if you want to
11:39
check it out. Thanks for watching.
11:42
Thanks to all of my subscribers and I
11:44
will see you next time.

