OpenCores
URL https://opencores.org/ocsvn/rtf_sprite_controller/rtf_sprite_controller/trunk

Subversion Repositories rtf_sprite_controller

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /rtf_sprite_controller
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

/trunk/doc/rtfSpriteController2.docx Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/trunk/doc/rtfSpriteController2.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/doc/rtfSpriteController2.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/rtl/verilog/rtfSpriteController2.v =================================================================== --- trunk/rtl/verilog/rtfSpriteController2.v (revision 5) +++ trunk/rtl/verilog/rtfSpriteController2.v (revision 6) @@ -1,6 +1,6 @@ // ============================================================================ // __ -// \\__/ o\ (C) 2018 Robert Finch, Waterloo +// \\__/ o\ (C) 2018-2019 Robert Finch, Waterloo // \ __ / All rights reserved. // \/_// robfinch@finitron.ca // || @@ -34,13 +34,13 @@ // A good value is just before the end of the scan, but that depends on // display resolution. `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, - m_clk_i, m_cyc_o, m_stb_o, m_ack_i, m_sel_o, m_adr_o, m_dat_i, - dot_clk_i, hsync_i, vsync_i, zrgb_i, zrgb_o, test +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_spriteno_o, + dot_clk_i, hsync_i, vsync_i, border_i, zrgb_i, zrgb_o, test ); // Bus slave port -input rst_i; input clk_i; input cs_i; input cyc_i; @@ -59,33 +59,33 @@ output [7:0] m_sel_o; output reg [`ABITS] m_adr_o; input [63:0] m_dat_i; +output reg [4:0] m_spriteno_o; // Video port input dot_clk_i; input vsync_i; input hsync_i; +input border_i; input [31:0] zrgb_i; output reg [31:0] zrgb_o; input test; parameter NSPR = 32; -parameter IDLE = 3'd0; -parameter DATA_FETCH = 3'd1; -parameter MEM_ACCESS = 3'd2; -parameter WAIT_NACK = 3'd3; -parameter NEXT_SPRITE = 3'd4; +parameter IDLE = 2'd0; +parameter DATA_FETCH = 2'd1; +parameter MEM_ACCESS = 2'd2; integer n; -reg controller_enable; +reg controller_enable = 1'b1; wire vclk; -reg [2:0] state; -reg [1:0] lowres; +reg [1:0] state = IDLE; +reg [1:0] lowres = 2'b00; wire [5:0] flashcnt; -reg rst_collision; +reg rst_collision = 1'b0; reg [31:0] collision, c_collision; -reg [4:0] spriteno; +reg [4:0] spriteno = 5'd0; reg sprite; -reg [31:0] spriteEnable; +reg [31:0] spriteEnable = 32'hFFFFFFFF; reg [31:0] spriteActive; reg [11:0] sprite_pv [0:31]; reg [11:0] sprite_ph [0:31]; @@ -103,19 +103,27 @@ reg [15:0] spriteWcnt [0:31]; reg [63:0] m_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]; initial 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 for (n = 0; n < 32; n = n + 1) begin - sprite_ph[n] <= 260 + n * 40; - sprite_pv[n] <= 41 + n * 20; - sprite_pz[n] <= 8'h00; - spriteMcnt[n] <= 60 * 32; + if (n < 16) begin + sprite_ph[n] <= 400 + n * 32; + sprite_pv[n] <= 100 + n * 8; + 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; + spriteAddr[n] <= 32'h40000 + (n << 12); end end @@ -123,67 +131,87 @@ wire [11:0] hctr, vctr; reg [11:0] m_hctr, m_vctr; -// Generate acknowledge signal -wire cs = cs_i & cyc_i & stb_i; -reg rdy1,rdy2,rdy3; -always @(posedge clk_i) - rdy1 <= cs; -always @(posedge clk_i) - rdy2 <= rdy1 & cs; -always @(posedge clk_i) - rdy3 <= rdy2 & cs; -assign ack_o = (cs & we_i) ? 1'b1 : rdy3; +reg cs; +reg we; +reg [7:0] sel; +reg [11:0] adr; +reg [63:0] dat; +wire clk; +`ifdef USE_CLOCK_GATE +BUFH uclk (.I(clk_i), .O(clk)); +`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" *) reg [63:0] shadow_ram [0:511]; +reg [63:0] shadow_ramo; reg [8:0] sradr; -always @(posedge clk_i) - if (cs & we_i) begin - if (sel_i[0]) shadow_ram[adr_i[11:3]][ 7: 0] <= dat_i; - if (sel_i[1]) shadow_ram[adr_i[11:3]][15: 8] <= dat_i; - if (sel_i[2]) shadow_ram[adr_i[11:3]][23:16] <= dat_i; - if (sel_i[3]) shadow_ram[adr_i[11:3]][31:24] <= dat_i; - if (sel_i[4]) shadow_ram[adr_i[11:3]][39:32] <= dat_i; - if (sel_i[5]) shadow_ram[adr_i[11:3]][47:40] <= dat_i; - if (sel_i[6]) shadow_ram[adr_i[11:3]][55:48] <= dat_i; - if (sel_i[7]) shadow_ram[adr_i[11:3]][63:56] <= dat_i; +always @(posedge clk) + if (cs & we) begin + if (|sel[1:0]) shadow_ram[adr[11:3]][15: 0] <= dat[15: 0]; + if (|sel[3:2]) shadow_ram[adr[11:3]][31:16] <= dat[31:16]; + if (|sel[5:4]) shadow_ram[adr[11:3]][47:32] <= dat[47:32]; + if (|sel[7:6]) shadow_ram[adr[11:3]][63:48] <= dat[63:48]; end -always @(posedge clk_i) - sradr <= adr_i[11:3]; -always @(posedge clk_i) -case(adr_i[11:3]) +always @(posedge clk) + sradr <= adr[11:3]; +always @(posedge clk) + shadow_ramo <= shadow_ram[sradr]; +always @(posedge clk) +case(adr[11:3]) 9'b1010_0001_0: dat_o <= c_collision; -default: dat_o <= shadow_ram[sradr]; +default: dat_o <= shadow_ramo; endcase -always @(posedge clk_i) -if (rst_i) begin +always @(posedge clk) +begin rst_collision <= `FALSE; - controller_enable <= `TRUE; - spriteEnable <= 32'hFFFFFFFF; - spriteLink1 <= 32'h0; -end -else begin - rst_collision <= `FALSE; - if (cs & we_i) begin - casez(adr_i[11:3]) - 9'b0???_????_?: sprite_color[adr_i[10:3]] <= dat_i[37:0]; - 9'b100?_????_0: spriteAddr[adr_i[8:4]] <= dat_i[`ABITS]; + if (cs & we) begin + casez(adr[11:3]) + 9'b0???_????_?: sprite_color[adr[10:3]] <= dat[37:0]; + 9'b100?_????_0: spriteAddr[adr[8:4]] <= dat[`ABITS]; 9'b100?_????_1: begin - if (|sel_i[1:0]) sprite_ph[adr_i[8:4]] <= dat_i[11: 0]; - if (|sel_i[3:2]) sprite_pv[adr_i[8:4]] <= dat_i[27:16]; - if ( sel_i[ 4]) sprite_pz[adr_i[8:4]] <= dat_i[39:32]; - if (|sel_i[7:6]) spriteMcnt[adr_i[8:4]] <= dat_i[63:48]; + if (|sel[1:0]) sprite_ph[adr[8:4]] <= dat[11: 0]; + if (|sel[3:2]) sprite_pv[adr[8:4]] <= dat[27:16]; + if (|sel[5:4]) sprite_pz[adr[8:4]] <= dat[39:32]; + if (|sel[7:6]) spriteMcnt[adr[8:4]] <= dat[63:48]; end - 9'b1010_0000_0: spriteEnable <= dat_i[31:0]; - 9'b1010_0000_1: spriteLink1 <= dat_i[31:0]; + 9'b1010_0000_0: spriteEnable <= dat[31:0]; + 9'b1010_0000_1: spriteLink1 <= dat[31:0]; 9'b1010_0001_0: rst_collision <= `TRUE; 9'b1010_0001_1: begin - lowres <= dat_i[1:0]; - controller_enable <= dat_i[8]; + lowres <= dat[1:0]; + controller_enable <= dat[8]; end + default: ; endcase end end @@ -191,67 +219,77 @@ assign m_stb_o = m_cyc_o; 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 -always @(posedge m_clk_i) +always @(posedge clkm) m_hctr <= hctr; // State machine -always @(posedge m_clk_i) -if (rst_i) - state <= IDLE; -else begin - case(state) - IDLE: - // dot_clk_i is likely faster than m_clk_i, so check for a trigger zone. - if (m_hctr < 12'd10 && controller_enable) - state <= DATA_FETCH; - DATA_FETCH: - if (spriteActive[spriteno]) +always @(posedge clkm) +case(state) +IDLE: + // dot_clk_i is likely faster than m_clk_i, so check for a trigger zone. + if (m_hctr < 12'd10 && controller_enable) + state <= DATA_FETCH; +DATA_FETCH: + if (spriteActive[spriteno]) begin + if (~m_ack_i) state <= MEM_ACCESS; - else - state <= NEXT_SPRITE; - MEM_ACCESS: - if (m_ack_i) - state <= WAIT_NACK; - WAIT_NACK: - if (~m_ack_i) - state <= NEXT_SPRITE; - NEXT_SPRITE: + end + else if (spriteno==5'd31) + state <= IDLE; +MEM_ACCESS: + if (m_ack_i|test) begin if (spriteno==5'd31) state <= IDLE; else state <= DATA_FETCH; - endcase -end + end +default: state <= IDLE; +endcase -always @(posedge m_clk_i) -if (rst_i) begin +always @(posedge clkm) +case(state) +IDLE: m_cyc_o <= `LOW; +DATA_FETCH: + if (!m_ack_i && spriteActive[spriteno]) begin + m_cyc_o <= ~test;//`HIGH; + m_adr_o <= spriteWaddr[spriteno]; + m_spriteno_o <= spriteno; + end +MEM_ACCESS: + if (m_ack_i|test) begin + m_cyc_o <= `LOW; + m_spriteBmp[spriteno] <= m_dat_i; + if (test) + m_spriteBmp[spriteno] <= 64'h00005555AAAAFFFF; + end +default: ; +endcase + +always @(posedge clkm) +case(state) +IDLE: spriteno <= 5'd0; -end -else begin - case(state) - IDLE: - spriteno <= 5'd0; - DATA_FETCH: - if (spriteActive[spriteno]) begin - m_cyc_o <= `HIGH; - m_adr_o <= spriteWaddr[spriteno]; - end - MEM_ACCESS: - if (m_ack_i) begin - m_cyc_o <= `LOW; - m_spriteBmp[spriteno] <= dat_i; - if (test) - m_spriteBmp[spriteno] <= 64'h00005555AAAAFFFF; - end - NEXT_SPRITE: +DATA_FETCH: + if (!spriteActive[spriteno]) spriteno <= spriteno + 5'd1; - endcase -end +MEM_ACCESS: + if (m_ack_i|test) + spriteno <= spriteno + 5'd1; +default: ; +endcase + // Register collision onto clk_i domain. -always @(posedge clk_i) +always @(posedge clk) c_collision <= collision; `ifdef USE_CLOCK_GATE @@ -268,9 +306,9 @@ 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()); -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) uvctr (.clk(vclk), .clr_n(!rst_i), .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 #(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(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(1'b1), .ent(pe_vsync), .enp(1'b1), .ld_n(1'b1), .d( 6'd0), .q(flashcnt), .rco()); always @(posedge vclk) begin @@ -325,52 +363,19 @@ reg [31:0] spriteShift; always @(posedge vclk) for (n = 0; n < NSPR; n = n + 1) - begin - 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 + spriteShift[n] <= ((hctr >> lowres) >= sprite_ph[n]); always @(posedge vclk) 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) for (n = 0; n < NSPR; n = n + 1) - begin - 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 + spriteWcnt[n] <= ((vctr >> lowres) - sprite_pv[n]) * 16'd32; always @(posedge vclk) for (n = 0; n < NSPR; n = n + 1) - begin - 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 + spriteWaddr[n] <= spriteAddr[n] + spriteWcnt[n][15:2]; // - - - - - - - - - - - - - - - - - - - - - - - - - - // clock edge #0 @@ -402,11 +407,15 @@ spriteBmp[n] <= m_spriteBmp[n]; for (n = 0; n < NSPR; n = n + 1) if (spriteShift[n]) +`ifdef SUPPORT_LOWRES case(lowres) 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'd2: if (&hctr[1:0]) spriteBmp[n] <= {spriteBmp[n][61:0],2'h0}; endcase +`else + spriteBmp[n] <= {spriteBmp[n][61:0],2'h0}; +`endif end always @(posedge vclk) @@ -423,8 +432,7 @@ // 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. // Pipelining register -reg blank1, blank2, blank3, blank4; -reg border1, border2, border3, border4; +reg border3, border4; reg any_sprite_on2, any_sprite_on3, any_sprite_on4; reg [31:0] zrgb_i3, zrgb_i4; reg [7:0] zb_i3, zb_i4; @@ -444,7 +452,7 @@ // Fetch sprite Z order always @(posedge vclk) - sprite_on_d1 <= sprite_on; + sprite_on_d1 <= sprite_on; always @(posedge vclk) begin @@ -472,10 +480,6 @@ always @(posedge vclk) any_sprite_on2 <= |sprite_on_d1; always @(posedge vclk) - blank2 <= blank1; -always @(posedge vclk) - border2 <= border1; -always @(posedge vclk) spriteColorOut2 <= sprite_color[spriteClrNdx]; always @(posedge vclk) sprite_z2 <= sprite_z1; @@ -501,10 +505,8 @@ always @(posedge vclk) zb_i3 <= zrgb_i[31:24]; always @(posedge vclk) - blank3 <= blank2; + border3 <= border_i; always @(posedge vclk) - border3 <= border2; -always @(posedge vclk) spriteColorOut3 <= spriteColorOut2; reg [23:0] flashOut; @@ -526,8 +528,6 @@ always @(posedge vclk) zb_i4 <= zb_i3; always @(posedge vclk) - blank4 <= blank3; -always @(posedge vclk) border4 <= border3; // - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -536,9 +536,10 @@ // final output registration always @(posedge dot_clk_i) - case(any_sprite_on4 & controller_enable) - 1'b1: zrgb_o <= (zb_i4 < sprite_z4) ? zrgb_i4 : {sprite_z4,flashOut}; - 1'b0: zrgb_o <= zrgb_i4; + casez({border4,any_sprite_on4 & controller_enable}) + 2'b01: zrgb_o <= (zb_i4 <= sprite_z4) ? zrgb_i4 : {sprite_z4,flashOut}; + 2'b00: zrgb_o <= zrgb_i4; + 2'b1?: zrgb_o <= zrgb_i4; endcase endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.