Запустить 8086 в минимальной обвязке?

8-битные микроконтроллеры и микропроцессоры от Intel и их клоны, а также компьютеры на них построенные

Moderator: Shaos

Vic3Dexe
Doomed
Posts: 370
Joined: 16 Dec 2014 11:58
Location: Киев

Post by Vic3Dexe »

Я обещал верилог и схему - собственно, готово... (более или менее).
По крайней мере, в симуляторе работает. Реализованы 8284, 8288, зачаток декодера адреса и, собственно, сам перестановщик (steer).

Куда посоветуете выложить архив? Желательно, чтобы интересующиеся (если таковые будут) могли скачать без говнорекламы. Ни разу на файлопомойки ничего не клал :)

Пока результат симуляции. Читается слово из порта 0, эталон = 55AAh.
На название "поиск" просьба не обращать внимание, надо же было его как-то назвать :)
Image

Дорисовал вручную такты, чуть правее, чем следовало бы, чтобы не затирало моменты изменения сигналов.
Вверху сигналы 8288, там в общем-то все очевидно, имеем два IORD вместо одного.
С помощью STEER_RDY роняем READY проца, заставляя вставлять Tw.
SELH служит сразу нескольким целям - добавляет через внешний OR единицу к A0 и переключает коммутарторы D15:D8 / D7:D0 <-> BD7:0.
При чтении нужно запомнить младший байт - при переключении коммутаторов во втором "цикле" он с шины пропадет. Поэтому фиксируем его у себя (D_IN -> D_OUT), после чего во втором цикле выставляем на шину. Старший байт поступает прямо с коммутатора, и проц забирает целое слово.
При записи таких проблем нет (проц держит данные на обеих половинках).
Сигнал EXT_DEV эмулирует IO16/MEM16 у ISA-16, т.е. сообщает нам, работаем мы с 8- или 16-битным девайсом (определяется по адресу).

Как выложу архив, напишу описание поподробнее.
newold86
Devil
Posts: 716
Joined: 30 Nov 2013 11:08
Location: WWW

Post by newold86 »

8284 и 8288 насколько полно реализованы ?

Если достаточно полно, откуда брали информацию насчет внутренних деталей работы - что-то помимо datasheets ?
Vic3Dexe
Doomed
Posts: 370
Joined: 16 Dec 2014 11:58
Location: Киев

Post by Vic3Dexe »

Кроме даташитов - ничем, ну разве что Казаринов (МП комплект 1810), но он почти слово в слово повторяет даташит. Ну и гугл, да...
Реализация:
8284 в рамках необходимого - т.е. по эквивалентной схеме (из даташита) сделан канал RDY1 (AEN1, второй канал, F/C, EFI выкинуты за ненадобностью), двойная синхра по READY (фронт/спад), нет генерации PCLK - так и не понял, на кой оно надо. Реализуется, при необходимости, имхо, элементарно. Reset, CLK из OSC - все по даташиту.
8288 - опять же, 1:1 тайминги даташита. В качестве сигналов записи взял AMWTC/AIOWC, так проще было :) Не делал AEN/CEN, точнее, AEN есть, но он внутренний, т.е. не вход, а выход схемы захвата шины от DMA, он же HLDA. Что касается CEN - DT/R при захвате шины DMA не выключаю - смысла нет, DEN все равно буфера задавит. Если очень надо 1:1 с оригиналом - выключить очень легко. DEN, разумеется, отключается, как и командные линии.
PDEN/MCE - выкинуты за ненадобностью.

Собственно, DMA уже почти есть, захват шины отрабатывается, регистры пишутся/читаются, но цикл работы не написан, зацепился за этот перестановщик.

Что касается внутренних деталей - а зачем? Есть ЧЯ, есть тайминги работы. Конечно, интересно было бы посмотреть на работу в нештатных ситуевинах, но я же не космический корабль делаю :) Так - ДОС погрузить, нортоном побаловаться.

Я прошу заметить, что это все исключительно в симуляторе, так что особых надежд не возлагайте :) Железки у меня попросту нету, ни альтеры, ни проца. Буду у китайцев брать в скором времени.
newold86
Devil
Posts: 716
Joined: 30 Nov 2013 11:08
Location: WWW

Post by newold86 »

Наверное, я плохо смотрел, но мне datasheet 8288 не хватило для точной (на мой взгляд) реализации, поэтому плюнул и сделал железно - viewtopic.php?t=10836&postdays=0&postorder=asc&start=15

Кстати, с Нортоном у меня какой-то затык - после загрузки ДОС думал, что все автоматом получится, но не тут то было. Пишет нормально copyright, доходит до вывода нижней строчки, а потом улетает в никуда очень странным образом... Учитывая, что у меня еще и BIOS свой, не до конца написанный, разобраться сходу не получилось. Возиться пока прекратил - времени не хватает...
Mixa64
Doomed
Posts: 481
Joined: 25 Aug 2009 07:02
Location: Москва

Post by Mixa64 »

Vic3Dexe wrote:... AEN1, второй канал, F/C, EFI выкинуты за ненадобностью...
... PCLK - так и не понял, на кой оно надо ...
... взял AMWTC/AIOWC, так проще было :)
... Не делал AEN/CEN ...
... PDEN/MCE - выкинуты за ненадобностью.
Вся эта лабуда ради разбивки по микросхемам и сопряжения их между собой. Ну и для многошинности. Внутри FPGA все по-другому, лишь бы логика работы сохранялась.
Vic3Dexe
Doomed
Posts: 370
Joined: 16 Dec 2014 11:58
Location: Киев

Post by Vic3Dexe »

http://my-files.ru/6exwbt
Собсна, вот. Внутри схема минимальной обвязки в DipTrace + проект под квартус.

О схеме
Не надо это собирать :) Схема более эскиз, нежели принципиальная - просто чтобы было понятно, какой сигнал чем рулит.
RAM нет, она для запуска не нужна. ROM 2 штуки по 32к, на младший и старший байт ШД. Можно обойтись одной 16-битной.
Разъем ISA условен, опять же, чтобы было понятно, что туда выводится.
Генератор OSC - KXO-97 на 30 МГц.

Нет ни защитных буферов, ни согласования 3.3V <-> 5V, ни блокирующих кондеров. Короче, голая логика.

О проекте
В качестве тэзэ я принял 8086-1 в максимальном режиме с возможностью обмена с 8-битной внешней шиной.

"Чипсет" сначала планировал на MAX V (CPLD), но отсутствие встроенной RAM хотя бы байт на 100-200 убило. Регистры DMA превратились в монстрообразную кашу из D-триггеров и коммутаторов, сожрав порядка 300 LE из 1500 доступных в топовом MAX V.
Поэтому переехал на циклон 4, меньшие последний квартус выбрать не дает. Да, из пушки по воробьям. Но это решаемо, я думаю.

Блок 8284 состоит из счетчика, который формирует CLK из OSC, двойной синхронизации READY и синхронизации RESET.
Входов READY три штуки - IORDY (сигнал с шины), DMARDY, его может ронять DMA, когда занимается своими делами, и STEER_RDY, который роняет перестановщик байтов, удлинняя цикл для обмена двумя байтами вместо одного. На вход синхронизатора в 8284 это все заведено через AND.
Вход RESET также является AND 2 входов - от кнопки и PWRGOOD от ATX БП.

Блок 8288.
Главной проблемой, как ни странно, стал момент определения начала цикла. Согласно спецификациям, S0-S2 могут упасть как до начала Т1, так и после. Соотв., ALE начинается от момента "кто позже упадет" - S или CLK. Вроде просто, но объяснить это квартусу я толком не сумел. Надо будет переделать, то, что есть, мне не нравится, хотя и работает.
Для DT_R фактически делается 2 одинаковых по длительности сигнала - один сам DT_R (т.е. падающий в 0 при чтении), второй - DT_R_POS, всегда =1, для формирования сигналов чтения-записи. Есть соблазн получать DT_R из DT_R_POS и сэкономить регистр, но не выйдет, пробовал.
DEN я сразу делаю инверсным (DEN_INV), так как для чтения и записи у него разная длительность, соотв. реально формируются 2 сигнала DEN_R и DEN_W, а результат суммируем по AND.
Отдельная тема INTA. Проц генерит их 2 штуки подряд, выставляя LOCK, дабы чего не вышло. Согласно спекам, DT_R/DEN нужно формировать только для второго INTA, поэтому введен счетчик таковых и учтен.
AEN_INV разрешает работу регистров адреса проца (которые по АЛЕ), встает в 1 только при захвате шины DMA. Для простоты будем считать, что AEN_INV всегда =0, т.е. DMA никогда не получит шину.

Перестановщик (bus steering, далее ПС). Собственно, зачем он нужен - примерно понятно, у проца ШД 16 бит, а на внешней шине - только 8.
Первоначальной идеей было просто генерить 2 полноценных цикла, т.е. ПС перехватывает S0-S2 между процом и 8288, после чего в "T3" на некоторое время подпирает их единицей и через такт снимает, имитируя начало нового цикла. Одновременно с подпиранием меняем A0 шине 0->1 и подсовываем ей старшую половину шины проца.
Сделал так, потом сунул нос в ISA bus architecture, а в 286 чипсете, оказывается, попросту дергают MRD/MWR/IORD/IOWR. Поэтому переделал именно в такой вид, экономия - аж 1 такт.
Попутно наткнулся на проблему: шина проца физически сводится к 8-битной двумя коммутаторами, переключаются которые по SELH. При записи все в порядке - источник (проц) предоставляет данные для обеих половин шины. Однако, при чтении, у нас так или иначе будет источник только для какой-то одной половины шины. Т.е. мы-то прочитаем с шины младший байт, но после переключения коммутаторов на старшую половину, он потеряется. Поэтому просто запоминаем его в FPGA, после чего подсовываем процу во 2 "цикле".

Работа перестановщика основана на счетчике тактов, он считает фронты CLK, как только упали S0-S2, доходит до 11b и более не меняется, обрано в 0 - по фронту S0-S2 либо если отработал "подпиратель" командных сигналов, т.е. мы начали 2 "цикл".
По этому счетчику ориентируется STEER_RDY, пока у нас первый такт, надо что-то быстро предпринять, иначе двойная синхра в 8284 растянет цикл. Поэтому, пока счетчик в 00b, по спаду CLK роняем этот сигнал в первом цикле (SELH = 0) или поднимаем в 1 во втором (SELH = 1). Далее, по следующему спаду, принимаем решение - формировать второй цикл или нет. Почему не сразу? Потому что только здесь A0 и BHE валидны, т.е., проц выставил их на ноги, и они по ALE попали в фиксаторы.
В остальном все просто. Так как адресный декодер работает только с командными сигналами, а не с сырыми S0-S2, он к моменту принятия решения еще не знает, адресуется внешнее устройство (т.е. 8-битное) или нет. Поэтому он исключительно по адресам формирует 2 предположения - EXT_MEM и EXT_IO (пока прибито в 1). Ну а ПС уже учитывает MEM_OP и IO_OP от 8288, т.е. если адрес является внешним для ИО, но не является таковым для памяти, а операция именно с памятью, то ничего не делаем. Результатом всех этих комбинаций является сигнал EXT_DEV, который и пишется с инверсией в STEER_RDY при принятии решения.
Мелочь, а важно. Если проц выполняет 8-битный цикл по старшему байту, нам тоже нужно переключить коммутаторы, что учтено в конечной формуле для SELH.

Разумеется, это все черновик. Но это то, что есть на данный момент, может кому будет интересно.

Как-то так. Извините, если невнятно изъясняюсь, комментарии в коде есть. Если чего - спрашивайте. :)
newold86
Devil
Posts: 716
Joined: 30 Nov 2013 11:08
Location: WWW

Post by newold86 »

Тут интересную особенность обнаружил... Пока не разбирался детально, поэтому причина может быть в чем-то другом, но вроде все просто.

В моем компьютере есть возможность в отладочных целях вызывать NMI при обращении к заданному порту. При очередных разборках поставил команду HLT перед чтением из такого порта, но к моему великому удивлению, NMI все-равно возникает !

Я знал, что HLT не вешает процессор намертво, прерывания (как минимум) остаются, но каким боком процессор читает порт уже ПОСЛЕ выполнения HLT, я пока не понимаю. Ладно бы в "ковейерных" целях он просто прочитал бы код самой команды из памяти, но он ее реально выполняет - как минимум, выставляется адрес порта и формируется /IORC...
jdigreze
God
Posts: 1388
Joined: 02 Jan 2006 02:28
Location: Abakan

Post by jdigreze »

Для интел не подскажу, а для z80: NMI - не маскируемое прерывание, а HALT - ожидание любого прерывания. Т.е. описанная выше ситуация - норма. Возможно для интел тоже.
newold86
Devil
Posts: 716
Joined: 30 Nov 2013 11:08
Location: WWW

Post by newold86 »

Да с обработкой прерывания вопросов нет, есть вопрос, откуда это прерывание взялось ???

У меня оно возникает при обращении к определенному порту, но это обращение в программе находится ПОСЛЕ команды HLT, т.е. до обращения (и, соответственно, прерывания) доходить не должно...

Хотя, пока это писал, вдруг сообразил, что у меня есть еще один источник (уже других) прерываний (таймер), так что, похоже, процессор просто проснулся от них и двинулся дальше к обращению к порту... Чуда не случилось :)
User avatar
VituZz
God
Posts: 1343
Joined: 13 Nov 2010 04:06

Post by VituZz »

Разве после обработки прерывания от таймера проц не должен снова вздремнуть на том же месте, где и был? Или ПП обработки прерывания от таймера завершается некорректно?
User avatar
Lavr
Supreme God
Posts: 16687
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

VituZz wrote:Разве после обработки прерывания от таймера проц не должен снова вздремнуть на том же месте, где и был?
Мне думается, что нет:
В результате выполнения команды HLT микропроцессор переходит в состояние остановки. Из этого состояния его можно вывести сигналами на входах RESET, NMI, INTR. Если для возобновления работы микропроцессора используется прерывание, то сохраненное значение пары cs:ip указывает на команду, следующую за HLT.
По идее там нужен jmp обратно на hlt, чтобы процессор смог "вздремнуть на том же месте, где и был".
iLavr
newold86
Devil
Posts: 716
Joined: 30 Nov 2013 11:08
Location: WWW

Post by newold86 »

Lavr wrote:По идее там нужен jmp обратно на hlt, чтобы процессор смог "вздремнуть на том же месте, где и был".
Именно так. На всякий случай, убрал таймер и проверил - естественно, никаких NMI больше не возникло, так что обнаружение недокументированной особенности 8088 откладываем до следующего раза :)
jdigreze
God
Posts: 1388
Joined: 02 Jan 2006 02:28
Location: Abakan

Post by jdigreze »

В результате выполнения команды HLT микропроцессор переходит в состояние остановки. Из этого состояния его можно вывести сигналами на входах RESET, NMI, INTR. Если для возобновления работы микропроцессора используется прерывание, то сохраненное значение пары cs:ip указывает на команду, следующую за HLT.
Собственно как я предположил - интел работает также как и z80.
User avatar
VituZz
God
Posts: 1343
Joined: 13 Nov 2010 04:06

Post by VituZz »

Lavr wrote:
В результате выполнения команды HLT микропроцессор переходит в состояние остановки. Из этого состояния его можно вывести сигналами на входах RESET, NMI, INTR. Если для возобновления работы микропроцессора используется прерывание, то сохраненное значение пары cs:ip указывает на команду, следующую за HLT.
По идее там нужен jmp обратно на hlt, чтобы процессор смог "вздремнуть на том же месте, где и был".
Но разве после простого выполнения HLT cs:ip не указывает на команду, следующую за HLT? Мне кажется странным такое поведение, когда действие HLT может быть отменено прерыванием после его завершения.
User avatar
Lavr
Supreme God
Posts: 16687
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

VituZz wrote:Но разве после простого выполнения HLT cs:ip не указывает на команду, следующую за HLT?
Ну я не знаю "сложного" выполнения HLT, он, собственно, ничем не отличается от других команд.
Любая команда, во время которой возникло прерывание, сначала заканчивается;
cs:ip, указывающий на команду, следующую за ней, запоминается в стеке, как
адрес возврата из прерывания.
HLT отличается только тем, что останавливает ЦПУ до прерывания или ресета, а в остальном -
он как и все команды.
VituZz wrote:Мне кажется странным такое поведение, когда действие HLT может быть отменено прерыванием после его завершения.
Странным, не странным, но поведение такое, как есть, по логике работы процессора.
Смысл фразы до конца я не очень понял, но никто и не в каких мануалах не обещал
же "вечный HLT" ?
iLavr