2,5МГц , 5МГц, 10МГц в принципе достаточно.
Ставить можно две ОЗУ для двух плоскостей, а там уж у кого какие есть - варианты от 2х64к (128кб) до 2х512кб (1024), просто развести два места по 32 ноги. Ну или промежуточные типа 128+512.
Вид для печати
Это справедливо только в Verilog'е, а я пишу на VHDL, где оператор сравнения - именно "=".
А по поводу двухпортовости - иначе при обращении процессора к памяти будут "выпадать" 1-2 столбца по 8 пикселей на таких частотах.
- - - Добавлено - - -
Вот честно - я больше программист, чем разработчик железа. Последнее является только хобби, да и опыта ещё маловато, так что подобные ляпы пока буду допускать.
- - - Добавлено - - -
По поводу памяти, вот картинка.
Красными прямоугольниками выделил вывод столбца из 8 пикселей, то есть 1 байта из памяти.
Если организовывать на стандартной памяти, то для устранения проблем следует организовывать буфер минимум для 2-х байт (4-х, если точнее, поскольку 2 плоскости), в которых будут храниться промежуточные значения - по адресам N+1 и N+2, а N+0 уже выводится на экран. В оригинальном Орионе частота вывода изображения значительно меньше, поэтому хватило одного буфера - для значений N+1.
Подумать над такой схемой вполне возможно, что бы использовать стандартную SRAM, чем скорее всего и займусь после оптимизации формирования видеосигналов.
- - - Добавлено - - -
Сейчас вот посмотрел на длительности сигналов процессора WR и RD в модели - оба занимают "в ширину" ровно 6 пикселей вывода.
При частоте тактирования всего (и памяти) в 25МГц получается, что на чтение видеоданных у нас максимум 80нс. Для большинства типов памяти хватит, конечно же. Но это справедливо только для ВМ80А - я не в курсе временных диаграмм этих сигналов у Z80.
Вот картинки с анализатора:
Чтение - https://image.prntscr.com/image/GTRA...Ex1AA_RbrQ.png Запись - https://image.prntscr.com/image/oq19...ssmSd17yeA.png
Второй ряд - Ф2, третий - Ф2.
То есть у нас, грубо говоря, в наихудшем случае около 40нс на цикл чтения байта из памяти.
Если не успеть прочитать байт - 8 пикселей "выпадут" из картинки.
- - - Добавлено - - -
Vslav, ты у нас более знаком с циклами ВМ80А - как можно их "обрезать" на графиках выше? В моей логике пока что используются "сырые" сигналы с процессора, то есть обращение к памяти формируется как "cpu_rd or cpu_wr".
Из того, что я вижу - можно делать сигнал обращения к памяти как "cpu_F2 and (cpu_rd or cpu_wr)", с защелкиванием данных на выходном буффере при чтении.
Похоже у тебя F1/F2 взяты с ножек pin_F1/F2, а они внутри обертки еще защелкиваются, то есть реально задержаны на такт. Если у тебя F1/F2 формируются внутри ПЛИС и синхронизированы с clk что на ядро подается, то защелки можно убрать.
А обрезать - уменьшить простой после F2, тогда быстрее молотить будет, сейчас частота делится на 6, потому что у тебя после F2 пауза в фазах есть - не подана ни одна из F1/F2.
Паузы - это для задания тактовой частоты, она сейчас 2,5МГц. Я же делаю модель компа, а не тестовой числодробилки, мне нужно блюсти частоты :) Хотя тут я с делителем накосячил - надо было делить на 5, а не на 6 =/
Корка затактирована на 25МГц, Ф1 и Ф2 - 2,5МГц на картинках.
Ф1 = orion_cpu:cpu|vm80a:cpu|pin_f1, то есть сигнал с ножки, а не с ядра. Как вижу, это до защелки ещё.
- - - Добавлено - - -
Вот, исправил счётчик для формирования тактов:
https://image.prntscr.com/image/EZQS...DMG0czsDpA.pnghttps://image.prntscr.com/image/ETbN...w8-vFB019w.png
Уже минимум 2 такта на чтение видео-данных, неплохо :)
То есть при неактивных RD и WR по фронту F1 выставляем адрес для чтения, по фронту F2 помещаем данные в буфер.
Если хочешь использовать старую корку vm80a, то попробуй паузы сделать через HOLD.
Новая корка vm80_wb содержит встроенный клок-модератор, имеет отдельный вход vm_cena. На него надо подавать импульсы высокого уровня в зависимости от желаемой эмулируемой частоты ядра, при этом ввод-вывод на шине от него не зависит. Например, затактируешь корку от 25МГц, если на vm_cena постоянно высокий то корка работает на 25МГц, если туда подавать единичку только каждый 10-ый такт - получишь 2.5МГц, каждый 5-ый такт - 5МГц. Можно получить и 10 МГц, подавая частоту на 2 такта каждые 5, или реализовать фазовый аккумулятор для генерации vm_cena. И vm_cena лучше регистром фиксировать, для устойчивости.
PS. Кстати, в новой корке я зря рестарт по прерыванию в halt выбросил, оказывается нужная штука, halt используется и прерывание из него выводит оказ. Совсем забыл, исправлю сейчас.
Не, я на старой корке делаю, для новой надо делать "прослойку", поскольку сигналы чутка другие и шина данных у меня полностью двунаправленная.
У меня там не паузы, а сигналы со счётчика ;) Вход 25МГц, выход - 2,5МГц. Делаю специально так, что бы потом "в железе" схему составить без проблем для генерации тактов.
- - - Добавлено - - -Код:clk_F <= (not cnt_clk(1)) and (not cnt_clk(2));clk_F1 <= clk_F and (not cnt_clk(0));
clk_F2 <= clk_F and cnt_clk(0);
process (clk)
begin
if (rising_edge(clk)) then
if (cnt_clk = 3D"4") then
cnt_clk <= (others => '0');
else
cnt_clk <= cnt_clk + '1';
end if;
end if;
end process;
Внутри ПЛИС - да. Но для воплощения "в железе" приходится всё сравнивать выборочно побитово, иначе плата раздуется на много-много корпусов для полноценного сравнения.
- - - Добавлено - - -
Глянул ДШ на Z80 - там примерно та же схема по циклам.
В итоге попробую завтра организовать работу с 1-портовой памятью.
Сигнал обращения к памяти будет формироваться как "F2 and (cpu_rd or cpu_wr)".
Для растягивания чтения добавится защёлка на памяти (сейчас её нет).
ША памяти будет переключаться на адреса видео при условии "F1 or F2".
Копирование видео-данных в буфер (DD47, DD48 в оригинальном Орионе) будет происходить по положительному фронту F2.
В итоге на чтение видео-данных отводится 40нс на любой частоте тактирования (2.5, 5, 10).
PS: Расписал больше для себя, что бы не забыть потом. Но может я где-то ошибся в своих рассуждениях...
Тогда тебе надо не на HDL писать, а использовать схемный ввод, из кубиков серии 74xxx. Потому что при таком подходе как сейчас ты и возможности HDL/FPGA не используешь нормально, а потом когда это все на логику будешь раскладывать - там свои проблемы вылезут. В итоге это все может отравить тебе фан, имхо.
Сейчас добиваюсь хоть какой-то работы от модели, потом да, буду в "кубики" модель переделывать.
Рисовать схему сразу в HDL'я - это изврат, который выйдет боком.
- - - Добавлено - - -
Тогда только TechMap. В RTL'е всё упрощено - те же сравнения так и записаны - блок Equal и 2 оператора на входе для сравнения:
https://image.prntscr.com/image/6oat...s4NfiR8Z-g.png
О чем и речь. Жду техмап. Он, кстати, зависим от конкретной FPGA.
Это да. В альтерах там просто куча LOGIC_CELL_COMB'ов =/ Зачастую каждый разбит на куски, раскиданные по "схеме". И внутри ещё хрен пойми какая логика - тяжело её вкуривать вообще =/ Приходится каждый элемент на бумажке расписывать.
Это может ещё от неопытности просто - это ведь мой первый проект на FPGA, lol :) До этого не в счёт - баловство в виде написания светофора и прочего, без вникания в суть работы.
Итак, сегодня весь день "убил" на перевод схемы на однопортовую память, и оно даже заработало. Правда, при частоте процессора 2,5МГц пока что имеются проблемы, но начиная с 3,125МГц (25МГц/8) всё идеально работает. Буду бороться за сокращение переднего фронта сигнала DSYN - он-то и препятствует обращению к памяти...
- - - Добавлено - - -
Итак, решение пока не самое лучшее, но оно работает 100%:
То есть мы по DSYN мультиплексируем шину адреса памяти, а для арбитража данных задерживаем DSYN на 4 такта (25МГц). Если не делать доп. сигнал с задержкой, то бывают ситуации, когда фронт чтения в буфер приходится на спад DSYN и память естественно ещё не успевает считать данные.Код:process (h_cnt(0))
begin
if (rising_edge(h_cnt(0))) then
dsyn_delayed <= dsyn;
end if;
end process;
mem_to_vbuf <= h_cnt(1) and (not (dsyn or dsyn_delayed));
process (mem_to_vbuf)
begin
if (rising_edge(mem_to_vbuf)) then
vdata <= mem_data1 & mem_data0;
end if;
end process;
mem_addr <= vaddr when (dsyn = '0')
else addr;
Позже запаяю на макетке подручную SRAM'ку и протестирую без этой задержки с изменением кода на защёлку:
Код:process (mem_to_vbuf) begin
if (mem_to_vbuf = '1') then
vdata <= mem_data1 & mem_data0;
end if;
end process;
Сделал формирователь тактовых импульсов из частоты 25МГц. Выходные частоты - 2.5МГц, 5МГц, 10МГц.
Для теста снял все варианты анализатором, частота семплирования - 50МГц.
10МГц: реализовывал как счётчик до 5, но с генерацией импульсов в 0-ой и 2-ой фазах - https://image.prntscr.com/image/eE4h...DmjR-iKS1w.png
5МГц: счётчик до 5, генерация в 0-ой фазе - https://image.prntscr.com/image/LuoU...6S3A3cNyIg.png
2.5МГц: счётчик до 10, генерация в 0-ой фазе - https://image.prntscr.com/image/1-qQ...M2OuC7grkQ.png
На частоте 2.5МГц надо задерживать передний фронт DSYN, пока не придумал как. Иначе на изображении постоянные черные полоски бегают из-за конфликта доступа.
Завтра ещё сперва оптимизирую формирование тактов, потом займусь DSYN...
Из минусов текущего решения - необходимы 2 раздельных счётчика после кварца для формирования сигналов для видео и для CPU. Но есть сдвоенные на подходящие частоты, можно попробовать.
Итак, сделал переключаемую тактовую 2.5/5/10МГц, а так же перевёл память на однопортовую. Пока что реализовано сильно "в лоб", но оно работает надёжно.
Так же пришлось ввести аналог сигнала CAS, по которому пишется положительный фронт DSYN, благодаря чему убрана цепочка задержки этого сигнала (из кода не убрал, но оно не используется уже).
Набросал формирователь видеосигналов из "кубиков" логики.
В качестве счётчиков использовал ИЕ19 (74393), имеются некоторые погрешности в синхросигналах (ровно на 1 такт, для упрощения логики).
Логику пока не упрощал, займусь этим только после стабильной работы с остальным компьютером.
21mux - в железе будет в виде джамперов.
Нипанятна. Есть оригинал?
Вот, в чутка лучшем качестве :)
Немного оптимизировал сигналы, начал формировать тактовые сигналы (пока только 2.5/5МГц).
Нехорошая схема. Учитесь мыслить синхронно. Будут много глитчей в цепи сброса.
Я вот тоже для своего Спеца в CPLD сначала по старинке, ИЕ5 да логика. А потом, когда проект приблизился к ёмкости CPLD и его работоспособность стала зависеть от фазы луны, переписал все наИЕ7ИЕ10 с синхронными установками (не сброс!) + синхронизация некоторых сигналов на выходе. И все заверте...
zst, пардон, я имел в виду ИЕ10, не ИЕ7. Если не использовать его ассинхронный сброс а только загрузку, то все отлично работает.
Переделал логику "по горизонтали" на синхронную. Асинхронными осталось только формирование синхроимпульса. "Вертикаль" пока не переделывал - сперва думаю оптимизировать горизонталь (особенно цепь задержки выключения гасящего сигнала, подумаю по адресации видео-ОЗУ).
Знакомые картинки :)
Я тоже макетировал синхроген под SVGA, и тоже использовал счётчики ИЕ18.
Игреки слиплись. Осторожнее с передвижением блоков.
Оптимизировал как мог...
Если у кого-либо имеются идеи по дальнейшей минимизации логики - готов выслушать ;) Своих знаний тут уже явно не хватает...
Теперь думаю о компоновке по корпусам:
1) Как есть, относительно много перемычек-переключателей для задания режимов;
2) Группировка по возможностям, то есть если человеку надо только 4:3, 384 столбца, то он часть деталей не запаивает и ставит мало перемычек;
3) Сделать переключение программным, поставив, например, КП11.
PS: Текущая схема видео-подсистемы занимает 28ALMs.
По оптимизации не скажу ибо все эти импортные "овалы" мой мозг считывать отказывается, приучен только к ГОСТу.
Имею вопрос по стратегии: этот комп планируется довести до выпуска или он проектируется только в качестве упражнений?
Если к выпуску, то что в итоге с видеовыходом: VGA? В каком разрешении?
Если VGA и в приличном разрешении, то я бы предложил ввести режим алфавитно-цифрового дисплея (АЦД). Наиболее просто (цена вопроса 3-4 МСХ логики/регистров и одно ПЗУ с шрифтами) можно было бы реализовать вывод символами 8х8. Логика АЦД такая: при последовательном сканировании в памяти восьми соседних строк, читается из ОЗУ только одна и та же из этих строк (т.е. код символа с отступом по номеру текстового экрана), и вычитанный из ОЗУ байт помещается не в сдвиговый регистр видеовыхода каждый раз напрямую как в графическом режиме, а в регистр-защелку адресных входов A3..A10 ПЗУ шрифтов один раз на все эти восемь строк, а вот выход ПЗУ шрифтов (все 8 строк адресуемого символа выводимые соответственно номеру текущей строки экрана 0..7 т.е. адресные входы A0..A2 ПЗУ шрифтов) уже помещается в сдвиговый регистр видеовыхода. Т.е. укрупненно: "ставим ПЗУ фонта в разрыв между памятью и видеовыходом, и содержимое памяти становится не изображением символа, а его адресом в ПЗУ"
Получим текстовый режим 60х32 символов для разрешения 480х256 (и имеет смысл не теряя совместимость увеличить экран c 15кб до 16кб т.е. до 512х256 получив 64 символа в строке) или 80х32 символов для режима 640х256.
Также очевидно что можно элементарно ввести и матрицу символа 8х16 прямо в этой же схеме как второй режим в дополнение к 8х8, но в этом режиме будет только 16 строк более крупых символов.
Там же подписаны функции все - AND2, XOR2, NOR2 и т .п...
Планируется хотя бы для себя. Но плат получится всё равно на 5-10 штук...
VGA - на два разрешения, 640х480 и 640х350. Для обоих можно выбирать режим отображения - 384х256 или 480х256. Всё это выбирается джамперами - на схеме это "21mux".
Тут проблема будет в перерасчёте таймингов по горизонтали - на схеме там и так логика самая сложная =/ А ввод ещё одного разрешения раздует логику ещё больше - смотри в посте выше схему по ссылке.Цитата:
Получим текстовый режим 60х32 символов для разрешения 480х256 (и имеет смысл не теряя совместимость увеличить экран c 15кб до 16кб т.е. до 512х256 получив 64 символа в строке) или 80х32 символов для режима 640х256.
Сегодня добиваю видео-часть из "кубиков", буду добиваться корректной работы. Так что может сегодня даже выложу полную схему узла :)
Ещё и переключение тактовой 2.5/5/10 сделал с возможностью софтварного доступа, если регистр на это дело поставить (0 - 2.5МГц, 1 - 5МГц, 2/3 - 10МГц). Вот фрагмент именно с формированием тактов, выполнено и проверено сегодня.
Чтобы излишне не усложнять, и раз уж у нас базовые 640 точек в кадре, я бы предложил использовать Орионовский режим 512х256 (широко применявшийся в Орионе-ПРО). На нем прекрасно будет отображаться и 480х256, совпадает по границе 16к (т.е. все совместимо по размещению экранов в ОЗУ), а 64 символа в строке (при символе шириной 8 точек) это все же лучше чем 60.
- - - Добавлено - - -
А почему ты не рад идее АЦД?
Какие я вижу плюсы:
- вывод символа в 8 раз быстрее.
- горизонтальный скроллинг (влево-вправо) в 8 раз быстрее
- оконные функции быстрее в 8 раз и в 8 раз меньше требуется места под буфера окон чем в графике
Что мало меняется: вертикальный скроллинг ускорится примерно на 20%-30% при символах 8х8 и примерно вдвое для символов 8х16. Ну, как говорится - и то хлеб.
Я больше волнуюсь о проблемах с разрешением - нужно дополнять формирователи и т.п...
АЦД - не проблема.
Но ведь ты уже ввел режим 480 точек. Если вместо него ввести 512 (тоже в-общем вполне Орионовский), то по количеству корпусов останется примерно то же самое? От 640 можно отказаться если оно сильно усложняет.
Те 512 не лезли в телек (и для режима 80 символов в строке при символе шириной 6 точек были избыточны), и раз так, то в 90х делали экран 480 чтобы экономить 1кб в каждой экранной области из четырех. А раз у нас кадр VGA-640 и получаются поля бордюра, то всё в экран влезает с запасом и можно сделать 512.
- - - Добавлено - - -
Еще раз вдумчиво посчитал (первоначально ошибся в оценке сколько tstates уходит на LDIR), при использовании АЦД вертикальный скроллинг получится быстрее в 2-3 раза чем в графическом режиме. Т.е. заметно быстрее, хотя и не в 8 раз.
Оно как бы не много, по корпусам если смотреть. Вся сложность именно в перерасчёте тактов и выяснение минимальных функций для всех сигналов по горизонтали ;) Я текущую схему уже дня 4 шлифую почти с утра и до вечера.
andreil, тебе уже HardWareMan говорил про синхронность. Все выходные сигналы управления внешними модулями/блоками, включая и сигнала такта проца и nCAS для DRAM, должны быть регистровыми, и должны быть синхронными от одного клока (заведомо большей частоты), и никаких латчей, только флипфлопы! Синхронность - залог устойчивой работы логики на больших частотах. У тебя же все на комбинаторике, это ох!"№;%:?*ые задержки и иголки/глитчи. Даже F[0..3] на 7490 у тебя каскадирован...
Можно сделать как в Векторе-06Ц: поставить отдельный регистр вертикального смещения. Номер текущей/отображаемой строки и содержимое регистра суммируются по модулю 256 и далее результат используется в адресации видеопамяти. В ПЛИСке реализуется элементарно, на рассыпухе, конечно, пожирнее выйдет...
Для текстообработки вполне нормально 16 строк, вписанных в растр 512*256, как в КОРВЕТЕ. При 32-х строках символы слишком плющенные, а для нортонов, чтобы влезало больше строк можно использовать графический режим.Цитата:
Сообщение от error404
Я в середине 90-тых собирался сделать лично для себя такой синхронный текстовый режим в ОРИОНЕ. Он прост в реализации. Но увы, руки до этого так и не дошли, потому что я не был уверен, что этот режим не нарушит регенерацию ОЗУ.
Конечно, лучше бы придумать текстовый экран в ОРИОНЕ на таком же синхронном принципе, но так, чтобы под экранное ОЗУ тратилось не 16 кб, а только 1 кб, как в КОРВЕТЕ. Это возможно сделать поставив свой мультиплексор, ОЗУ 1 кб (на 537РУ17) и весь видеовыход с выходным регистром сдвига и ПЗУ с фонтом. Получится почти КОРВЕТ, но деталей в этом варианте намного больше. Тут проблем с регенерацией не возникает.
Зато вариант когда на экран тратятся те же 16 кб, намного проще (отпадают ОЗУ, защёлки и адресные мультиплексоры), хотя нужна коррекция и на основной плате - там надо ставить КП11, которая обнуляет веса V0...V3 идущие от счётчиков на мультиплексор (это чтобы в знакоместе все 16 линий читались из одного адреса ОЗУ). Конструктивно с краю платы ОРИОНА монтируется разъём, куда вставляется крошечная платка текстового видеовыхода. Там ПЗУ 2764 с фонтом (4 кб на один фонт), ИР9 и КП11, которая при включении текстового режима подаёт сигнал с выхода ИР9 на цепь 101 вместо DD51/20. В DD51 ИР13 банки 0 запрещается сдвиг (единица на DD51/1). Через разъём выходы 8 битов из ИР13 DD51 поступают прямо на ПЗУ фонта, куда также поступают веса счётчиков V0...V3 (соответствующие адресам CPU A0...A3).
Как видите деталей совсем немного и смакетировать это можно за пару вечеров. А текстовый режим, даже такой несуразный, что занимает 16 кб, намного быстрее, чем графический. Проблема только в том, что я не уверен, что ОЗУ будет регенерироваться. Кто-нибудь может высказаться на этот счет?