Line 1... |
Line 1... |
// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2018 Robert Finch, Waterloo
|
// \\__/ o\ (C) 2018-2019 Robert Finch, Waterloo
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@finitron.ca
|
// \/_// robfinch<remove>@finitron.ca
|
// ||
|
// ||
|
//
|
//
|
// rtfSpriteController2.v
|
// rtfSpriteController2.v
|
Line 32... |
Line 32... |
`define ABITS 31:0
|
`define ABITS 31:0
|
// The cycle at which it's safe to update the working count and address.
|
// The cycle at which it's safe to update the working count and address.
|
// A good value is just before the end of the scan, but that depends on
|
// A good value is just before the end of the scan, but that depends on
|
// display resolution.
|
// display resolution.
|
`define SPR_WCA 12'd638
|
`define SPR_WCA 12'd638
|
|
//`define SUPPORT_LOWRES 1'b1
|
|
|
module rtfSpriteController2(rst_i, clk_i, cs_i, cyc_i, stb_i, ack_o, we_i, sel_i, adr_i, dat_i, dat_o,
|
module rtfSpriteController2(clk_i, cs_i, cyc_i, stb_i, ack_o, we_i, sel_i, adr_i, dat_i, dat_o,
|
m_clk_i, m_cyc_o, m_stb_o, m_ack_i, m_sel_o, m_adr_o, m_dat_i,
|
m_clk_i, m_cyc_o, m_stb_o, m_ack_i, m_sel_o, m_adr_o, m_dat_i, m_spriteno_o,
|
dot_clk_i, hsync_i, vsync_i, zrgb_i, zrgb_o, test
|
dot_clk_i, hsync_i, vsync_i, border_i, zrgb_i, zrgb_o, test
|
);
|
);
|
// Bus slave port
|
// Bus slave port
|
input rst_i;
|
|
input clk_i;
|
input clk_i;
|
input cs_i;
|
input cs_i;
|
input cyc_i;
|
input cyc_i;
|
input stb_i;
|
input stb_i;
|
output ack_o;
|
output ack_o;
|
Line 57... |
Line 57... |
output m_stb_o;
|
output m_stb_o;
|
input m_ack_i;
|
input m_ack_i;
|
output [7:0] m_sel_o;
|
output [7:0] m_sel_o;
|
output reg [`ABITS] m_adr_o;
|
output reg [`ABITS] m_adr_o;
|
input [63:0] m_dat_i;
|
input [63:0] m_dat_i;
|
|
output reg [4:0] m_spriteno_o;
|
// Video port
|
// Video port
|
input dot_clk_i;
|
input dot_clk_i;
|
input vsync_i;
|
input vsync_i;
|
input hsync_i;
|
input hsync_i;
|
|
input border_i;
|
input [31:0] zrgb_i;
|
input [31:0] zrgb_i;
|
output reg [31:0] zrgb_o;
|
output reg [31:0] zrgb_o;
|
input test;
|
input test;
|
|
|
parameter NSPR = 32;
|
parameter NSPR = 32;
|
parameter IDLE = 3'd0;
|
parameter IDLE = 2'd0;
|
parameter DATA_FETCH = 3'd1;
|
parameter DATA_FETCH = 2'd1;
|
parameter MEM_ACCESS = 3'd2;
|
parameter MEM_ACCESS = 2'd2;
|
parameter WAIT_NACK = 3'd3;
|
|
parameter NEXT_SPRITE = 3'd4;
|
|
|
|
integer n;
|
integer n;
|
|
|
reg controller_enable;
|
reg controller_enable = 1'b1;
|
wire vclk;
|
wire vclk;
|
reg [2:0] state;
|
reg [1:0] state = IDLE;
|
reg [1:0] lowres;
|
reg [1:0] lowres = 2'b00;
|
wire [5:0] flashcnt;
|
wire [5:0] flashcnt;
|
reg rst_collision;
|
reg rst_collision = 1'b0;
|
reg [31:0] collision, c_collision;
|
reg [31:0] collision, c_collision;
|
reg [4:0] spriteno;
|
reg [4:0] spriteno = 5'd0;
|
reg sprite;
|
reg sprite;
|
reg [31:0] spriteEnable;
|
reg [31:0] spriteEnable = 32'hFFFFFFFF;
|
reg [31:0] spriteActive;
|
reg [31:0] spriteActive;
|
reg [11:0] sprite_pv [0:31];
|
reg [11:0] sprite_pv [0:31];
|
reg [11:0] sprite_ph [0:31];
|
reg [11:0] sprite_ph [0:31];
|
reg [3:0] sprite_pz [0:31];
|
reg [3:0] sprite_pz [0:31];
|
(* ram_style="distributed" *)
|
(* ram_style="distributed" *)
|
Line 101... |
Line 101... |
reg [`ABITS] spriteWaddr [0:31];
|
reg [`ABITS] spriteWaddr [0:31];
|
reg [15:0] spriteMcnt [0:31];
|
reg [15:0] spriteMcnt [0:31];
|
reg [15:0] spriteWcnt [0:31];
|
reg [15:0] spriteWcnt [0:31];
|
reg [63:0] m_spriteBmp [0:31];
|
reg [63:0] m_spriteBmp [0:31];
|
reg [63:0] spriteBmp [0:31];
|
reg [63:0] spriteBmp [0:31];
|
reg [31:0] spriteLink1;
|
reg [31:0] spriteLink1 = 32'h0;
|
reg [7:0] spriteColorNdx [0:31];
|
reg [7:0] spriteColorNdx [0:31];
|
|
|
initial begin
|
initial begin
|
for (n = 0; n < 256; n = n + 1) begin
|
for (n = 0; n < 256; n = n + 1) begin
|
sprite_color[n] <= 38'h0000FF1F1F;
|
sprite_color[n] <= {6'h00,8'h00,n[7:5],5'd0,n[4:3],6'd0,n[2:0],5'd0};
|
|
// sprite_color[n][31:0] <= {8'h00,n[7:5],5'd0,n[4:3],6'd0,n[2:0],5'd0}; // <- doesn't work
|
end
|
end
|
for (n = 0; n < 32; n = n + 1) begin
|
for (n = 0; n < 32; n = n + 1) begin
|
sprite_ph[n] <= 260 + n * 40;
|
if (n < 16) begin
|
sprite_pv[n] <= 41 + n * 20;
|
sprite_ph[n] <= 400 + n * 32;
|
sprite_pz[n] <= 8'h00;
|
sprite_pv[n] <= 100 + n * 8;
|
spriteMcnt[n] <= 60 * 32;
|
end
|
|
else begin
|
|
sprite_ph[n] <= 400 + (n - 16) * 32;
|
|
sprite_pv[n] <= 200 + n * 8;
|
|
end
|
|
sprite_pz[n] <= 8'h08;
|
|
spriteMcnt[n] <= 80 * 32;
|
spriteBmp[n] <= 64'hFFFFFFFFFFFFFFFF;
|
spriteBmp[n] <= 64'hFFFFFFFFFFFFFFFF;
|
|
spriteAddr[n] <= 32'h40000 + (n << 12);
|
end
|
end
|
end
|
end
|
|
|
wire pe_hsync, pe_vsync;
|
wire pe_hsync, pe_vsync;
|
wire [11:0] hctr, vctr;
|
wire [11:0] hctr, vctr;
|
reg [11:0] m_hctr, m_vctr;
|
reg [11:0] m_hctr, m_vctr;
|
|
|
// Generate acknowledge signal
|
reg cs;
|
wire cs = cs_i & cyc_i & stb_i;
|
reg we;
|
reg rdy1,rdy2,rdy3;
|
reg [7:0] sel;
|
always @(posedge clk_i)
|
reg [11:0] adr;
|
rdy1 <= cs;
|
reg [63:0] dat;
|
always @(posedge clk_i)
|
|
rdy2 <= rdy1 & cs;
|
wire clk;
|
always @(posedge clk_i)
|
`ifdef USE_CLOCK_GATE
|
rdy3 <= rdy2 & cs;
|
BUFH uclk (.I(clk_i), .O(clk));
|
assign ack_o = (cs & we_i) ? 1'b1 : rdy3;
|
`else
|
|
wire clk = clk_i;
|
|
`endif
|
|
|
|
always @(posedge clk)
|
|
cs <= cs_i & cyc_i & stb_i;
|
|
always @(posedge clk)
|
|
we <= we_i;
|
|
always @(posedge clk)
|
|
sel <= sel_i;
|
|
always @(posedge clk)
|
|
adr <= adr_i;
|
|
always @(posedge clk)
|
|
dat <= dat_i;
|
|
|
|
ack_gen #(
|
|
.READ_STAGES(4),
|
|
.WRITE_STAGES(0),
|
|
.REGISTER_OUTPUT(1)
|
|
) uag1
|
|
(
|
|
.clk_i(clk),
|
|
.ce_i(1'b1),
|
|
.i(cs),
|
|
.we_i(cs & we),
|
|
.o(ack_o)
|
|
);
|
|
|
(* ram_style="block" *)
|
(* ram_style="block" *)
|
reg [63:0] shadow_ram [0:511];
|
reg [63:0] shadow_ram [0:511];
|
|
reg [63:0] shadow_ramo;
|
reg [8:0] sradr;
|
reg [8:0] sradr;
|
always @(posedge clk_i)
|
always @(posedge clk)
|
if (cs & we_i) begin
|
if (cs & we) begin
|
if (sel_i[0]) shadow_ram[adr_i[11:3]][ 7: 0] <= dat_i;
|
if (|sel[1:0]) shadow_ram[adr[11:3]][15: 0] <= dat[15: 0];
|
if (sel_i[1]) shadow_ram[adr_i[11:3]][15: 8] <= dat_i;
|
if (|sel[3:2]) shadow_ram[adr[11:3]][31:16] <= dat[31:16];
|
if (sel_i[2]) shadow_ram[adr_i[11:3]][23:16] <= dat_i;
|
if (|sel[5:4]) shadow_ram[adr[11:3]][47:32] <= dat[47:32];
|
if (sel_i[3]) shadow_ram[adr_i[11:3]][31:24] <= dat_i;
|
if (|sel[7:6]) shadow_ram[adr[11:3]][63:48] <= dat[63:48];
|
if (sel_i[4]) shadow_ram[adr_i[11:3]][39:32] <= dat_i;
|
end
|
if (sel_i[5]) shadow_ram[adr_i[11:3]][47:40] <= dat_i;
|
always @(posedge clk)
|
if (sel_i[6]) shadow_ram[adr_i[11:3]][55:48] <= dat_i;
|
sradr <= adr[11:3];
|
if (sel_i[7]) shadow_ram[adr_i[11:3]][63:56] <= dat_i;
|
always @(posedge clk)
|
end
|
shadow_ramo <= shadow_ram[sradr];
|
always @(posedge clk_i)
|
always @(posedge clk)
|
sradr <= adr_i[11:3];
|
case(adr[11:3])
|
always @(posedge clk_i)
|
|
case(adr_i[11:3])
|
|
9'b1010_0001_0: dat_o <= c_collision;
|
9'b1010_0001_0: dat_o <= c_collision;
|
default: dat_o <= shadow_ram[sradr];
|
default: dat_o <= shadow_ramo;
|
endcase
|
endcase
|
|
|
always @(posedge clk_i)
|
always @(posedge clk)
|
if (rst_i) begin
|
begin
|
rst_collision <= `FALSE;
|
|
controller_enable <= `TRUE;
|
|
spriteEnable <= 32'hFFFFFFFF;
|
|
spriteLink1 <= 32'h0;
|
|
end
|
|
else begin
|
|
rst_collision <= `FALSE;
|
rst_collision <= `FALSE;
|
if (cs & we_i) begin
|
if (cs & we) begin
|
casez(adr_i[11:3])
|
casez(adr[11:3])
|
9'b0???_????_?: sprite_color[adr_i[10:3]] <= dat_i[37:0];
|
9'b0???_????_?: sprite_color[adr[10:3]] <= dat[37:0];
|
9'b100?_????_0: spriteAddr[adr_i[8:4]] <= dat_i[`ABITS];
|
9'b100?_????_0: spriteAddr[adr[8:4]] <= dat[`ABITS];
|
9'b100?_????_1:
|
9'b100?_????_1:
|
begin
|
begin
|
if (|sel_i[1:0]) sprite_ph[adr_i[8:4]] <= dat_i[11: 0];
|
if (|sel[1:0]) sprite_ph[adr[8:4]] <= dat[11: 0];
|
if (|sel_i[3:2]) sprite_pv[adr_i[8:4]] <= dat_i[27:16];
|
if (|sel[3:2]) sprite_pv[adr[8:4]] <= dat[27:16];
|
if ( sel_i[ 4]) sprite_pz[adr_i[8:4]] <= dat_i[39:32];
|
if (|sel[5:4]) sprite_pz[adr[8:4]] <= dat[39:32];
|
if (|sel_i[7:6]) spriteMcnt[adr_i[8:4]] <= dat_i[63:48];
|
if (|sel[7:6]) spriteMcnt[adr[8:4]] <= dat[63:48];
|
end
|
end
|
9'b1010_0000_0: spriteEnable <= dat_i[31:0];
|
9'b1010_0000_0: spriteEnable <= dat[31:0];
|
9'b1010_0000_1: spriteLink1 <= dat_i[31:0];
|
9'b1010_0000_1: spriteLink1 <= dat[31:0];
|
9'b1010_0001_0: rst_collision <= `TRUE;
|
9'b1010_0001_0: rst_collision <= `TRUE;
|
9'b1010_0001_1:
|
9'b1010_0001_1:
|
begin
|
begin
|
lowres <= dat_i[1:0];
|
lowres <= dat[1:0];
|
controller_enable <= dat_i[8];
|
controller_enable <= dat[8];
|
end
|
end
|
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
assign m_stb_o = m_cyc_o;
|
assign m_stb_o = m_cyc_o;
|
assign m_sel_o = 8'hFF;
|
assign m_sel_o = 8'hFF;
|
|
|
|
wire clkm;
|
|
`ifdef USE_CLOCK_GATE
|
|
BUFHCE uclkm (.I(m_clk_i), .CE(controller_enable), .O(clkm));
|
|
`else
|
|
wire clkm = m_clk_i;
|
|
`endif
|
|
|
// Register hctr to m_clk_i domain
|
// Register hctr to m_clk_i domain
|
always @(posedge m_clk_i)
|
always @(posedge clkm)
|
m_hctr <= hctr;
|
m_hctr <= hctr;
|
|
|
// State machine
|
// State machine
|
always @(posedge m_clk_i)
|
always @(posedge clkm)
|
if (rst_i)
|
|
state <= IDLE;
|
|
else begin
|
|
case(state)
|
case(state)
|
IDLE:
|
IDLE:
|
// dot_clk_i is likely faster than m_clk_i, so check for a trigger zone.
|
// dot_clk_i is likely faster than m_clk_i, so check for a trigger zone.
|
if (m_hctr < 12'd10 && controller_enable)
|
if (m_hctr < 12'd10 && controller_enable)
|
state <= DATA_FETCH;
|
state <= DATA_FETCH;
|
DATA_FETCH:
|
DATA_FETCH:
|
if (spriteActive[spriteno])
|
if (spriteActive[spriteno]) begin
|
|
if (~m_ack_i)
|
state <= MEM_ACCESS;
|
state <= MEM_ACCESS;
|
else
|
end
|
state <= NEXT_SPRITE;
|
else if (spriteno==5'd31)
|
|
state <= IDLE;
|
MEM_ACCESS:
|
MEM_ACCESS:
|
if (m_ack_i)
|
if (m_ack_i|test) begin
|
state <= WAIT_NACK;
|
|
WAIT_NACK:
|
|
if (~m_ack_i)
|
|
state <= NEXT_SPRITE;
|
|
NEXT_SPRITE:
|
|
if (spriteno==5'd31)
|
if (spriteno==5'd31)
|
state <= IDLE;
|
state <= IDLE;
|
else
|
else
|
state <= DATA_FETCH;
|
state <= DATA_FETCH;
|
endcase
|
|
end
|
end
|
|
default: state <= IDLE;
|
|
endcase
|
|
|
always @(posedge m_clk_i)
|
always @(posedge clkm)
|
if (rst_i) begin
|
|
m_cyc_o <= `LOW;
|
|
spriteno <= 5'd0;
|
|
end
|
|
else begin
|
|
case(state)
|
case(state)
|
IDLE:
|
IDLE:
|
spriteno <= 5'd0;
|
m_cyc_o <= `LOW;
|
DATA_FETCH:
|
DATA_FETCH:
|
if (spriteActive[spriteno]) begin
|
if (!m_ack_i && spriteActive[spriteno]) begin
|
m_cyc_o <= `HIGH;
|
m_cyc_o <= ~test;//`HIGH;
|
m_adr_o <= spriteWaddr[spriteno];
|
m_adr_o <= spriteWaddr[spriteno];
|
|
m_spriteno_o <= spriteno;
|
end
|
end
|
MEM_ACCESS:
|
MEM_ACCESS:
|
if (m_ack_i) begin
|
if (m_ack_i|test) begin
|
m_cyc_o <= `LOW;
|
m_cyc_o <= `LOW;
|
m_spriteBmp[spriteno] <= dat_i;
|
m_spriteBmp[spriteno] <= m_dat_i;
|
if (test)
|
if (test)
|
m_spriteBmp[spriteno] <= 64'h00005555AAAAFFFF;
|
m_spriteBmp[spriteno] <= 64'h00005555AAAAFFFF;
|
end
|
end
|
NEXT_SPRITE:
|
default: ;
|
|
endcase
|
|
|
|
always @(posedge clkm)
|
|
case(state)
|
|
IDLE:
|
|
spriteno <= 5'd0;
|
|
DATA_FETCH:
|
|
if (!spriteActive[spriteno])
|
|
spriteno <= spriteno + 5'd1;
|
|
MEM_ACCESS:
|
|
if (m_ack_i|test)
|
spriteno <= spriteno + 5'd1;
|
spriteno <= spriteno + 5'd1;
|
|
default: ;
|
endcase
|
endcase
|
end
|
|
|
|
// Register collision onto clk_i domain.
|
// Register collision onto clk_i domain.
|
always @(posedge clk_i)
|
always @(posedge clk)
|
c_collision <= collision;
|
c_collision <= collision;
|
|
|
`ifdef USE_CLOCK_GATE
|
`ifdef USE_CLOCK_GATE
|
BUFHCE ucb1
|
BUFHCE ucb1
|
(
|
(
|
Line 266... |
Line 304... |
`endif
|
`endif
|
|
|
edge_det ued1 (.clk(vclk), .ce(1'b1), .i(hsync_i), .pe(pe_hsync), .ne(), .ee());
|
edge_det ued1 (.clk(vclk), .ce(1'b1), .i(hsync_i), .pe(pe_hsync), .ne(), .ee());
|
edge_det ued2 (.clk(vclk), .ce(1'b1), .i(vsync_i), .pe(pe_vsync), .ne(), .ee());
|
edge_det ued2 (.clk(vclk), .ce(1'b1), .i(vsync_i), .pe(pe_vsync), .ne(), .ee());
|
|
|
VT163 #(12) uhctr (.clk(vclk), .clr_n(!rst_i), .ent(1'b1), .enp(1'b1), .ld_n(!pe_hsync), .d(12'd0), .q(hctr), .rco());
|
VT163 #(12) uhctr (.clk(vclk), .clr_n(1'b1), .ent(1'b1), .enp(1'b1), .ld_n(!pe_hsync), .d(12'd0), .q(hctr), .rco());
|
VT163 #(12) uvctr (.clk(vclk), .clr_n(!rst_i), .ent(pe_hsync), .enp(1'b1), .ld_n(!pe_vsync), .d(12'd0), .q(vctr), .rco());
|
VT163 #(12) uvctr (.clk(vclk), .clr_n(1'b1), .ent(pe_hsync), .enp(1'b1), .ld_n(!pe_vsync), .d(12'd0), .q(vctr), .rco());
|
VT163 # (6) ufctr (.clk(vclk), .clr_n(!rst_i), .ent(pe_vsync), .enp(1'b1), .ld_n(1'b1), .d( 6'd0), .q(flashcnt), .rco());
|
VT163 # (6) ufctr (.clk(vclk), .clr_n(1'b1), .ent(pe_vsync), .enp(1'b1), .ld_n(1'b1), .d( 6'd0), .q(flashcnt), .rco());
|
|
|
always @(posedge vclk)
|
always @(posedge vclk)
|
begin
|
begin
|
if (rst_collision)
|
if (rst_collision)
|
collision <= 32'd0;
|
collision <= 32'd0;
|
Line 323... |
Line 361... |
// Increment working count and address
|
// Increment working count and address
|
|
|
reg [31:0] spriteShift;
|
reg [31:0] spriteShift;
|
always @(posedge vclk)
|
always @(posedge vclk)
|
for (n = 0; n < NSPR; n = n + 1)
|
for (n = 0; n < NSPR; n = n + 1)
|
begin
|
spriteShift[n] <= ((hctr >> lowres) >= sprite_ph[n]);
|
spriteShift[n] <= `FALSE;
|
|
case(lowres)
|
|
2'd0,2'd3: if (hctr >= sprite_ph[n]) spriteShift[n] <= `TRUE;
|
|
2'd1: if (hctr[11:1] >= sprite_ph[n]) spriteShift[n] <= `TRUE;
|
|
2'd2: if (hctr[11:2] >= sprite_ph[n]) spriteShift[n] <= `TRUE;
|
|
endcase
|
|
end
|
|
|
|
always @(posedge vclk)
|
always @(posedge vclk)
|
for (n = 0; n < NSPR; n = n + 1)
|
for (n = 0; n < NSPR; n = n + 1)
|
spriteActive[n] = (spriteWcnt[n] <= spriteMcnt[n]) && spriteEnable[n];
|
spriteActive[n] <= (spriteWcnt[n] <= spriteMcnt[n]) && spriteEnable[n];
|
|
|
always @(posedge vclk)
|
always @(posedge vclk)
|
for (n = 0; n < NSPR; n = n + 1)
|
for (n = 0; n < NSPR; n = n + 1)
|
begin
|
spriteWcnt[n] <= ((vctr >> lowres) - sprite_pv[n]) * 16'd32;
|
case(lowres)
|
|
2'd0,2'd3: if ((vctr == sprite_pv[n]) && (hctr == 12'h005)) spriteWcnt[n] <= 16'd0;
|
|
2'd1: if ((vctr[11:1] == sprite_pv[n]) && (hctr == 12'h005)) spriteWcnt[n] <= 16'd0;
|
|
2'd2: if ((vctr[11:2] == sprite_pv[n]) && (hctr == 12'h005)) spriteWcnt[n] <= 16'd0;
|
|
endcase
|
|
// The following assumes there are at least 640 clocks in a scan line.
|
|
if (hctr==`SPR_WCA) // must be after image data fetch
|
|
if (spriteActive[n])
|
|
case(lowres)
|
|
2'd0,2'd3: spriteWcnt[n] <= spriteWcnt[n] + 16'd32;
|
|
2'd1: if (vctr[0]) spriteWcnt[n] <= spriteWcnt[n] + 16'd32;
|
|
2'd2: if (vctr[1:0]==2'b11) spriteWcnt[n] <= spriteWcnt[n] + 16'd32;
|
|
endcase
|
|
end
|
|
|
|
always @(posedge vclk)
|
always @(posedge vclk)
|
for (n = 0; n < NSPR; n = n + 1)
|
for (n = 0; n < NSPR; n = n + 1)
|
begin
|
spriteWaddr[n] <= spriteAddr[n] + spriteWcnt[n][15:2];
|
case(lowres)
|
|
2'd0,2'd3: if ((vctr == sprite_pv[n]) && (hctr == 12'h005)) spriteWaddr[n] <= spriteAddr[n];
|
|
2'd1: if ((vctr[11:1] == sprite_pv[n]) && (hctr == 12'h005)) spriteWaddr[n] <= spriteAddr[n];
|
|
2'd2: if ((vctr[11:2] == sprite_pv[n]) && (hctr == 12'h005)) spriteWaddr[n] <= spriteAddr[n];
|
|
endcase
|
|
if (hctr==`SPR_WCA) // must be after image data fetch
|
|
case(lowres)
|
|
2'd0,2'd3: spriteWaddr[n] <= spriteWaddr[n] + 32'd8;
|
|
2'd1: if (vctr[0]) spriteWaddr[n] <= spriteWaddr[n] + 32'd8;
|
|
2'd2: if (vctr[1:0]==2'b11) spriteWaddr[n] <= spriteWaddr[n] + 32'd8;
|
|
endcase
|
|
end
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// clock edge #0
|
// clock edge #0
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// Get the sprite display status
|
// Get the sprite display status
|
Line 400... |
Line 405... |
if (hctr==12'h5)
|
if (hctr==12'h5)
|
for (n = 0; n < NSPR; n = n + 1)
|
for (n = 0; n < NSPR; n = n + 1)
|
spriteBmp[n] <= m_spriteBmp[n];
|
spriteBmp[n] <= m_spriteBmp[n];
|
for (n = 0; n < NSPR; n = n + 1)
|
for (n = 0; n < NSPR; n = n + 1)
|
if (spriteShift[n])
|
if (spriteShift[n])
|
|
`ifdef SUPPORT_LOWRES
|
case(lowres)
|
case(lowres)
|
2'd0,2'd3: spriteBmp[n] <= {spriteBmp[n][61:0],2'h0};
|
2'd0,2'd3: spriteBmp[n] <= {spriteBmp[n][61:0],2'h0};
|
2'd1: if (hctr[0]) spriteBmp[n] <= {spriteBmp[n][61:0],2'h0};
|
2'd1: if (hctr[0]) spriteBmp[n] <= {spriteBmp[n][61:0],2'h0};
|
2'd2: if (&hctr[1:0]) spriteBmp[n] <= {spriteBmp[n][61:0],2'h0};
|
2'd2: if (&hctr[1:0]) spriteBmp[n] <= {spriteBmp[n][61:0],2'h0};
|
endcase
|
endcase
|
|
`else
|
|
spriteBmp[n] <= {spriteBmp[n][61:0],2'h0};
|
|
`endif
|
end
|
end
|
|
|
always @(posedge vclk)
|
always @(posedge vclk)
|
for (n = 0; n < NSPR; n = n + 1)
|
for (n = 0; n < NSPR; n = n + 1)
|
if (spriteLink1[n])
|
if (spriteLink1[n])
|
Line 421... |
Line 430... |
// Compute index into sprite color palette
|
// Compute index into sprite color palette
|
// If none of the sprites are linked, each sprite has it's own set of colors.
|
// If none of the sprites are linked, each sprite has it's own set of colors.
|
// If the sprites are linked once the colors are available in groups.
|
// If the sprites are linked once the colors are available in groups.
|
// If the sprites are linked twice they all share the same set of colors.
|
// If the sprites are linked twice they all share the same set of colors.
|
// Pipelining register
|
// Pipelining register
|
reg blank1, blank2, blank3, blank4;
|
reg border3, border4;
|
reg border1, border2, border3, border4;
|
|
reg any_sprite_on2, any_sprite_on3, any_sprite_on4;
|
reg any_sprite_on2, any_sprite_on3, any_sprite_on4;
|
reg [31:0] zrgb_i3, zrgb_i4;
|
reg [31:0] zrgb_i3, zrgb_i4;
|
reg [7:0] zb_i3, zb_i4;
|
reg [7:0] zb_i3, zb_i4;
|
reg [7:0] sprite_z1, sprite_z2, sprite_z3, sprite_z4;
|
reg [7:0] sprite_z1, sprite_z2, sprite_z3, sprite_z4;
|
reg [7:0] sprite_pzx;
|
reg [7:0] sprite_pzx;
|
Line 470... |
Line 478... |
always @(posedge vclk)
|
always @(posedge vclk)
|
sprite_on_d2 <= sprite_on_d1;
|
sprite_on_d2 <= sprite_on_d1;
|
always @(posedge vclk)
|
always @(posedge vclk)
|
any_sprite_on2 <= |sprite_on_d1;
|
any_sprite_on2 <= |sprite_on_d1;
|
always @(posedge vclk)
|
always @(posedge vclk)
|
blank2 <= blank1;
|
|
always @(posedge vclk)
|
|
border2 <= border1;
|
|
always @(posedge vclk)
|
|
spriteColorOut2 <= sprite_color[spriteClrNdx];
|
spriteColorOut2 <= sprite_color[spriteClrNdx];
|
always @(posedge vclk)
|
always @(posedge vclk)
|
sprite_z2 <= sprite_z1;
|
sprite_z2 <= sprite_z1;
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
Line 499... |
Line 503... |
always @(posedge vclk)
|
always @(posedge vclk)
|
zrgb_i3 <= zrgb_i;
|
zrgb_i3 <= zrgb_i;
|
always @(posedge vclk)
|
always @(posedge vclk)
|
zb_i3 <= zrgb_i[31:24];
|
zb_i3 <= zrgb_i[31:24];
|
always @(posedge vclk)
|
always @(posedge vclk)
|
blank3 <= blank2;
|
border3 <= border_i;
|
always @(posedge vclk)
|
|
border3 <= border2;
|
|
always @(posedge vclk)
|
always @(posedge vclk)
|
spriteColorOut3 <= spriteColorOut2;
|
spriteColorOut3 <= spriteColorOut2;
|
|
|
reg [23:0] flashOut;
|
reg [23:0] flashOut;
|
wire [23:0] reverseVideoOut = spriteColorOut2[37] ? alphaOut ^ 24'hFFFFFF : alphaOut;
|
wire [23:0] reverseVideoOut = spriteColorOut2[37] ? alphaOut ^ 24'hFFFFFF : alphaOut;
|
Line 524... |
Line 526... |
always @(posedge vclk)
|
always @(posedge vclk)
|
any_sprite_on4 <= any_sprite_on3;
|
any_sprite_on4 <= any_sprite_on3;
|
always @(posedge vclk)
|
always @(posedge vclk)
|
zb_i4 <= zb_i3;
|
zb_i4 <= zb_i3;
|
always @(posedge vclk)
|
always @(posedge vclk)
|
blank4 <= blank3;
|
|
always @(posedge vclk)
|
|
border4 <= border3;
|
border4 <= border3;
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// clock edge #5
|
// clock edge #5
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// final output registration
|
// final output registration
|
|
|
always @(posedge dot_clk_i)
|
always @(posedge dot_clk_i)
|
case(any_sprite_on4 & controller_enable)
|
casez({border4,any_sprite_on4 & controller_enable})
|
1'b1: zrgb_o <= (zb_i4 < sprite_z4) ? zrgb_i4 : {sprite_z4,flashOut};
|
2'b01: zrgb_o <= (zb_i4 <= sprite_z4) ? zrgb_i4 : {sprite_z4,flashOut};
|
1'b0: zrgb_o <= zrgb_i4;
|
2'b00: zrgb_o <= zrgb_i4;
|
|
2'b1?: zrgb_o <= zrgb_i4;
|
endcase
|
endcase
|
|
|
endmodule
|
endmodule
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|