Лучше сделать и жалеть, чем не сделать и жалеть.
Некоторые из моих поделок тут: https://github.com/serge-404
Лучше сделать и жалеть, чем не сделать и жалеть.
Некоторые из моих поделок тут: https://github.com/serge-404
Это справедливо только в 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.
Вот картинки с анализатора:
Чтение - Запись -
Второй ряд - Ф2, третий - Ф2.
То есть у нас, грубо говоря, в наихудшем случае около 40нс на цикл чтения байта из памяти.
Если не успеть прочитать байт - 8 пикселей "выпадут" из картинки.
- - - Добавлено - - -
Vslav, ты у нас более знаком с циклами ВМ80А - как можно их "обрезать" на графиках выше? В моей логике пока что используются "сырые" сигналы с процессора, то есть обращение к памяти формируется как "cpu_rd or cpu_wr".
Из того, что я вижу - можно делать сигнал обращения к памяти как "cpu_F2 and (cpu_rd or cpu_wr)", с защелкиванием данных на выходном буффере при чтении.
Последний раз редактировалось andreil; 06.02.2018 в 19:26.
"Байт-48"
Похоже у тебя 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, то есть сигнал с ножки, а не с ядра. Как вижу, это до защелки ещё.
- - - Добавлено - - -
Вот, исправил счётчик для формирования тактов:
Уже минимум 2 такта на чтение видео-данных, неплохо
То есть при неактивных RD и WR по фронту F1 выставляем адрес для чтения, по фронту F2 помещаем данные в буфер.
"Байт-48"
Если хочешь использовать старую корку 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: Расписал больше для себя, что бы не забыть потом. Но может я где-то ошибся в своих рассуждениях...
"Байт-48"
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)