What's new? | Help | Directory | Sign in
Google
vector06cc
Vector-06C FPGA Replica / Вектор-06Ц на ПЛИС
  
  
  
  
    
Search
for
Updated Mar 08, 2008 by svofski
Labels: Phase-Design, Featured
ImplementationNotes  
FPGA implementation notes

This page contains constantly updated project notes. Also see ArchitecturalOverview.

Contents

Clock Distribution

Clock distribution:


Keyboard

In this implementation an attempt is made to make the keyboard as accessible possible to the modern user, while keeping the impact on compatibility minimal. A complex interface maps PS/2 keyboard codes into Vector-06C keyboard matrix, while keeping track of both PS/2 and Vector Shift status. This results in smooth interaction with modern keyboards, the user doesn't need to know where certain characters were located on the original keyboard at all. One drawback is Cyrillic keyboard layout, which is currently not mapped out. This may also cause problems in programs that assume the keyboard geometry to be fixed, e.g. piano keys simulators. Such functionality can be added: see related issue.

Keyboard interface consists of low level PS/2 driver located in ps2k.v, scancode converter roms in scan2matrix.v and toplevel interface with matrix encoder in vectorkeys.v.

PS/2 driver, ps2k.v is very basic and provides no possibility to send commands to the keyboard, e.g. to set typematic rate or change the status of keyboard LED's. The main module is vectorkeys.v. The state machine there handles make and release codes, while keeping track on natural, forced and negated shifts. This is necessary to properly implement keys that have different shift status on different keyboards, e.g. to enter a ':' one presses ':' key on the original Vector without Shift, while on a PS/2 one normally presses Shift+; to enter a ':'. Thus, a shift has to be neglected from the keyboard matrix. Same ':' key with shift on Vector would enter an asterisk, '*'. On a PS/2 keyboard, asterisk is entered by pressing Shift+8, thus the shift status is kept natural for "Shift+8". Other interesting case of shift handling is dictated by the PS/2 keyboard itself which sends make shift code before each grey arrow keypress and break shift code after it's released.

The matrix itself is simulated rather physically, see rowbits assignment in vectorkeys.v. This ensures proper emulation but, of course, is far from being compact or elegant. Ideally, keymatrix should be made a RAM block and rowbits would then be updated sequentially. Unfortunately, to make this possible, the main state machine with all logic would have to be slightly rewritten.

Special keys on the keyboard:

F11БЛК+ВВОДсброс ПК с подключением ПЗУ загрузчика. Программа в загрузчике отслеживает состояние клавиш при старте и удерживая F1, F2, F1+F2 можно принудительно выбирать загрузку с кассеты, квазидиска или дискеты
F12БЛК+СБРзапуск загруженной программы. При нажатии на эту клавишу, отключается ПЗУ загрузчика и осуществляется сброс процессора, который начинает исполнять программу в ОЗУ с адреса $0000
ScrollLockOSD Menuнажатие на эту клавишу вызывает экранное меню из которого можно выбрать образ дискеты (DISK), сбросить ПК (RESET), перезапустить программу (RESTART), захватить шину для JTAG интерфейса/приостановить работу (HOLD).
CapsLockРУС/ЛАТПереключение языка ввода в некоторых программах; см. красный светодиод #9
ControlУCВвод управляющих символов
ShiftCCСмена регистра
AltПСПеревод строки
DelСТРНе знаю

See also: Scan Codes Demystifiedexternal

See also: Interfacing the AT keyboardexternal

See also: Техническое описание


Mock Disk

Aka kvaz, квазидиск.

Same SRAM chip is used for main memory and for the RAM disk. The complete memory map can be laid out approximately like this (addresses given in byte mode, divide by 2 for physical figures):

00000Main RAM
10000Ramdisk page 0
20000Ramdisk page 1
30000Ramdisk page 2
40000Ramdisk page 3

Important signals in the toplevel:

kvaz is basically just another level of SRAM multiplexer. Its mode of operation is controlled by the ramdisk control register. Depending on configuration, it would select SRAM page, bits [16:15] of external SRAM address bus, during regular memory access (in window mode) or stack access (in stack mode). Output ramdisk_page is then fed through to sram_map module where it's joined into the complete SRAM address.

See also: Описание функционирования квазидиска, JTAG_Implementation.


Floppy Drive

This section describes inner structure of floppy drive emulator. For information about how to use it, see HOWTO_Floppy.

Theory

Overview

The floppy drive system is implemented as a separate entity based on a 6502 CPU. All used memory (see breakdown below) fits within existing M4K blocks of a Cyclone II. According to Quartus reports, total of 86% of memory bits are used.

The code that lives in the 6502 unit is written in C and compiled by cc65 compiler. C language library, crt0.s and linker configuration file, vector.lc, are provided. Architecture is mostly defined by vector.lc file which contains memory map and specialio.h, which defines I/O locations. It seems that for succesful operation, memory size 1 byte smaller than real should be specified -- must could be investigated.

FAT support is based on Elm-Chan's awesome Generic FAT Filesystem module. This module is the best FAT implementation can ever wish for, it provides most everything right out of the box. However, being exceptionally robust, it's also not tiny.

WD1793

Some information about WD1793:

Also see Technical_Description for Vector-06C port map, Секреты Вектора от Лебедева and Секреты Вектора и Кристы

Practice

-

FDC Memory Map

0000-01FF512lowmem_enZeropage and 6502 stack
0200-05FF1024bufmem_enDisk exchange buffer
0800-(8000)18Krammem_enGeneral purpose RAM
E000-E0FF ioports_enI/O area
E100-E1FF256osd_enDisplay RAM

-

CPU I/O Ports

Ports start at memory location $E000:

E000MMC_A: bit0 = SD_DAT3/CS
E001SPDR: SPI data register, same as in AVR
E002SPSR: read: SPI status register: bit 0=SPIF; write: bits [6:4] number of 512-byte blocks to read, initiate transfer; bit 7=write/read
E003OSD Joystick: {0,0,0,Right,Left,Up,Down,Fire}
E004TxD
E005RxD (not implemented)
E006SERIAL_CTL (status, bit 0 == busy)
E00710mS timer/counter 1
E00810mS timer/counter 2
E009CPU_REQUEST (bit 0 == side) request port, polled
E00ACPU_STATUS (write-only) return status here
E00BTRACK (read-only) track index from the hardware
EOOCSECTOR (read-only) sector index from the hardware
EOOEDMA buffer start MSB
EOOFDMA buffer start LSB
E010GLEDS green leds (wo)
E011OSD control (wo): {0,0,0,0,0,F11,F12,bus hold}

-

CPU Requests

CPU_REQUEST_READ 8'h10 Request to read one sector at oTRACK, oSECTOR, bit1=drive,bit0=side (head #)
CPU_REQUEST_WRITE8'h20 Request to write one sector at oTRACK, oSECTOR; bit1=drive,bit0=side (head #)
CPU_REQUEST_READADDR 8'h30 Request to read sector address (return 6 byte header),bit 1=drive,bit0=side
CPU_REQUEST_NOP8'h40 A time waster
CPU_REQUEST_ACK 8'h80 Acknowledge: clear CPU status bits

After CPU has done with processing any request other than CPU_REQUEST_ACK, it sets two bits in iCPU_STATUS:

The host then enters CPU_ENDCOMMAND state, which issues a CPU_REQUEST_ACK command, with LSB containing the boo code. The CPU must react by clearing its status register. After the CPU has cleared its status, the machine is switched back into STATE_READY.

Small Things

One serious behavioural difference between the emulator and the real thing: normally in the write sector mode, BUSY flag is cleared almost instantaneously after the last byte is fed to the controller. Here a write op transfers data to the RAM buffer first and some (relatively long) time is required to flush the buffer before the next operation can begin. But software may expect BUSY bit to be cleared on a really short notice. Hence, after DMA transfer is over, the BUSY bit is cleared but the state changes to STATE_WAIT_CPUWRITE. The software may send new requests then, but next request will only be processed after the state changes to STATE_READY again. This seems to be the only possible compromise that works with both versions of MicroDOS.

However, if the software sends another command before the first one started to be processed, the machine will enter STATE_DEAD with all error bits set, oCPU_REQUEST set to CPU_REQUEST_FAIL, sector register will contain the last written command, the track will contain 0, 0 DRQ, BUSY in the MSB and the last machine state in LSB. wtf line will be set high, which in turn should lock the host computer CPU forever in the vicinity of the offending instruction. A crude, but useful debugging measure.

WD1793 State Diagram

Notes:


OSD Menu

OSD Menu is a cooperative effort of a secondary hardware display and the floppy workhorse CPU.

Display

The display implements a hardware text mode: 5x7 characters with 1-pixel padding. Bit 7 of character code is the inversion attribute. Only characters between $20-$60 exist in the character generator, although characters up to $80 can be added at the expense of some M4K. The character generator ROM is M4K-based, organized in 5-bit wide words. ASCII codes starting with $20 are mapped to 0x00 internally.

Video RAM is 256x8 dual-port RAM located in M4K. It is mapped into CPU memory space at addresses $E100-$E200. The screen configuration is 8 lines of 32 characters each.

When OSD is active, its display is overlaid on top of the primary display. High bits of the primary display true colour components are shifted to the LSB of RGB signals, thus providing simple transparency effect.

Input

When ScrollLock key is pressed, "not in matrix" bit is forced for all keys in the keyboard driver. Instead, Arrow keys and the Enter key start toggling corresponding bits in the OSD joystick ($E003) register.


Sound

See SoundCodec


Comment by tim.tashpulatov, Dec 26, 2007

Why 6502?

Comment by svofski, Dec 27, 2007

There was choice of:

  • Z80
  • 8080
  • AX8 (AVR-tiny)
  • 6502

  • T80 core in Z80 mode takes up some 1800 LE's, which is not really too bad. Unfortunately, the only compiler for it is SDCC, which produces one of the least efficient codes ever which makes it the least favourable choice: largest LE count, largest code size.
  • T80 core in 8080 mode takes only some 1100 LE's, which is awesome. Unfortunately, there are no free C compilers for 8080 whatsoever. It is of course possible to run old CP/M compilers with ZRUN but there's something disturbing in that.
  • AX8 is great, takes whereabouts of some 1200 LE's, has fantastic compiler support.. But it's only a AVR2 core, AT90S2313, and I don't really know how to make e.g. a Mega out of it: that seems to be a separate project on its own (hint hint!)
  • 6502: Peter Wendrich's 65C02 core takes up roughly 1000 LE's; it is very simple to use. cc65 compiler isn't fantastic but it's very configurable and with optimizer it produces moderately adequate code.

And that is why I chose 6502. Besides, it's really punk.

Comment by tim.tashpulatov, Dec 27, 2007

Besides, it's really punk

That must be the reason No.1!


Sign in to add a comment