/* * Renders Background and Window plane */ module Spriterenderer #( parameter H_RES = 320, // horizontal resolution (pixels) parameter V_RES = 200, // vertical resolution (lines) parameter H_FP = 34, // horizontal front porch parameter H_SYNC = 32, // horizontal sync parameter H_BP = 56, // horizontal back porch parameter V_FP = 23, // vertical front porch parameter V_SYNC = 5, // vertical sync parameter V_BP = 34, // vertical back porch parameter H_POL = 0, // horizontal sync polarity (0:neg, 1:pos) parameter V_POL = 0 // vertical sync polarity ) ( //VGA I/O input vga_clk, //9MHz input vga_hs, input vga_vs, output wire [2:0] vga_r, output wire [2:0] vga_g, output wire [1:0] vga_b, input [9:0] h_count, // line position in pixels including blanking input [8:0] v_count, // frame position in lines including blanking input o_hs, input o_vs, input o_h, input o_v, input o_frame, //VRAM32 output [13:0] vram32_addr, input [31:0] vram32_q, //VRAMSPR output [13:0] vramSPR_addr, input [8:0] vramSPR_q, //Draw pixel signal output wire draw_sprite, output wire draw_behind_bg ); //x: 9b //y: 8b //tile: 8b //palette: 5b //hflip: 1b //vflip: 1b //priority: 1b //disable : 1b //------------ + // 34b wire o_de; assign o_de = h_count > HA_STA & h_count <= HA_END & v_count > VA_STA & v_count <= VA_END; parameter MAX_SPRITES = 16; //currently two sprites reg [33:0] sprites [0:MAX_SPRITES-1]; reg [33:0] sprites_next [0:MAX_SPRITES-1]; reg [5:0] spriteIdx = 0; reg [9:0] h_count_delay; reg [9:0] h_count_visible_delay; reg [8:0] v_count_delay; reg [8:0] v_count_visible_delay; always @(negedge vga_clk) begin h_count_delay <= h_count; v_count_delay <= v_count; h_count_visible_delay <= h_count_visible; v_count_visible_delay <= v_count_visible; end reg [5:0] spriteSelectionList [0:MAX_SPRITES-1]; reg [5:0] spriteSelectionCount; //select for next line during h_count_visible (delay) integer x=0; always @(posedge vga_clk) begin if (h_count_visible_delay == 319) //do somewhere at end of hline begin spriteSelectionCount <= 6'd0; for (x=0; x= vramSPR_q && (v_count_visible_delay + 1) < vramSPR_q + 8) begin spriteSelectionList[spriteSelectionCount] <= h_count_visible_delay; spriteSelectionCount <= spriteSelectionCount + 1'b1; end end end end end end assign vramSPR_addr = (v_count_visible != 511 && v_count_visible > 239) ? 15'd0: (h_count_visible >= 0 && h_count_visible < 128) ? (h_count_visible * 4) + 1'b1: (spriteSelectionList[(h_count_visible-128)>>2]<<2) + h_count_visible[1:0]; integer v=0; always @(posedge vga_clk) begin if (h_count_visible_delay == 127) //right before writing the sprites begin for (v=0; v= 128 && h_count_visible_delay < 192) begin case (h_count_visible_delay[1:0]) 2'd0 : sprites_next[(h_count_visible_delay-128)/4][33:25] <= vramSPR_q[8:0]; 2'd1 : sprites_next[(h_count_visible_delay-128)/4][24:17] <= vramSPR_q[7:0]; 2'd2 : sprites_next[(h_count_visible_delay-128)/4][16:9] <= vramSPR_q[7:0]; 2'd3 : sprites_next[(h_count_visible_delay-128)/4][8:0] <= vramSPR_q[8:0]; endcase end end end integer b=0; always @(posedge vga_clk) begin if (h_count_visible_delay == 319) begin for (b=0; b> 1; reg [9:0] h_count_div2_offset; always @(negedge vga_clk) begin h_count_div2_offset <= h_count_div2; end wire [5:0] spritephase; reg [5:0] spritephaseOffset; always @(negedge vga_clk) begin spritephaseOffset <= spritephase; end assign spritephase = (v_count_visible >= 240) ? 0: (h_count >= MAX_SPRITES*2) ? 0: (h_count[0] == 0) ? 1: (h_count[0] == 1) ? 2: 0; wire spriteVisible [0:MAX_SPRITES-1]; genvar m; generate for (m=0; m= sprites[m][33:25] && h_count_visible < sprites[m][33:25] + 8 && v_count_visible >= sprites[m][24:17] && v_count_visible < sprites[m][24:17] + 8); end endgenerate //For reversing the tile data wire [31:0] vram32_q_reverse; genvar i; generate for (i=0; i<=31; i=i+1) begin:y assign vram32_q_reverse[31-i] = vram32_q[i]; end endgenerate reg [63:0] rendered_sprite [0:MAX_SPRITES-1]; reg [15:0] pattern; reg [31:0] palette; always @(posedge vga_clk) begin if (spritephaseOffset == 1) begin //get pattern if (spriteVpixel[h_count_div2_offset][0] == 1) pattern <= vram32_q_reverse[31:16]; else pattern <= vram32_q_reverse[15:0]; end if (spritephaseOffset == 2) begin //get color palette <= vram32_q; case (pattern[1:0]) 2'b00: rendered_sprite[h_count_div2_offset][7:0] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][7:0] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][7:0] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][7:0] <= vram32_q[7:0]; endcase case (pattern[3:2]) 2'b00: rendered_sprite[h_count_div2_offset][15:8] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][15:8] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][15:8] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][15:8] <= vram32_q[7:0]; endcase case (pattern[5:4]) 2'b00: rendered_sprite[h_count_div2_offset][23:16] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][23:16] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][23:16] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][23:16] <= vram32_q[7:0]; endcase case (pattern[7:6]) 2'b00: rendered_sprite[h_count_div2_offset][31:24] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][31:24] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][31:24] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][31:24] <= vram32_q[7:0]; endcase case (pattern[9:8]) 2'b00: rendered_sprite[h_count_div2_offset][39:32] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][39:32] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][39:32] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][39:32] <= vram32_q[7:0]; endcase case (pattern[11:10]) 2'b00: rendered_sprite[h_count_div2_offset][47:40] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][47:40] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][47:40] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][47:40] <= vram32_q[7:0]; endcase case (pattern[13:12]) 2'b00: rendered_sprite[h_count_div2_offset][55:48] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][55:48] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][55:48] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][55:48] <= vram32_q[7:0]; endcase case (pattern[15:14]) 2'b00: rendered_sprite[h_count_div2_offset][63:56] <= vram32_q[31:24]; 2'b01: rendered_sprite[h_count_div2_offset][63:56] <= vram32_q[23:16]; 2'b10: rendered_sprite[h_count_div2_offset][63:56] <= vram32_q[15:8]; 2'b11: rendered_sprite[h_count_div2_offset][63:56] <= vram32_q[7:0]; endcase end end assign vram32_addr = (spritephase == 1) ? (sprites[h_count_div2][16:9] * 4) + (spriteVpixel[h_count_div2])/2 : (spritephase == 2) ? 1024 + sprites[h_count_div2][8:4]: 14'd0; //RENDERING assign draw_sprite = 1'b0; assign draw_behind_bg = 1'b0; //Render all sprites wire [3:0] sprite_r [0:MAX_SPRITES-1]; wire [3:0] sprite_g [0:MAX_SPRITES-1]; wire [2:0] sprite_b [0:MAX_SPRITES-1]; //For generating sprite rgb assignments genvar j; generate for (j=0; j