1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-06 08:04:41 +00:00
Files
mist-devel.mist-board/cores/gameboy/sprites.v
2019-07-07 01:54:44 +02:00

221 lines
7.0 KiB
Verilog

//
// sprites.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module sprites (
input clk,
input clk_reg,
input size16,
input isGBC_game,
// pixel position input which the current pixel is generated for
input [7:0] v_cnt,
input [7:0] h_cnt,
// pixel output
output pixel_active, // current pixel
output [1:0] pixel_data,
output pixel_cmap,
output pixel_prio,
//gbc
output [2:0] pixel_cmap_gbc,
input sort,
input [3:0] index, // index of sprite which video wants to read data for
output [10:0] addr,
input [1:0] dvalid,
input [7:0] data,
input [7:0] data1,
// oam memory interface
input oam_wr,
input [7:0] oam_addr,
input [7:0] oam_di,
output [7:0] oam_do
);
localparam SPRITES = 40;
// ------------------------------------------------------------------------
// ---------------------------- priority sorting --------------------------
// ------------------------------------------------------------------------
// sprites have priority from left to right and the leftmost 10 are
// being displayed. We thus need to sort them
wire [SPRITES*8-1:0] sprite_x;
wire [SPRITES*6-1:0] sprite_idx;
sprite_sort #(.WIDTH(SPRITES)) sprite_sort (
.clk ( clk ),
.load ( sort ), // begin of oam phase
.x ( sprite_x ),
.idx ( sprite_idx )
);
wire [SPRITES-1:0] sprite_pixel_active;
wire [SPRITES-1:0] sprite_pixel_cmap;
wire [SPRITES-1:0] sprite_pixel_prio;
wire [1:0] sprite_pixel_data [SPRITES-1:0];
wire [10:0] sprite_addr [SPRITES-1:0];
wire [7:0] sprite_oam_do [SPRITES-1:0];
assign oam_do = sprite_oam_do[oam_addr[7:2]];
// address where the sprite wants to read data from
wire [5:0] sprite_idx_array [SPRITES-1:0];
wire [5:0] padded_index = {2'd0,index};
wire [5:0] prio_index = sprite_idx_array[padded_index];
assign addr = sprite_addr[prio_index];
//gbc
wire [2:0] sprite_pixel_cmap_gbc [SPRITES-1:0];
wire sprite_tile_vbank [SPRITES-1:0];
generate
genvar i;
for(i=0;i<SPRITES;i=i+1) begin : spr
// map 1d array to 2d array
assign sprite_idx_array[i] = sprite_idx[6*i+5:6*i];
sprite sprite (
.clk ( clk_reg ),
.size16 ( size16 ),
.isGBC_game ( isGBC_game ),
.sprite_index ( i ),
.v_cnt ( v_cnt ),
.h_cnt ( h_cnt ),
.x ( sprite_x[(8*i)+7:(8*i)] ),
.addr ( sprite_addr[i] ),
.ds ( (prio_index == i)?dvalid:2'b00),
.data ( data ),
.data_1 ( data1 ),
.pixel_cmap ( sprite_pixel_cmap[i] ),
.pixel_prio ( sprite_pixel_prio[i] ),
.pixel_active ( sprite_pixel_active[i] ),
.pixel_data ( sprite_pixel_data[i] ),
//gbc
.pixel_cmap_gbc ( sprite_pixel_cmap_gbc[i] ),
.oam_wr ( oam_wr && (oam_addr[7:2] == i) ),
.oam_addr ( oam_addr[1:0] ),
.oam_di ( oam_di ),
.oam_do ( sprite_oam_do[i] )
);
end
endgenerate
// ------------------------------------------------------------------------
// ---------------------------- priority display --------------------------
// ------------------------------------------------------------------------
// only the 10 leftmost sprites are potentially being displayed
// get the indices of the 10 leftmost sprites
wire [5:0] spr0 = sprite_idx_array[0];
wire [5:0] spr1 = sprite_idx_array[1];
wire [5:0] spr2 = sprite_idx_array[2];
wire [5:0] spr3 = sprite_idx_array[3];
wire [5:0] spr4 = sprite_idx_array[4];
wire [5:0] spr5 = sprite_idx_array[5];
wire [5:0] spr6 = sprite_idx_array[6];
wire [5:0] spr7 = sprite_idx_array[7];
wire [5:0] spr8 = sprite_idx_array[8];
wire [5:0] spr9 = sprite_idx_array[9];
// if any of these is active then the current pixel is being driven by
// the sprite engine
assign pixel_active =
sprite_pixel_active[spr0] ||
sprite_pixel_active[spr1] ||
sprite_pixel_active[spr2] ||
sprite_pixel_active[spr3] ||
sprite_pixel_active[spr4] ||
sprite_pixel_active[spr5] ||
sprite_pixel_active[spr6] ||
sprite_pixel_active[spr7] ||
sprite_pixel_active[spr8] ||
sprite_pixel_active[spr9];
// get the pixel information of the leftmost sprite
assign pixel_data =
sprite_pixel_active[spr0]?sprite_pixel_data[spr0]:
sprite_pixel_active[spr1]?sprite_pixel_data[spr1]:
sprite_pixel_active[spr2]?sprite_pixel_data[spr2]:
sprite_pixel_active[spr3]?sprite_pixel_data[spr3]:
sprite_pixel_active[spr4]?sprite_pixel_data[spr4]:
sprite_pixel_active[spr5]?sprite_pixel_data[spr5]:
sprite_pixel_active[spr6]?sprite_pixel_data[spr6]:
sprite_pixel_active[spr7]?sprite_pixel_data[spr7]:
sprite_pixel_active[spr8]?sprite_pixel_data[spr8]:
sprite_pixel_active[spr9]?sprite_pixel_data[spr9]:
2'b00;
// get the colormap of the leftmost sprite
assign pixel_cmap =
sprite_pixel_active[spr0]?sprite_pixel_cmap[spr0]:
sprite_pixel_active[spr1]?sprite_pixel_cmap[spr1]:
sprite_pixel_active[spr2]?sprite_pixel_cmap[spr2]:
sprite_pixel_active[spr3]?sprite_pixel_cmap[spr3]:
sprite_pixel_active[spr4]?sprite_pixel_cmap[spr4]:
sprite_pixel_active[spr5]?sprite_pixel_cmap[spr5]:
sprite_pixel_active[spr6]?sprite_pixel_cmap[spr6]:
sprite_pixel_active[spr7]?sprite_pixel_cmap[spr7]:
sprite_pixel_active[spr8]?sprite_pixel_cmap[spr8]:
sprite_pixel_active[spr9]?sprite_pixel_cmap[spr9]:
1'b0;
// get the colormap of the leftmost sprite gbc
assign pixel_cmap_gbc =
sprite_pixel_active[spr0]?sprite_pixel_cmap_gbc[spr0]:
sprite_pixel_active[spr1]?sprite_pixel_cmap_gbc[spr1]:
sprite_pixel_active[spr2]?sprite_pixel_cmap_gbc[spr2]:
sprite_pixel_active[spr3]?sprite_pixel_cmap_gbc[spr3]:
sprite_pixel_active[spr4]?sprite_pixel_cmap_gbc[spr4]:
sprite_pixel_active[spr5]?sprite_pixel_cmap_gbc[spr5]:
sprite_pixel_active[spr6]?sprite_pixel_cmap_gbc[spr6]:
sprite_pixel_active[spr7]?sprite_pixel_cmap_gbc[spr7]:
sprite_pixel_active[spr8]?sprite_pixel_cmap_gbc[spr8]:
sprite_pixel_active[spr9]?sprite_pixel_cmap_gbc[spr9]:
1'b0;
// get the priority of the leftmost sprite
assign pixel_prio =
sprite_pixel_active[spr0]?sprite_pixel_prio[spr0]:
sprite_pixel_active[spr1]?sprite_pixel_prio[spr1]:
sprite_pixel_active[spr2]?sprite_pixel_prio[spr2]:
sprite_pixel_active[spr3]?sprite_pixel_prio[spr3]:
sprite_pixel_active[spr4]?sprite_pixel_prio[spr4]:
sprite_pixel_active[spr5]?sprite_pixel_prio[spr5]:
sprite_pixel_active[spr6]?sprite_pixel_prio[spr6]:
sprite_pixel_active[spr7]?sprite_pixel_prio[spr7]:
sprite_pixel_active[spr8]?sprite_pixel_prio[spr8]:
sprite_pixel_active[spr9]?sprite_pixel_prio[spr9]:
1'b0;
endmodule