Eveeeet, bitmemiş projeye bir de montaj kılavuzu ekleyelim gece gece. Yoksa bitmiş de henüz post edilmemiş mi desek?

Neyse VGA-16 kartımızın sol tarafında toplam 20 hattan oluşan bir şerit kablo mevcut. Bu şerit kablo ile Neo Geo MVS'den 3x5=15 Bit RGB datası, satır senkron sinyali, +5V Besleme, iki adet GND ve Neo Geo nun 12MHz sistem saat sinyali VGA-16 içerisine alınıyor.
Sağ tarafta ise VGA çıkış mevcut. Alt kısımdaki AS PROG Port sadece FPGA kodunu yenilemek için kullanılıyor. Hemen yanındaki Config Jumper bölümü ise bazı opsiyonları set etmek için kullanılıyor.

20 hatlık şerit kabloya dönecek olursak, bu kablo Neo Geo'ya bağlı olan tek kablo aslında. BAğlantı şeması aşağıdaki gibi;
Üst:

Alt:

Config Jumperları:
C0,C1 Scanline Ayarı
0 0 Scanline Kapalı
1 0 Scanline Min (Bir satır %100, ikinci satır %50 değerinde)
0 1 Scanline Med (Bir satır %100, ikinci satır %25 değerinde)
1 1 Scanline Full (Bir satır %100, ikinci satır siyah)
C2,C3 Yatay Blending Miktarı
0 0 Blending Kapalı (yan yana gelen pikseller arasında karıştırma yok)
1 0 Blending Min (yan yana gelen iki piksel arasında %25 %75 karıştırma var)
0 1 Blending Med (yan yana gelen iki piksel arasında %50 %50 karıştırma var)
1 1 Blending Max (yan yana gelen üç piksel arasında %25 %25 %50 karıştırma var)
Bu Blending opsiyonu, eski tüplü manitör yada TV lerdeki analog renk geçişlerini simüle etmek için eklenmiş bir filtre.
Şimdi final FPGA kodunu hızlıca özetleyeiliriz.
// ----------------------------------------------------------------------------
// VGA Encoder Module
// [url]www.commodore.gen.tr[/url] - delimawi'2016
// ----------------------------------------------------------------------------
module VGA_Encoder
(
// Video Input
input [4:0] InputRed,
input [4:0] InputGreen,
input [4:0] InputBlue,
// Video Sync Signal
input Sync,
output DAC_Clock, // 6 MHz Neo Geo Video DAC Clock
// Video Clock
input VGA_Clock, // 25 MHz VGA Clock (24MHz :) )
// Scanline RAM Write
output reg [9:0] RamWrAddr,
output [15:0] RamWrData,
// Scanline RAM Read
output [9:0] RamRdAddr,
input [15:0] RamRdData,
// Config Bits ...
input [3:0] Config,
// Analog VGA Output
output reg [4:0] VGA_Red,
output reg [4:0] VGA_Green,
output reg [4:0] VGA_Blue,
output reg VGA_H_Sync,
output reg VGA_V_Sync
);
Burada FPGA içerisine yazdığımız mdülün giriş ve çıkışları tanımlanıyor. Önemli birşey yok.
Sadece şu nüans önemli. Normalde Neo Geo'dan 12MHz clock sinyali alıyoruz. Bu sinyal FPGA içerisindeki PLL ile x2 yapılarak 24MHz'e çıkartılıyor. Ve bu sinyali VGA Clock olarak kullanıyoruz.
Aynı zamanda biliyoruz ki Neo Geo RGB çıkışlarını 6MHz ile yeniliyor. Bizim de bu RGB gişirlerini 6MHz ile örneklememiz gerekiyor. Bunu yapabilmek için elimizdeki 24MHz clock'u ilerleyen bölümlerin birinde /4 yaparak 6MHz'e düşürüp kullanacağız.
`define DISPLAY_WIDTH 640
`define DISPLAY_HEIGHT 480
`define FULL_WIDTH 768
`define FULL_HEIGHT 528
`define H_FRONT_PORCH 10 // 16
`define H_SYNC 96 // 96
`define V_FRONT_PORCH 10 // 10
`define V_SYNC 2
// ------------------------------------------------------
// Neo Geo RGB Video Input
// ------------------------------------------------------
// 6 MHz Pixel Clock
// 384 Pixels/Line
// 264 Lines/Frame
// 59.1856 Frames/Second
// ------------------------------------------------------
Bu bölümde ise VGA sinyalini Neo Geo çıkışı ile senkron olabilecek şekilde nasıl çekiştirdiğimizi görüyoruz.
// ------------------------------------------------------
// VGA Signal Generator
// 640x480 VGA Video Output
// ------------------------------------------------------
// 800 Pixels/Line (Modified to 768)
// 525 Lines/Frame (Modified to 528)
// ------------------------------------------------------
always @(posedge VGA_Clock)
begin
// VGA Clock 24MHz ...
// Her 4 Clock'ta bir DAC Sample Edelim. (6MHz)
DAC_SubClock <= DAC_SubClock+1;
if (DAC_SubClock==0)
begin
// Horizontal Sync Detector & Horizontal Counter ...
// Sync sinyalinin bir önceki halini saklayalım ki, değişim olduğu anda yakalayabilelim ... (one shot)
pHSync<=HSync;
HSync<=Sync;
if ((Sync==1) && (HSync==0))
begin
RamWrAddr<=0;
end else
begin
RamWrAddr<=RamWrAddr+1;
end;
// Vertical Sync Detector ...
if (RamWrAddr==182)
begin
pVSync<=VSync;
VSync<=Sync;
if (Sync==1) VSyncCounter<=0; else VSyncCounter<=VSyncCounter+1;
end;
end;
// VGA Raster Counters
if (VGA_X_Pos==(`FULL_WIDTH-1))
begin
VGA_X_Pos<=0;
// if ( (VGA_Y_Pos==(`FULL_HEIGHT-1)) || ((pVSync==0)&&(VSync==1)) )
if ( (VGA_Y_Pos==(`FULL_HEIGHT-1)) || (VSyncCounter==12) )
begin
VGA_Y_Pos<=0;
end else
begin
VGA_Y_Pos<=VGA_Y_Pos+1;
end
end else
begin
if ((Sync==1) && (HSync==0) && (VGA_X_Pos>5))
begin
VGA_X_Pos<=0;
end else
begin
VGA_X_Pos<=VGA_X_Pos+1;
end;
end
VGA_H_Sync <= !( (VGA_X_Pos>=(`DISPLAY_WIDTH+`H_FRONT_PORCH)) && (VGA_X_Pos<(`DISPLAY_WIDTH+`H_FRONT_PORCH+`H_SYNC)) );
VGA_V_Sync <= !( (VGA_Y_Pos>=(`DISPLAY_HEIGHT+`V_FRONT_PORCH)) && (VGA_Y_Pos<(`DISPLAY_HEIGHT+`V_FRONT_PORCH+`V_SYNC)) );
end
İşte bu bölüm VGA sinyalini üreten kısım.
// ------------------------------------------------------
// Effects & Processing
// ------------------------------------------------------
always @(posedge VGA_Clock)
begin
// -------------------------------------------------------------
// Horizontal Pixel Blur
// -------------------------------------------------------------
pR1[4:0]<=pR0[4:0];
pG1[4:0]<=pG0[4:0];
pB1[4:0]<=pG0[4:0];
pR0[4:0]<=RamRdData[4:0];
pG0[4:0]<=RamRdData[9:5];
pB0[4:0]<=RamRdData[14:10];
// 0-Blur None
if (Config[3:2]==3)
begin
Red[7:0]= RamRdData[4:0]*8;
Green[7:0]= RamRdData[9:5]*8;
Blue[7:0]= RamRdData[14:10]*8;
end
// 1-Blur Low
else if (Config[3:2]==2)
begin
Red[7:0]= (pR0[4:0]+RamRdData[4:0]+RamRdData[4:0]+RamRdData[4:0])*2;
Green[7:0]= (pG0[4:0]+RamRdData[9:5]+RamRdData[9:5]+RamRdData[9:5])*2;
Blue[7:0]= (pB0[4:0]+RamRdData[14:10]+RamRdData[14:10]+RamRdData[14:10])*2;
end
// 2-Blur Mid
else if (Config[3:2]==1)
begin
Red[7:0]= (pR0[4:0]+pR0[4:0]+RamRdData[4:0]+RamRdData[4:0])*2;
Green[7:0]= (pG0[4:0]+pG0[4:0]+RamRdData[9:5]+RamRdData[9:5])*2;
Blue[7:0]= (pB0[4:0]+pB0[4:0]+RamRdData[14:10]+RamRdData[14:10])*2;
end
// 3-Blur High
else
begin
Red[7:0]= (pR0[4:0]+pR1[4:0]+RamRdData[4:0]+RamRdData[4:0])*2;
Green[7:0]= (pG0[4:0]+pG1[4:0]+RamRdData[9:5]+RamRdData[9:5])*2;
Blue[7:0]= (pB0[4:0]+pB1[4:0]+RamRdData[14:10]+RamRdData[14:10])*2;
end
// Draw Limits ...
if (VGA_Y_Pos>=460)
begin
VGA_Red[4:0]<=0;
VGA_Green[4:0]<=0;
VGA_Blue[4:0]<=0;
end else
// Scanline Generator ...
if (VGA_Y_Pos[0]==0)
begin
if (Config[1:0]==3)
begin
VGA_Red[4:0]<=Red/8;
VGA_Green[4:0]<=Green/8;
VGA_Blue[4:0]<=Blue/8;
end
else if (Config[1:0]==2)
begin
VGA_Red[4:0]<=Red/16;
VGA_Green[4:0]<=Green/16;
VGA_Blue[4:0]<=Blue/16;
end
else if (Config[1:0]==1)
begin
VGA_Red[4:0]<=Red/32;
VGA_Green[4:0]<=Green/32;
VGA_Blue[4:0]<=Blue/32;
end else
begin
VGA_Red[4:0]<=0;
VGA_Green[4:0]<=0;
VGA_Blue[4:0]<=0;
end
// Normal Lines ...
end else
begin
VGA_Red[4:0]<=Red/8;
VGA_Green[4:0]<=Green/8;
VGA_Blue[4:0]<=Blue/8;
end;
end
Bu kısımda ise scanline ve blending efektleri ekleniyor...
FPGA kodu bu kadar. Aslında toplam FPGA'in sadece %3'ü kullanıldı bu projede.
Önümüzdeki günlerde birkaç video da ekleyeceğim.