⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.v

📁 DE1-FPGA-Board
💻 V
字号:
// FPGA PACMAN video hardware
//
// Version : beta2
//
// Copyright(c) 2002,2003 Tatsuyuki Satoh , All rights reserved
//
// Important !
//
// This program is freeware for non-commercial use. 
// An author does no guarantee about this program.
// You can use this under your own risk. 
//
// 2003. 2. 6 beta2 export Xilinx dependent BlockSelectRAMs
//                  remove object timing patch.
//                  fix cpu I/F timing
// 2003. 2. 7 beta2 minimize
//


//
// Signal Assign of Video Memory
//
// 1.tilemap code RAM
//
// Area    : 4000-43ff
// Size    : 8bit x 1024word
// RD Timng: ??? (2H, 333ns-@)
// WR Timng: ??? (2H, 333ns-@)
// Address : AB[9:0]
// Dout    : DB_I
// Din     : (DI)
// CS      : TRAM_CS
// WE      : TRAM_WE
// OE      : ~TRAM_WE
//
//
// 2.tilemap color RAM
//
// parts   : 
// Area    : 4400-47ff
// Size    : 8bit x 1024word
// RD Timng: ??? (2H, 333ns-@)
// WR Timng: ??? (2H, 333ns-@)
// Address : AB[9:0]
// Dout    : DB_I
// Din     : (DI)
// CS      : CRAM_CS
// WE      : CRAM_WE
// OE      : ~CRAM_WE
// 
//
// 3.work & object RAM
//
// parts   : 4R,4M
// Area    : 4c00-4fff
// Size    : 8bit x 1024word
// RD Timng: ??? (2H, 333ns-@)
// WR Timng: ??? (2H, 333ns-@)
// Address : AB[9:0]
// Dout    : DB_I
// Din     : (DI)
// CS      : WRAM_CS
// WE      : WRAM_WE
// OE      : ~WRAM_WE
// 
//
// 4.object position RAM
//
// parts   : 3F,3E
// Area    : 5060-506f
// Size    : 8bit x 16word
// RD Timng: 2H fall -> 2H raise , 333ns-@
// WR Timng: ??? (2H fall -> 2H raise ? , 333ns-@)
// Address : AB[3:0]
// Dout    : PRAM_DI
// Din     : PRAM_DO (inverted di)
// CS      : always select
// WE      : PRAM_WE
// OE      : ~PRAM_WE
//
// 5.object line RAM
//
// parts   : (1A,1B,1C,1D) or (2A,2B,2B,2D)
// Area    : none
// Size    : 4bit x 256word
// RD Timng: pclk.up to pclk.dn , 166ns
// WR Timng: pclk.dn to pclk.up , 166ns
// Address : LRAM_A
// Dout    : LRAM_DI
// Din     : LRAM_DO
// CS&OE   : LRAM_CS
// WE      : LRAM_WE(~pclk)
//
//
// 6.color lockup table ROM
//
// parts   : 4A
// Area    : none
// Size    : 4bit x 256word
// RD Timng: non-buffer,GATED ROM
// Address : CLUT_A
// Din     : CLUT_D
// CS&OE   : always on
//
// 7.palette ROM
//
// parts   : 7F
// Area    : none
// Size    : 8bit x 32word
// RD Timng: non-buffer,GATED ROM
// Address : PAL_A
// Din     : n.c. (output are {B220,B470,G220,G470,G1K,R220,R470,R1K})
// CS&OE   : always on
//
// 8.object pattern ROM : async 8192 x 8bit
//
// parts   : 5E,5H,5F,5J
// Area    : none
// Size    : 8bit x 8192word
// RD Timng: 2H.up -> 2H.up (666ns-@)
// Address : CA
// Din     : CD
// other   : CA_as,CA_en
//

module video(
// CPU interface
	A,di,vdo,n_rd,WAIT_N,
// decoder input
	csvram,		//chip select video RAM  4000-4fff,c000-cfff
	csxyram,	//chip select object XY RAM 5060-506f
// VIDEO input
	pclk,flip,
// VIDEO output
	hc,vb,hs,vs,
// pattern ROM address & data
	CA,CD,CA_as,CA_en,
// TILE,COLOR,WORK RAM
	AB,DB_I,
	TRAM_WE,TRAM_CS,
	CRAM_WE,CRAM_CS,
	WRAM_WE,WRAM_CS,
// object Line RAM
	LRAM_A, LRAM_DO , LRAM_DI , LRAM_CS , LRAM_WE,
// Object Position RAM
	PRAM_DO,PRAM_DI,PRAM_WE,
// ColorLookupTable ROM
	CLUT_A,CLUT_DI,
// PaletteROM
	PAL_A
);

// CPU interface
input [11:0] A;
input [7:0] di;
output [7:0] vdo;
input WAIT_N;
input n_rd;

// decoder input
input csvram,csxyram;

// VIDEO input
input pclk;		// 6.144MHz video clock
input flip;		// screen flip register

// VIDEO output
output [8:0] hc;// H-counter
output vb;		// V-BLANK
output hs;		// H-SYNC
output vs;		// V-SYNC

output [12:0] CA;
input  [7:0] CD;
output CA_as,CA_en;

output [11:0] AB;	// shared address , CPU & VIDEO & sound timming
input [7:0] DB_I;	// shared data-in , (DB_O == di)
output TRAM_WE,TRAM_CS; // TileCode RAM
output CRAM_WE,CRAM_CS; // TileColor RAM
output WRAM_WE,WRAM_CS; // Work&Object RAM

// object Line RAM
output [7:0] LRAM_A;	// Address
output [3:0] LRAM_DO;	// DataOut
input  [3:0] LRAM_DI;	// DataIn
output LRAM_CS;
output LRAM_WE;

// object position RAM
output [7:0] PRAM_DO;
input [7:0] PRAM_DI;
output PRAM_WE;

// ColorLookupTable ROM
output [7:0] CLUT_A;
input  [3:0] CLUT_DI;

// PaletteROM
output [3:0] PAL_A;

//
// H timming generator
//
// counter = 0-255,384-511
// hblank  = 400(0x190)-495(0x1ef)
// hsync   = 416(0x1a0)-447(0x1bf)
//
reg [8:0] hcnt;
reg hblank,hsync;
always @(posedge pclk)
begin
	//hblank
	if( hcnt == 399)
		hblank <= 1;
	if(hcnt[6:0] == 7'h6f)
		hblank <= 0;

 	//hsync
	if( hblank && hcnt[6:0] == 7'h20)
		hsync <= 1;
	if(hcnt[4:0] == 5'h1f)
		hsync <= 0;

	//H counter
	hcnt <= (hcnt==255) ? 384 : hcnt + 1;
end

//
// V timming generator
//
// counter = 0-255,504-511
// vblank  = 240(0x0f0)-255(0x0ff)-504(0x1f8)-511(0x1fe)-015(0x0f)
// vsync   = 504-511
//
reg [8:0] vcnt;
reg vblank;
wire vsync;

always @(posedge hsync)
begin
	// V blank
	if(vcnt==239)
		vblank <= 1;
	if( vcnt[5:0] == 6'h0f)
		vblank <= 0;

	// V counter
	vcnt <= (vcnt==255) ? 504 : vcnt+1;
end
assign vsync = vcnt[8]; //504-511

//
// output timming signal
//
assign hc = hcnt;
assign vb = vblank;
assign hs = hsync;
assign vs = vsync;

//
// AB[11:0] multiplexed address bus
//
//  +---------------+----+----+-----+-----+----+----+----+-----+----+----+----+----+
//  | output        |AB11|AB10| AB9 | AB8 |AB7 |AB6 |AB5 | AB4 |AB3 |AB2 |AB1 |AB0 |
//  +---------------+----+----+-----+-----+----+----+----+-----+----+----+----+----+
//  |CPU Address    | A11| A10|  A9 |  A8 | A7 | A6 | A5 |  A4 | A3 | A2 | A1 | A0 |2H=0
//  |object Address | 1  | 1  |  1  |  1  | 1  | 1  | 1  |  1  |64H |32H |16H | 4H |2H=1,HC=400-495
//  |Left&Right tile| 0  | 4H | 64Hp| 64Hp|64Hp|64Hp| 8Hp|128Vp|64Vp|32Vp|16Vp| 8Vp|2H=1,HC=384-399,496-511
//  |Center tile    | 0  | 4H |128Vp|128Vp|32Vp|16Vp| 8Vp|128Hp|64Hp|32Hp|16Hp| 8Hp|2H=1,HC=0-255
//  +---------------+----+----+-----+-----+----+----+----+-----+----+----+----+----+
//
// parts 5S
//
// flipped address
wire [7:3] hcp = hcnt[7:3] ^ { flip,flip,flip,flip,flip };
wire [7:3] vcp = vcnt[7:3] ^ { flip,flip,flip,flip,flip };
// address bus
wire [11:0] ab_obj = { 8'b11111111,hcnt[6:4],hcnt[2]}; // object draw
wire [11:0] ab_lr  = { 1'b0,hcnt[2],hcp[6],hcp[6],hcp[6],hcp[6],hcp[3],vcp[7:3] }; // L&R tile
wire [11:0] ab_ctr = { 1'b0,hcnt[2],vcp[7:3],hcp[7:3] }; // center tile
// multiplex
wire [11:0] AB_tile  = (hcnt[8]) ? ab_lr    : ab_ctr; // L,R    / center
wire [11:0] AB_video = (hblank ) ? ab_obj   : AB_tile;// object / tile
//
// Shared Address Bus
//
assign AB = (hcnt[1]) ? AB_video : A[11:0];// video  / CPU

//
// CPU write enable
//

wire vram_we = csvram  & n_rd & (~hcnt[1]);
wire yx_we   = csxyram & n_rd & (~hcnt[1]);

//
//
// VRAM Address decoder
//
//
wire cs_code = AB[11:10]==2'b00; // 4000-43ff , tile code RAM
wire cs_col  = AB[11:10]==2'b01; // 4400-47ff , tile color RAM
wire cs_obj  = AB[11:10]==2'b11; // 4c00-4fff , work / object RAM
wire code_we = cs_code & vram_we;
wire col_we  = cs_col  & vram_we;
wire obj_we  = cs_obj  & vram_we;

wire [7:0] DR;      // output DATA from object XY RAM
wire yxram_ce = hblank | ~hcnt[1]; // chip enable to object XY RAM

//
// DB_I[7:0] : shared data bus in
//
// parts 6S
//
// data output for cpu
reg  [7:0] cpu_do;
always @(posedge pclk)
begin
	if( hcnt[1:0] == 2'b01) // (2H raise)
	begin
		cpu_do <= DB_I;
	end
end
//assign vdo = ~WAIT_N ? cpu_do : 8'h00;
assign vdo = (csvram & ~n_rd) ? cpu_do : 8'h00;

//
// object V match & offset ,or tile V pos
//
// parts 1F,2F,3E,4D,1H,2H,4E,5L,5H,4F 
//

reg  [7:0] tile_code;  // latch of tile code / object code,flipV,flipH
reg match;             // object Y position match
reg [3:0] cv;          // V address low
reg obj_sel;           // 4H delayed HBLANK == tile / object selector

// object V+Y or tile V pos
wire [7:0] cv_add = vcnt[7:0]+(yxram_ce ? DR : 8'h00);
always @(posedge pclk)
begin
	if( hcnt[2:0] == 3'b011) // (4H raise)
	begin
		// latch tile code / object code+flip data from RAM
		tile_code <= DB_I;
		// latch Y position , match & delayed hblank
		cv <= cv_add[3:0];
		// latch object V match flag
		match <= (cv_add[7:4] == 4'b1111);
		// latch hblank for object selector
		obj_sel <= hblank;
	end
end

//
// pixel data ROM address geneator
//
wire flipv = obj_sel ? tile_code[1] : flip; // V flip : object / tile 
wire fliph = obj_sel ? tile_code[0] : flip; // H flip : object / tile
//
assign CA[12]   = obj_sel;
assign CA[11:6] = tile_code[7:2];                       // object code / tile code[7:2]
assign CA[5]    = obj_sel ? cv[3]^flipv : tile_code[1]; // object 8V   / tile code[1]
assign CA[4]    = obj_sel ? hcnt[3]     : tile_code[0]; // object 8H   / tile code[0]
assign CA[3]    = hcnt[2] ^ fliph;                      // 4H byte select
assign CA[2:0]  = cv[2:0] ^ { flipv,flipv,flipv};       // 4V,2V,1V
assign CA_as    = hcnt[1:0] == 2'b00; // CA assert timming
assign CA_en    = hcnt[1:0] == 2'b10; // CD latch timming


//
// object LRAM access enable signal , latch color data from RAM
//
// parts 3P,2P,4B,
//
reg obj_on;					// LRAM access enable
reg hblank8;				// display enable
reg [4:0] clut_sel;			// Color Lookup Page Select from color RAM
reg fliph8;

always @(posedge pclk)
begin
	if(hcnt[2:0] == 3'b111) // 1H==2H==4H==1
	begin
		// delayed HBLANK == display outout enable
		hblank8 <= hblank;
		// object line RAM enable
		obj_on <= match | ~hcnt[8];
		// latch color RAM & H-flip for pixel generator
		clut_sel <= DB_I[4:0];
		fliph8   <= fliph; 
	end
end

//
// object line RAM address generator
//
// parts 4C,1E,2E
//
// load enable for reset tile Hpos or object Hpos
wire cntr_ld = (~obj_on | hblank8) & (hcnt[3:0] == 4'b0111);
reg [7:0] RA_I;
always @(posedge pclk)
begin
	if( cntr_ld )
	begin
		// H pos add + latch
		RA_I <= yxram_ce ? DR : 255;
	end else begin
		// H pos countup
		RA_I <= RA_I + 1;
	end
end

//
//pixel data -> 2bpp pixel selector
//
// parts 5B,5C,5H,5A
//
reg [7:0] pixel_byte;
always @(posedge pclk)
begin
	if( hcnt[1:0] == 2'b11 )
	begin
		pixel_byte <= CD;
	end else begin
		if( fliph8 )
		begin // flip , right shift
			pixel_byte[6:4] <= pixel_byte[7:5];
			pixel_byte[2:0] <= pixel_byte[3:1];
		end else begin // noflip , left shift
			pixel_byte[7:5] <= pixel_byte[6:4];
			pixel_byte[3:1] <= pixel_byte[2:0];
		end
	end
end
// 2bpp pixel data
wire [1:0] pixel = fliph8 ?
				{ pixel_byte[4],pixel_byte[0] } : // flip
				{ pixel_byte[7],pixel_byte[3] } ; // no flip


//
// Color Lookup Table ROM
//
wire clut_bank = 0;     // ColorBack , solder-selecter 0,1 or hblank8
wire [3:0] clut_d;	// data
wire [3:0] pal_code;	// palette code from pixel data
reg  [3:0] pal_obj;		// palette code of object LRAM


//
// priority selector
//
// parts 3A,3B,3E
//

assign pal_code = (pal_obj==4'b0000) ? clut_d : pal_obj;

//
// object LRAM (line ram)
//
wire [3:0] lram_wd = (hblank8 & ~vblank) ? pal_code : 4'b0000;
assign LRAM_A = RA_I;
assign LRAM_DO = lram_wd;
assign LRAM_CS = obj_on;
assign LRAM_WE = ~pclk;

// part (3C or 3D) , lineRAM output latch
always @(negedge pclk)
begin
  pal_obj <= obj_on ? LRAM_DI : 4'b0000;
end

//
// Palette Lookup Table
//

wire [3:0] pal_ad = (hblank8 | vblank) ? 4'h0 : pal_code;
//wire [7:0] pal_do;   // data output from PaletteRAM
//assign { b,g,r } = pal_do; // RGB output

//
// VIDEO Memory controll
//
// tile code RAM ,4000-43ff : 8bit x 1024word
assign TRAM_WE = code_we;
assign TRAM_CS = cs_code;

// tile color RAM ,4400-47ff : 8bit x 1024word
assign CRAM_WE = col_we;
assign CRAM_CS = cs_col;

// work , object code,flip & color ram , 4c00-4fff : 8bit x 1024word
assign WRAM_WE = obj_we;
assign WRAM_CS = cs_obj;

// object YX RAM , 5060-506f : 8bit x 16word
assign PRAM_DO = ~di;
assign DR = PRAM_DI;
assign PRAM_WE = yx_we;

// ColorLookupTable ROM
assign CLUT_A = {clut_bank,clut_sel,pixel};
assign clut_d = CLUT_DI;

// PaletteROM
assign PAL_A = pal_ad;

endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -