Skocz do zawartości

Pomocna odpowiedź

Cześć.

Kolejne testy mojej karty VGA współpracującej z Arduino UNO.

Test obejmuje zapis znaków do DDRAM z atrybutami kolorów oraz sterowanie adresem DDRAM.

W kodzie Arduino dodałem kilka funkcji ułatwiających obsługę karty VGA, np.: setCursorColor(255, 255, 255); setFontColor(255, 200, 0); ddramAddressSet();

Dzięki temu zarządzanie kartą VGA jest znacznie prostsze niż w assemblerze.

Poniżej pełny kod testowy oraz krótki film pokazujący działanie.

.

// Linie danych DB0..DB7
const byte DB[8] = {2, 3, 4, 5, 6, 7, 8, 9};

// Linie sterujące
const byte RS = 12;
const byte RW = 11;
const byte E  = 10;

bool endInit = 0;

//rejestry karty VGA
byte entryModeSet = 0b00000100;
byte displayCon   = 0b00001000;
byte registerSet  = 0b00100000;
byte addressSet   = 0b01000000;
byte ramWriteSet  = 0b10000000;

// rejestr adresu ddram w arduino
unsigned long ddramAddress = 0;

// przykładowy tekst
const char *txt = "          HELLO VGA    test koloru znaku i kursora    ";
const char *txt1 = "          VGA_HD44780-extendet. Test zapisu DDRAM zakonczony sukcesem    ";

//------------------------------------------------


// funkcja zapisująca 1 bajt komendy lub danych
void writeDB(byte value) {
  for (byte i = 0; i < 8; i++) {
    digitalWrite(DB[i], (value >> (7 - i)) & 1);
  }
  digitalWrite(E, HIGH);
  digitalWrite(E, LOW);
}

//------------------------------------------------

// funkcja zapisu danych
void dataWrite(byte value) {
  digitalWrite(RS, HIGH);     // RS=1 → dane
  writeDB(value);       // zapis zmian
}

// funkcja obsługi komend
void vgaControll(byte value) {
  digitalWrite(RS, LOW);     // RS=0 → komenda
  writeDB(value);       // zapis zmian
}

//------------------------------------------------

void clearScreen() {
    vgaControll(0b00000001);
}

void cursorHome() {
    vgaControll(0b00000010);
}

void displayON() {
  displayCon |= (1 << 2);
  vgaControll (displayCon);
}

void displayOFF() {
  displayCon &= ~(1 << 2);
  vgaControll (displayCon);
}

void cursorON() {
  displayCon |= (1 << 1);
  vgaControll (displayCon);
}

void cursorOFF() {
  displayCon &= ~(1 << 1);
  vgaControll (displayCon);
}

void cursorBlinkON() {
  displayCon |= (1 << 0);
  vgaControll (displayCon);
}

void cursorBlinkOFF() {
  displayCon &= ~(1 << 0);
  vgaControll (displayCon);
}

void fullBlockCursor() {
  addressSet |= (1 << 2);
  addressSet |= (1 << 1);
  vgaControll (addressSet);
}

void horizontalBarCursor() {
  addressSet |= (1 << 2);
  addressSet &= ~(1 << 1);
  vgaControll (addressSet);
}

void verticalBarCursor() {
  addressSet &= ~(1 << 2);
  addressSet |= (1 << 1);
  vgaControll (addressSet);
}

void autoIncrementON() {
  entryModeSet |= (1 << 1);
  entryModeSet |= (1 << 0);
  vgaControll (entryModeSet);
}

void autoDecrementON() {
  entryModeSet |= (1 << 1);
  entryModeSet &= ~(1 << 0);
  vgaControll (entryModeSet);
}

void autoIncrementOFF() {
  entryModeSet &= ~(1 << 1);
  vgaControll (entryModeSet);
}

void ddramWriteON() {
  ramWriteSet |= (1 << 6);
  vgaControll (ramWriteSet);
}

void ddramWriteOFF() {
  ramWriteSet &= ~(1 << 6);
  vgaControll (ramWriteSet);
}

void cgramWriteON() {
  ramWriteSet |= (1 << 5);
  vgaControll (ramWriteSet);
}

void cgramWriteOFF() {
  ramWriteSet &= ~(1 << 5);
  vgaControll (ramWriteSet);
}

void sramWriteON() {
  ramWriteSet |= (1 << 4);
  vgaControll (ramWriteSet);
}

void sramWriteOFF() {
  ramWriteSet &= ~(1 << 4);
  vgaControll (ramWriteSet);
  clearRegB();
}

//------------------------------------------------

// funkcja usuwająca zapis
void clearRegB() {
  vgaControll(0b00100000);
}

// funkcja zapis do B0
void setB0 (byte value) {
  vgaControll(0b00110000);
  dataWrite(value);
  clearRegB();
}

// funkcja zapis do B1
void setB1 (byte value) { 
  vgaControll(0b00101000);
  dataWrite(value);
  clearRegB();
}

// funkcja zapis do B2
void setB2(byte value) {
  vgaControll(0b00100100);
  dataWrite(value);
  clearRegB();
}

//------------------------------------------------

// funkcja zapisu danych o kolorze
void setColor(byte red, byte green, byte blue) {
  setB0(red);
  setB1(green);
  setB2(blue);
}

// funkcja zapisująca kolor kursora
void setCursorColor(byte red, byte green, byte blue) {
  setColor(red, green, blue);
  vgaControll(0b00100001);
}

// funkcja zapisująca kolor czcionki
void setFontColor(byte red, byte green, byte blue) {
  setColor(red, green, blue);
  vgaControll(0b00100010);
}

//------------------------------------------------
// funkcja inicjująca adres ddram w karcie VGA
void ddramAddressSet() {
  setB0((ddramAddress >> 0) & 0xFF);
  setB1((ddramAddress >> 8) & 0xFF);
  setB2((ddramAddress >> 16) & 0xFF);
  addressSet |= (1 << 5);
  vgaControll (addressSet);
  addressSet &= ~(1 << 5);
}

//------------------------------------------------

// inicjacja linii sterujących
void setup() {
  for (byte i = 0; i < 8; i++) {
    pinMode(DB[i], OUTPUT);
  }

  pinMode(RS, OUTPUT); // bit wyboru między komendą i danymi wysyłanymi do karty VGA
  pinMode(RW, OUTPUT); // w naszym kodzie nie używamy (służy do odczytu bitu zajętości karty VGA)
  pinMode(E, OUTPUT);  // sygnał zapisu dla karty VGA (zapis wyzwalamy dodatnim zboczem)
  pinMode (LED_BUILTIN, OUTPUT); // kontrolka LED sygnalizująca zakończoną inicjacjię karty VGA

  digitalWrite(RS, LOW);
  digitalWrite(RW, LOW);
  digitalWrite(E, LOW);
  digitalWrite(LED_BUILTIN, LOW);

  writeDB(0x00);
}

// program główny
void loop() {

  if (endInit == 0) {
    // Inicjacja układu FPGA (oczekiwanie ok 0.5 sek.)
    delay(500);
    clearScreen();
    delay(500);
    setCursorColor(255, 255, 255); // R, G, B
    cursorON();
    cursorBlinkON();
    fullBlockCursor();
    autoIncrementON();
    displayON();
    
    setFontColor(255, 200, 0);
    ddramAddress = 0;
    ddramAddressSet();
    ddramWriteON();
    // DATA_RAM_WRITE_SET zapis do ddram ciągu znaków zdefiniowanych w tabeli (const char *txt)
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);       // ASCII znak
    }
    ddramWriteOFF();
    
    setFontColor(0, 200, 255);
    ddramAddress += 80; // przesuń kursor do następnego wiersza na pierwszą kolumnę
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);       // ASCII znak
    }
    ddramWriteOFF();
    
    setFontColor(255, 0, 0);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();
    
    setFontColor(255, 100, 0);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();
    
    setFontColor(60, 255, 0);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();
    
    setFontColor(255, 0, 255);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();
    
    setFontColor(255, 255, 255);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();
    
    setFontColor(200, 200, 200);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);       // ASCII znak
    }
    ddramWriteOFF();
    
    setFontColor(100, 100, 100);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();
    
    setFontColor(32, 32, 32);
    ddramAddress += 80;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();

    delay(3000);
    cursorOFF();

    for (byte i = 0; i < 2; i++) {
      delay(500);
      displayOFF();
      delay(500);
      displayON();
    }
    delay(1000);
    
    setFontColor(200, 64, 100);
    ddramAddress += 240;
    ddramAddressSet();
    ddramWriteON();
    for (byte i = 0; txt1[i] != 0; i++) {
      dataWrite(txt1[i]);
    }
    ddramWriteOFF();
    
    endInit = 1; // koniec inicjacji
    digitalWrite(LED_BUILTIN, HIGH);
  }
}

 

 

 

  • Lubię! 2
12 minut temu, kroszkanorber napisał:

W kodzie Arduino dodałem kilka funkcji ułatwiających obsługę karty VGA, np.: setCursorColor(255, 255, 255); setFontColor(255, 200, 0); ddramAddressSet();

Do tego bym jeszcze dodał setCursorColor(uint32_t hexColor), setFontColor(uint32_t hexColor) wraz z zabezpieczaniem wartości (0x00FFFFFF). Bo jednak dużo częściej dla kolorów stosuje się kody hex niż rozdzielone wartości numeryczne.

  • Lubię! 1

@H1M4W4R1  ten kod jest tylko do testów. Z ciekawości chciałem sprawdzić czy Arduino będzie współpracować z fpga. Takie połączenie jest dla mnie nowością. Zapis o którym piszesz nie jest dla mnie taki oczywisty ponieważ mało programuje w języku c. Dziękuję za podpowiedzi 

Dla wyjaśnienia. Kod vhdl został kolejny raz zmieniony i nie wstawiłem ostatniej wersji ponieważ będę testować pozostałe funkcje. Jak wszystkie testy przejdą pomyślnie wrzucę ostateczne kody vhdl które będą w pełni zoptymalizowane. Moim celem jest pokazanie rozwoju i problemów podczas projektowania, w mojej opinii. Oczywiście wyjaśnię trudności i rozwiązania wraz z sugestiami odnośnie pisania kodów vhdl. Na początek chcę zwrócić uwagę na fpga i sprzętowe ograniczenia dla początkujących które są nieoczywiste.  Kolokwialnie mówiąc fpga, to nie śmietnik połączeń komórek lut... Będę o tym pisać w następnych postach...

  • Lubię! 1

Cześć

Kolejny test dotyczy generowania obrazów o rozdzielczości 640x480 , 4096 kolorów (4 bit RGB).

Napisałem kod testowy dla Arduino który wysyła plik RGB obrazu i zapisuje do pamięci SRAM w karcie VGA

Kod i krotki filmik demonstrujący działanie karty:

// Linie danych DB0..DB7
const byte DB[8] = {2, 3, 4, 5, 6, 7, 8, 9};

// Linie sterujące
const byte RS = 12;
const byte RW = 11;
const byte E  = 10;

bool endInit = 0;

//rejestry karty VGA
byte entryModeSet = 0b00000100;
byte displayCon   = 0b00001000;
byte registerSet  = 0b00100000;
byte addressSet   = 0b01000000;
byte ramWriteSet  = 0b10000000;

// rejestr adresu ddram, sram w arduino
unsigned long ddramAddress = 0;
unsigned long sramAddress = 0;

// przykładowy tekst
const char *txt = "          VGA_HD44780-extendet. Test zapisu SRAM zakonczony sukcesem    ";

//------------------------------------------------


// funkcja zapisująca 1 bajt komendy lub danych
void writeDB(byte value) {
  for (byte i = 0; i < 8; i++) {
    digitalWrite(DB[i], (value >> (7 - i)) & 1);
  }
  digitalWrite(E, HIGH);
  digitalWrite(E, LOW);
}

//------------------------------------------------

// funkcja zapisu danych
void dataWrite(byte value) {
  digitalWrite(RS, HIGH);     // RS=1 → dane
  writeDB(value);       // zapis zmian
}

// funkcja obsługi komend
void vgaControll(byte value) {
  digitalWrite(RS, LOW);     // RS=0 → komenda
  writeDB(value);       // zapis zmian
}

//------------------------------------------------

void clearScreen() {
    vgaControll(0b00000001);
}

void cursorHome() {
    vgaControll(0b00000010);
}

void displayON() {
  displayCon |= (1 << 2);
  vgaControll (displayCon);
}

void displayOFF() {
  displayCon &= ~(1 << 2);
  vgaControll (displayCon);
}

void cursorON() {
  displayCon |= (1 << 1);
  vgaControll (displayCon);
}

void cursorOFF() {
  displayCon &= ~(1 << 1);
  vgaControll (displayCon);
}

void cursorBlinkON() {
  displayCon |= (1 << 0);
  vgaControll (displayCon);
}

void cursorBlinkOFF() {
  displayCon &= ~(1 << 0);
  vgaControll (displayCon);
}

void fullBlockCursor() {
  addressSet |= (1 << 2);
  addressSet |= (1 << 1);
  vgaControll (addressSet);
}

void horizontalBarCursor() {
  addressSet |= (1 << 2);
  addressSet &= ~(1 << 1);
  vgaControll (addressSet);
}

void verticalBarCursor() {
  addressSet &= ~(1 << 2);
  addressSet |= (1 << 1);
  vgaControll (addressSet);
}

void autoIncrementON() {
  entryModeSet |= (1 << 1);
  entryModeSet |= (1 << 0);
  vgaControll (entryModeSet);
}

void autoDecrementON() {
  entryModeSet |= (1 << 1);
  entryModeSet &= ~(1 << 0);
  vgaControll (entryModeSet);
}

void autoIncrementOFF() {
  entryModeSet &= ~(1 << 1);
  vgaControll (entryModeSet);
}

void ddramWriteON() {
  ramWriteSet |= (1 << 6);
  vgaControll (ramWriteSet);
}

void ddramWriteOFF() {
  ramWriteSet &= ~(1 << 6);
  vgaControll (ramWriteSet);
}

void cgramWriteON() {
  ramWriteSet |= (1 << 5);
  vgaControll (ramWriteSet);
}

void cgramWriteOFF() {
  ramWriteSet &= ~(1 << 5);
  vgaControll (ramWriteSet);
}

void sramWriteON() {
  ramWriteSet |= (1 << 4);
  vgaControll (ramWriteSet);
}

void sramWriteOFF() {
  ramWriteSet &= ~(1 << 4);
  vgaControll (ramWriteSet);
  clearRegB();
}

//------------------------------------------------

// funkcja usuwająca zapis
void clearRegB() {
  vgaControll(0b00100000);
}

// funkcja zapis do B0
void setB0 (byte value) {
  vgaControll(0b00110000);
  dataWrite(value);
  clearRegB();
}

// funkcja zapis do B1
void setB1 (byte value) { 
  vgaControll(0b00101000);
  dataWrite(value);
  clearRegB();
}

// funkcja zapis do B2
void setB2(byte value) {
  vgaControll(0b00100100);
  dataWrite(value);
  clearRegB();
}

//------------------------------------------------

// funkcja zapisu danych o kolorze
void setColor(byte red, byte green, byte blue) {
  setB0(red);
  setB1(green);
  setB2(blue);
}

// funkcja zapisująca kolor kursora
void setCursorColor(byte red, byte green, byte blue) {
  setColor(red, green, blue);
  vgaControll(0b00100001);
}

// funkcja zapisująca kolor czcionki
void setFontColor(byte red, byte green, byte blue) {
  setColor(red, green, blue);
  vgaControll(0b00100010);
}

//------------------------------------------------
// funkcja inicjująca adres ddram w karcie VGA
void ddramAddressSet() {
  setB0((ddramAddress >> 0) & 0xFF);
  setB1((ddramAddress >> 8) & 0xFF);
  setB2((ddramAddress >> 16) & 0xFF);
  addressSet |= (1 << 5);
  vgaControll (addressSet);
  addressSet &= ~(1 << 5);
}

// funkcja inicjująca adres sram w karcie VGA
void sramAddressSet() {
  setB0((sramAddress >> 0) & 0xFF);
  setB1((sramAddress >> 8) & 0xFF);
  setB2((sramAddress >> 16) & 0xFF);
  addressSet |= (1 << 3);
  vgaControll (addressSet);
  addressSet &= ~(1 << 3);
}

//------------------------------------------------

// inicjacja linii sterujących
void setup() {
  for (byte i = 0; i < 8; i++) {
    pinMode(DB[i], OUTPUT);
  }

  pinMode(RS, OUTPUT); // bit wyboru między komendą i danymi wysyłanymi do karty VGA
  pinMode(RW, OUTPUT); // w naszym kodzie nie używamy (służy do odczytu bitu zajętości karty VGA)
  pinMode(E, OUTPUT);  // sygnał zapisu dla karty VGA (zapis wyzwalamy dodatnim zboczem)
  pinMode (LED_BUILTIN, OUTPUT); // kontrolka LED sygnalizująca zakończoną inicjacjię karty VGA

  digitalWrite(RS, LOW);
  digitalWrite(RW, LOW);
  digitalWrite(E, LOW);
  digitalWrite(LED_BUILTIN, LOW);

  writeDB(0x00);
}

// program główny
void loop() {

  if (endInit == 0) {
    // Inicjacja układu FPGA (oczekiwanie ok 0.5 sek.)
    delay(500);
    clearScreen();
    delay(500);
    autoIncrementON();
    displayON();
    
    // ------------------------- zapis obrazu do pamięci sram -----------------------------------
    sramAddress = 0;
    sramAddressSet();
    sramWriteON();
    
    for (unsigned long y = 0; y < 480; y++) {
    
      for (unsigned long x = 0; x < 640; x += 2) {
    
        // -------------------------
        // GRADIENT – piksel 1 i 2
        // -------------------------
    
        // skala 0..95 (6 segmentów po ~16 wartości)
        byte k1 = (x / 2) % 96;
        byte k2 = ((x + 1) / 2) % 96;
    
        auto computeRGB = [](byte k, byte &r, byte &g, byte &b) {
    
          if (k < 16) {
            // segment 1: G rośnie 0 → 15
            r = 0;
            g = k;
            b = 0;
          }
          else if (k < 32) {
            // segment 2: G = 15, R rośnie 0 → 15
            r = k - 16;
            g = 15;
            b = 0;
          }
          else if (k < 48) {
            // segment 3: R = 15, G maleje 15 → 0, B rośnie 0 → 15
            r = 15;
            g = 15 - (k - 32);
            b = (k - 32);
          }
          else if (k < 64) {
            // segment 4: B = 15, R maleje 15 → 0
            r = 15 - (k - 48);
            g = 0;
            b = 15;
          }
          else if (k < 80) {
            // segment 5: R = 0, B maleje 15 → 0
            r = 0;
            g = 0;
            b = 15 - (k - 64);
          }
          else {
            // segment 6: mieszanie R+G+B (biały → czarny)
            r = 15 - (k - 80);
            g = 15 - (k - 80);
            b = 15 - (k - 80);
          }
        };
    
        byte r1, g1, b1;
        byte r2, g2, b2;
    
        computeRGB(k1, r1, g1, b1);
        computeRGB(k2, r2, g2, b2);
    
        // -------------------------
        // BUŹKA – współrzędne
        // -------------------------
        long x1 = (long)x - 320;
        long y1 = (long)y - 240;
    
        long x2 = (long)(x + 1) - 320;
        long y2 = (long)y - 240;
    
        // -------------------------
        // OKRĄG TWARZY
        // -------------------------
        bool circle1 = (x1*x1 + y1*y1) < 40000;
        bool circle2 = (x2*x2 + y2*y2) < 40000;
    
        // -------------------------
        // OCZY
        // -------------------------
        bool eye1 =
          ((x1 + 60)*(x1 + 60) + (y1 + 20)*(y1 + 20)) < 400 ||
          ((x1 - 60)*(x1 - 60) + (y1 + 20)*(y1 + 20)) < 400;
    
        bool eye2 =
          ((x2 + 60)*(x2 + 60) + (y2 + 20)*(y2 + 20)) < 400 ||
          ((x2 - 60)*(x2 - 60) + (y2 + 20)*(y2 + 20)) < 400;
    
        // -------------------------
        // UŚMIECH
        // -------------------------
        bool mouth1 =
          ((x1*x1) + ((y1 - 20)*(y1 - 40))) < 9000 &&
          (y1 > 40);
    
        bool mouth2 =
          ((x2*x2) + ((y2 - 20)*(y2 - 40))) < 9000 &&
          (y2 > 40);
    
        // -------------------------
        // NADPISYWANIE GRADIENTU
        // -------------------------
        if (circle1) { r1 = 15; g1 = 15; b1 = 0; }
        if (eye1 || mouth1) { r1 = 0; g1 = 0; b1 = 0; }
    
        if (circle2) { r2 = 15; g2 = 15; b2 = 0; }
        if (eye2 || mouth2) { r2 = 0; g2 = 0; b2 = 0; }
        // -------------------------
        
        // BIAŁE TŁO POD TEKSTEM
        // -------------------------
        if (y >= 413 && y < 429) {
            // biały kolor: R=15, G=15, B=15
            r1 = 15; g1 = 15; b1 = 15;
            r2 = 15; g2 = 15; b2 = 15;
        }
    
        // -------------------------
        // KONWERSJA DO 3 BAJTÓW
        // -------------------------
        byte byte1 = (g1 << 4) | r1;
        byte byte2 = (b1 << 4) | b2;
        byte byte3 = (g2 << 4) | r2;
    
        dataWrite(byte1);
        dataWrite(byte2);
        dataWrite(byte3);
      }
    }
    
    sramWriteOFF();

    ddramAddress = 1840;
    ddramAddressSet();
    setFontColor(0,0,0);
    ddramWriteON();
    for (byte i = 0; txt[i] != 0; i++) {
      dataWrite(txt[i]);
    }
    ddramWriteOFF();

    endInit = 1; // koniec inicjacji
    digitalWrite(LED_BUILTIN, HIGH);
  }
}

 

 

Karta VGA generuje pełne 640×480 @ 60 Hz

Obsługuje 4096 kolorów (4‑bit RGB)

Posiada własny zestaw rejestrów sterujących

Arduino wysyła dane przez 8‑bitową magistralę DB0..DB7

Piksele są pakowane w 3 bajty = 2 piksele

SRAM jest zapisywana w czasie rzeczywistym

DDRAM pozwala na wyświetlanie tekstu jak w HD44780

Można mieszać grafikę z tekstem

Gradient pokazuje pełną paletę kolorów

Buźka jest renderowana matematycznie (okręgi + łuk)

Tło pod tekstem jest generowane w SRAM

Całość działa na  autorskim kontrolerze FPGA

 

Nad kodem VHDL jeszcze pracuję. Jak będzie gotowy to opublikuje. 

Witam

Umieszczam po niżej działający kod. Trochę poprawiłem timming. Nie wprowadzałem do kodu dodatkowych funkcji jak rysowanie figur 2d ponieważ układ xc3s50a który zastosowałem nie ma zasobów by zrobić z niego mini gpu. Ograniczeniem też jest czas propagacji. Karta działa stabilnie i jest alternatywą dla wyświetlacza znakowego lcd.

moduł główny:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity VgaModule is
    Port ( 
           CLK : in   STD_LOGIC;
           HS : out  STD_LOGIC;
           VS : out  STD_LOGIC;
           RGB : out  STD_LOGIC_VECTOR (11 downto 0);
           OE : inout STD_LOGIC;
           WE : out STD_LOGIC;
           A : out STD_LOGIC_VECTOR (18 downto 0);
           D : inout STD_LOGIC_VECTOR (7 downto 0);
           RS : in STD_LOGIC;
           RW : in STD_LOGIC;
           E : in STD_LOGIC;
           DB : inout STD_LOGIC_VECTOR (7 downto 0)
          );
end VgaModule;

architecture Behavioral of VgaModule is

   signal H, V, BL, EnH, EnV, Ph1, Ph3, Ph5, Pfl, Pse, Ren, Fen, Cen, Cat, Cch, Endl, CG_B0, CG_G0, CG_R0 : std_logic;
   signal Pixel0, CGreg : std_logic_vector(7 downto 0);
   signal Pixel1, CG_RGB : std_logic_vector(11 downto 0);
   signal Cnt25 : std_logic_vector(2 downto 0) := (others => '0');
   signal CntH, CntV, CntF : std_logic_vector(9 downto 0) := (others => '0');
   signal CntR : std_logic_vector(8 downto 0) := (others => '0');
   signal Afl : std_logic_vector(18 downto 0);
   signal Dfl : std_logic_vector(10 downto 0);
   signal CntC : std_logic_vector(5 downto 0) := (others => '0');
   

	COMPONENT CGRam
	PORT(
		CLK : IN std_logic;
		CG_WE : IN std_logic;
		DD_WE : IN std_logic;
		CG_DI : IN std_logic_vector(7 downto 0);
		DD_DI : IN std_logic_vector(16 downto 0);
		CG_A_RD : IN std_logic_vector(10 downto 0);
		DD_A_RD : IN std_logic_vector(10 downto 0);
		CG_A_WE : IN std_logic_vector(10 downto 0);
		DD_A_WE : IN std_logic_vector(10 downto 0);          
		CG_DO : OUT std_logic_vector(7 downto 0);
		DD_DO : OUT std_logic_vector(16 downto 0)
		);
	END COMPONENT;
   
   signal CG_WE : std_logic;
   signal DD_WE : std_logic;
   signal CG_DI : std_logic_vector(7 downto 0);
   signal DD_DI : std_logic_vector(16 downto 0);
   signal CG_ADDR_RD : std_logic_vector(10 downto 0);
   signal DD_ADDR_RD : std_logic_vector(10 downto 0);
   signal CG_ADDR_WE : std_logic_vector(10 downto 0);
   signal DD_ADDR_WE : std_logic_vector(10 downto 0);          
   signal CG_DO : std_logic_vector(7 downto 0);
   signal DD_DO : std_logic_vector(16 downto 0);

	COMPONENT InstructionDecoder
	PORT(
		CLK : IN std_logic;
		RS : IN std_logic;
		RW : IN std_logic;
		E : IN std_logic;    
		DB : INOUT std_logic_vector(7 downto 0);
		DDRAM_ADDR : INOUT std_logic_vector(10 downto 0);
		CGRAM_ADDR : INOUT std_logic_vector(10 downto 0);
		STRAM_ADDR : INOUT std_logic_vector(18 downto 0);      
		CURSOR_ON_OFF : OUT std_logic;
		CURSOR_BLINK : OUT std_logic;
		DISPLAY_ON_OFF : OUT std_logic;
		CGRAM_WE : OUT std_logic;
		DDRAM_WE : OUT std_logic;
		STRAM_WE : OUT std_logic;
		CURSOR_SHAPE : OUT std_logic_vector(1 downto 0);
		CURSOR_RGB : OUT std_logic_vector(11 downto 0);
		DDRAM_DATA : OUT std_logic_vector(16 downto 0);
		CGRAM_DATA : OUT std_logic_vector(7 downto 0);
		STRAM_DATA : OUT std_logic_vector(7 downto 0)
		);
	END COMPONENT;
   
   signal CURSOR_ON_OFF : std_logic;
   signal CURSOR_BLINK : std_logic;
   signal DISPLAY_ON_OFF : std_logic;
   signal CURSOR_RGB : std_logic_vector(11 downto 0);
   signal CURSOR_SHAPE : std_logic_vector(1 downto 0);
   signal ST_ADDR_WE : std_logic_vector(18 downto 0);
   signal ST_DI : std_logic_vector(7 downto 0);
   signal ST_WE : std_logic;

begin   

	Inst_CGRam: CGRam PORT MAP(
		CLK => CLK,
		CG_WE => CG_WE,
		DD_WE => DD_WE,
		CG_DI => CG_DI,
		DD_DI => DD_DI,
		CG_DO => CG_DO,
		DD_DO => DD_DO,
		CG_A_RD => CG_ADDR_RD,
		DD_A_RD => DD_ADDR_RD,
		CG_A_WE => CG_ADDR_WE,
		DD_A_WE => DD_ADDR_WE
	);

	Inst_InstructionDecoder: InstructionDecoder PORT MAP(
		CLK => CLK,
		RS => RS,
		RW => RW,
		E => E,
		DB => DB,
		CURSOR_ON_OFF => CURSOR_ON_OFF,
		CURSOR_BLINK => CURSOR_BLINK,
		DISPLAY_ON_OFF => DISPLAY_ON_OFF,
		CGRAM_WE => CG_WE,
		DDRAM_WE => DD_WE,
		STRAM_WE => ST_WE,
		DDRAM_ADDR => DD_ADDR_WE,
		CGRAM_ADDR => CG_ADDR_WE,
		STRAM_ADDR => ST_ADDR_WE,
		CURSOR_SHAPE => CURSOR_SHAPE,
		CURSOR_RGB => CURSOR_RGB,
		DDRAM_DATA => DD_DI,
		CGRAM_DATA => CG_DI,
		STRAM_DATA => ST_DI
	);
   
   ------------------------------------------------------------
   -- wyświetlanie obrazu --
   -------------------------
   process(CLK)
   begin
      if rising_edge(CLK) then
         if EnH = '1' then -- zapis sygnałów co 4 cykle
            HS <= H;
            VS <= V;
            if ((BL = '0') or (DISPLAY_ON_OFF = '0')) then
               RGB <= (others => '0');
            elsif Cen = '1' then
               RGB <= CURSOR_RGB;
            elsif Fen = '1' then
               RGB <= CG_RGB;
            elsif Cnt25(2) = '1' then
               RGB <= Pixel1;
            else
               RGB <= D(7 downto 4) & Pixel0; -- piksel kolor
            end if;
         end if;
      end if;
   end process;

   
   ------------------------------------------------------------
   -- generator sygnałów vga --
   ----------------------------
   --dzielnik częstotliwości Clk = 100MHz
   process(CLK)
   begin
      if rising_edge(CLK) then
         if Cnt25 = "111" then
            Cnt25 <= "000";
         else
            Cnt25 <= Cnt25 + 1;
         end if;
      end if;
   end process;

   EnH <= '1' when (Cnt25(1 downto 0) = 3) else '0';  --EnH = 100MHz/4 = 25MHz

   --licznik kolumn
   process(CLK)
   begin
      if rising_edge(CLK) then
         if EnH = '1' then
            if CntH = 799 then
               CntH <= (others => '0');
            else
               CntH <= CntH + 1;
            end if;
         end if;
      end if;
   end process;

   EnV <= '1' when ((CntH = 799) and (EnH = '1')) else '0';  --EnV = 25MHz/800 = 31,25kHz

   --licznik wierszy
   process(CLK)
   begin
      if rising_edge(CLK) then
         if EnV = '1' then
            if (CntV = 524) then
               CntV <= (others => '0');
               CntC <= CntC + 1;
            else
               CntV <= CntV + 1;
            end if;
         end if;
      end if;
   end process;

   --dekoder synchronizacji poziomej
   H  <= '0' when ((CntH > 655) and (CntH < 753)) else '1';

   --dekoder synchronizacji pionowej
   V  <= '0' when ((CntV > 489) and (CntV < 493)) else '1';

   --dekoder wygaszania obrazu poza obszarem wyświetlanym
   Bl <= '0' when ((CntH > 639) or  (CntV > 479)) else '1';
   
   Endl <= '1' when ((CntH = 799) and (Cnt25(1 downto 0) = 3)) else '0';
   
   ------------------------------------------------------------
   -- obsługa pamięci sram --
   --------------------------
   --sygnały pomocnicze
   Ph1 <= not Cnt25(2) and not Cnt25(1) and Cnt25(0); -- 001
   Ph3 <= not Cnt25(2) and     Cnt25(1) and Cnt25(0); -- 011
   Ph5 <=     Cnt25(2) and not Cnt25(1) and Cnt25(0); -- 101
   Pse <=     Cnt25(2) and     Cnt25(1); -- Pse > 110
   Pfl <= Ph1 or Ph3 or Ph5;
   
   --fazy odczytu danych z pamięci sram
   process(CLK)
   begin
      if rising_edge(CLK) then
         if Ph1 = '1' then
            Pixel0 <= D;
      elsif Ph3 = '1' then
            Pixel1(11 downto 8) <= D(3 downto 0);
      elsif Ph5 = '1' then
            Pixel1(7 downto 0) <= D;
         end if;
      end if;
   end process;
   
   --fazy inkrementacji licznika kolumn dla adresu odczytu pamięci sram
   process(CLK)
   begin
      if rising_edge(CLK) then
         if BL = '0' then
            CntF <= (others => '0');
         else
            if Pfl = '1' then
               CntF <= CntF + 1;
            end if;
         end if;
      end if;
   end process;
   
   --spłaszczanie adresu odczytu pamięci sram   
   Afl <= ("1111000000" * CntV(8 downto 0)) + CntF;
   
   --przypisanie sygnałów sterujących pamięcią sram
   A <= Afl when OE = '0' else ST_ADDR_WE;
   D <= ST_DI when OE = '1' else (others => 'Z');
   OE <= Pse and ST_WE;
   WE <= not OE;
   
   
   ------------------------------------------------------------
   -- obsługa pamięci cgram --
   ---------------------------
   -- wykrywanie obszaru tekstu (od 40 linii do 440 linii)
   Ren <= '1' when ((CntV > 39) and (CntV < 441)) else '0';
   
   -- licznik wierszy tekstu i znaków
   process(CLK)
   begin
      if rising_edge(CLK) then
         if Ren = '0' then
            CntR <= (others => '0');
         elsif Endl = '1' then
            CntR <= CntR + 1;
         end if;
      end if;
   end process;
   
   -- odczyt pamięci ddram (80 kolumn * 25 wierszy = 2000 znaków)
--   DD_ADDR_RD <= ("1010000" * CntR(8 downto 4)) + CntH(9 downto 3); -- (80 * 25) = 2000
   Dfl <= (CntR(8 downto 4) & "000000") + -- row * 64 +
          (CntR(8 downto 4) & "0000") +   -- row * 16 +
           CntH(9 downto 3);              -- col
   
   DD_ADDR_RD <= Dfl;
   
   -- odczyt pamięci cgram (kod znaku & wiersz znaku)
   CG_ADDR_RD <= DD_DO(7 downto 0) & CntR(2 downto 0);
   
   --odczyt zawartości wiersza znaku
   process(CLK)
   begin
      if rising_edge(CLK) then
         if Cnt25(1 downto 0) = "10" then
            if CntH(2 downto 0) = "000" then
               CGreg <= CG_DO;
            else
               CGreg <= CGreg(6 downto 0) & '0';
            end if;
         end if;
      end if;
   end process;
   
   -- dekoder znaku
   Fen <= CGreg(7) and CntR(3);
   
   -- odczyt atrybutu koloru znaków
   CG_RGB <= DD_DO(16 downto 14) & CG_B0 & DD_DO(13 downto 11) & CG_G0 & DD_DO(10 downto 8) & CG_R0 ;
   -- rozszerzenie do 12 bit
   CG_R0 <= DD_DO(10) or DD_DO(9)  or DD_DO(8);
   CG_G0 <= DD_DO(13) or DD_DO(12) or DD_DO(11);
   CG_B0 <= DD_DO(16) or DD_DO(15) or DD_DO(14);
   
   
   ------------------------------------------------------------
   -- generator kursora --
   -----------------------
   
   -- dekoder zezwolenia na wyświetlanie kursora (stabilizacja sygnału w procesie zegarowym)
   process(CLK)
   begin
      if rising_edge(CLK) then
         Cen <= CURSOR_ON_OFF and Cch and Cat and CntR(3) and (not CURSOR_BLINK or CntC(CntC'left));
      end if;
   end process;
   
   -- dekoder pozycji kursora (adres zapisu do ddram = adres odczytu ddram)
   Cat <= '1' when (DD_ADDR_WE = DD_ADDR_RD) else '0';
   -- dekoder kształtu kursora (pionowa kreska za znakiem)
   with CURSOR_SHAPE select
   Cch <= (CntR(2) or CntR(1) or CntR(0)) and
                    (CntH(2) and CntH(1) and CntH(0))    when "01", -- kreska pionowa
                    (CntH(2) or CntH(1) or CntH(0)) and 
                    (CntR(2) and CntR(1) and CntR(0))    when "10", -- podłoga
                    '1'                                  when "11", -- pełny kształt
                    '0'                                  when others;
   

end Behavioral;

 

moduł pamięci BRAM:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity CGRam is
    Port ( 
           CLK        : in   STD_LOGIC;
           CG_WE      : in   STD_LOGIC;
           DD_WE      : in   STD_LOGIC;
           CG_DI      : in   STD_LOGIC_VECTOR (7 downto 0);
           DD_DI      : in   STD_LOGIC_VECTOR (16 downto 0);
           CG_DO      : out  STD_LOGIC_VECTOR (7 downto 0);
           DD_DO      : out  STD_LOGIC_VECTOR (16 downto 0);
           CG_A_RD    : in   STD_LOGIC_VECTOR (10 downto 0);
           DD_A_RD    : in   STD_LOGIC_VECTOR (10 downto 0);
           CG_A_WE    : in   STD_LOGIC_VECTOR (10 downto 0);
           DD_A_WE    : in   STD_LOGIC_VECTOR (10 downto 0)
          );
end CGRam;

architecture Behavioral of CGRam is

   -- tablica tekstu (2048 znaków asci)
   type ram_ddtype is array (0 to 2047) of std_logic_vector (7 downto 0);   
	signal DD_RAM : ram_ddtype;
   -- tablica atrybutów tekstu (kolory znaku) (R 0:2), (G 3:5), (B 6:8)
   type ram_attrtype is array (0 to 2047) of std_logic_vector (8 downto 0);
	signal ATTR_RAM : ram_attrtype;
   -- tablica znaków (definicje znaków 8 x 8 pikseli)
   type ram_cgtype is array (0 to 2047) of std_logic_vector (7 downto 0);   
	signal CG_RAM : ram_cgtype:= (
   -- tablica znaków CharRom
      --
      -- Implementacja BRAM FPGA SPARTAN 3
      -- Adres 11 bit = 2048x8
      --
      -- przykład kodowania znaku 'A':
      --
      -- X"1C', X"22", X"22, X"22", X"3E", X"22", X"22", X"00"
      --
      --             0 1 2 3 4 5 6 7
      --            _________________
      -- X"1C"   0 | 0 0 0 1 1 1 0 0
      -- X"22"   1 | 0 0 1 0 0 0 1 0
      -- X"22"   2 | 0 0 1 0 0 0 1 0
      -- X"22"   3 | 0 0 1 0 0 0 1 0
      -- X"3E"   4 | 0 0 1 1 1 1 1 0
      -- X"22"   5 | 0 0 1 0 0 0 1 0
      -- X"22"   6 | 0 0 1 0 0 0 1 0
      -- X"00"   7 | 0 0 0 0 0 0 0 0

      -- adres(8 bitów) | bajty danych znaku (wybierane przez dolne 3 bity adresu) razem 11 bitów adresu
      --00 = (górne 8 bitów)
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", -- (dolne 3 bity)
      --01
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --02
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --03
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --04
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --05
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --06
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --07
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --08
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --09
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --0A
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --0B
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --0C
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --0D
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --0E
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --0F
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --10
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --11
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --12
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --13
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --14
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --15
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --16
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --17
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --18
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --19
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --1A
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --1B
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --1C
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --1D
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --1E
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --1F
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      
      --20
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --21
         X"08", X"08", X"08", X"08", X"08", X"00", X"08", X"00", -- !
      --22
         X"14", X"14", X"14", X"00", X"00", X"00", X"00", X"00", -- "
      --23
         X"14", X"14", X"3E", X"14", X"3E", X"14", X"14", X"00", -- #
      --24
         X"08", X"1E", X"28", X"1C", X"0A", X"3C", X"08", X"00", -- $
      --25
         X"30", X"32", X"04", X"08", X"10", X"26", X"05", X"00", -- %
      --26
         X"18", X"24", X"28", X"10", X"2A", X"24", X"1A", X"00", -- &
      --27
         X"18", X"08", X"08", X"00", X"00", X"00", X"00", X"00", -- '
      --28
         X"04", X"08", X"10", X"10", X"10", X"08", X"04", X"00", -- (
      --29
         X"10", X"08", X"04", X"04", X"04", X"08", X"10", X"00", -- )
      --2A
         X"00", X"2A", X"1C", X"3E", X"1C", X"2A", X"00", X"00", -- *
      --2B
         X"00", X"08", X"08", X"3E", X"08", X"08", X"00", X"00", -- +
      --2C
         X"00", X"00", X"00", X"00", X"18", X"18", X"08", X"10", -- ,
      --2D
         X"00", X"00", X"00", X"3E", X"00", X"00", X"00", X"00", -- -
      --2E
         X"00", X"00", X"00", X"00", X"00", X"18", X"18", X"00", -- .
      --2F
         X"00", X"02", X"04", X"08", X"10", X"20", X"00", X"00", -- /

      --30
         X"1C", X"22", X"26", X"2A", X"32", X"22", X"1C", X"00", --0
      --31
         X"08", X"18", X"08", X"08", X"08", X"08", X"1C", X"00", --1
      --32
         X"1C", X"22", X"02", X"04", X"08", X"10", X"3E", X"00", --2
      --33
         X"3E", X"04", X"08", X"04", X"02", X"22", X"1C", X"00", --3
      --34
         X"04", X"0C", X"14", X"24", X"3E", X"04", X"04", X"00", --4
      --35
         X"3E", X"20", X"3C", X"02", X"02", X"22", X"1C", X"00", --5
      --36
         X"0C", X"10", X"20", X"3C", X"22", X"22", X"1C", X"00", --6
      --37
         X"3E", X"22", X"04", X"08", X"10", X"10", X"10", X"00", --7
      --38
         X"1C", X"22", X"22", X"1C", X"22", X"22", X"1C", X"00", --8
      --39
         X"1C", X"22", X"22", X"1E", X"02", X"22", X"1C", X"00", --9
      --3A
         X"00", X"00", X"18", X"18", X"00", X"18", X"18", X"00", -- :
      --3B
         X"00", X"00", X"18", X"18", X"00", X"18", X"08", X"10", -- ;
      --3C
         X"04", X"08", X"10", X"20", X"10", X"08", X"04", X"00", -- <
      --3D
         X"00", X"00", X"3E", X"00", X"3E", X"00", X"00", X"00", -- =
      --3E
         X"10", X"08", X"04", X"02", X"04", X"08", X"10", X"00", -- >
      --3F
         X"1C", X"22", X"02", X"04", X"08", X"00", X"08", X"00", -- ?

      --40
         X"1C", X"22", X"02", X"1A", X"2A", X"2A", X"1C", X"00", -- @
      --41
         X"1C", X"22", X"22", X"22", X"3E", X"22", X"22", X"00", --A
      --42
         X"3C", X"22", X"22", X"3C", X"22", X"22", X"3C", X"00", --B
      --43
         X"1C", X"22", X"20", X"20", X"20", X"22", X"1C", X"00", --C
      --44
         X"38", X"24", X"22", X"22", X"22", X"24", X"38", X"00", --D
      --45
         X"3E", X"20", X"20", X"3C", X"20", X"20", X"3E", X"00", --E
      --46
         X"3E", X"20", X"20", X"3C", X"20", X"20", X"20", X"00", --F
      --47
         X"1C", X"22", X"20", X"2E", X"22", X"22", X"1E", X"00", --G
      --48
         X"22", X"22", X"22", X"3E", X"22", X"22", X"22", X"00", --H
      --49
         X"1C", X"08", X"08", X"08", X"08", X"08", X"1C", X"00", --I
      --4A
         X"1C", X"04", X"04", X"04", X"04", X"24", X"18", X"00", --J
      --4B
         X"22", X"24", X"28", X"30", X"28", X"24", X"22", X"00", --K
      --4C
         X"20", X"20", X"20", X"20", X"20", X"20", X"3E", X"00", --L
      --4D
         X"22", X"36", X"2A", X"22", X"22", X"22", X"22", X"00", --M
      --4E
         X"22", X"22", X"32", X"2A", X"26", X"22", X"22", X"00", --N
      --4F
         X"1C", X"22", X"22", X"22", X"22", X"22", X"1C", X"00", --O
      --50
         X"3C", X"22", X"22", X"3C", X"20", X"20", X"20", X"00", --P
      --51
         X"1C", X"22", X"22", X"22", X"2A", X"24", X"1A", X"00", --Q
      --52
         X"3C", X"22", X"22", X"3E", X"28", X"24", X"22", X"00", --R
      --53
         X"1E", X"20", X"20", X"1C", X"02", X"02", X"3C", X"00", --S
      --54
         X"3E", X"08", X"08", X"08", X"08", X"08", X"08", X"00", --T
      --55
         X"22", X"22", X"22", X"22", X"22", X"22", X"1C", X"00", --U
      --56
         X"22", X"22", X"22", X"22", X"22", X"14", X"08", X"00", --V
      --57
         X"22", X"22", X"22", X"2A", X"2A", X"2A", X"14", X"00", --W
      --58
         X"22", X"22", X"14", X"08", X"14", X"22", X"22", X"00", --X
      --59
         X"22", X"22", X"22", X"14", X"08", X"08", X"08", X"00", --Y
      --5A
         X"3E", X"02", X"04", X"08", X"10", X"20", X"3E", X"00", --Z
      --5B
         X"1C", X"10", X"10", X"10", X"10", X"10", X"1C", X"00", -- [
      --5C
         X"00", X"20", X"10", X"08", X"04", X"02", X"00", X"00", -- \
      --5D
         X"1C", X"04", X"04", X"04", X"04", X"04", X"1C", X"00", -- ]
      --5E
         X"08", X"14", X"22", X"00", X"00", X"00", X"00", X"00", -- ^
      --5F
         X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"3E", -- _

      --60
         X"10", X"08", X"04", X"00", X"00", X"00", X"00", X"00", -- `
      --61
         X"00", X"00", X"1C", X"02", X"1E", X"22", X"1E", X"00", --a
      --62
         X"20", X"20", X"2C", X"32", X"22", X"22", X"3C", X"00", --b
      --63
         X"00", X"00", X"1C", X"20", X"20", X"22", X"1C", X"00", --c
      --64
         X"02", X"02", X"1A", X"26", X"22", X"22", X"1E", X"00", --d
      --65
         X"00", X"00", X"1C", X"22", X"3E", X"20", X"1C", X"00", --e
      --66
         X"0C", X"10", X"10", X"38", X"10", X"10", X"10", X"00", --f
      --67
         X"00", X"00", X"1E", X"22", X"22", X"1E", X"02", X"1C", --g
      --68
         X"20", X"20", X"2C", X"32", X"22", X"22", X"22", X"00", --h
      --69
         X"08", X"00", X"18", X"08", X"08", X"08", X"1C", X"00", --i
      --6A
         X"04", X"00", X"0C", X"04", X"04", X"04", X"24", X"18", --j
      --6B
         X"20", X"20", X"24", X"28", X"30", X"28", X"24", X"00", --k
      --6C
         X"18", X"08", X"08", X"08", X"08", X"08", X"1C", X"00", --l
      --6D
         X"00", X"00", X"34", X"2A", X"2A", X"2A", X"2A", X"00", --m
      --6E
         X"00", X"00", X"2C", X"32", X"22", X"22", X"22", X"00", --n
      --6F
         X"00", X"00", X"1C", X"22", X"22", X"22", X"1C", X"00", --o
         
      --70
         X"00", X"00", X"3C", X"22", X"22", X"3C", X"20", X"20", --p
      --71
         X"00", X"00", X"1A", X"26", X"22", X"1E", X"02", X"02", --q
      --72
         X"00", X"00", X"2C", X"32", X"20", X"20", X"20", X"00", --r
      --73
         X"00", X"00", X"1E", X"20", X"1C", X"02", X"3C", X"00", --s
      --74
         X"10", X"10", X"38", X"10", X"10", X"12", X"0C", X"00", --t
      --75
         X"00", X"00", X"22", X"22", X"22", X"26", X"1A", X"00", --u
      --76
         X"00", X"00", X"22", X"22", X"22", X"14", X"08", X"00", --v
      --77
         X"00", X"00", X"22", X"22", X"2A", X"2A", X"14", X"00", --w
      --78
         X"00", X"00", X"22", X"14", X"08", X"14", X"22", X"00", --x
      --79
         X"00", X"00", X"22", X"22", X"22", X"1E", X"02", X"1C", --y
      --7A
         X"00", X"00", X"3E", X"04", X"08", X"10", X"3E", X"00", --z
      --7B
         X"04", X"08", X"08", X"10", X"08", X"08", X"04", X"00", -- {
      --7C
         X"08", X"08", X"08", X"08", X"08", X"08", X"08", X"00", -- |
      --7D
         X"10", X"08", X"08", X"04", X"08", X"08", X"10", X"00", -- }
      --7E
         X"00", X"00", X"10", X"2A", X"04", X"00", X"00", X"00", -- ~
      --7F
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --80
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --81
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --82
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --83
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --84
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --85
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --86
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --87
      X"04", X"2A", X"32", X"32", X"2A", X"26", X"22", X"00", --Ń
      --88
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --89
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --8A
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --8B
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --8C
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --8D
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --8E
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --8F
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --90
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --91
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --92
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --93
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --94
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --95
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --96
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --97
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --98
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --99
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --9A
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --9B
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --9C
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --9D
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --9E
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --9F
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --A0
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A1
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A2
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A3
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A4
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A5
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A6
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A7
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A8
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --A9
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --AA
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --AB
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --AC
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --AD
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --AE
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --AF
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --B0
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B1
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B2
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B3
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B4
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B5
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B6
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B7
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B8
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --B9
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --BA
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --BB
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --BC
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --BD
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --BE
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --BF
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --C0
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C1
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C2
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C3
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C4
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C5
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C6
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C7
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C8
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --C9
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --CA
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --CB
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --CC
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --CD
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --CE
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --CF
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --D0
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D1
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D2
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D3
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D4
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D5
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D6
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D7
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D8
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --D9
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --DA
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --DB
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --DC
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --DD
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --DE
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --DF
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --E0
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E1
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E2
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E3
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E4
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E5
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E6
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E7
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E8
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --E9
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --EA
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --EB
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --EC
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --ED
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --EE
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --EF
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",

      --F0
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F1
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F2
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F3
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F4
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F5
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F6
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F7
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F8
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --F9
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --FA
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --FB
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --FC
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --FD
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --FE
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
      --FF
      X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00"
        ); 

begin

   -- odczyt (zapis) znaków w tablicy tekstu
   process(Clk)
   begin
      if rising_edge(CLK) then
         if DD_WE = '1' then
            DD_RAM(conv_integer(DD_A_WE)) <= DD_DI(7 DOWNTO 0);
         end if;
         DD_DO(7 DOWNTO 0) <= DD_RAM(conv_integer(DD_A_RD));
      end if;
   end process;

   -- odczyt (zapis) znaków w tablicy atrybutów tekstu
   process(Clk)
   begin
      if rising_edge(CLK) then
         if DD_WE = '1' then
            ATTR_RAM(conv_integer(DD_A_WE)) <= DD_DI(16) & DD_DI(15 DOWNTO 8);
         end if;
         DD_DO(16 DOWNTO 8) <= ATTR_RAM(conv_integer(DD_A_RD));
      end if;
   end process;
   
   -- odczyt (zapis) znaków w tablicy znaków
   process(Clk)
   begin
      if rising_edge(CLK) then
         if CG_WE = '1' then
            CG_RAM(conv_integer(CG_A_WE)) <= CG_DI;
         end if;
         CG_DO <= CG_RAM(conv_integer(CG_A_RD));
      end if;
   end process;

end Behavioral;

 

moduł kontrolera podobnego do HD44780:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity InstructionDecoder is
    Port ( 
           -- zegar systemowy
           CLK             : in     STD_LOGIC;
           -- linie komunikacyjne dla kontrolera zewnętrznego
           RS              : in     STD_LOGIC;
           RW              : in     STD_LOGIC;
           E               : in     STD_LOGIC;
           DB              : inout  STD_LOGIC_VECTOR (7 downto 0);
           -- linie sygnałowe wewnętrzne
           CURSOR_ON_OFF   : out    STD_LOGIC;
           CURSOR_BLINK    : out    STD_LOGIC;
           DISPLAY_ON_OFF  : out    STD_LOGIC;
           CGRAM_WE        : out    STD_LOGIC;
           DDRAM_WE        : out    STD_LOGIC;
           STRAM_WE        : out    STD_LOGIC;
           DDRAM_ADDR      : inout  STD_LOGIC_VECTOR (10 downto 0);
           CGRAM_ADDR      : inout  STD_LOGIC_VECTOR (10 downto 0);
           STRAM_ADDR      : inout  STD_LOGIC_VECTOR (18 downto 0);
           CURSOR_SHAPE    : out    STD_LOGIC_VECTOR (1 downto 0);
           CURSOR_RGB      : out    STD_LOGIC_VECTOR (11 downto 0);
           DDRAM_DATA      : out    STD_LOGIC_VECTOR (16 downto 0);
           CGRAM_DATA      : out    STD_LOGIC_VECTOR (7 downto 0);
           STRAM_DATA      : out    STD_LOGIC_VECTOR (7 downto 0)
          );
end InstructionDecoder;

architecture Behavioral of InstructionDecoder is

   signal DISPLAY_DATA, CLK_EDGE, REG_B0, REG_B1 : std_logic_vector (7 downto 0);
   signal REG_B2 : std_logic_vector (6 downto 0);
   signal RGBF : std_logic_vector (8 downto 0);
   signal RGBC : std_logic_vector (11 downto 0);
   signal CLS_CNT : std_logic_vector (22 downto 0) := "10000000000000000000000";
   
   -- sygnały dekodera instrukcji HD44780
   signal INSTRUCTION, CURSOR_AT_HOME, ENTRY_MODE_SET, DISPLAY_ON_OFF_CONTROL, CURSOR_SHIFT,
          REGISTER_SET, ADDRESS_SET, DATA_RAM_WRITE_SET, DATA_WRITE, CLEAR_DISPLAY,
          AI, I_D, DON, CON, CBL, B0, B1, B2, DDW, CGW, STW, SHP0, SHP1, CLS, BF : std_logic := '0';
          
   type state_type is (idle, state1, state2, state3, state4);
   signal state : state_type := idle;
   
begin

   INSTRUCTION <= not RS and not RW;
   DATA_WRITE <= RS and not RW; 
   

   --dekoder instrukcji w procesie kombinatoryjnym
   process(INSTRUCTION, DB)
   begin
   
      CLEAR_DISPLAY <= '0';           -- " 0   0   0   0   0   0   0  CLS "
      CURSOR_AT_HOME <= '0';          -- " 0   0   0   0   0   0   1   *  "
      ENTRY_MODE_SET <= '0';          -- " 0   0   0   0   0   1   AI I/D "
      DISPLAY_ON_OFF_CONTROL <= '0';  -- " 0   0   0   0   1  DON CON CBL "
      CURSOR_SHIFT <= '0';            -- " 0   0   0   1  L/R  *   *   *  "
      REGISTER_SET <= '0';            -- " 0   0   1   B0  B1  B2 RGB RGB "
      ADDRESS_SET <= '0';             -- " 0   1  DDA CGA STA SHP SHP  *  "
      DATA_RAM_WRITE_SET <= '0';      -- " 1  DDW CGW STW  *   *   *   *  "
      
      if INSTRUCTION = '1' then
         if DB = "00000001" then
            CLEAR_DISPLAY <= '1';
         elsif DB(7 downto 1) = "0000001" then
            CURSOR_AT_HOME <= '1';
         elsif DB(7 downto 2) = "000001" then
            ENTRY_MODE_SET <= '1';
         elsif DB(7 downto 3) = "00001" then
            DISPLAY_ON_OFF_CONTROL <= '1';
         elsif DB(7 downto 4) = "0001" then
            CURSOR_SHIFT <= '1';
         elsif DB(7 downto 5) = "001" then
            REGISTER_SET <= '1';
         elsif DB(7 downto 6) = "01" then
            ADDRESS_SET <= '1';
         elsif DB(7) = '1' then
            DATA_RAM_WRITE_SET <= '1';
         end if;
      end if;
      
   end process;
   
   
   
   -- rejestrowanie sygnału E w rejestrze przesuwającym
   process(CLK)
   begin
      if rising_edge(CLK) then
         CLK_EDGE <= E & CLK_EDGE(7 downto 1);
      end if;
   end process;
   
   -- fazy wykonania instrukcji w maszynie stanów
   process(CLK)
   begin
      if rising_edge(CLK) then
         case state is
         
            when idle =>
            if (CLK_EDGE = "10000000") then -- wykrycie narastającego zbocza sygnału E
               BF <= '1';
               -- instrukcje kontrolera:
               if CLEAR_DISPLAY = '1' then -- nadpisywanie pamięci ddram i sram
                  CLS <= '1';
                  DDRAM_WE <= '1';
                  STRAM_WE <= '1';
                  CLS_CNT <= (others => '0');
                  state <= state4;
               end if;
               
               if CURSOR_AT_HOME = '1' then -- ustawienie kursora na początku wiersza i kolumny
                  DDRAM_ADDR <= (others => '0');  -- cursor/ddram addr = 0
               end if; 
               
               if ENTRY_MODE_SET = '1' then -- ustawienie postkrementacji
                  AI <= DB(1);  -- auto increment
                  I_D <= DB(0); -- inc/dec
               end if; 
               
               if DISPLAY_ON_OFF_CONTROL = '1' then
                  DON <= DB(2); -- displ on/off
                  CON <= DB(1); -- cursor on/off
                  CBL <= DB(0); -- cursor blink on/off
               end if; 
               
               if CURSOR_SHIFT = '1' then -- przesuwanie kurosra o jedną pozycję
                  if DB(3) = '1' then
                     DDRAM_ADDR <= DDRAM_ADDR + 1; -- cursor/ddram addr shiift right
                  else
                     DDRAM_ADDR <= DDRAM_ADDR - 1; -- cursor/ddram addr shiift left
                  end if;
               end if; 
               
               if REGISTER_SET = '1' then -- zapis danych do rejestrów pomocniczych
                  B0 <= DB(4); -- B0 set
                  B1 <= DB(3); -- B1 set
                  B2 <= DB(2); -- B2 set
                  if DB(1) = '1' then
                     RGBF <= REG_B2(6 downto 4) & REG_B1(7 downto 5) & REG_B0(7 downto 5); --  set fond color
                  end if;
                  if DB(0) = '1' then
                     RGBC <= REG_B2(6 downto 3) & REG_B1(7 downto 4) & REG_B0(7 downto 4); --  set cursor color
                  end if;
               end if;
               
               if ADDRESS_SET = '1' then -- zapis informacji o adresie z rejestrów pomocniczych
                  if DB(5) = '1' then
                     DDRAM_ADDR <= REG_B1(2 downto 0) & REG_B0; --  set ddram addr
                  end if;
                  if DB(4) = '1' then
                     CGRAM_ADDR <= REG_B1(2 downto 0) & REG_B0; --  set cgram addr
                  end if;
                  if DB(3) = '1' then
                     STRAM_ADDR <= REG_B2(2 downto 0) & REG_B1 & REG_B0; --  set sram addr
                  end if;
                  SHP0 <= DB(1); -- ustawienie kształtu kursora
                  SHP1 <= DB(2);
               end if;
               
               if DATA_RAM_WRITE_SET = '1' then -- wybór pamięci do zapisu danych
                  DDW <= DB(6); --  set ddram data
                  CGW <= DB(5); --  set cgram data
                  STW <= DB(4); --  set sram data
               end if;
               
               if DATA_WRITE = '1' then -- zapis danych
                  if B0 = '1' then -- test aktywacji zapisu danych do rejestru B0
                     REG_B0 <= DB;
                  end if;
                  if B1 = '1' then -- test aktywacji zapisu danych do rejestru B1
                     REG_B1 <= DB;
                  end if;
                  if B2 = '1' then -- test aktywacji zapisu danych do rejestru B2
                     REG_B2 <= DB(7 downto 4) & DB(2 downto 0);
                  end if;
                  if DDW = '1' or CGW = '1' or STW = '1' then -- test aktywacji zapisu danych do wybranej pamięci
                     state <= state1;
                  end if;
               end if;
               
            end if;
         
            when state1 => -- włączanie wybranych sygnałów zapisu
               DDRAM_WE <= DDW;
               CGRAM_WE <= CGW;
               STRAM_WE <= STW;
               state <= state2;
         
            when state2 => -- wyłączanie sygnałów zapisu wewnętrznych bram
               DDRAM_WE <= '0';
               CGRAM_WE <= '0';
               state <= state3;
         
            when state3 => -- sprawdzanie sygnału E
               -- koniec sygnału E
               if (CLK_EDGE = "00000000") then
                  
                  BF <= '0'; -- wyłaczanie sygnału zajętości
                  STRAM_WE <= '0'; -- wyłaczanie zapisu zewnętrznej pamięci sram
                  state <= idle;
                  
                  if DATA_WRITE = '1' then -- sprawdzanie warunków postinkrementacji
                     if AI = '1' then -- auto increment on
                        if DDW = '1' then
                           if I_D = '1' then
                              DDRAM_ADDR <= DDRAM_ADDR + 1;
                           else
                              DDRAM_ADDR <= DDRAM_ADDR - 1;
                           end if;
                        end if;
                        if CGW = '1' then
                           if I_D = '1' then
                              CGRAM_ADDR <= CGRAM_ADDR + 1;
                           else
                              CGRAM_ADDR <= CGRAM_ADDR - 1;
                           end if;
                        end if;
                        if STW = '1' then
                           if I_D = '1' then
                              STRAM_ADDR <= STRAM_ADDR + 1;
                           else
                              STRAM_ADDR <= STRAM_ADDR - 1;
                           end if;
                        end if;
                     end if;
                  end if;
               end if;
               
            when state4 => -- blok nadpisywania pamięci ddram i sram (logiczne 0)
               if CLS = '1' then -- clear display
                  if ClS_CNT(22) = '1' then -- wykrycie końca zapisu przez licznik adresu (22 = przepełnienie licznika adresu)
                     CLS <= '0';
                     BF <= '0';
                     DDRAM_WE <= '0';
                     STRAM_WE <= '0';
                     STRAM_ADDR <= (others => '0');
                     DDRAM_ADDR <= (others => '0');
                     state <= idle;
                  else
                     CLS_CNT <= CLS_CNT + 1;
                     STRAM_ADDR <= CLS_CNT(21 downto 3);
                     DDRAM_ADDR <= CLS_CNT(21 downto 11);
                  end if;
               end if;
         
         end case;
      end if;
   end process;
   
   DISPLAY_ON_OFF <= DON;
   CURSOR_ON_OFF <= CON;
   CURSOR_BLINK <= CBL;
   CURSOR_SHAPE <= SHP1 & SHP0;
   CURSOR_RGB <= RGBC;
   DDRAM_DATA <= RGBF & DB when (CLS = '0') else (others => '0'); -- znak i kolor do zapisu dla ddram
   CGRAM_DATA <= DB when (CLS = '0') else (others => '0'); -- dane do zapisu dla cgram
   STRAM_DATA <= DB when (CLS = '0') else (others => '0'); -- dane do zapisu dla sram
   
   -- konfiguracja portu danych (IN/OUT)
   DB <= DISPLAY_DATA when (RW = '1') else (others => 'Z');
   DISPLAY_DATA <= (BF & "0000000");

end Behavioral;

 

plik UCF:

#
## VGA_SPATAN3_CARD
#
#
NET   "CLK"     LOC = "p43"  | IOSTANDARD = LVCMOS33 ;
NET "CLK" TNM_NET = "CLKGRP";
TIMESPEC TS_CLK = PERIOD "CLKGRP" 10 ns HIGH 50%;

#
NET   "A<0>"    LOC = "p3"   | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<1>"    LOC = "p4"   | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<2>"    LOC = "p5"   | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<3>"    LOC = "p6"   | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<4>"    LOC = "p9"   | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<5>"    LOC = "p44"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<6>"    LOC = "p49"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<7>"    LOC = "p50"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<8>"    LOC = "p52"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<9>"    LOC = "p56"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<10>"   LOC = "p35"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<11>"   LOC = "p34"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<12>"   LOC = "p33"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<13>"   LOC = "p32"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<14>"   LOC = "p31"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<15>"   LOC = "p16"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<16>"   LOC = "p15"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<17>"   LOC = "p13"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "A<18>"   LOC = "p12"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<0>"    LOC = "p10"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<1>"    LOC = "p36"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<2>"    LOC = "p37"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<3>"    LOC = "p40"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<4>"    LOC = "p30"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<5>"    LOC = "p29"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<6>"    LOC = "p28"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "D<7>"    LOC = "p20"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "OE"      LOC = "p19"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "WE"      LOC = "p41"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
##
NET   "RS"      LOC = "p57"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RW"      LOC = "p68"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "E"       LOC = "p82"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<0>"   LOC = "p59"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<1>"   LOC = "p60"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<2>"   LOC = "p61"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<3>"   LOC = "p62"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<4>"   LOC = "p64"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<5>"   LOC = "p65"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<6>"   LOC = "p70"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "DB<7>"   LOC = "p71"  | PULLDOWN | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
##
NET   "HS"      LOC = "p73"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST |  TIG;
NET   "VS"      LOC = "p72"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST |  TIG;
NET   "RGB<3>"  LOC = "p98"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST; # RED
NET   "RGB<2>"  LOC = "p94"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<1>"  LOC = "p93"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<0>"  LOC = "p90"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<7>"  LOC = "p89"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST; # GREEN
NET   "RGB<6>"  LOC = "p88"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<5>"  LOC = "p86"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<4>"  LOC = "p85"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<11>"  LOC = "p84"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST; # BLUE
NET   "RGB<10>"  LOC = "p83"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<9>" LOC = "p78"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;
NET   "RGB<8>" LOC = "p77"  | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = FAST;

 

obraz zainstalowanych modułów vhdl w programie ise webpack 14.6:

image.thumb.png.be07daf5958ec326b605267f8a55f2c0.png

PS: Mam problem z inicjalizacją układu przez spi. wszystko działa poza odczytem pamięci SRAM. (Przesunięte piksele). Dla odmiany gdy programuje przez JTAG obraz poprawny. Będę wdzięczny za każdą sugestię.

  • Lubię! 1

@piotr96 Brak ostrzeżeń dotyczących timingu lub sygnałów i tu mam problem, bo nie wiem co sie dzieje.Jedyna informacja jest o nie wykorzystanym pinie parzystości z bram na wyjściu porta. Tego pinu nie używam bo mam pamięć skonfigurowaną jako 2 portową i logicznie zapisuje przez port A, odczytuje przez port B, Dodatkowy 9 bit parzystości wykorzystuje dla 3 bitu koloru niebieskiego jako uzupełnienie R,G,B = 3,3,2+1 = 8 bitów bram+1 bit parzystości. I to jest jedyne ostrzeżenie. ta informacja nie wpływa na działanie układu.

Jak masz ochotę zerknąć niżej jest raport syntezy:

Release 14.6 - xst P.68d (nt64)
Copyright (c) 1995-2013 Xilinx, Inc.  All rights reserved.
--> Parameter TMPDIR set to xst/projnav.tmp


Total REAL time to Xst completion: 0.00 secs
Total CPU time to Xst completion: 0.14 secs
 
--> Parameter xsthdpdir set to xst


Total REAL time to Xst completion: 0.00 secs
Total CPU time to Xst completion: 0.14 secs
 
--> Reading design: VgaModule.prj

TABLE OF CONTENTS
  1) Synthesis Options Summary
  2) HDL Compilation
  3) Design Hierarchy Analysis
  4) HDL Analysis
  5) HDL Synthesis
     5.1) HDL Synthesis Report
  6) Advanced HDL Synthesis
     6.1) Advanced HDL Synthesis Report
  7) Low Level Synthesis
  8) Partition Report
  9) Final Report
	9.1) Device utilization summary
	9.2) Partition Resource Summary
	9.3) TIMING REPORT


=========================================================================
*                      Synthesis Options Summary                        *
=========================================================================
---- Source Parameters
Input File Name                    : "VgaModule.prj"
Input Format                       : mixed
Ignore Synthesis Constraint File   : NO

---- Target Parameters
Output File Name                   : "VgaModule"
Output Format                      : NGC
Target Device                      : xc3s50a-4-vq100

---- Source Options
Top Module Name                    : VgaModule
Automatic FSM Extraction           : YES
FSM Encoding Algorithm             : Auto
Safe Implementation                : No
FSM Style                          : LUT
RAM Extraction                     : Yes
RAM Style                          : Auto
ROM Extraction                     : Yes
Mux Style                          : Auto
Decoder Extraction                 : YES
Priority Encoder Extraction        : Yes
Shift Register Extraction          : YES
Logical Shifter Extraction         : YES
XOR Collapsing                     : YES
ROM Style                          : Auto
Mux Extraction                     : Yes
Resource Sharing                   : YES
Asynchronous To Synchronous        : NO
Multiplier Style                   : Auto
Automatic Register Balancing       : No

---- Target Options
Add IO Buffers                     : YES
Global Maximum Fanout              : 100000
Add Generic Clock Buffer(BUFG)     : 24
Register Duplication               : YES
Slice Packing                      : YES
Optimize Instantiated Primitives   : NO
Use Clock Enable                   : Yes
Use Synchronous Set                : Yes
Use Synchronous Reset              : Yes
Pack IO Registers into IOBs        : Auto
Equivalent register Removal        : YES

---- General Options
Optimization Goal                  : Speed
Optimization Effort                : 1
Keep Hierarchy                     : No
Netlist Hierarchy                  : As_Optimized
RTL Output                         : Yes
Global Optimization                : AllClockNets
Read Cores                         : YES
Write Timing Constraints           : NO
Cross Clock Analysis               : NO
Hierarchy Separator                : /
Bus Delimiter                      : <>
Case Specifier                     : Maintain
Slice Utilization Ratio            : 100
BRAM Utilization Ratio             : 100
Verilog 2001                       : YES
Auto BRAM Packing                  : NO
Slice Utilization Ratio Delta      : 5

=========================================================================


=========================================================================
*                          HDL Compilation                              *
=========================================================================
Compiling vhdl file "C:/xilinx_project/VGA_HD44780/CGRam.vhd" in Library work.
Architecture behavioral of Entity cgram is up to date.
Compiling vhdl file "C:/xilinx_project/VGA_HD44780-extendet/InstructionDecoder.vhd" in Library work.
Entity <instructiondecoder> compiled.
Entity <instructiondecoder> (Architecture <behavioral>) compiled.
Compiling vhdl file "C:/xilinx_project/VGA_HD44780/top_module.vhd" in Library work.
Architecture behavioral of Entity vgamodule is up to date.

=========================================================================
*                     Design Hierarchy Analysis                         *
=========================================================================
Analyzing hierarchy for entity <VgaModule> in library <work> (architecture <behavioral>).

Analyzing hierarchy for entity <CGRam> in library <work> (architecture <behavioral>).

Analyzing hierarchy for entity <InstructionDecoder> in library <work> (architecture <behavioral>).


=========================================================================
*                            HDL Analysis                               *
=========================================================================
Analyzing Entity <VgaModule> in library <work> (Architecture <behavioral>).
Entity <VgaModule> analyzed. Unit <VgaModule> generated.

Analyzing Entity <CGRam> in library <work> (Architecture <behavioral>).
Entity <CGRam> analyzed. Unit <CGRam> generated.

Analyzing Entity <InstructionDecoder> in library <work> (Architecture <behavioral>).
Entity <InstructionDecoder> analyzed. Unit <InstructionDecoder> generated.


=========================================================================
*                           HDL Synthesis                               *
=========================================================================

Performing bidirectional port resolution...

Synthesizing Unit <CGRam>.
    Related source file is "C:/xilinx_project/VGA_HD44780/CGRam.vhd".
    Found 2048x9-bit dual-port RAM <Mram_ATTR_RAM> for signal <ATTR_RAM>.
    Found 2048x8-bit dual-port RAM <Mram_DD_RAM> for signal <DD_RAM>.
    Found 2048x8-bit dual-port RAM <Mram_CG_RAM> for signal <CG_RAM>.
    Found 8-bit register for signal <CG_DO>.
    Found 17-bit register for signal <DD_DO>.
    Summary:
	inferred   3 RAM(s).
	inferred  25 D-type flip-flop(s).
Unit <CGRam> synthesized.


Synthesizing Unit <InstructionDecoder>.
    Related source file is "C:/xilinx_project/VGA_HD44780-extendet/InstructionDecoder.vhd".
    Found finite state machine <FSM_0> for signal <state>.
    -----------------------------------------------------------------------
    | States             | 5                                              |
    | Transitions        | 15                                             |
    | Inputs             | 9                                              |
    | Outputs            | 6                                              |
    | Clock              | CLK                       (rising_edge)        |
    | Power Up State     | idle                                           |
    | Encoding           | automatic                                      |
    | Implementation     | LUT                                            |
    -----------------------------------------------------------------------
    Found 11-bit register for signal <DDRAM_ADDR>.
    Found 11-bit register for signal <CGRAM_ADDR>.
    Found 1-bit register for signal <DDRAM_WE>.
    Found 8-bit tristate buffer for signal <DB>.
    Found 1-bit register for signal <CGRAM_WE>.
    Found 1-bit register for signal <STRAM_WE>.
    Found 19-bit register for signal <STRAM_ADDR>.
    Found 1-bit register for signal <AI>.
    Found 1-bit register for signal <B0>.
    Found 1-bit register for signal <B1>.
    Found 1-bit register for signal <B2>.
    Found 1-bit register for signal <BF>.
    Found 1-bit register for signal <CBL>.
    Found 11-bit addsub for signal <CGRAM_ADDR$addsub0000>.
    Found 1-bit register for signal <CGW>.
    Found 8-bit register for signal <CLK_EDGE>.
    Found 1-bit register for signal <CLS>.
    Found 23-bit register for signal <CLS_CNT>.
    Found 23-bit adder for signal <CLS_CNT$addsub0000> created at line 248.
    Found 1-bit register for signal <CON>.
    Found 11-bit adder for signal <DDRAM_ADDR$add0000> created at line 136.
    Found 11-bit subtractor for signal <DDRAM_ADDR$sub0000> created at line 138.
    Found 1-bit register for signal <DDW>.
    Found 1-bit register for signal <DON>.
    Found 1-bit register for signal <I_D>.
    Found 8-bit register for signal <REG_B0>.
    Found 8-bit register for signal <REG_B1>.
    Found 7-bit register for signal <REG_B2>.
    Found 12-bit register for signal <RGBC>.
    Found 9-bit register for signal <RGBF>.
    Found 1-bit register for signal <SHP0>.
    Found 1-bit register for signal <SHP1>.
    Found 19-bit addsub for signal <STRAM_ADDR$addsub0000>.
    Found 1-bit register for signal <STW>.
    Summary:
	inferred   1 Finite State Machine(s).
	inferred 134 D-type flip-flop(s).
	inferred   5 Adder/Subtractor(s).
	inferred   8 Tristate(s).
Unit <InstructionDecoder> synthesized.


Synthesizing Unit <VgaModule>.
    Related source file is "C:/xilinx_project/VGA_HD44780/top_module.vhd".
    Found 1-bit register for signal <HS>.
    Found 1-bit register for signal <VS>.
    Found 12-bit register for signal <RGB>.
    Found 8-bit tristate buffer for signal <D>.
    Found 19-bit adder for signal <Afl>.
    Found 9x10-bit multiplier for signal <Afl$mult0000> created at line 258.
    Found 11-bit comparator greater for signal <BL$cmp_gt0000> created at line 215.
    Found 11-bit comparator greater for signal <BL$cmp_gt0001> created at line 215.
    Found 11-bit comparator equal for signal <Cat$cmp_eq0000> created at line 334.
    Found 1-bit 4-to-1 multiplexer for signal <Cch>.
    Found 1-bit register for signal <Cen>.
    Found 8-bit register for signal <CGreg>.
    Found 3-bit up counter for signal <Cnt25>.
    Found 6-bit up counter for signal <CntC>.
    Found 10-bit up counter for signal <CntF>.
    Found 10-bit up counter for signal <CntH>.
    Found 9-bit up counter for signal <CntR>.
    Found 10-bit up counter for signal <CntV>.
    Found 11-bit adder for signal <Dfl>.
    Found 11-bit adder for signal <Dfl$addsub0000> created at line 287.
    Found 11-bit comparator greater for signal <H$cmp_gt0000> created at line 209.
    Found 11-bit comparator less for signal <H$cmp_lt0000> created at line 209.
    Found 8-bit register for signal <Pixel0>.
    Found 12-bit register for signal <Pixel1>.
    Found 11-bit comparator greater for signal <Ren$cmp_gt0000> created at line 271.
    Found 11-bit comparator less for signal <Ren$cmp_lt0000> created at line 271.
    Found 11-bit comparator greater for signal <V$cmp_gt0000> created at line 212.
    Found 11-bit comparator less for signal <V$cmp_lt0000> created at line 212.
    Summary:
	inferred   6 Counter(s).
	inferred  43 D-type flip-flop(s).
	inferred   3 Adder/Subtractor(s).
	inferred   1 Multiplier(s).
	inferred   9 Comparator(s).
	inferred   1 Multiplexer(s).
	inferred   8 Tristate(s).
Unit <VgaModule> synthesized.

INFO:Xst:1767 - HDL ADVISOR - Resource sharing has identified that some arithmetic operations in this design can share the same physical resources for reduced device utilization. For improved clock frequency you may try to disable resource sharing.

=========================================================================
HDL Synthesis Report

Macro Statistics
# RAMs                                                 : 3
 2048x8-bit dual-port RAM                              : 2
 2048x9-bit dual-port RAM                              : 1
# Multipliers                                          : 1
 9x10-bit multiplier                                   : 1
# Adders/Subtractors                                   : 8
 11-bit adder                                          : 3
 11-bit addsub                                         : 1
 11-bit subtractor                                     : 1
 19-bit adder                                          : 1
 19-bit addsub                                         : 1
 23-bit adder                                          : 1
# Counters                                             : 6
 10-bit up counter                                     : 3
 3-bit up counter                                      : 1
 6-bit up counter                                      : 1
 9-bit up counter                                      : 1
# Registers                                            : 64
 1-bit register                                        : 50
 11-bit register                                       : 2
 12-bit register                                       : 2
 19-bit register                                       : 1
 23-bit register                                       : 1
 7-bit register                                        : 1
 8-bit register                                        : 6
 9-bit register                                        : 1
# Comparators                                          : 9
 11-bit comparator equal                               : 1
 11-bit comparator greater                             : 5
 11-bit comparator less                                : 3
# Multiplexers                                         : 1
 1-bit 4-to-1 multiplexer                              : 1
# Tristates                                            : 2
 8-bit tristate buffer                                 : 2

=========================================================================

=========================================================================
*                       Advanced HDL Synthesis                          *
=========================================================================

Analyzing FSM <FSM_0> for best encoding.
Optimizing FSM <Inst_InstructionDecoder/state/FSM> on signal <state[1:3]> with user encoding.
--------------------
 State  | Encoding
--------------------
 idle   | 000
 state1 | 001
 state2 | 010
 state3 | 011
 state4 | 100
--------------------

Synthesizing (advanced) Unit <VgaModule>.
INFO:Xst:3226 - The RAM <Inst_CGRam/Mram_CG_RAM> will be implemented as a BLOCK RAM, absorbing the following register(s): <Inst_CGRam/CG_DO>
    -----------------------------------------------------------------------
    | ram_type           | Block                               |          |
    -----------------------------------------------------------------------
    | Port A                                                              |
    |     aspect ratio   | 2048-word x 8-bit                   |          |
    |     mode           | read-first                          |          |
    |     clkA           | connected to signal <CLK>           | rise     |
    |     weA            | connected to signal <CG_WE>         | high     |
    |     addrA          | connected to signal <CG_ADDR_WE>    |          |
    |     diA            | connected to signal <CG_DI>         |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
    | Port B                                                              |
    |     aspect ratio   | 2048-word x 8-bit                   |          |
    |     mode           | write-first                         |          |
    |     clkB           | connected to signal <CLK>           | rise     |
    |     addrB          | connected to signal <CntR>          |          |
    |     doB            | connected to signal <CG_DO>         |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
INFO:Xst:3226 - The RAM <Inst_CGRam/Mram_DD_RAM> will be implemented as a BLOCK RAM, absorbing the following register(s): <Inst_CGRam/DD_DO_7_0_varindex0000>
    -----------------------------------------------------------------------
    | ram_type           | Block                               |          |
    -----------------------------------------------------------------------
    | Port A                                                              |
    |     aspect ratio   | 2048-word x 8-bit                   |          |
    |     mode           | read-first                          |          |
    |     clkA           | connected to signal <CLK>           | rise     |
    |     weA            | connected to signal <DD_WE>         | high     |
    |     addrA          | connected to signal <DD_ADDR_WE>    |          |
    |     diA            | connected to signal <DD_DI>         |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
    | Port B                                                              |
    |     aspect ratio   | 2048-word x 8-bit                   |          |
    |     mode           | write-first                         |          |
    |     clkB           | connected to signal <CLK>           | rise     |
    |     addrB          | connected to signal <Dfl>           |          |
    |     doB            | connected to signal <DD_DO>         |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
INFO:Xst:3226 - The RAM <Inst_CGRam/Mram_ATTR_RAM> will be implemented as a BLOCK RAM, absorbing the following register(s): <Inst_CGRam/DD_DO_16_8_varindex0000>
    -----------------------------------------------------------------------
    | ram_type           | Block                               |          |
    -----------------------------------------------------------------------
    | Port A                                                              |
    |     aspect ratio   | 2048-word x 9-bit                   |          |
    |     mode           | read-first                          |          |
    |     clkA           | connected to signal <CLK>           | rise     |
    |     weA            | connected to signal <DD_WE>         | high     |
    |     addrA          | connected to signal <DD_ADDR_WE>    |          |
    |     diA            | connected to signal <DD_DI>         |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
    | Port B                                                              |
    |     aspect ratio   | 2048-word x 9-bit                   |          |
    |     mode           | write-first                         |          |
    |     clkB           | connected to signal <CLK>           | rise     |
    |     addrB          | connected to signal <Dfl>           |          |
    |     doB            | connected to signal <DD_DO>         |          |
    -----------------------------------------------------------------------
    | optimization       | speed                               |          |
    -----------------------------------------------------------------------
Unit <VgaModule> synthesized (advanced).

=========================================================================
Advanced HDL Synthesis Report

Macro Statistics
# RAMs                                                 : 3
 2048x8-bit dual-port block RAM                        : 2
 2048x9-bit dual-port block RAM                        : 1
# Multipliers                                          : 1
 9x10-bit multiplier                                   : 1
# Adders/Subtractors                                   : 8
 11-bit adder                                          : 3
 11-bit addsub                                         : 1
 11-bit subtractor                                     : 1
 19-bit adder                                          : 1
 19-bit addsub                                         : 1
 23-bit adder                                          : 1
# Counters                                             : 6
 10-bit up counter                                     : 3
 3-bit up counter                                      : 1
 6-bit up counter                                      : 1
 9-bit up counter                                      : 1
# Registers                                            : 180
 Flip-Flops                                            : 180
# Comparators                                          : 9
 11-bit comparator equal                               : 1
 11-bit comparator greater                             : 5
 11-bit comparator less                                : 3

=========================================================================

=========================================================================
*                         Low Level Synthesis                           *
=========================================================================

Optimizing unit <VgaModule> ...

Mapping all equations...
Building and optimizing final netlist ...
Found area constraint ratio of 100 (+ 5) on block VgaModule, actual ratio is 43.

Final Macro Processing ...

=========================================================================
Final Register Report

Macro Statistics
# Registers                                            : 228
 Flip-Flops                                            : 228

=========================================================================

=========================================================================
*                           Partition Report                            *
=========================================================================

Partition Implementation Status
-------------------------------

  No Partitions were found in this design.

-------------------------------

=========================================================================
*                            Final Report                               *
=========================================================================
Final Results
RTL Top Level Output File Name     : VgaModule.ngr
Top Level Output File Name         : VgaModule
Output Format                      : NGC
Optimization Goal                  : Speed
Keep Hierarchy                     : No

Design Statistics
# IOs                              : 55

Cell Usage :
# BELS                             : 802
#      GND                         : 1
#      INV                         : 20
#      LUT1                        : 77
#      LUT2                        : 100
#      LUT2_D                      : 5
#      LUT3                        : 64
#      LUT3_D                      : 3
#      LUT3_L                      : 10
#      LUT4                        : 202
#      LUT4_D                      : 12
#      LUT4_L                      : 17
#      MULT_AND                    : 3
#      MUXCY                       : 134
#      MUXF5                       : 14
#      VCC                         : 1
#      XORCY                       : 139
# FlipFlops/Latches                : 228
#      FD                          : 35
#      FDE                         : 105
#      FDR                         : 3
#      FDRE                        : 39
#      FDS                         : 46
# RAMS                             : 3
#      RAMB16BWE                   : 3
# Clock Buffers                    : 1
#      BUFGP                       : 1
# IO Buffers                       : 54
#      IBUF                        : 3
#      IOBUF                       : 16
#      OBUF                        : 35
# MULTs                            : 1
#      MULT18X18SIO                : 1
=========================================================================

Device utilization summary:
---------------------------

Selected Device : 3s50avq100-4 

 Number of Slices:                      273  out of    704    38%  
 Number of Slice Flip Flops:            228  out of   1408    16%  
 Number of 4 input LUTs:                510  out of   1408    36%  
 Number of IOs:                          55
 Number of bonded IOBs:                  55  out of     68    80%  
 Number of BRAMs:                         3  out of      3   100%  
 Number of MULT18X18SIOs:                 1  out of      3    33%  
 Number of GCLKs:                         1  out of     24     4%  

---------------------------
Partition Resource Summary:
---------------------------

  No Partitions were found in this design.

---------------------------


=========================================================================
TIMING REPORT

NOTE: THESE TIMING NUMBERS ARE ONLY A SYNTHESIS ESTIMATE.
      FOR ACCURATE TIMING INFORMATION PLEASE REFER TO THE TRACE REPORT
      GENERATED AFTER PLACE-and-ROUTE.

Clock Information:
------------------
-----------------------------------+------------------------+-------+
Clock Signal                       | Clock buffer(FF name)  | Load  |
-----------------------------------+------------------------+-------+
CLK                                | BUFGP                  | 231   |
-----------------------------------+------------------------+-------+

Asynchronous Control Signals Information:
----------------------------------------
No asynchronous control signals found in this design

Timing Summary:
---------------
Speed Grade: -4

   Minimum period: 8.199ns (Maximum Frequency: 121.966MHz)
   Minimum input arrival time before clock: 9.711ns
   Maximum output required time after clock: 15.083ns
   Maximum combinational path delay: 7.819ns

Timing Detail:
--------------
All values displayed in nanoseconds (ns)

=========================================================================
Timing constraint: Default period analysis for Clock 'CLK'
  Clock period: 8.199ns (frequency: 121.966MHz)
  Total number of paths / destination ports: 7354 / 506
-------------------------------------------------------------------------
Delay:               8.199ns (Levels of Logic = 10)
  Source:            CntR_6 (FF)
  Destination:       Cen (FF)
  Source Clock:      CLK rising
  Destination Clock: CLK rising

  Data Path: CntR_6 to Cen
                                Gate     Net
    Cell:in->out      fanout   Delay   Delay  Logical Name (Net Name)
    ----------------------------------------  ------------
     FDRE:C->Q             5   0.591   0.776  CntR_6 (CntR_6)
     LUT3:I0->O            1   0.648   0.452  Madd_DflR21 (Madd_DflR2)
     LUT3:I2->O            1   0.648   0.000  Madd_Dfl_Madd_lut<6> (Madd_Dfl_Madd_lut<6>)
     MUXCY:S->O            1   0.632   0.000  Madd_Dfl_Madd_cy<6> (Madd_Dfl_Madd_cy<6>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Dfl_Madd_cy<7> (Madd_Dfl_Madd_cy<7>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Dfl_Madd_cy<8> (Madd_Dfl_Madd_cy<8>)
     MUXCY:CI->O           0   0.065   0.000  Madd_Dfl_Madd_cy<9> (Madd_Dfl_Madd_cy<9>)
     XORCY:CI->O           3   0.844   0.611  Madd_Dfl_Madd_xor<10> (Dfl<10>)
     LUT2:I1->O            1   0.643   0.000  Mcompar_Cat_cmp_eq0000_lut<5> (Mcompar_Cat_cmp_eq0000_lut<5>)
     MUXCY:S->O            1   0.836   0.423  Mcompar_Cat_cmp_eq0000_cy<5> (Cat)
     LUT4:I3->O            1   0.648   0.000  Cen_and000055 (Cen_and0000)
     FD:D                      0.252          Cen
    ----------------------------------------
    Total                      8.199ns (5.937ns logic, 2.262ns route)
                                       (72.4% logic, 27.6% route)

=========================================================================
Timing constraint: Default OFFSET IN BEFORE for Clock 'CLK'
  Total number of paths / destination ports: 1465 / 244
-------------------------------------------------------------------------
Offset:              9.711ns (Levels of Logic = 7)
  Source:            RS (PAD)
  Destination:       Inst_InstructionDecoder/DDRAM_ADDR_0 (FF)
  Destination Clock: CLK rising

  Data Path: RS to Inst_InstructionDecoder/DDRAM_ADDR_0
                                Gate     Net
    Cell:in->out      fanout   Delay   Delay  Logical Name (Net Name)
    ----------------------------------------  ------------
     IBUF:I->O            10   0.849   1.025  RS_IBUF (RS_IBUF)
     LUT2:I0->O            3   0.648   0.674  Inst_InstructionDecoder/DATA_WRITE1 (Inst_InstructionDecoder/DATA_WRITE)
     LUT4:I0->O            1   0.648   0.500  Inst_InstructionDecoder/state_cmp_eq00001_SW2 (N93)
     LUT4:I1->O           11   0.643   0.936  Inst_InstructionDecoder/DDRAM_ADDR_mux0003<0>4 (N25)
     LUT4:I3->O            1   0.648   0.423  Inst_InstructionDecoder/DDRAM_ADDR_mux0003<0>15_SW0 (N1311)
     LUT4_L:I3->LO         1   0.648   0.132  Inst_InstructionDecoder/DDRAM_ADDR_mux0003<0>15 (Inst_InstructionDecoder/DDRAM_ADDR_mux0003<0>15)
     LUT3:I2->O            1   0.648   0.420  Inst_InstructionDecoder/DDRAM_ADDR_mux0003<0>35 (Inst_InstructionDecoder/DDRAM_ADDR_mux0003<0>35)
     FDS:S                     0.869          Inst_InstructionDecoder/DDRAM_ADDR_0
    ----------------------------------------
    Total                      9.711ns (5.601ns logic, 4.110ns route)
                                       (57.7% logic, 42.3% route)

=========================================================================
Timing constraint: Default OFFSET OUT AFTER for Clock 'CLK'
  Total number of paths / destination ports: 2035 / 44
-------------------------------------------------------------------------
Offset:              15.083ns (Levels of Logic = 13)
  Source:            CntV_5 (FF)
  Destination:       A<18> (PAD)
  Source Clock:      CLK rising

  Data Path: CntV_5 to A<18>
                                Gate     Net
    Cell:in->out      fanout   Delay   Delay  Logical Name (Net Name)
    ----------------------------------------  ------------
     FDRE:C->Q             7   0.591   0.708  CntV_5 (CntV_5)
     MULT18X18SIO:A5->P10    1   4.602   0.563  Mmult_Afl_mult0000 (Afl_mult0000<10>)
     LUT1:I0->O            1   0.648   0.000  Madd_Afl_cy<10>_rt (Madd_Afl_cy<10>_rt)
     MUXCY:S->O            1   0.632   0.000  Madd_Afl_cy<10> (Madd_Afl_cy<10>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Afl_cy<11> (Madd_Afl_cy<11>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Afl_cy<12> (Madd_Afl_cy<12>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Afl_cy<13> (Madd_Afl_cy<13>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Afl_cy<14> (Madd_Afl_cy<14>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Afl_cy<15> (Madd_Afl_cy<15>)
     MUXCY:CI->O           1   0.065   0.000  Madd_Afl_cy<16> (Madd_Afl_cy<16>)
     MUXCY:CI->O           0   0.065   0.000  Madd_Afl_cy<17> (Madd_Afl_cy<17>)
     XORCY:CI->O           1   0.844   0.452  Madd_Afl_xor<18> (Afl<18>)
     LUT3:I2->O            1   0.648   0.420  A<18>1 (A_18_OBUF)
     OBUF:I->O                 4.520          A_18_OBUF (A<18>)
    ----------------------------------------
    Total                     15.083ns (12.940ns logic, 2.143ns route)
                                       (85.8% logic, 14.2% route)

=========================================================================
Timing constraint: Default path analysis
  Total number of paths / destination ports: 16 / 16
-------------------------------------------------------------------------
Delay:               7.819ns (Levels of Logic = 3)
  Source:            DB<3> (PAD)
  Destination:       D<3> (PAD)

  Data Path: DB<3> to D<3>
                                Gate     Net
    Cell:in->out      fanout   Delay   Delay  Logical Name (Net Name)
    ----------------------------------------  ------------
     IOBUF:IO->O          21   0.849   1.271  DB_3_IOBUF (N54)
     LUT2:I0->O            3   0.648   0.531  CG_DI<3>1 (CG_DI<3>)
     IOBUF:I->IO               4.520          D_3_IOBUF (D<3>)
    ----------------------------------------
    Total                      7.819ns (6.017ns logic, 1.802ns route)
                                       (77.0% logic, 23.0% route)

=========================================================================


Total REAL time to Xst completion: 12.00 secs
Total CPU time to Xst completion: 12.29 secs
 
--> 

Total memory usage is 283056 kilobytes

Number of errors   :    0 (   0 filtered)
Number of warnings :    0 (   0 filtered)
Number of infos    :    4 (   0 filtered)

 

płytka jest mojego autorstwa. to trzecia z tym układem i pierwsza z takim dziwnym problemem. jak by był problem z inicjacją po spi to żaden program by się nie wgrał bo weryfikacja by nie przeszła. Tak sądzę... 

W raporcie raczej nie widać nic szczególnego.
Skoro nie ma problemów ze spełnieniem zależności czasowych, to niezależnie od sposobu wgrywania konfiguracji powinno działać. Nie mam pomysłu, trzeba by dokładniej przeanalizować kod, czy nie ma jakiś pułapek. Nie używasz żadnego sygnału resetującego, to warto prześledzić, czy na pewno wszystkie rejestry, zwłaszcza sterujące adresami odczytu z pamięci SRAM, są na pewno zainicjalizowane właściwie (w pierwszym rzucie można sprawdzić w symulacji).

Gdybyś miał wolne bloki BRAM (ewentualnie można spróbować pamięć osadzić tymczasowo w rejestrach, chociaż chyba nie ma na to zasobów), to sugerowałbym sprawdzenie co dzieje się w układzie za pomocą ILA. Też nie wiem jak działa w ISE, używałem tylko w Vivado.

  • Lubię! 1

@piotr96 Dzięki za odpowiedź. Zmieniłem kod i dodałem twardy reset na zewnętrznym pinie który zerował wszystkie rejestry. Nie pomogło. Zamiast używać mnożnika sprzętowego dodałem dodatkowy licznik adresów dla zewnętrznej pamięci sram co zmniejszyło czas propagacji  do 9,2ns z 15ns. zamiast muxa wprowadziłem maskę and i or dla adresu zapisu/odczytu. Nie pomogło. Jtag działa poprawnie spi nie konfiguruje poprawnie. Kolega H1M4W4R1 podpowiedział, że linie sygnałowe CCLK i DI mogą robić szumy i spartan może źle czytać konfigurację więc wstawię rezystory odsprzęgające. Możliwe że ma rację bo ścieżki są trochę długie i sprtan3a podobno jest czuły na szumy. Jak będzie czas to wstawię rezystory i sprawdzę. Synchronizacja jest po pełnym przejściu licznika kolumn i wierszy (softreset). Pamięć bram jest poprawnie czytana i zapisywana i obraz generowanych znaków wraz z atrybutem kolorów działa bezbłędnie i stabilnie. zapis do sram i bram bez problemów. Maszyna stanów dla wykonywania zadanej instrukcji działa bezbłędnie. Jedyne co się rozjeżdża, to odczyt sram po inicjacji z spi. Poza tym cały kod działa w obu przypadkach inicjacji jtag i spi poprawnie.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...