`timescale 1ns / 1ps module sprite(CLK_50M, VGA_R, VGA_G, VGA_B, VGA_HSYNC, VGA_VSYNC, LED, ROT_CENTER, RS232_DCE_RXD); input CLK_50M; output [3:0] VGA_R; output [3:0] VGA_G; output [3:0] VGA_B; output VGA_HSYNC; output VGA_VSYNC; output [7:0] LED; input ROT_CENTER; input RS232_DCE_RXD; wire reset; assign reset = ROT_CENTER; wire rxd; assign rxd = RS232_DCE_RXD; reg [1:0] clock_count; wire clk; assign clk = clock_count[0]; reg [9:0] hcount; reg [9:0] vcount; wire [9:0] x; wire [9:0] y; assign x = hcount; assign y = vcount; // reg [3:0] vga_r_out; // reg [3:0] vga_g_out; // reg [3:0] vga_b_out; reg vga_r_out; reg vga_g_out; reg vga_b_out; reg vga_hsync_out; reg vga_vsync_out; // assign VGA_R = vga_r_out; // assign VGA_G = vga_g_out; // assign VGA_B = vga_b_out; assign VGA_R[3:0] = { vga_r_out, vga_r_out, vga_r_out, vga_r_out }; assign VGA_G[3:0] = { vga_g_out, vga_g_out, vga_g_out, vga_g_out }; assign VGA_B[3:0] = { vga_b_out, vga_b_out, vga_b_out, vga_b_out }; assign VGA_HSYNC = vga_hsync_out; assign VGA_VSYNC = vga_vsync_out; parameter H_ACTIVE_PIXEL_LIMIT = 640; parameter H_FPORCH_PIXEL_LIMIT = 656; // 640+16 parameter H_SYNC_PIXEL_LIMIT = 752; // 640+16+96 parameter H_BPORCH_PIXEL_LIMIT = 800; // 640+16+96+48 parameter V_ACTIVE_LINE_LIMIT = 480; parameter V_FPORCH_LINE_LIMIT = 490; // 480+10 parameter V_SYNC_LINE_LIMIT = 492; // 480+10+2 parameter V_BPORCH_LINE_LIMIT = 521; // 480+10+2+29 reg [63:0] spbitmap[0:15][0:3]; // 16x16x4 reg [9:0] spreg_dx[0:3]; reg [9:0] spreg_dy[0:3]; reg [1:0] spreg_mx[0:3]; reg [1:0] spreg_my[0:3]; reg [2:0] spreg_image[0:3]; reg spreg_enable[0:3]; wire [7:0] rch; wire rcv; reg rcv_old; rx rx(CLK_50M, rxd, rch, rcv, reset); reg [15:0] rcv_cmd; reg [79:0] rcv_data; reg [7:0] led_out; assign LED = led_out; function [3:0] a2b4; input [7:0] a; begin if ((a >= 8'h30) && (a <= 8'h39)) a2b4 = (a - 8'h30); else if ((a >= 8'h61) && (a <= 8'h66)) a2b4 = (a - 8'h57); else if ((a >= 8'h41) && (a <= 8'h46)) a2b4 = (a - 8'h37); else a2b4 = 0; end endfunction function [7:0] a2b8; input [15:0] a; begin a2b8[7:4] = a2b4(a[15:8]); a2b8[3:0] = a2b4(a[ 7:0]); end endfunction // シリアル受信モジュール(rx)はクロックの立下りで動作するので、 // クロックの立ち上がりで受信文字を読み込む。 // rcvとrchの立ち上がりがタイミング的にずれている場合が考えられるので。 always @(posedge CLK_50M) begin if (reset) begin spbitmap[ 0][0][63:0] <= 64'hffffffffffffffff; spbitmap[ 1][0][63:0] <= 64'hffffff7777ffffff; spbitmap[ 2][0][63:0] <= 64'hffff77777777ffff; spbitmap[ 3][0][63:0] <= 64'hffff77777777ffff; spbitmap[ 4][0][63:0] <= 64'hffffff7777ffffff; spbitmap[ 5][0][63:0] <= 64'hfffffff77ffff77f; spbitmap[ 6][0][63:0] <= 64'hfffffff77ffff77f; spbitmap[ 7][0][63:0] <= 64'hf77777777777777f; spbitmap[ 8][0][63:0] <= 64'hf77777777777777f; spbitmap[ 9][0][63:0] <= 64'hf77fff1111ffffff; spbitmap[10][0][63:0] <= 64'hf77fff1111ffffff; spbitmap[11][0][63:0] <= 64'hffffff2222ffffff; spbitmap[12][0][63:0] <= 64'hfffff222222fffff; spbitmap[13][0][63:0] <= 64'hffff222ff222ffff; spbitmap[14][0][63:0] <= 64'hfff222ffff222fff; spbitmap[15][0][63:0] <= 64'h222222ffff222222; spbitmap[ 0][1][63:0] <= 64'hffffffffffffffff; spbitmap[ 1][1][63:0] <= 64'hffffff2222ffffff; spbitmap[ 2][1][63:0] <= 64'hffff22222222ffff; spbitmap[ 3][1][63:0] <= 64'hffff22222222ffff; spbitmap[ 4][1][63:0] <= 64'hffffff2222ffffff; spbitmap[ 5][1][63:0] <= 64'hfffffff22ffff77f; spbitmap[ 6][1][63:0] <= 64'hfffffff22ffff77f; spbitmap[ 7][1][63:0] <= 64'hf77777777777777f; spbitmap[ 8][1][63:0] <= 64'hf77777777777777f; spbitmap[ 9][1][63:0] <= 64'hf77fff3333ffffff; spbitmap[10][1][63:0] <= 64'hf77fff3333ffffff; spbitmap[11][1][63:0] <= 64'hffffff2222ffffff; spbitmap[12][1][63:0] <= 64'hfffff222222fffff; spbitmap[13][1][63:0] <= 64'hffff222ff222ffff; spbitmap[14][1][63:0] <= 64'hfff222ffff222fff; spbitmap[15][1][63:0] <= 64'h222222ffff222222; spreg_dx[0] <= 0; spreg_dy[0] <= 0; spreg_mx[0] <= 0; spreg_my[0] <= 0; spreg_dx[1] <= 0; spreg_dy[1] <= 0; spreg_mx[1] <= 0; spreg_my[1] <= 0; spreg_image[0] <= 0; spreg_image[1] <= 1; spreg_enable[0] <= 1; spreg_enable[1] <= 1; led_out <= 8'b00000000; end else if (rcv_old != rcv) begin rcv_old <= rcv; led_out <= rch; case (rch) 8'h24 : // '$' begin rcv_cmd <= 16'd0; rcv_data <= 0; end 8'h2b : // '+' begin case (rcv_cmd) 16'h6478 : // dx spreg_dx[rcv_data[19:16]] <= rcv_data[9:0]; 16'h6479 : // dy spreg_dy[rcv_data[19:16]] <= rcv_data[9:0]; 16'h6d78 : // mx spreg_mx[rcv_data[11:8]] <= rcv_data[1:0]; 16'h6d79 : // my spreg_my[rcv_data[11:8]] <= rcv_data[1:0]; 16'h696d : // im spreg_image[rcv_data[11:8]] <= rcv_data[2:0]; 16'h656e : // en spreg_enable[rcv_data[11:8]] <= rcv_data[0]; 16'h6964 : //id spbitmap[rcv_data[67:64]][rcv_data[73:72]] <= rcv_data[63:0]; default : ; endcase end default : begin if (rcv_cmd[15:8] == 8'b00000000) begin rcv_cmd[15:8] <= rcv_cmd[7:0]; rcv_cmd[ 7:0] <= rch; end else begin rcv_data[79:4] <= rcv_data[75:0]; rcv_data[ 3:0] <= a2b4(rch); end end endcase end end always @(posedge CLK_50M) begin clock_count <= clock_count + 1; end function inrange; input [9:0] px; input [9:0] py; input [9:0] pdx; input [9:0] pdy; input [1:0] pmx; input [1:0] pmy; begin if ( (py >= pdy) && (px >= pdx) && (((py - pdy) >> pmy) < 16) && (((px - pdx) >> pmx) < 16)) inrange = 1; else inrange = 0; end endfunction function spenable; input [9:0] px; input [9:0] py; input [3:0] index; begin if (spreg_enable[index] && inrange(px, py, spreg_dx[index], spreg_dy[index], spreg_mx[index], spreg_my[index])) if (!( (spbitmap[(py - spreg_dy[index]) >> spreg_my[index]][spreg_image[index]] >> ((((px - spreg_dx[index]) >> spreg_mx[index]) << 2) | 2'b11)) & 1'b1)) spenable = 1; else spenable = 0; else spenable = 0; end endfunction function [3:0] calc_spindex; input [9:0] px; input [9:0] py; begin if (spenable(px, py, 0)) calc_spindex = 0; else if (spenable(px, py, 1)) calc_spindex = 1; else if (spenable(px, py, 2)) calc_spindex = 2; else if (spenable(px, py, 3)) calc_spindex = 3; else calc_spindex = 4'b1111; end endfunction wire [3:0] spindex; assign spindex = calc_spindex(x, y); always @(posedge clk) begin if (hcount < H_BPORCH_PIXEL_LIMIT) hcount <= hcount + 1; else begin hcount <= 0; if (vcount < V_BPORCH_LINE_LIMIT) vcount <= vcount + 1; else vcount <= 0; end if (hcount < H_ACTIVE_PIXEL_LIMIT && vcount < V_ACTIVE_LINE_LIMIT) // active video begin if (spindex != 4'b1111) begin vga_b_out <= (spbitmap[(y - spreg_dy[spindex]) >> spreg_my[spindex]][spreg_image[spindex]] >> ((((x - spreg_dx[spindex]) >> spreg_mx[spindex]) << 2) | 2'b00)) & 1'b1; vga_r_out <= (spbitmap[(y - spreg_dy[spindex]) >> spreg_my[spindex]][spreg_image[spindex]] >> ((((x - spreg_dx[spindex]) >> spreg_mx[spindex]) << 2) | 2'b01)) & 1'b1; vga_g_out <= (spbitmap[(y - spreg_dy[spindex]) >> spreg_my[spindex]][spreg_image[spindex]] >> ((((x - spreg_dx[spindex]) >> spreg_mx[spindex]) << 2) | 2'b10)) & 1'b1; end else begin if ((x == 0) || (x == 639) || (y == 0) || (y == 479)) begin vga_b_out <= 1; vga_r_out <= 1; vga_g_out <= 1; end else begin vga_b_out <= 0; vga_r_out <= 0; vga_g_out <= 0; end end end else case (hcount) H_ACTIVE_PIXEL_LIMIT : // front porch begin vga_r_out <= 4'd0; vga_g_out <= 4'd0; vga_b_out <= 4'd0; end H_FPORCH_PIXEL_LIMIT : // sync pulse vga_hsync_out <= 1'b0; H_SYNC_PIXEL_LIMIT : // back porch vga_hsync_out <= 1'b1; endcase case (vcount) V_ACTIVE_LINE_LIMIT : // front porch ; V_FPORCH_LINE_LIMIT : // sync pulse vga_vsync_out <= 1'b0; V_SYNC_LINE_LIMIT : // back porch vga_vsync_out <= 1'b1; endcase end endmodule