mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-19 07:11:22 +03:00
update tsconf to commit 83afbba6f5d366f96297028aa3d64512fa254a51
This commit is contained in:
@ -1,383 +1,459 @@
|
||||
|
||||
// This is the Tile Sprite Processing Unit
|
||||
|
||||
// Tiles map address:
|
||||
// bits desc
|
||||
// 20:13 tmpage
|
||||
// 12:
|
||||
|
||||
// Graphics address:
|
||||
// bits desc
|
||||
// 20:13 Xgpage
|
||||
// 15:7 line (bits 15:13 are added) - 512 lines
|
||||
// 6:0 word within line - 128 words = 512 pixels
|
||||
|
||||
|
||||
module video_ts
|
||||
(
|
||||
|
||||
// clocks
|
||||
input wire clk,
|
||||
|
||||
// video controls
|
||||
input wire start,
|
||||
input wire [8:0] line, // = vcount - vpix_beg + 9'b1;
|
||||
input wire v_ts,
|
||||
input wire v_pf, // vertical tilemap prefetch window
|
||||
|
||||
// video config
|
||||
input wire [7:0] tsconf,
|
||||
input wire [7:0] t0gpage,
|
||||
input wire [7:0] t1gpage,
|
||||
input wire [7:0] sgpage,
|
||||
input wire [7:0] tmpage,
|
||||
input wire [5:0] num_tiles,
|
||||
input wire [8:0] t0x_offs,
|
||||
input wire [8:0] t1x_offs,
|
||||
input wire [8:0] t0y_offs,
|
||||
input wire [8:0] t1y_offs,
|
||||
input wire [1:0] t0_palsel,
|
||||
input wire [1:0] t1_palsel,
|
||||
|
||||
// SFYS interface
|
||||
input wire [7:0] sfile_addr_in,
|
||||
input wire [15:0] sfile_data_in,
|
||||
input wire sfile_we,
|
||||
|
||||
// renderer interface
|
||||
output wire tsr_go,
|
||||
output wire [5:0] tsr_addr, // graphics address within the line
|
||||
output wire [8:0] tsr_line, // bitmap line
|
||||
output wire [7:0] tsr_page, // bitmap 1st page
|
||||
output wire [8:0] tsr_x, // addr in buffer (0-359 visibles)
|
||||
output wire [2:0] tsr_xs, // size (8-64 pix)
|
||||
output wire tsr_xf, // X flip
|
||||
output wire [3:0] tsr_pal, // palette
|
||||
input wire tsr_rdy, // renderer is done and ready to receive a new task
|
||||
|
||||
// DRAM interface
|
||||
output wire [20:0] dram_addr,
|
||||
output wire dram_req,
|
||||
input wire dram_next,
|
||||
input wire [15:0] dram_rdata
|
||||
);
|
||||
|
||||
|
||||
// config
|
||||
wire s_en = tsconf[7];
|
||||
wire t1_en = tsconf[6];
|
||||
wire t0_en = tsconf[5];
|
||||
wire t1z_en = tsconf[3];
|
||||
wire t0z_en = tsconf[2];
|
||||
|
||||
|
||||
// TS renderer interface
|
||||
assign tsr_go = sprite_go || tile_go;
|
||||
assign tsr_x = sprites ? sprites_x : tile_x;
|
||||
assign tsr_xs = sprites ? sprites_xs : 3'd0;
|
||||
assign tsr_xf = sprites ? sprites_xf : t_xflp;
|
||||
assign tsr_page = sprites ? sgpage : tile_page;
|
||||
assign tsr_line = sprites ? sprites_line : tile_line;
|
||||
assign tsr_addr = sprites ? sprites_addr : tile_addr;
|
||||
assign tsr_pal = sprites ? s_pal : tile_pal;
|
||||
|
||||
|
||||
// Layer selectors control
|
||||
|
||||
localparam LAYERS = 6; // Total number of layers to process
|
||||
localparam TM = 0; // Individual layers
|
||||
localparam S0 = 1;
|
||||
localparam T0 = 2;
|
||||
localparam S1 = 3;
|
||||
localparam T1 = 4;
|
||||
localparam S2 = 5;
|
||||
|
||||
wire tmap = layer_active[TM];
|
||||
wire sprites = layer_active[S0] || layer_active[S1] || layer_active[S2];
|
||||
wire tiles = layer_active[T0] || layer_active[T1];
|
||||
|
||||
reg [LAYERS-1:0] layer;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
layer <= 1;
|
||||
else if (|(layer & layer_skip))
|
||||
layer <= {layer[LAYERS-2:0], 1'b0};
|
||||
|
||||
reg [LAYERS-1:0] layer_active;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
layer_active <= 0;
|
||||
else
|
||||
layer_active <= layer & ~layer_skip;
|
||||
|
||||
wire [LAYERS-1:0] layer_enabled = {s_en, t1_en, s_en, t0_en, s_en, t1_en || t0_en};
|
||||
wire [LAYERS-1:0] layer_allowed = {{5{v_ts}}, v_pf};
|
||||
wire [LAYERS-1:0] layer_end = {spr_end[2], tile_end[1], spr_end[1], tile_end[0], spr_end[0], tm_end};
|
||||
|
||||
reg [LAYERS-1:0] layer_skip;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
layer_skip <= ~(layer_enabled & layer_allowed);
|
||||
else
|
||||
layer_skip <= layer_skip | layer_end;
|
||||
|
||||
|
||||
// --- Tile map prefetch ---
|
||||
|
||||
// DRAM controls
|
||||
assign dram_addr = {tmpage, tm_b_row, tm_layer, tm_b_line, tm_num}; // 20:13 - page, 12:7 - row, 6 - layer, 5:0 - column (burst number : number in burst)
|
||||
assign dram_req = tmap;
|
||||
|
||||
// TMB control
|
||||
wire [8:0] tmb_waddr = {tm_line[4:3], tm_b_line, tm_num, tm_layer}; // 8:7 - buffer #, 6:4 - burst number (of 8 bursts), 3:1 - number in burst (8 tiles per burst), 0 - layer
|
||||
wire [8:0] tm_line = line + 9'd16;
|
||||
wire [2:0] tm_b_line = tm_line[2:0];
|
||||
wire [5:0] tm_b_row = tm_line[8:3] + (tm_layer ? t1y_offs[8:3] : t0y_offs[8:3]);
|
||||
wire [2:0] tm_num = tm_x[2:0];
|
||||
wire tm_layer = tm_x[3];
|
||||
|
||||
// internal layers control
|
||||
wire tm_end = tm_x == (t1_en ? 5'd16 : 5'd8);
|
||||
wire tm_next = dram_next && tmap;
|
||||
|
||||
reg [1:0] m_layer;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
m_layer <= 2'b1;
|
||||
else if (tm_end)
|
||||
m_layer <= {m_layer[0], 1'b0};
|
||||
|
||||
// tilemap X coordinate
|
||||
reg [4:0] tm_x;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
tm_x <= t0_en ? 5'd0 : 5'd8;
|
||||
else if (tm_next)
|
||||
tm_x <= tm_x + 5'd1;
|
||||
|
||||
|
||||
// --- Tiles ---
|
||||
|
||||
// tile descriptor fields
|
||||
wire [11:0] t_tnum = tmb_rdata[11:0];
|
||||
wire [1:0] t_pal = tmb_rdata[13:12];
|
||||
wire t_xflp = tmb_rdata[14];
|
||||
wire t_yflp = tmb_rdata[15];
|
||||
|
||||
// TSR control
|
||||
wire [7:0] tile_page = t_sel ? t0gpage : t1gpage;
|
||||
wire [8:0] tile_line = {t_tnum[11:6], (t_line[2:0] ^ {3{t_yflp}})};
|
||||
wire [5:0] tile_addr = t_tnum[5:0];
|
||||
wire [8:0] tile_x = {(tx - 6'd1), 3'd0} - tx_offs[2:0];
|
||||
wire [3:0] tile_pal = {t_sel ? t0_palsel : t1_palsel, t_pal};
|
||||
|
||||
// TMB control
|
||||
wire [8:0] tmb_raddr = {t_line[4:3], tx + tx_offs[8:3], ~t_sel};
|
||||
|
||||
// layer parameter selectors
|
||||
wire [8:0] tx_offs = t_sel ? t0x_offs : t1x_offs;
|
||||
wire [3:0] ty_offs = t_sel ? t0y_offs[2:0] : t1y_offs[2:0];
|
||||
wire t_sel = t_layer[0];
|
||||
|
||||
// internal layers control
|
||||
wire [1:0] tile_end = {2{t_layer_end}} & t_layer[1:0];
|
||||
wire t_layer_end = tx == num_tiles;
|
||||
wire t_layer_start = start || t_layer_end;
|
||||
|
||||
reg [1:0] t_layer;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
t_layer <= t0_en ? 2'b01 : 2'b10;
|
||||
else if (t_layer_end)
|
||||
t_layer <= {t_layer[0], 1'b0};
|
||||
|
||||
// TMBUF control
|
||||
// condition write to tx write to tm_valid
|
||||
// t_layer_start 0 TM_PRE_VALID
|
||||
// tm_pre_valid tx+1 TM_VALID
|
||||
// tile_skip tx+1 -
|
||||
// tile_go tx+1 TM_VALID
|
||||
// tile_wait tx-1 TM_PRE_VALID
|
||||
|
||||
localparam TM_PRE_VALID = 2'b01;
|
||||
localparam TM_VALID = 2'b10;
|
||||
|
||||
wire tile_go = tile_good && tsr_allowed;
|
||||
wire tile_wait = tile_good && !tsr_allowed;
|
||||
wire tile_good = tm_valid && tile_valid;
|
||||
wire tile_skip = tm_valid && !tile_valid;
|
||||
wire tsr_allowed = tiles && tsr_rdy;
|
||||
wire tile_valid = |t_tnum || (t_sel ? t0z_en : t1z_en);
|
||||
|
||||
wire tm_pre_valid = tm_valid_r[0];
|
||||
wire tm_valid = tm_valid_r[1];
|
||||
|
||||
reg [1:0] tm_valid_r;
|
||||
always @(posedge clk)
|
||||
if (t_layer_start || tile_wait)
|
||||
tm_valid_r <= TM_PRE_VALID;
|
||||
else if (tm_pre_valid || tile_go)
|
||||
tm_valid_r <= TM_VALID;
|
||||
|
||||
reg [5:0] tx;
|
||||
always @(posedge clk)
|
||||
if (t_layer_start)
|
||||
tx <= 6'd0;
|
||||
else if (tm_pre_valid || tile_skip || tile_go)
|
||||
tx <= tx + 6'd1;
|
||||
else if (tile_wait)
|
||||
tx <= tx - 6'd1;
|
||||
|
||||
// tile Y geometry
|
||||
wire [4:0] t_line = line[4:0] + ty_offs;
|
||||
|
||||
|
||||
// --- Sprites ---
|
||||
|
||||
// sprite descriptor fields
|
||||
// R0
|
||||
wire [8:0] s_ycrd = sfile_rdata[8:0];
|
||||
wire [2:0] s_ysz = sfile_rdata[11:9];
|
||||
wire s_act = sfile_rdata[13];
|
||||
wire s_leap = sfile_rdata[14];
|
||||
wire s_yflp = sfile_rdata[15];
|
||||
// R1
|
||||
wire [8:0] s_xcrd = sfile_rdata[8:0];
|
||||
wire [2:0] s_xsz = sfile_rdata[11:9];
|
||||
wire s_xflp = sfile_rdata[15];
|
||||
// R2
|
||||
wire [11:0] s_tnum = sfile_rdata[11:0];
|
||||
wire [3:0] s_pal = sfile_rdata[15:12];
|
||||
|
||||
// TSR control
|
||||
reg [8:0] sprites_x;
|
||||
reg [2:0] sprites_xs;
|
||||
reg sprites_xf;
|
||||
wire [5:0] sprites_addr = s_tnum[5:0];
|
||||
|
||||
// internal layers control
|
||||
wire [2:0] spr_end = ({3{s_layer_end}} & s_layer[2:0]) | {3{sprites_last}};
|
||||
wire s_layer_end = (sr0_valid && !spr_valid && s_leap) || (sprite_go && s_leap_r);
|
||||
wire sprites_last = sr0_valid && sprites_last_r;
|
||||
|
||||
reg sprites_last_r;
|
||||
always @(posedge clk) sprites_last_r <= sreg == 8'd255;
|
||||
|
||||
|
||||
reg [2:0] s_layer;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
s_layer <= 3'b1;
|
||||
else if (s_layer_end)
|
||||
s_layer <= {s_layer[1:0], 1'b0};
|
||||
|
||||
// SFile registers control
|
||||
// condition write to sreg write to sr_valid action
|
||||
// start 0 SR0_PRE_VALID Start
|
||||
// sr0_pre_valid sreg+3 SR0_VALID SR0 pre-read
|
||||
// sr0_valid && !spr_valid sreg+3 - Skip sprite
|
||||
// sr0_valid && spr_valid sreg-2 SR1_PRE_VALID SR1 pre-read
|
||||
// sr1_pre_valid sreg+1 SR1_VALID SR1 read
|
||||
// sr1_valid sreg+1 SR2_VALID SR2 pre-read
|
||||
// sr2_valid && !tsr_rdy - - Wait for TSR ready
|
||||
// sr2_valid && tsr_rdy sreg+1 SR0_PRE_VALID Next sprite
|
||||
// sprites_last - NONE_VALID End
|
||||
|
||||
localparam NONE_VALID = 5'b00000;
|
||||
localparam SR0_PRE_VALID = 5'b00001;
|
||||
localparam SR0_VALID = 5'b00010;
|
||||
localparam SR1_PRE_VALID = 5'b00100;
|
||||
localparam SR1_VALID = 5'b01000;
|
||||
localparam SR2_VALID = 5'b10000;
|
||||
|
||||
wire sprite_go = sr2_valid && sprites && tsr_rdy; // kick to renderer
|
||||
wire spr_valid = s_visible && s_act;
|
||||
|
||||
wire sr0_pre_valid = sr_valid[0];
|
||||
wire sr0_valid = sr_valid[1];
|
||||
wire sr1_pre_valid = sr_valid[2];
|
||||
wire sr1_valid = sr_valid[3];
|
||||
wire sr2_valid = sr_valid[4];
|
||||
|
||||
reg [4:0] sr_valid;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
sr_valid <= SR0_PRE_VALID;
|
||||
else if (sprites_last)
|
||||
sr_valid <= NONE_VALID;
|
||||
else if (sr0_pre_valid)
|
||||
sr_valid <= SR0_VALID;
|
||||
else if (sr0_valid && spr_valid)
|
||||
sr_valid <= SR1_PRE_VALID;
|
||||
else if (sr1_pre_valid)
|
||||
sr_valid <= SR1_VALID;
|
||||
else if (sr1_valid)
|
||||
sr_valid <= SR2_VALID;
|
||||
else if (sprite_go)
|
||||
sr_valid <= SR0_PRE_VALID;
|
||||
|
||||
reg [7:0] sreg;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
sreg <= 8'd0;
|
||||
else if (sr0_pre_valid)
|
||||
sreg <= sreg + 8'd3;
|
||||
else if (sr0_valid)
|
||||
sreg <= spr_valid ? (sreg - 8'd2) : (sreg + 8'd3);
|
||||
else if (sr1_pre_valid || sprite_go)
|
||||
sreg <= sreg + 8'd1;
|
||||
|
||||
// SFile control
|
||||
reg [5:0] s_bmline_offset_r;
|
||||
reg s_leap_r;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (sr0_valid)
|
||||
begin
|
||||
s_leap_r <= s_leap;
|
||||
s_bmline_offset_r <= s_bmline_offset;
|
||||
end
|
||||
|
||||
if (sr1_valid)
|
||||
begin
|
||||
sprites_x <= s_xcrd;
|
||||
sprites_xs <= s_xsz;
|
||||
sprites_xf <= s_xflp;
|
||||
end
|
||||
end
|
||||
|
||||
// sprite Y geometry
|
||||
wire [8:0] s_line = line - s_ycrd; // visible line of sprite in current video line
|
||||
wire s_visible = (s_line <= s_ymax); // check if sprite line is within Y size
|
||||
wire [5:0] s_ymax = {s_ysz, 3'b111};
|
||||
|
||||
wire [8:0] sprites_line = {s_tnum[11:6], 3'b0} + s_bmline_offset_r;
|
||||
wire [5:0] s_bmline_offset = s_yflp ? (s_ymax - s_line[5:0]) : s_line[5:0];
|
||||
|
||||
|
||||
// SFile
|
||||
wire [15:0] sfile_rdata;
|
||||
dpram #(.DATAWIDTH(16), .ADDRWIDTH(8)) video_sfile
|
||||
`include "tune.v"
|
||||
|
||||
// This is the Tile Sprite Processing Unit
|
||||
|
||||
// Tiles map address:
|
||||
// bits desc
|
||||
// 20:13 tmpage
|
||||
// 12:
|
||||
|
||||
// Graphics address:
|
||||
// bits desc
|
||||
// 20:13 Xgpage
|
||||
// 15:7 line (bits 15:13 are added) - 512 lines
|
||||
// 6:0 word within line - 128 words = 512 pixels
|
||||
|
||||
|
||||
module video_ts
|
||||
(
|
||||
.clock (clk),
|
||||
.address_a (sfile_addr_in),
|
||||
.data_a (sfile_data_in),
|
||||
.wren_a (sfile_we),
|
||||
.address_b (sreg),
|
||||
.q_b (sfile_rdata)
|
||||
);
|
||||
|
||||
// 4 buffers * 2 tile-planes * 64 tiles * 16 bits (9x16) - used to prefetch tiles
|
||||
// (2 altdprams)
|
||||
wire [15:0] tmb_rdata;
|
||||
dpram #(.DATAWIDTH(16), .ADDRWIDTH(9)) video_tmbuf
|
||||
(
|
||||
.clock (clk),
|
||||
.address_a (tmb_waddr),
|
||||
.data_a (dram_rdata),
|
||||
.wren_a (tm_next),
|
||||
.address_b (tmb_raddr),
|
||||
.q_b (tmb_rdata)
|
||||
// clocks
|
||||
input wire clk,
|
||||
|
||||
// video controls
|
||||
input wire start,
|
||||
input wire [8:0] line, // = vcount - vpix_beg + 9'b1;
|
||||
input wire v_ts,
|
||||
input wire v_pf, // vertical tilemap prefetch window
|
||||
|
||||
// video config
|
||||
input wire [7:0] tsconf,
|
||||
input wire [7:0] t0gpage,
|
||||
input wire [7:0] t1gpage,
|
||||
input wire [7:0] sgpage,
|
||||
input wire [7:0] tmpage,
|
||||
input wire [5:0] num_tiles,
|
||||
input wire [8:0] t0x_offs,
|
||||
input wire [8:0] t1x_offs,
|
||||
input wire [8:0] t0y_offs,
|
||||
input wire [8:0] t1y_offs,
|
||||
input wire [1:0] t0_palsel,
|
||||
input wire [1:0] t1_palsel,
|
||||
|
||||
// SFYS interface
|
||||
input wire [7:0] sfile_addr_in,
|
||||
input wire [15:0] sfile_data_in,
|
||||
input wire sfile_we,
|
||||
|
||||
// renderer interface
|
||||
output wire tsr_go,
|
||||
output wire [5:0] tsr_addr, // graphics address within the line
|
||||
output wire [8:0] tsr_line, // bitmap line
|
||||
output wire [7:0] tsr_page, // bitmap 1st page
|
||||
output wire [8:0] tsr_x, // addr in buffer (0-359 visibles)
|
||||
output wire [2:0] tsr_xs, // size (8-64 pix)
|
||||
output wire tsr_xf, // X flip
|
||||
output wire [3:0] tsr_pal, // palette
|
||||
input wire tsr_rdy, // renderer is done and ready to receive a new task
|
||||
|
||||
// DRAM interface
|
||||
output wire [20:0] dram_addr,
|
||||
output wire dram_req,
|
||||
input wire dram_next,
|
||||
input wire [15:0] dram_rdata
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
// config
|
||||
wire s_en = tsconf[7];
|
||||
wire t1_en = tsconf[6];
|
||||
wire t0_en = tsconf[5];
|
||||
wire t1z_en = tsconf[3];
|
||||
wire t0z_en = tsconf[2];
|
||||
|
||||
// tile descriptor fields
|
||||
wire [15:0] tmb_rdata;
|
||||
|
||||
wire [11:0] t_tnum = tmb_rdata[11:0];
|
||||
wire [1:0] t_pal = tmb_rdata[13:12];
|
||||
wire t_xflp = tmb_rdata[14];
|
||||
wire t_yflp = tmb_rdata[15];
|
||||
|
||||
// Layer selectors control
|
||||
localparam LAYERS = 6; // total number of layers to process
|
||||
|
||||
localparam TM = 0; // Individual layers
|
||||
localparam S0 = 1;
|
||||
localparam T0 = 2;
|
||||
localparam S1 = 3;
|
||||
localparam T1 = 4;
|
||||
localparam S2 = 5;
|
||||
|
||||
reg [LAYERS-1:0] layer_active;
|
||||
reg [LAYERS-1:0] layer_skip;
|
||||
|
||||
wire tmap = layer_active[TM];
|
||||
wire sprites = layer_active[S0] || layer_active[S1] || layer_active[S2];
|
||||
wire tiles = layer_active[T0] || layer_active[T1];
|
||||
|
||||
reg [LAYERS-1:0] layer;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
layer <= 1;
|
||||
else if (|(layer & layer_skip))
|
||||
layer <= {layer[LAYERS-2:0], 1'b0};
|
||||
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
layer_active <= 0;
|
||||
else
|
||||
layer_active <= layer & ~layer_skip;
|
||||
|
||||
wire [2:0] spr_end;
|
||||
wire [1:0] tile_end;
|
||||
wire tm_end;
|
||||
wire [LAYERS-1:0] layer_enabled = {s_en, t1_en, s_en, t0_en, s_en, t1_en || t0_en};
|
||||
wire [LAYERS-1:0] layer_allowed = {{5{v_ts}}, v_pf};
|
||||
wire [LAYERS-1:0] layer_end = {spr_end[2], tile_end[1], spr_end[1], tile_end[0], spr_end[0], tm_end};
|
||||
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
layer_skip <= ~(layer_enabled & layer_allowed);
|
||||
else
|
||||
layer_skip <= layer_skip | layer_end;
|
||||
|
||||
// --- Tile map prefetch ---
|
||||
// TMB control
|
||||
reg [4:0] tm_x;
|
||||
|
||||
wire [8:0] tm_line = line + 9'd16;
|
||||
wire [2:0] tm_b_line = tm_line[2:0];
|
||||
wire [2:0] tm_num = tm_x[2:0];
|
||||
wire tm_layer = tm_x[3];
|
||||
wire [8:0] tmb_waddr = {tm_line[4:3], tm_b_line, tm_num, tm_layer}; // 8:7 - buffer #, 6:4 - burst number (of 8 bursts), 3:1 - number in burst (8 tiles per burst), 0 - layer
|
||||
wire [5:0] tm_b_row = tm_line[8:3] + (tm_layer ? t1y_offs[8:3] : t0y_offs[8:3]);
|
||||
|
||||
// DRAM controls
|
||||
assign dram_addr = {tmpage, tm_b_row, tm_layer, tm_b_line, tm_num}; // 20:13 - page, 12:7 - row, 6 - layer, 5:0 - column (burst number : number in burst)
|
||||
assign dram_req = tmap;
|
||||
|
||||
// internal layers control
|
||||
assign tm_end = tm_x == (t1_en ? 5'd16 : 5'd8);
|
||||
wire tm_next = dram_next && tmap;
|
||||
|
||||
reg [1:0] m_layer;
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
m_layer <= 2'b1;
|
||||
else if (tm_end)
|
||||
m_layer <= {m_layer[0], 1'b0};
|
||||
|
||||
// tilemap X coordinate
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
tm_x <= t0_en ? 5'd0 : 5'd8;
|
||||
else if (tm_next)
|
||||
tm_x <= tm_x + 5'd1;
|
||||
|
||||
// --- Tiles ---
|
||||
// layer parameter selectors
|
||||
reg [1:0] t_layer;
|
||||
reg [5:0] tx;
|
||||
|
||||
wire t_sel = t_layer[0];
|
||||
wire [8:0] tx_offs = t_sel ? t0x_offs : t1x_offs;
|
||||
wire [3:0] ty_offs = t_sel ? t0y_offs[2:0] : t1y_offs[2:0];
|
||||
|
||||
// TSR control
|
||||
wire [4:0] t_line;
|
||||
wire [7:0] tile_page = t_sel ? t0gpage : t1gpage;
|
||||
wire [8:0] tile_line = {t_tnum[11:6], (t_line[2:0] ^ {3{t_yflp}})};
|
||||
wire [5:0] tile_addr = t_tnum[5:0];
|
||||
wire [8:0] tile_x = {(tx - 6'd1), 3'd0} - tx_offs[2:0];
|
||||
wire [3:0] tile_pal = {t_sel ? t0_palsel : t1_palsel, t_pal};
|
||||
|
||||
// TMB control
|
||||
wire [8:0] tmb_raddr = {t_line[4:3], tx + tx_offs[8:3], ~t_sel};
|
||||
|
||||
// internal layers control
|
||||
wire t_layer_end = tx == num_tiles;
|
||||
wire t_layer_start = start || t_layer_end;
|
||||
assign tile_end = {2{t_layer_end}} & t_layer[1:0];
|
||||
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
t_layer <= t0_en ? 2'b01 : 2'b10;
|
||||
else if (t_layer_end)
|
||||
t_layer <= {t_layer[0], 1'b0};
|
||||
|
||||
// TMBUF control
|
||||
// condition write to tx write to tm_valid
|
||||
// t_layer_start 0 TM_PRE_VALID
|
||||
// tm_pre_valid tx+1 TM_VALID
|
||||
// tile_skip tx+1 -
|
||||
// tile_go tx+1 TM_VALID
|
||||
// tile_wait tx-1 TM_PRE_VALID
|
||||
|
||||
localparam TM_PRE_VALID = 2'b01;
|
||||
localparam TM_VALID = 2'b10;
|
||||
|
||||
reg [1:0] tm_valid_r;
|
||||
wire tm_valid = tm_valid_r[1];
|
||||
wire tm_pre_valid = tm_valid_r[0];
|
||||
|
||||
wire tile_valid = |t_tnum || (t_sel ? t0z_en : t1z_en);
|
||||
wire tsr_allowed = tiles && tsr_rdy;
|
||||
wire tile_good = tm_valid && tile_valid;
|
||||
wire tile_wait = tile_good && !tsr_allowed;
|
||||
wire tile_skip = tm_valid && !tile_valid;
|
||||
wire tile_go = tile_good && tsr_allowed;
|
||||
|
||||
always @(posedge clk)
|
||||
if (t_layer_start || tile_wait)
|
||||
tm_valid_r <= TM_PRE_VALID;
|
||||
else if (tm_pre_valid || tile_go)
|
||||
tm_valid_r <= TM_VALID;
|
||||
|
||||
always @(posedge clk)
|
||||
if (t_layer_start)
|
||||
tx <= 6'd0;
|
||||
else if (tm_pre_valid || tile_skip || tile_go)
|
||||
tx <= tx + 6'd1;
|
||||
else if (tile_wait)
|
||||
tx <= tx - 6'd1;
|
||||
|
||||
// tile Y geometry
|
||||
assign t_line = line[4:0] + ty_offs;
|
||||
|
||||
// --- Sprites ---
|
||||
// sprite descriptor fields
|
||||
// R0
|
||||
wire [15:0] sfile_rdata;
|
||||
|
||||
wire [8:0] s_ycrd = sfile_rdata[8:0];
|
||||
wire [2:0] s_ysz = sfile_rdata[11:9];
|
||||
wire s_act = sfile_rdata[13];
|
||||
wire s_leap = sfile_rdata[14];
|
||||
wire s_yflp = sfile_rdata[15];
|
||||
// R1
|
||||
wire [8:0] s_xcrd = sfile_rdata[8:0];
|
||||
wire [2:0] s_xsz = sfile_rdata[11:9];
|
||||
wire s_xflp = sfile_rdata[15];
|
||||
// R2
|
||||
wire [11:0] s_tnum = sfile_rdata[11:0];
|
||||
wire [3:0] s_pal = sfile_rdata[15:12];
|
||||
|
||||
// TSR control
|
||||
wire [5:0] sprites_addr = s_tnum[5:0];
|
||||
|
||||
// internal layers control
|
||||
reg sprites_last_r;
|
||||
reg [2:0] s_layer;
|
||||
reg [7:0] sreg;
|
||||
reg [4:0] sr_valid;
|
||||
reg s_leap_r;
|
||||
|
||||
wire sr0_pre_valid = sr_valid[0];
|
||||
wire sr0_valid = sr_valid[1];
|
||||
wire sr1_pre_valid = sr_valid[2];
|
||||
wire sr1_valid = sr_valid[3];
|
||||
wire sr2_valid = sr_valid[4];
|
||||
|
||||
wire sprite_go;
|
||||
wire s_visible;
|
||||
wire spr_valid = s_visible && s_act;
|
||||
wire s_layer_end = (sr0_valid && !spr_valid && s_leap) || (sprite_go && s_leap_r);
|
||||
wire sprites_last = sr0_valid && sprites_last_r;
|
||||
assign spr_end = ({3{s_layer_end}} & s_layer[2:0]) | {3{sprites_last}};
|
||||
|
||||
always @(posedge clk)
|
||||
sprites_last_r <= sreg == 8'd255;
|
||||
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
s_layer <= 3'b1;
|
||||
else if (s_layer_end)
|
||||
s_layer <= {s_layer[1:0], 1'b0};
|
||||
|
||||
// SFile registers control
|
||||
// condition write to sreg write to sr_valid action
|
||||
// start 0 SR0_PRE_VALID Start
|
||||
// sr0_pre_valid sreg+3 SR0_VALID SR0 pre-read
|
||||
// sr0_valid && !spr_valid sreg+3 - Skip sprite
|
||||
// sr0_valid && spr_valid sreg-2 SR1_PRE_VALID SR1 pre-read
|
||||
// sr1_pre_valid sreg+1 SR1_VALID SR1 read
|
||||
// sr1_valid sreg+1 SR2_VALID SR2 pre-read
|
||||
// sr2_valid && !tsr_rdy - - Wait for TSR ready
|
||||
// sr2_valid && tsr_rdy sreg+1 SR0_PRE_VALID Next sprite
|
||||
// sprites_last - NONE_VALID End
|
||||
|
||||
localparam NONE_VALID = 5'b00000;
|
||||
localparam SR0_PRE_VALID = 5'b00001;
|
||||
localparam SR0_VALID = 5'b00010;
|
||||
localparam SR1_PRE_VALID = 5'b00100;
|
||||
localparam SR1_VALID = 5'b01000;
|
||||
localparam SR2_VALID = 5'b10000;
|
||||
|
||||
assign sprite_go = sr2_valid && sprites && tsr_rdy; // a kick to renderer
|
||||
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
sr_valid <= SR0_PRE_VALID;
|
||||
else if (sprites_last)
|
||||
sr_valid <= NONE_VALID;
|
||||
else if (sr0_pre_valid)
|
||||
sr_valid <= SR0_VALID;
|
||||
else if (sr0_valid && spr_valid)
|
||||
sr_valid <= SR1_PRE_VALID;
|
||||
else if (sr1_pre_valid)
|
||||
sr_valid <= SR1_VALID;
|
||||
else if (sr1_valid)
|
||||
sr_valid <= SR2_VALID;
|
||||
else if (sprite_go)
|
||||
sr_valid <= SR0_PRE_VALID;
|
||||
|
||||
always @(posedge clk)
|
||||
if (start)
|
||||
sreg <= 8'd0;
|
||||
else if (sr0_pre_valid)
|
||||
sreg <= sreg + 8'd3;
|
||||
else if (sr0_valid)
|
||||
sreg <= spr_valid ? (sreg - 8'd2) : (sreg + 8'd3);
|
||||
else if (sr1_pre_valid || sprite_go)
|
||||
sreg <= sreg + 8'd1;
|
||||
|
||||
// sprite Y geometry
|
||||
reg [5:0] s_bmline_offset_r;
|
||||
|
||||
wire [8:0] s_line = line - s_ycrd; // visible line of sprite in current video line
|
||||
wire [5:0] s_ymax = {s_ysz, 3'b111};
|
||||
assign s_visible = (s_line <= s_ymax); // check if sprite line is within Y size
|
||||
|
||||
wire [8:0] sprites_line = {s_tnum[11:6], 3'b0} + s_bmline_offset_r;
|
||||
wire [5:0] s_bmline_offset = s_yflp ? (s_ymax - s_line[5:0]) : s_line[5:0];
|
||||
|
||||
// SFile control
|
||||
reg [8:0] sprites_x;
|
||||
reg [2:0] sprites_xs;
|
||||
reg sprites_xf;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (sr0_valid)
|
||||
begin
|
||||
s_leap_r <= s_leap;
|
||||
s_bmline_offset_r <= s_bmline_offset;
|
||||
end
|
||||
|
||||
if (sr1_valid)
|
||||
begin
|
||||
sprites_x <= s_xcrd;
|
||||
sprites_xs <= s_xsz;
|
||||
sprites_xf <= s_xflp;
|
||||
end
|
||||
end
|
||||
|
||||
// SFile
|
||||
dpram #(.DATAWIDTH(16), .ADDRWIDTH(8)) video_sfile
|
||||
(
|
||||
.clock (clk),
|
||||
.address_a (sfile_addr_in),
|
||||
.data_a (sfile_data_in),
|
||||
.wren_a (sfile_we),
|
||||
.address_b (sreg),
|
||||
.q_b (sfile_rdata)
|
||||
);
|
||||
/*
|
||||
altdpram video_sfile
|
||||
(
|
||||
.outclock (clk),
|
||||
.wren (sfile_we),
|
||||
.inclock (clk),
|
||||
.data (sfile_data_in),
|
||||
.rdaddress (sreg),
|
||||
.wraddress (sfile_addr_in),
|
||||
.q (sfile_rdata),
|
||||
.aclr (1'b0),
|
||||
.byteena (1'b1),
|
||||
.inclocken (1'b1),
|
||||
.outclocken (1'b1),
|
||||
.rdaddressstall (1'b0),
|
||||
.rden (1'b1),
|
||||
.wraddressstall (1'b0)
|
||||
);
|
||||
|
||||
defparam
|
||||
video_sfile.indata_aclr = "OFF",
|
||||
video_sfile.indata_reg = "INCLOCK",
|
||||
video_sfile.intended_device_family = "ACEX1K",
|
||||
video_sfile.lpm_type = "altdpram",
|
||||
video_sfile.outdata_aclr = "OFF",
|
||||
video_sfile.outdata_reg = "OUTCLOCK",
|
||||
video_sfile.rdaddress_aclr = "OFF",
|
||||
video_sfile.rdaddress_reg = "UNREGISTERED",
|
||||
video_sfile.rdcontrol_aclr = "OFF",
|
||||
video_sfile.rdcontrol_reg = "UNREGISTERED",
|
||||
video_sfile.width = 16,
|
||||
video_sfile.widthad = 8,
|
||||
video_sfile.wraddress_aclr = "OFF",
|
||||
video_sfile.wraddress_reg = "INCLOCK",
|
||||
video_sfile.wrcontrol_aclr = "OFF",
|
||||
video_sfile.wrcontrol_reg = "INCLOCK";
|
||||
*/
|
||||
// 4 buffers * 2 tile-planes * 64 tiles * 16 bits (9x16) - used to prefetch tiles
|
||||
// (2 altdprams)
|
||||
dpram #(.DATAWIDTH(16), .ADDRWIDTH(9)) video_tmbuf
|
||||
(
|
||||
.clock (clk),
|
||||
.address_a (tmb_waddr),
|
||||
.data_a (dram_rdata),
|
||||
.wren_a (tm_next),
|
||||
.address_b (tmb_raddr),
|
||||
.q_b (tmb_rdata)
|
||||
);
|
||||
/*
|
||||
altdpram video_tmbuf
|
||||
(
|
||||
.outclock (clk),
|
||||
.wren (tm_next),
|
||||
.inclock (clk),
|
||||
.data (dram_rdata),
|
||||
.rdaddress (tmb_raddr),
|
||||
.wraddress (tmb_waddr),
|
||||
.q (tmb_rdata),
|
||||
.aclr (1'b0),
|
||||
.byteena (1'b1),
|
||||
.inclocken (1'b1),
|
||||
.outclocken (1'b1),
|
||||
.rdaddressstall (1'b0),
|
||||
.rden (1'b1),
|
||||
.wraddressstall (1'b0)
|
||||
);
|
||||
|
||||
defparam
|
||||
video_tmbuf.indata_aclr = "OFF",
|
||||
video_tmbuf.indata_reg = "INCLOCK",
|
||||
video_tmbuf.intended_device_family = "ACEX1K",
|
||||
video_tmbuf.lpm_type = "altdpram",
|
||||
video_tmbuf.outdata_aclr = "OFF",
|
||||
video_tmbuf.outdata_reg = "OUTCLOCK",
|
||||
video_tmbuf.rdaddress_aclr = "OFF",
|
||||
video_tmbuf.rdaddress_reg = "UNREGISTERED",
|
||||
video_tmbuf.rdcontrol_aclr = "OFF",
|
||||
video_tmbuf.rdcontrol_reg = "UNREGISTERED",
|
||||
video_tmbuf.width = 16,
|
||||
video_tmbuf.widthad = 9,
|
||||
video_tmbuf.wraddress_aclr = "OFF",
|
||||
video_tmbuf.wraddress_reg = "INCLOCK",
|
||||
video_tmbuf.wrcontrol_aclr = "OFF",
|
||||
video_tmbuf.wrcontrol_reg = "INCLOCK";
|
||||
*/
|
||||
// TS renderer interface
|
||||
assign tsr_go = sprite_go || tile_go;
|
||||
assign tsr_x = sprites ? sprites_x : tile_x;
|
||||
assign tsr_xs = sprites ? sprites_xs : 3'd0;
|
||||
assign tsr_xf = sprites ? sprites_xf : t_xflp;
|
||||
assign tsr_page = sprites ? sgpage : tile_page;
|
||||
assign tsr_line = sprites ? sprites_line : tile_line;
|
||||
assign tsr_addr = sprites ? sprites_addr : tile_addr;
|
||||
assign tsr_pal = sprites ? s_pal : tile_pal;
|
||||
|
||||
endmodule
|
||||
|
Reference in New Issue
Block a user