Русский клон ZX Spectrumа из прошлого

Старый спектрумистский форум

Moderator: Shaos

bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

В данный момент "в лоб" схемный проект. Но позже все же попробую перевести на верилог, в рамках изучения. Очень понравилось отсутствие ограничения на применяемые элементы, т.к. не привязан к конкретным корпусам как если бы собирал на мелкой логике.
jdigreze
God
Posts: 1388
Joined: 02 Jan 2006 02:28
Location: Abakan

Post by jdigreze »

Между тем у меня внезапно обнаружились несколько Panasonic NM41C4256-08 256Kx4 DRAM, аккурат с совмещенными DI/DO.
Надо будет попробовать использовать для спектрума.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

Что-то по этой маркировке гуглится только данный форум. А есть датащит?

PS Статическое ОЗУ отбирает слишком много ножек у CPLD. Надо найти способ подключения DRAM без нарушения таймингов либо придется чем-то жертвовать. Например функциями на ногах CPLD или установкой более ёмкого корпуса CPLD. Этот всего 100 ножек, следующий получается 144.
jdigreze
God
Posts: 1388
Joined: 02 Jan 2006 02:28
Location: Abakan

Post by jdigreze »

Апшибочка вышла. Должно быть MN41C4256. Доков в инете нет, но известно что это типовая CMOS DRAM 4bit 256k 20pin.
User avatar
Black_Cat
Doomed
Posts: 459
Joined: 23 Nov 2007 15:53
Location: Saint Petersburg, Russia

Post by Black_Cat »

jdigreze личку глянь
"Очень трудно найти чёрную кошку в тёмной комнате... особенно, если её там нет.", "Forever!". :wink:
zx.clan.su - Soviet Union ZX Spectrum Community - форум посвящённый развитию Спека.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

Сегодня мне повезло! Разгребая закрома я обнаружил-таки свою заначку из 8ми микросхем LH21256-12. Это аналоги РУ7. Так что откачу проект до использования этой памяти. Использование SRAM конечно удобнее и логичнее, но она слишком много съедает ног у CPLD. Не остается на остальные устройства. Как переделаю печатку и подправлю схему внутри CPLD сразу отпишу о результатах.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

В общем решил все-же отказаться от DRAM. Проблема регенерации идет в ущерб оригинальным таймингам. Поэтому, остаемся на SRAM. Однако, чтобы сэкономить ноги в CPLD адреса придется мультиплексировать. А сигналы управления уже готовы - это RAS/CAS. Как только перепаяю макетку согласно новому плану - отпишусь.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

Сегодня мультиплексировал шину адреса ОЗУ. 8 бит адреса пропустил через защелку. А так как в Ленинграде Z80 работает от сигнала RAS, то подключил сигнал LE защелки к тактовому выводу процессора. И, таким образом, освободил не 7 ног а 8!
Image
Работает, сижу и паяю кнопки клавиатуры...
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

Вернулся из отпуска, вспомнил про спектрум. Подпаял клавиатуру:
Image
Дополнил портом ввода и вывода (пока только управление бордюром). USB тюнер куда-то делся, а встроенный показывает ужасно:
Image
Image
Image
Однако, работает. Осталось только привести в порядок видеовыход, магнитофонный интерфейс. После этого можно начать пересматривать текущий вариант проекта и попробовать переписать его на верилог. Я его еще толком не изучал, так несколько книжек почитал. Надеюсь, получится.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

В общем пока вот так получилось:
Image
Выгрузка:
Image
Image
Кодер PAL говно, ЧБ изображение с RGBI просто конфетка. Либо внешний аналоговый кодер цеплять, либо нормальный писать, который может и не влезть. Схему уже переложил на Verilog, наверняка накосячил прилично. Нужно нарисовать схему по текущему варианту. А тут можно загружать файлы или надо пользоваться внешними хранилищами? Я бы проект приложил, пусть знающие люди посмотрят.
jdigreze
God
Posts: 1388
Joined: 02 Jan 2006 02:28
Location: Abakan

Post by jdigreze »

Shaos'у на мыло отправь, наверно прикрепит.

По второму изображению есть мнение, что привязка к уровню чёрного не работает.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

Это кодер. В статике любой цвет бордюра достаточно насыщен и основное поле от этого не страдает. Именно для этого и выставлена первая картинка - там простая программка на бейсике, картинка статична. А вот в динамике мало того кодер врет да еще и тюнер деинтерлейсит. Картинка с пилоттоном там два цвета накладываются деинтерлейсом. На телевизоре вроде получше. Сейчас еще раз окину код взглядом и попробую как-нибудь прикрепить.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

В общем, получилось как-то так:

Code: Select all

// ULA клона ZX Spectrum Ленинград
module LeninULA(
       // Входы общие
       input       MClk,              // Тактовая частота 14.31818 (компьютерный кварц)
       // Входы Z80
       input       [15:0]A,           // Шина адреса
       input       M1,                // Сигнал Machine Cycle 1
       input       RFSH,              // Сигнал Refresh
       input       MREQ,              // Сигнал Memory Request
       input       IORQ,              // Сигнал Input-Output Request
       input       RD,                // Сигнал Read Strobe
       input       WR,                // Сигнал Write Strobe
       // Входы периферии
       input       [4:0]KI,           // Вход матрицы клавиатуры
       input       TAPEIN,            // Вход магнитофона
       // Выходы периферии
       output       reg SOUND,        // Выход звука
       output       reg TAPEOUT,      // Выход магнитофона
       // Выходы Z80
       output       reg CLK,          // Выход тактовой частоты
       output       reg WAIT,         // Выход Wait
       output       reg INT,          // Выход Interrupt
       output       reg NMI,          // Выход NonMaskable Interrupt
       output       reg BUSR,         // Выход Bus Request
       output       reg RES,          // Выход Reset
       // Выходы памяти
       output       reg [7:0]MA,      // Выход мультиплексированной шины адреса ОЗУ
       output       reg RWE,          // Выход строба записи ОЗУ
       output       reg ROE,          // Выход строба чтения ОЗУ
       output       reg ROM,          // Выход обращения к ПЗУ
       // Выход видео
       output       SYNC,             // Выход синхронизации
       output       reg R,            // Выход сигнала R
       output       reg G,            // Выход сигнала G
       output       reg B,            // Выход сигнала B
       output       reg I,            // Выход сигнала I
       output       ODD,              // Выход чет/нечет
       output       reg BURST,        // Снхровспышка цветности
       // Двунаправленные шины
       inout       [7:0]D,            // Шина данных Z80
       inout       [7:0]MD	      // Шина данных ОЗУ
);
assign SYNC = !SS & !KS;
assign ODD = VC[0];
assign D[7:0] = (CSRAM & !RD) ? LATCH[7:0] :
       (!IORQ & !RD) ? (A[0]) ? 8'h00 : {1'h0,TAPEIN,1'h0,KI[4:0]} : 8'hzz;
assign MD[7:0] = (!RWE) ? D[7:0] : 8'hzz;
// Основной арбитр
reg  [3:0]STATE;                            // Состояние арбитра
reg  [7:0]LATCH;                            // Защелка входных данных Z80
reg  [7:0]ATTR;                             // Регистр атрибутов
reg  [11:0]VID;                             // Регистр видеосигнала
reg  [7:0]RA;                               // Адресный регистр
reg  [2:0]BORDER;                           // Регистр бордюра
reg  RAMEDGE;                               // Перепад обращения к ОЗУ
reg  DLATCH;                                // Запрос на запись данных
reg  WINDOW;                                // Окно отображения
wire CSRAM = !MREQ & !RD & (A[14] | A[15]); // Выборка ОЗУ
wire WERAM = !MREQ & RD & RFSH;             // Запись в ОЗУ
//
always @(posedge MClk)
begin
       // RAS / CLK для Z80 с небольшой задержкой
       CLK <= STATE[1];
       // CAS / ROE/RWE
       if (STATE[2])
          begin
               // Обращение видеопроцессора
               ROE <= !(STATE[1] ^ STATE[0]);
          end
          else
          begin
               // Обращение Z80
               ROE <= !(!MREQ & !(RD & RFSH) & (A[14] | A[15]) & (STATE[1] ^ STATE[0]));
               // CAS / RWE
               RWE <= !(WERAM & (A[14] | A[15]) & !STATE[1] & STATE[0]);
          end
       // Ожидание и выборка ПЗУ
       ROM <= MREQ | RD | A[14] | A[15];
       if (!STATE[2] & !STATE[1] & STATE[0])
          begin
               // Загрузка латча, снятие ожидания
               DLATCH <= 1'b1; WAIT <= 1'b1;
          end
          else
          begin
               DLATCH <= 1'b0;
          end;
       RAMEDGE <= CSRAM;
       if (!RAMEDGE & CSRAM & !M1) WAIT <= 1'b0;
       // Видео ???
       if (!STATE[3] & STATE[2] & STATE[1])
          begin
               // Загрузка новых данных
               if (!STATE[0]) VID[11:0] <= {VID[10:7],MD[7:0]};
          end
          else
          begin
               // Сдвиг видеорегистра
               if (!STATE[0]) VID[11:0] <= {VID[10:0],1'b1};
          end;
       // Атрибуты
       if (STATE[3] & STATE[2] & STATE[1] & !STATE[0])
          begin
               WINDOW <= !HC[5] & !(VC[8] | (VC[7] & VC[6]));
               ATTR[7:0] <= MD[7:0];
          end
       // Видеовыход
       if (WINDOW)
          begin
               // Вывод видео
               I <= ATTR[6];
               if (VID[11] ^ (ATTR[7] & FLASH[4]))
                  begin
                       // INK
                       B <= ATTR[0]; R <= ATTR[1]; G <= ATTR[2];
                  end
                  else
                  begin
                       // PAPER
                       B <= ATTR[3]; R <= ATTR[4]; G <= ATTR[5];
                  end
          end
          else
          begin
               if (!SG & !KG)
                  begin
                       // Бордюр
                       B <= BORDER[0]; R <= BORDER[1]; G <= BORDER[2]; I <= 1'b0;
                  end
                  else
                  begin
                       // Гашение
                       B <= 1'b0; R <= 1'b0; G <= 1'b0; I <= 1'b0;
                  end
          end
       // Адресный мультплексор
       case (STATE[3:1])
            3'h0 : RA[7:0] <= A[7:0];
            3'h1 : RA[7:0] <= {3'h2,VC[7:6],VC[2:0]};
            3'h2 : RA[7:0] <= {VC[5:3],HC[4:0]};
            3'h3 : RA[7:0] <= A[15:8];
            3'h4 : RA[7:0] <= A[7:0];
            3'h5 : RA[7:0] <= {6'h16,VC[7:6]};
            3'h6 : RA[7:0] <= {VC[5:3],HC[4:0]};
            3'h7 : RA[7:0] <= A[15:8];
       endcase
       // Цветовая вспышка
       if (HC[5] & !HC[4] & HC[3] & HC[2] & !HC[1] & HC[0] & STATE[3]) BURST <= 1'b1;
       if (HC[5] & !HC[4] & HC[3] & HC[2] & HC[1] & HC[0] & STATE[3]) BURST <= 1'b0;
       // Строчное гашение
       if (HC[5] & !HC[4] & !HC[3] & HC[2] & HC[1] & HC[0]) SG <= 1'b1;
       if (HC[5] & HC[4] & !HC[3] & !HC[2] & !HC[1] & !HC[0]) SG <= 1'b0;
       // Гоняем состояние по кругу
       STATE[3:0] <= STATE[3:0] + 4'h1;
       // Загрузка в порт
       if (!IORQ & !WR) {SOUND,TAPEOUT,BORDER[2:0]} <= D[4:0];
       // Заглушки
       NMI <= 1'b1;
       BUSR <= 1'b1;
       RES <= 1'b1;
end
always @(negedge MClk)
begin
       MA[7:0] <= RA[7:0];
       if (DLATCH) LATCH[7:0] <= MD[7:0];
end
// Строчный счетчик
reg [5:0]HC;         // Строчный счетчик
reg SS;              // Строчная синхронизация
reg SG;              // Строчное гашение
reg INTEDGE;         // Перепад прерывания
always @(negedge STATE[3])
begin
       // Счет
       if (HC[5:0] == 6'h38)
          begin
               // Сброс счетчика
               HC[5:0] <= 6'h00;
          end
          else
          begin
               // Счет
               HC[5:0] <= HC[5:0] + 6'h01;
          end;
       SS <= HC[5] & !HC[4] & HC[3] & !HC[2];
       if (!INTEDGE & !VC[8] & VC[7] & VC[6])
          begin
               INT <= 1'b0;
          end
          else
          begin
               INT <= 1'b1;
          end
       INTEDGE <= !VC[8] & VC[7] & VC[6];
end
// Кадровый счетчик
reg [8:0]VC;         // Кадровый счетчик
reg KS;              // Кадровая синхронизация
reg KG;              // Кадровое гашение
always @(negedge SS)
begin
       // Счет
       if (VC[8:0] == 9'h137)
          begin
               VC[8:0] <= 9'h00;
          end
          else
          begin
               VC[8:0] <= VC[8:0] + 9'h01;
          end
       KS <= !VC[8] & VC[7] & VC[6] & VC[5] & VC[4] & VC[3] & !VC[2];
       KG <= (!VC[8] & VC[7] & VC[6] & VC[5] & VC[4]) | (VC[8] & !VC[7] & !VC[6] & !VC[5] & !VC[4]);
end
// Мигалка
reg [4:0]FLASH;
always @(posedge KS)
begin
       FLASH[4:0] <= FLASH[4:0] + 5'h01;
end
// Конец модуля
endmodule
Специалистам просьба глянуть и указать на явные ошибки.
bigmax
Fanat
Posts: 79
Joined: 10 Feb 2014 03:37

Post by bigmax »

Хоть кто-нибудь смотрел код?
jdigreze
God
Posts: 1388
Joined: 02 Jan 2006 02:28
Location: Abakan

Post by jdigreze »

Я смтрел, но так как я не копенгаген в hdl, то толку от меня не много.