nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 28 Mar 2024 02:42



Reply to topic  [ 193 posts ]  Go to page 1, 2, 3, 4, 5 ... 13  Next
Самодельный процессор nedoRISC-0 (NEDONAND) 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Чего-то перечитывая Lavr-a решил я для начала вместо 16-битного проца с 8-битным АЛУ сделать 8-битный проц с 4-битным АЛУ (эдакий nedoZ80). И делать естественно буду только на NAND из сотен 74F00, что у меня есть. Назвал было этот гипотетический проц "nedoRISC-0", однако потом понял, что это не RISC, а скорее некий недогибрид z80 и 6502. Однако потом таки осознал, что это всё-таки RISC (как минимум в духе PIC-a с двумя стадиями конвейера - эдакий nedoPIC). Так что пусть nedoRISC-0 остаётся как наименование абстрактного процессора и его системы команд, а вот нижеописанная реализация на 74F00 будет называться NEDONAND (кодовое наименование nedoPC-00)...

Последняя версия либ для Logisim v2.7.1 всегда будет тут: http://nedopc.org/nedopc/files/logisim-nedonand.zip

Image

Последняя версия печатных плат для бесплатного Eagle v5.12.0 всегда будет тут:
http://nedopc.org/nedopc/files/eagle-nedonand.zip
И кое-что нарисовано в pcb (gEDA):
http://nedopc.org/nedopc/files/geda-nedonand.zip
Кроме того голые платы можно заказать через OSHPark.com:
https://oshpark.com/profiles/Shaos


Ввиду того, что получение OR через NANDы выглядит тяжеловато, я решил убрать операцию OR из списка команд (а потом и от AND отказался, заменив его на NAND) - оставшиеся операции отдалённо напоминают систему команд nedoRISC-1:
000 - RRC (сдвиг произвольного регистра вправо через флаг C и сохранение результата в аккумуляторе);
001 - RLC (сдвиг произвольного регистра влево через флаг C и сохранение результата в аккумуляторе);
010 - NAN (побитная операция И-НЕ между аккумулятором и произвольным регистром с сохранением результата в аккумуляторе);
011 - XOR (побитная операция исключающее ИЛИ между аккумулятором и произвольным регистром с сохранением результата в аккумуляторе);
100 - ADC (сложение аккумулятора с произвольным регистром с учётом флага C и сохранение результата в аккумуляторе);
101 - SBC (вычитание из аккумулятора произвольного регистра с учётом флага C и сохранение результата в аккумуляторе);
110 - ADI (сложение аккумулятора с 3-битным числом и сохранение результата в аккумуляторе);
111 - SBI (вычитание из аккумулятора 3-битного числа и сохранение результата в аккумуляторе).

Все инструкции будут однобайтовыми:
0xxxxxxx - A=0xxxxxxx (записать в аккумулятор 7-битное число);
10xxxyyy - xxx=yyy (скопировать значение регистра ууу в регистр xxx - если xxx и yyy это один и тот же регистр, то его содержимое инвертируется, а в случае xxx=0 это работа с подпрограммами RST/RET);
11oooxxx - операция АЛУ ooo (см. выше) над регистром (или числом) xxx и аккумулятором () - результат ВСЕГДА сохраняется в аккумуляторе, а также меняются ВСЕ флаги.

Регистры:
000 - 0 (всегда 0)
001 - A (аккумулятор)
010 - B
011 - C
100 - D
101 - E
110 - F (регистр флагов и старших битов адреса)
111 - G (младшие 8 битов программного указателя)

Чтобы передать управление по какому-то адресу придётся загрузить число в аккумулятор и потом скопировать его в регистр G (если же надо перейти за пределы текущей 256-байтовой страницы, то придётся ещё и в регистре флагов кое-какие биты установить)...

Code:
  |  x0 |  x1 |  x2 |  x3 |  x4 |  x5 |  x6 |  x7 |  x8 |  x9 |  xA |  xB |  xC |  xD |  xE |  xF |
--+------------------------------------------------------------------------------------------------
0x| A=0 | A=1 | A=2 | A=3 | A=4 | A=5 | A=6 | A=7 | A=8 | A=9 |A=10 |A=11 |A=12 |A=13 |A=14 |A=15 |
---------------------------------------------------------------------------------------------------
1x|A=16 |A=17 |A=18 |A=19 |A=20 |A=21 |A=22 |A=23 |A=24 |A=25 |A=26 |A=27 |A=28 |A=29 |A=30 |A=31 |
---------------------------------------------------------------------------------------------------
2x|A=32 |A=33 |A=34 |A=35 |A=36 |A=37 |A=38 |A=39 |A=40 |A=41 |A=42 |A=43 |A=44 |A=45 |A=46 |A=47 |
---------------------------------------------------------------------------------------------------
3x|A=48 |A=49 |A=50 |A=51 |A=52 |A=53 |A=54 |A=55 |A=56 |A=57 |A=58 |A=59 |A=60 |A=61 |A=62 |A=63 |
---------------------------------------------------------------------------------------------------
4x|A=64 |A=65 |A=66 |A=67 |A=68 |A=69 |A=70 |A=71 |A=72 |A=73 |A=74 |A=75 |A=76 |A=77 |A=78 |A=79 |
---------------------------------------------------------------------------------------------------
5x|A=80 |A=81 |A=82 |A=83 |A=84 |A=85 |A=86 |A=87 |A=88 |A=89 |A=90 |A=91 |A=92 |A=93 |A=94 |A=95 |
---------------------------------------------------------------------------------------------------
6x|A=96 |A=97 |A=98 |A=99 |A=100|A=101|A=102|A=103|A=104|A=105|A=106|A=107|A=108|A=109|A=110|A=111|
---------------------------------------------------------------------------------------------------
7x|A=112|A=113|A=114|A=115|A=116|A=117|A=118|A=119|A=120|A=121|A=122|A=123|A=124|A=125|A=126|A=127|
---------------------------------------------------------------------------------------------------
8x| RET |RST 1|RST 2|RST 3|RST 4|RST 5|RST 6|RST 7| NOP | A=~A| A=B | A=C | A=D | A=E | A=F | A=G |
---------------------------------------------------------------------------------------------------
9x| B=0 | B=A | B=~B| B=C | B=D | B=E | B=F | B=G | C=0 | C=A | C=B | C=~C| C=D | C=E | C=F | C=G |
---------------------------------------------------------------------------------------------------
Ax| D=0 | D=A | D=B | D=C | D=~D| D=E | D=F | D=G | E=0 | E=A | E=B | E=C | E=D | E=~E| E=F | E=G |
---------------------------------------------------------------------------------------------------
Bx| F=0 | F=A | F=B | F=C | F=D | F=E | F=~F| F=G | G=0 | G=A | G=B | G=C | G=D | G=E |SAEFF|SANFF|
---------------------------------------------------------------------------------------------------
Cx|RRC 0|RRC A|RRC B|RRC C|RRC D|RRC E|RRC F|RRC G|RLC 0|RLC A|RLC B|RLC C|RLC D|RLC E|RLC F|RLC G|
---------------------------------------------------------------------------------------------------
Dx|NAN 0|NAN A|NAN B|NAN C|NAN D|NAN E|NAN F|NAN G|XOR 0|XOR A|XOR B|XOR C|XOR D|XOR E|XOR F|XOR G|
---------------------------------------------------------------------------------------------------
Ex|ADC 0|ADC A|ADC B|ADC C|ADC D|ADC E|ADC F|ADC G|SBC 0|SBC A|SBC B|SBC C|SBC D|SBC E|SBC F|SBC G|
---------------------------------------------------------------------------------------------------
Fx|A=A+0|A=A+1|A=A+2|A=A+3|A=A+4|A=A+5|A=A+6|A=A+7|A=A-8|A=A-7|A=A-6|A=A-5|A=A-4|A=A-3|A=A-2|A=A-1|
---------------------------------------------------------------------------------------------------

P.S. Выше версия таблицы опкодов от 25 февраля 2016 года (0x88 стал NOP, 0x80 стал RET, а 0xBE и 0xBF стали инструкциями SAEFF и SANFF - см. тут)

P.P.S. С февраля веду страничку проекта на Hackaday: https://hackaday.io/project/9795-nedonand-homebrew-computer

P.P.P.S. 19 марта 2016 прикрутил 4-битное АЛУ со схемой сопряжения с 8-битным остальным (см. картинку выше)

P.P.P.P.S. 26 марта 2016 зарелизил NEDONAND LITE, в котором ещё нету SAEFF/SANFF (на их месте всё ещё находятся G=F и G=~G), а RET/RST вводят проц в состояние HALT (надо нажимать на кнопку GO, чтобы оно побежало дальше)

_________________
:dj: https://mastodon.social/@Shaos


11 Jan 2016 23:24
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Флаги (регистр F):
bit 7: S - sign (результат оказался отрицательным);
bit 6: Z - zero (результат оказался нулевым);
bit 5: V - overflow (было переполнение при сложении или вычитании чисел со знаком);
bit 4: C - carry/borrow (был перенос при сложении или небыло заимствования при вычитании);
bit 3: H - half carry (был перенос между нибблами);
bit 2: P10 \
bit 1: P9 - старшие 3 бита программного указателя
bit 0: P8 /

Старшие 5 бит флагов повторяют старшие 5 бит регистра R14 из nedoRISC-1, а младшие 3 бита задают старшие 3 бита адреса программного указателя (младший байт которого хранится в регистре G) - получается, что наш недопроцессор может адресовать 2Кб, что очень даже неплохо...

_________________
:dj: https://mastodon.social/@Shaos


11 Jan 2016 23:32
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Все команды, где в качестве приёмника выступает 0, будут абсолютно бессмысленны - поэтому на месте этих 8 инструкций (с кодами от 0x80 до 0x87) можно предусмотреть какие-то другие операции или даже вызов микропрограмм - эдакий RST с запоминанием адреса возврата (и флагов)...

P.S. Получается, что у нас нету памяти данных - только код. Эту проблему можно решить скажем путём отображения какого-то регистра (скажем E) на внешнюю память в некоторых случаях (скажем если код выполняется в младших 64 байтах) - тогда адрес ячейки, к которой происходит обращение, может задаваться двумя другими регистрами (скажем C и D) - например по команде RST (одной из восьми) управление передаётся в начало памяти и регистр E становится шлюзом во внешнюю память данных - тогда подпрограмма чтения байта по адресу CD может выглядеть так:

10010101 (B=E - скопировать значение из E в регистр B)
10111111 (G=G - этот код может означать возврат из подпрограммы RET с автоматическим восстановлением регистров F и G)

а подпрограмма записи байта из B по адресу CD - так:

10101010 (E=B - скопировать значение из регистра B в E)
10111111 (G=G - возврат из подпрограммы RET)

чтобы передать управление на произвольный адрес нужно максимум 5 байтов (если младший байт адреса >=128):

00000xxx (A=00000xxx)
10110001 (F=A - записать 3 младших бита в регистр F)
0yyyyyyy (A=0yyyyyyy)
10001001 (A=A - инвертировать A, если младший байт адреса должен быть >=128)
10111000 (G=A - в этот момент происходит передача управления по полному адресу, включая 3 младших бита из регистра F)

Значит RST могут идти с шагом 8 байт как в старом добром 8080:

RST0 - 0x000 (25 февраля поставил сюда RET)
RST1 - 0x008
RST2 - 0x010
RST3 - 0x018
RST4 - 0x020
RST5 - 0x028
RST6 - 0x030
RST7 - 0x038

Управление после ребута передаётся на адрес 0x000...

_________________
:dj: https://mastodon.social/@Shaos


11 Jan 2016 23:40
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
По поводу разнообразных вариаций передачи управления:

1) передача управления в первые 64 байта памяти с шагом 8 байт с сохранением адреса возврата и флагов (1 байт):

10000xxx (0=xxx - RST xxx)

2) передача управления в начало текущей 256-байтовой страницы (1 байт):

10111000 (G=0)

3) передача управления в пределах первой половины текущей 256-байтовой страницы (2 байта):

0xxxxxxx (A=0xxxxxxx)
10111001 (G=A)

4) передача управления в пределах второй половины текущей 256-байтовой страницы (3 байта):

0xxxxxxx (A=0xxxxxxx)
10001001 (A=~A - инвертировать A)
10111001 (G=A)

5) передача управления в начало произвольной 256-байтовой страницы (3 байта):

00000xxx (A=00000xxx)
10110001 (F=A)
10111000 (G=0)

6) передача управления в первую половину произвольной 256-байтовой страницы (4 байта):

00000xxx (A=00000xxx)
00110001 (F=A)
0yyyyyyy (A=0yyyyyyy)
00111001 (G=A)

7) передача управления во вторую половину произвольной 256-байтовой страницы (5 байт):

00000xxx (A=00000xxx)
10110001 (F=A)
0yyyyyyy (A=0yyyyyyy)
10001001 (A=~A - инвертировать A)
10111001 (G=A)

P.S. Условная передача управления будет представлять из себя взятие маски от регистра F и затем сдвиг вправо на нужное количество бит, чтобы потом прибавить это к некоему числу и получить адрес перехода по условию...

_________________
:dj: https://mastodon.social/@Shaos


12 Jan 2016 00:44
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Ты б что-нибуть прикинул уже в вентилях. По собственному опыту знаю, когда начинаешь "хотелки" превращать в вентиля,
ой как не гладко оно, порой получается... :osad:

У тебя я сразу вижу один весьма "негладкий" момент:
Quote:
Получается, что у нас нету памяти данных - только код. Эту проблему можно решить скажем путём отображения какого-то регистра (скажем E) на внешнюю память

Нет, он в теории красивый, но вот в вентилях... :-?

И еще один вопрос интересный: по моим прикидкам, как не крути, но в схеме приходится применить хотя бы один тристабильный
буфер. Как ты собираешься "делать естественно только на NAND"?

_________________
iLavr


12 Jan 2016 04:39
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Мультиплексор на NAND-ах я уже прикинул на бумажке :)

А по поводу такого хитровывернутого доступа к памяти данных всё вроде как наоборот проще схемотехнически получается ;)

P.S. Я вот думаю, а не сделать ли вместо сдвига произвольного регистра на 1 бит сдвиг аккумулятора на N бит? Хотя это потребует ещё порядка полусотни корпусов 74F00 - пожалуй ненадо...

_________________
:dj: https://mastodon.social/@Shaos


12 Jan 2016 07:44
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Shaos wrote:
А по поводу такого хитровывернутого доступа к памяти данных всё вроде как наоборот проще схемотехнически получается ;)

Да на словах всё проще схемотехнически получается ;)
Как дело доходит до вентилей... так и - нет. Но - желаю удачи... :wink:

_________________
iLavr


12 Jan 2016 09:43
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Вот прямо сегодня и начну городить вентиля в Logisim-e :roll:

_________________
:dj: https://mastodon.social/@Shaos


12 Jan 2016 10:05
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Shaos wrote:
Вот прямо сегодня и начну городить вентиля в Logisim-e :roll:


Вот две первые "ласточки", нарисованные в Logisim v2.7.1 - простейший D-триггер на NAND-ах (1 корпус 7400):

Image

и 8-входовой мультиплексор на NAND-ах (аналог 74151, но без входа разрешения - 6 корпусов 7400):



P.S. Вот отдельно два "кирпичика", которые я буду использовать чаще всего (чтобы читатель научился их с ходу узнавать в больших схемах) - MUX2:1 (слева) и XOR (справа):

Image Image

P.P.S. Несколько базовых схем одной картинкой (нарисовал 2 марта 2016 года):

Image

_________________
:dj: https://mastodon.social/@Shaos


13 Jan 2016 01:09
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
А вот и один "слайс" АЛУ (6 корпусов 7400), сделанный по мотивам АЛУ на NAND от Lavr-а:



Входы O0,O1,O2 задают код операции. Входы A,B,C - аргументы АЛУ. Входы H и L - соседний старший и соседний младший биты соответственно для операций RRC (000) и RLC (001). Операция 010 выдаёт на DOUT логическое NAND входных аргументов A и B, а операция 011 - XOR. Для операций 100,101,110,111 на выход DOUT просто подаётся сумма с полного сумматора (манипулирование входными аргументами для реализации ADI,SBI,ADC,SBC будет происходить снаружи).

P.S. Поначалу хотел сделать операцию AND, однако в этом случае потребовалось бы на один NAND-гейт больше и оно не влезло бы в ровное количество корпусов 7400 (я хочу каждый "слайс" в отдельной платке сделать) - в результате в системе команд имеем операцию NAND вместо AND и для реализации побитного И между аккумулятором и каким-то регистром придётся инвертировать аккумулятор:
11010rrr ; NAN rrr
10001001 ; A=A (или наверное лучше завести отдельный способ записи такой инверсии, например ~A или A=~A)

P.P.S. Интересно, что для ИЛИ теперь меньше операций потребуется, чем если бы у нас был только AND, например OR между аккумулятором и скажем регистром B делается так:
10001001 ; A=~A
10010010 ; B=~B
11010010 ; NAN B (теперь в аккумуляторе сидит A OR B)
Правда после этого регистре B остаётся с инвертированными битами...

_________________
:dj: https://mastodon.social/@Shaos


13 Jan 2016 02:48
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
А вообще можно весь ассемблер таким сделать - A=A-1, A=A+8, A=B*2 и т д :)
Правда надо помнить, что в некоторых случаях (ADC,SBC,RRC,RLC) учитывается флаг C...
P.S. Как минимум можно так записать команды, где флаг C не учитывается - например вместо ADI 2 писать A=A+2, а вместо SBI 2 - A=A-2

_________________
:dj: https://mastodon.social/@Shaos


14 Jan 2016 14:42
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
А может таки сделать полноценные AND и OR, а вместо двух линеек ADI и SBI сделать одну от A=A-4 до A=A+4?...

P.S. Хотя ладно - пусть пока будет так как есть...

_________________
:dj: https://mastodon.social/@Shaos


14 Jan 2016 20:39
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Вот нагородил 4-битное АЛУ, построенное из четырёх "слайсов" (см. выше) - тут тоже любая арифметическая операция 1xx осуществляет простое сложение 4-битных входных величин A и B (обнуление флага С для ADI/SBI уже есть, а вот инверсию B для SBC надо будет делаться этажом выше) - всего получилось 4*6+6=30 корпусов 7400:



Всё проверил - работает! Всё - это RRC,RLC,NAN,XOR и A+B+C. Кстати тут мне удалось вывести C'=1 в случае логических операций NAN и XOR (в первом варианте C' выводился как при сложении даже для логических операций, т.е. его значение зависело от аргументов)

P.S. В-принципе, можно уже нарисовать и заказать платки "слайсов", которые по приходу можно собрать и воткнуть в бредборду, на которой собрать это 4-битное АЛУ и погонять на разных скоростях, наблюдая за результатом по осциллографу, чтобы оценить пиковое быстродействие...

P.P.S. На самом деле оценить можно прямо сейчас, прикинув задержки в схеме - т.к. один 74F00 гейт в среднем имеет задержку порядка 3.5 нс (5 в худшем случае), то задержка в одном слайсе будет до 9*3.5=31.5 нс (45 в худшем случае), а на всём АЛУ - 4*31.5+4*3.5=140 нс (в худшем случае 180+20=200) или 1/(2*140e-9)=3.5 МГц (в худшем случае 2.5 МГц)!

P.P.P.S. Чуть позже добавил вычисление флага переполнения V', который используется если аргументы сложения и вычитания были со знаком, а в случае неарифметических операций там будет мусор...

P.P.P.P.S. 23 февраля 2016 года добавил пару NAND-гейтов, чтоб выдавать V'=1 только в случае сложений-вычитаний (когда O2=1) и теперь количество корпусов стало ровным - можно разводить платку ;)

P.P.P.P.P.S. 1 марта 2016 года поправил взятие аргумента для сдвигов RRC/RLC (надо было B вместо A), добавил обнуление флага C в случае операций A=A+n и A=A-n, а также сделал вывод наружу сигнала /ZERO, который сигнализирует нулём, что выполняемая операция это RRC, для которой порядок исполнения нибблов должен быть обратный (сначала старший ниббл, потом младший)...

_________________
:dj: https://mastodon.social/@Shaos


14 Jan 2016 22:31
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Shaos wrote:
тут мне удалось вывести C'=1 в случае логических операций NAN и XOR ;)

Хозяин, конечно, барин... но "в случае логических операций", мне что-то помнится, флаг переноса в 0 сбрасывают... нет?

_________________
iLavr


15 Jan 2016 06:18
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Lavr wrote:
Shaos wrote:
тут мне удалось вывести C'=1 в случае логических операций NAN и XOR ;)

Хозяин, конечно, барин... но "в случае логических операций", мне что-то помнится, флаг переноса в 0 сбрасывают... нет?


C'=1 проще ;)
Без этих гейтов на выходе C' выдавал переполнение как при сложении, даже если операция была логическая, то есть оно было то 0, то 1 в зависимости от аргументов :)
А вообще мне надо бы ещё и "overflow" флаг V тут сделать (вумные люди пишут что это просто XOR переполнения из 6 бита и переполнения из 7 бита) - и флаг V тоже вроде как должен обнуляться при логических операциях...

P.S. С другой стороны на V при логических операциях можно наплювать (пусть будет мусор), а C'=1 может оказаться полезной фичей, позволяющей достаточно просто установить флаг C в 1...

_________________
:dj: https://mastodon.social/@Shaos


15 Jan 2016 08:20
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 193 posts ]  Go to page 1, 2, 3, 4, 5 ... 13  Next

Who is online

Users browsing this forum: Bing [Bot] and 23 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.