`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 = 10'd640; parameter H_FPORCH_PIXEL_LIMIT = 10'd656; // 640+16 parameter H_SYNC_PIXEL_LIMIT = 10'd752; // 640+16+96 parameter H_BPORCH_PIXEL_LIMIT = 10'd800; // 640+16+96+48 parameter V_ACTIVE_LINE_LIMIT = 10'd480; parameter V_FPORCH_LINE_LIMIT = 10'd490; // 480+10 parameter V_SYNC_LINE_LIMIT = 10'd492; // 480+10+2 parameter V_BPORCH_LINE_LIMIT = 10'd521; // 480+10+2+29 reg [63:0] spbitmap[0:63]; // 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 = 8'd0; 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[6'h00][63:0] <= 64'hffffffffffffffff; spbitmap[6'h01][63:0] <= 64'hffffff7777ffffff; spbitmap[6'h02][63:0] <= 64'hffff77777777ffff; spbitmap[6'h03][63:0] <= 64'hffff77777777ffff; spbitmap[6'h04][63:0] <= 64'hffffff7777ffffff; spbitmap[6'h05][63:0] <= 64'hfffffff77ffff77f; spbitmap[6'h06][63:0] <= 64'hfffffff77ffff77f; spbitmap[6'h07][63:0] <= 64'hf77777777777777f; spbitmap[6'h08][63:0] <= 64'hf77777777777777f; spbitmap[6'h09][63:0] <= 64'hf77fff1111ffffff; spbitmap[6'h0a][63:0] <= 64'hf77fff1111ffffff; spbitmap[6'h0b][63:0] <= 64'hffffff2222ffffff; spbitmap[6'h0c][63:0] <= 64'hfffff222222fffff; spbitmap[6'h0d][63:0] <= 64'hffff222ff222ffff; spbitmap[6'h0e][63:0] <= 64'hfff222ffff222fff; spbitmap[6'h0f][63:0] <= 64'h222222ffff222222; spbitmap[6'h10][63:0] <= 64'hffffffffffffffff; spbitmap[6'h11][63:0] <= 64'hffffff2222ffffff; spbitmap[6'h12][63:0] <= 64'hffff22222222ffff; spbitmap[6'h13][63:0] <= 64'hffff22222222ffff; spbitmap[6'h14][63:0] <= 64'hffffff2222ffffff; spbitmap[6'h15][63:0] <= 64'hfffffff22ffff77f; spbitmap[6'h16][63:0] <= 64'hfffffff22ffff77f; spbitmap[6'h17][63:0] <= 64'hf77777777777777f; spbitmap[6'h18][63:0] <= 64'hf77777777777777f; spbitmap[6'h19][63:0] <= 64'hf77fff3333ffffff; spbitmap[6'h1a][63:0] <= 64'hf77fff3333ffffff; spbitmap[6'h1b][63:0] <= 64'hffffff2222ffffff; spbitmap[6'h1c][63:0] <= 64'hfffff222222fffff; spbitmap[6'h1d][63:0] <= 64'hffff222ff222ffff; spbitmap[6'h1e][63:0] <= 64'hfff222ffff222fff; spbitmap[6'h1f][63:0] <= 64'h222222ffff222222; */ spreg_dx[0] <= 10'd0; spreg_dy[0] <= 10'd0; spreg_mx[0] <= 2'd0; spreg_my[0] <= 2'd0; spreg_dx[1] <= 10'd0; spreg_dy[1] <= 10'd0; spreg_mx[1] <= 2'd0; spreg_my[1] <= 2'd0; spreg_image[0] <= 3'd0; spreg_image[1] <= 3'd1; spreg_enable[0] <= 1'b1; spreg_enable[1] <= 1'b1; 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 begin spbitmap[{rcv_data[73:72], rcv_data[67:64]}] <= rcv_data[63:0]; /* spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 0][3:0] <= rcv_data[63:60]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 1][3:0] <= rcv_data[59:56]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 2][3:0] <= rcv_data[55:52]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 3][3:0] <= rcv_data[51:48]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 4][3:0] <= rcv_data[47:44]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 5][3:0] <= rcv_data[43:40]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 6][3:0] <= rcv_data[39:36]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 7][3:0] <= rcv_data[35:32]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 8][3:0] <= rcv_data[31:28]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][ 9][3:0] <= rcv_data[27:24]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][10][3:0] <= rcv_data[23:20]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][11][3:0] <= rcv_data[19:16]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][12][3:0] <= rcv_data[15:12]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][13][3:0] <= rcv_data[11: 8]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][14][3:0] <= rcv_data[ 7: 4]; spbitmap[{rcv_data[73:72], rcv_data[67:64]}][15][3:0] <= rcv_data[ 3: 0]; */ end 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 wire [9:0] dmx[0:3]; wire [9:0] dmy[0:3]; assign dmx[0] = (x - spreg_dx[0]) >> spreg_mx[0]; assign dmy[0] = (y - spreg_dy[0]) >> spreg_my[0]; assign dmx[1] = (x - spreg_dx[1]) >> spreg_mx[1]; assign dmy[1] = (y - spreg_dy[1]) >> spreg_my[1]; assign dmx[2] = (x - spreg_dx[2]) >> spreg_mx[2]; assign dmy[2] = (y - spreg_dy[2]) >> spreg_my[2]; assign dmx[3] = (x - spreg_dx[3]) >> spreg_mx[3]; assign dmy[3] = (y - spreg_dy[3]) >> spreg_my[3]; function [3:0] calc_spenable; input [9:0] px; input [9:0] py; input [3:0] index; begin if (!spreg_enable[index]) calc_spenable = 4'b1111; else if ((dmx[index] >= 10'd16) || (dmy[index] >= 10'd16)) calc_spenable = 4'b1111; else calc_spenable = spbitmap[{spreg_image[index], dmy[index][3:0]}] >> ({dmx[index][3:0], 2'b00}); end endfunction wire [3:0] spenable[0:3]; assign spenable[0][3:0] = calc_spenable(x, y, 4'd0); assign spenable[1][3:0] = calc_spenable(x, y, 4'd1); assign spenable[2][3:0] = calc_spenable(x, y, 4'd2); assign spenable[3][3:0] = calc_spenable(x, y, 4'd3); wire [3:0] spuse; assign spuse[0] = spenable[0][3]; assign spuse[1] = spenable[1][3]; assign spuse[2] = spenable[2][3]; assign spuse[3] = spenable[3][3]; function [3:0] calc_spindex; input [9:0] px; input [9:0] py; begin casex (spuse) 4'bxxx0 : calc_spindex = spenable[0][3:0]; 4'bxx01 : calc_spindex = spenable[1][3:0]; 4'bx011 : calc_spindex = spenable[2][3:0]; 4'b0111 : calc_spindex = spenable[3][3:0]; default: begin if ((px == 10'd0) || (px == 10'd639) || (py == 10'd0) || (py == 10'd479)) calc_spindex = 4'b0111; else calc_spindex = 4'b0000; end endcase end endfunction wire [3:0] spindex; assign spindex = calc_spindex(x, y); always @(posedge clk) begin if (hcount < H_BPORCH_PIXEL_LIMIT) hcount <= hcount + 10'd1; else begin hcount <= 10'd0; if (vcount < V_BPORCH_LINE_LIMIT) vcount <= vcount + 10'd1; else vcount <= 10'd0; end if (hcount < H_ACTIVE_PIXEL_LIMIT && vcount < V_ACTIVE_LINE_LIMIT) // active video begin vga_b_out <= spindex[0]; vga_r_out <= spindex[1]; vga_g_out <= spindex[2]; end else case (hcount) H_ACTIVE_PIXEL_LIMIT : // front porch begin vga_b_out <= 1'b0; vga_r_out <= 1'b0; vga_g_out <= 1'b0; 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