blob: 6484bcad1daa1016b53b88f70b0fa654a06ae6c6 [file] [log] [blame]
// vdp_vram_bus_arbiter_standard.v
//
// Copyright (C) 2020 Dan Rodrigues <danrr.gh.oss@gmail.com>
//
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
`include "debug.vh"
`include "layer_encoding.vh"
// 3 layer, non-interleaved bus arbiter
// Unlike vdp_vram_bus_arbiter_interleaved, tilemaps are stored in VRAM contiguously
// This sacrifices 1 layer in exchange for more flexible, less wasteful VRAM management
module vdp_vram_bus_arbiter_standard(
input clk,
// Reference raster positions
input [10:0] raster_x_offset,
input [10:0] raster_x,
input [9:0] raster_y,
// Scroll attributes
input [9:0] scroll_x_0, scroll_x_1, scroll_x_2, scroll_x_3,
input [8:0] scroll_y_0, scroll_y_1, scroll_y_2, scroll_y_3,
// 4 layers combined
input [15:0] scroll_tile_base,
input [15:0] scroll_map_base,
// Affine attributes
input affine_enabled,
input affine_offscreen,
input [13:0] affine_vram_address_even, affine_vram_address_odd,
// Sprite attributes
input [13:0] vram_sprite_address,
// 4 layers combined
input [3:0] scroll_use_wide_map,
// Output scroll attributes
output [3:0] scroll_palette_0, scroll_palette_1, scroll_palette_2, scroll_palette_3,
output scroll_x_flip_0, scroll_x_flip_1, scroll_x_flip_2, scroll_x_flip_3,
// Output control for various functional blocks
output reg load_all_scroll_row_data,
output reg vram_written,
output reg vram_sprite_read_data_valid,
output reg [3:0] scroll_char_load,
output reg [3:0] scroll_meta_load,
// VRAM write control
input [1:0] vram_port_write_en_mask,
input [13:0] vram_write_address_16b,
input [15:0] vram_write_data_16b,
// VRAM interface
input [15:0] vram_read_data_even, vram_read_data_odd,
// vdp_lite has one address instead of split even / odd (affine layer used it only)
output reg [13:0] vram_address,
output reg [15:0] vram_write_data_even, vram_write_data_odd,
output reg vram_we_even, vram_we_odd
);
// No scrolling layers in vdp_lite, so these sections have been removed completely
// --- Layer attribute selection ---
// --- Tile address generator ---
// --- Map address generators ---
assign scroll_palette_0 = 0;
assign scroll_palette_1 = 0;
assign scroll_palette_2 = 0;
assign scroll_palette_3 = 0;
assign scroll_x_flip_0 = 0;
assign scroll_x_flip_1 = 0;
assign scroll_x_flip_2 = 0;
assign scroll_x_flip_3 = 0;
// --- VRAM bus control ---
reg [13:0] vram_address_nx;
reg [1:0] vram_render_write_en_mask_nx;
reg [1:0] map_address_layer_select;
reg [1:0] tile_address_layer_select;
always @* begin
scroll_meta_load = 0;
scroll_char_load = 0;
map_address_layer_select = 0;
tile_address_layer_select = 0;
load_all_scroll_row_data = 0;
vram_render_write_en_mask_nx = 0;
vram_address_nx = 0;
vram_written = 0;
vram_sprite_read_data_valid = 0;
case (raster_x_offset[2:0])
0: begin
// now: s0 map data
// scroll_meta_load = `LAYER_SCROLL0_OHE;
// host write - every 8 cycles
vram_address_nx = vram_write_address_16b;
vram_written = 1;
vram_render_write_en_mask_nx = vram_port_write_en_mask;
end
1: begin
// now: s1 map
// scroll_meta_load = `LAYER_SCROLL1_OHE;
// next: sprite access
vram_address_nx = vram_sprite_address;
// next next: s0 tile address
// tile_address_layer_select = `LAYER_SCROLL0;
end
2: begin
// now: s2 map
// scroll_meta_load = `LAYER_SCROLL2_OHE;
// next: s0 tile
// vram_address_nx = tile_address;
// next next: s1 tile address
// tile_address_layer_select = `LAYER_SCROLL1;
end
3: begin
// next: s1 tile
// vram_address_nx = tile_address;
// next next: s2 tile address
// tile_address_layer_select = `LAYER_SCROLL2;
end
4: begin
// now: sprites acccess
vram_sprite_read_data_valid = 1;
// next: s2 tile
// vram_address_nx = tile_address;
// next next: s0 map
// map_address_layer_select = `LAYER_SCROLL0;
end
5: begin
// now: s0 tile
// scroll_char_load = `LAYER_SCROLL0_OHE;
// next: s0 map
// vram_address_nx = map_address;
// next next: s1 map
// map_address_layer_select = `LAYER_SCROLL1;
end
6: begin
// now: s1 tile
// scroll_char_load = `LAYER_SCROLL1_OHE;
// next: s1 map
// vram_address_nx = map_address;
// next next: s2 map
// map_address_layer_select = `LAYER_SCROLL2;
end
7: begin
// now: s1 tile
// scroll_char_load = `LAYER_SCROLL2_OHE;
// next: s2 map
// vram_address_nx = map_address;
// now: s3 tile, which is loaded simultaneously with the previously prefetched layers
// load_all_scroll_row_data = 1;
end
endcase
end
// --- VRAM write data passthrough ---
always @* begin
vram_write_data_even = vram_write_data_16b;
vram_write_data_odd = vram_write_data_16b;
end
// --- VRAM bus registers ---
always @(posedge clk) begin
vram_address <= vram_address_nx;
vram_we_even <= vram_render_write_en_mask_nx[0];
vram_we_odd <= vram_render_write_en_mask_nx[1];
end
// --- VRAM base address mapping functions ---
function [13:0] full_scroll_tile_base;
input [1:0] layer;
begin
full_scroll_tile_base = {scroll_tile_base >> (layer * 4), 11'b0};
end
endfunction
function [14:0] full_scroll_map_base;
input [1:0] layer;
begin
full_scroll_map_base = {scroll_map_base >> (layer * 4), 12'b0};
end
endfunction
endmodule