diff --git a/gl/gl_frame_buffer.sv b/gl/gl_frame_buffer.sv index 1d1bf1c8af9bd4886145223c82ca4dfacfca43fd..a45ef544e4458bb5a5fc460ab8c69d4ce10ef458 100644 --- a/gl/gl_frame_buffer.sv +++ b/gl/gl_frame_buffer.sv @@ -8,15 +8,11 @@ module gl_frame_buffer ( // VGA Read input logic VGA_REQ, - // input logic VGA_FG, input logic [9:0] VGA_X, VGA_Y, output logic [23:0] VGA_RGB, - // input logic [19:0] VGA_ADDR, - // output logic [15:0] VGA_DATA, // GL Read input logic GL_REQ, - // input logic GL_FG, input logic [9:0] GL_X, GL_Y, input logic [19:0] GL_ADDR, output logic [15:0] GL_DATA, @@ -134,6 +130,44 @@ module gl_frame_buffer ( end + // GL read steps + enum logic [2:0] { + s_query_rc, s_query_pix, s_query_pl, s_got_pl, s_fin + } gl_readstate, gl_readstate_next; + + logic gl_fb_req, gl_fb_req_in; + logic [19:0] gl_fb_addr, gl_fb_addr_in; + logic [15:0] gl_fb_data, gl_fb_data_in; + logic [15:0] gl_pl_data, gl_pl_data_in; + // Pipeline step coordinates + logic [19:0] gl_rc_coord, gl_fb_coord, gl_pl_coord; + logic [19:0] gl_rc_coord_in, gl_fb_coord_in, gl_pl_coord_in; + // PL usage + logic gl_from_pl, gl_from_pl_next; + // SRAM 8-bit reads cache + logic [19:0] gl_fb_prev_addr, gl_fb_prev_addr_in; + logic [15:0] gl_fb_prev_data, gl_fb_prev_data_in; + + always_ff @(posedge CLK) begin + if(RESET | !GL_REQ) begin + gl_readstate <= s_query_rc; + gl_fb_req <= 1'b0; + gl_fb_addr <= 19'h00000; + gl_fb_data <= 16'hCCCC; + gl_from_pl <= 1'b0; + gl_pl_data <= 16'hCCCC; + end else begin + gl_readstate <= gl_readstate_next; + gl_fb_req <= gl_fb_req_in; + gl_fb_addr <= gl_fb_addr_in; + gl_fb_data <= gl_fb_data_in; + gl_from_pl <= gl_from_pl_next; + gl_pl_data <= gl_pl_data_in; + end + gl_fb_prev_addr <= gl_fb_prev_addr_in; + gl_fb_prev_data <= gl_fb_prev_data_in; + end + logic rc_avail, pl_avail; always_comb begin @@ -141,6 +175,8 @@ module gl_frame_buffer ( rc_avail = 1'b1; pl_avail = 1'b1; + // VGA Combinational logic + // Pipeline shifting vga_rc_en_next = VGA_REQ; vga_fb_en_next = vga_rc_en; @@ -213,7 +249,7 @@ module gl_frame_buffer ( if (vga_pl_coord[19:16] >= 4'hA) begin // A palette access - rc_avail = 1'b0; + pl_avail = 1'b0; if (vga_pl_coord[10]) begin // Upper bits PL_ADDR = vga_fb_data[15:8]; @@ -245,6 +281,108 @@ module gl_frame_buffer ( end end else VGA_RGB = 24'h0000ff; + + // GL Combinational logic + + // Default values + gl_readstate_next = gl_readstate; + gl_fb_req_in = 1'b0; + gl_fb_addr_in = gl_fb_addr; + gl_fb_data_in = gl_fb_data; + gl_from_pl_next = gl_from_pl; + gl_pl_data_in = gl_pl_data; + gl_fb_prev_data_in = gl_fb_prev_data; + gl_fb_prev_addr_in = gl_fb_prev_addr; + + GL_DATA = 16'hXXXX; + GL_READY = 1'b0; + + case (gl_readstate) + s_query_rc: begin + if (~GL_ADDR[19] && rc_avail) begin + RC_ADDR = {GL_X, GL_Y[8:0], BUF_ACTIVE}; + gl_readstate_next = s_query_pix; + end + end + + s_query_pix: begin + if (!gl_fb_data) begin + if (RC_DATA_OUT) begin + // Read from drawn pixels + gl_fb_addr_in = {GL_X, GL_Y[8:0], BUF_ACTIVE}; + gl_from_pl_next = 1'b0; + end else begin + // Read from background + gl_fb_addr_in = {4'hA+{2'b0,GL_X[9:8]}, + GL_X[7:1], // X without last bit + GL_Y[8:0]}; + + gl_from_pl_next = 1'b1; + end + if (gl_fb_addr_in == gl_fb_prev_addr) begin + gl_fb_data_in = gl_fb_prev_data; + gl_readstate_next = s_query_pl; + end + end + gl_fb_req_in = 1'b1; + if (read2_ready) begin + gl_fb_data_in = read2_data; + gl_readstate_next = s_query_pl; + end + end + + s_query_pl: begin + gl_fb_prev_addr_in = gl_fb_addr; + gl_fb_prev_data_in = gl_fb_data; + + if (gl_fb_addr[19:17] > 3'b100) begin + // Need to lookup palette + if (pl_avail) begin + if (GL_X[0]) + PL_ADDR = vga_fb_data[15:8]; + else + PL_ADDR = vga_fb_data[7:0]; + gl_readstate_next = s_query_pl; + end + end else begin + // Done, just return + GL_DATA = gl_fb_data; + GL_READY = 1'b1; + gl_readstate_next = s_fin; + end + end + + s_got_pl: begin + gl_pl_data_in = {PL_DATA_OUT[23:19], + PL_DATA_OUT[15:10], + PL_DATA_OUT[7:3]}; + GL_DATA = gl_pl_data_in; + gl_readstate_next = s_fin; + end + + s_fin: begin + GL_READY = 1'b1; + if (gl_from_pl) + GL_DATA = gl_pl_data; + else + GL_DATA = gl_fb_data; + + // Will leave this state on state-machine reset by falling REQ + end + endcase + + // Wiring + if (GL_ADDR[19]) begin + // Direct read from data region + read2_req = GL_REQ; + read2_addr = GL_ADDR; + GL_READY = read2_ready; + GL_DATA = read2_data; + end else begin + read2_req = gl_fb_req; + read2_addr = gl_fb_addr; + end + end endmodule diff --git a/gl/gl_mgr.sv b/gl/gl_mgr.sv index 9bd47063ef09c29b7f9cb8e20791b55acc97b337..3dc247c1be46e7270174492eeec341ec43eb6f37 100644 --- a/gl/gl_mgr.sv +++ b/gl/gl_mgr.sv @@ -273,9 +273,9 @@ module gl_mgr ( // Polygon logic polygon_en, polygon_done; // Memory write connection - logic polygon_PAINT_REQ /*synthesis keep*/; - logic [9:0] polygon_PAINT_X, polygon_PAINT_Y /*synthesis keep*/; - logic [15:0] polygon_PAINT_RGB16 /*synthesis keep*/; + logic polygon_PAINT_REQ; + logic [9:0] polygon_PAINT_X, polygon_PAINT_Y; + logic [15:0] polygon_PAINT_RGB16; // Redraw cache connection logic [18:0] polygon_RC_ADDR; logic polygon_RC_DATA_WR; @@ -309,6 +309,61 @@ module gl_mgr ( .RC_DATA_RD (rc_data_out1) ); + // Image + logic image_en, image_done; + // Memory write connection + logic image_PAINT_REQ; + logic [9:0] image_PAINT_X, image_PAINT_Y; + logic [15:0] image_PAINT_RGB16; + // Memory read connection + logic image_GL_REQ; + logic [19:0] image_GL_ADDR; + // Redraw cache connection + logic [18:0] image_RC_ADDR; + logic image_RC_DATA_WR; + logic image_RC_WE; + logic image_RC_DATA_RD; + // Destination coordinate set + logic [9:0] image_X[6], image_Y[6]; + assign image_X[0] = GL_ARG3[19:10]; + assign image_X[1] = GL_ARG4[19:10]; + assign image_X[2] = GL_ARG5[19:10]; + assign image_X[3] = GL_ARG6[19:10]; + assign image_X[4] = GL_ARG7[19:10]; + assign image_X[5] = GL_ARG8[19:10]; + assign image_Y[0] = GL_ARG3[9:0]; + assign image_Y[1] = GL_ARG4[9:0]; + assign image_Y[2] = GL_ARG5[9:0]; + assign image_Y[3] = GL_ARG6[9:0]; + assign image_Y[4] = GL_ARG7[9:0]; + assign image_Y[5] = GL_ARG8[9:0]; + gl_painter_image painter_image( + .CLOCK (CLOCK), + .RESET (RESET), + .IMG_BASE (GL_ARG1), + .W (GL_ARG1[19:10]), + .H (GL_ARG1[9:0]), + .TRANSPARENCY (GL_ARG2[15:0]), + .X (image_X), + .Y (image_Y), + .EN (image_en), + .DONE (image_done), + .PAINT_BUFFER (paint_buffer), + .fb_PAINT_REQ (image_PAINT_REQ), + .fb_PAINT_X (image_PAINT_X), + .fb_PAINT_Y (image_PAINT_Y), + .fb_PAINT_RGB16(image_PAINT_RGB16), + .fb_PAINT_READY(fb_PAINT_READY), + .fb_GL_REQ (image_GL_REQ), + .fb_GL_ADDR (image_GL_ADDR), + .fb_GL_DATA (fb_GL_RGB), + .fb_GL_READY (fb_GL_READY), + .RC_ADDR (image_RC_ADDR), + .RC_DATA_WR (image_RC_DATA_WR), + .RC_WE (image_RC_WE), + .RC_DATA_RD (rc_data_out1) + ); + always_comb begin // Route memory access @@ -317,6 +372,10 @@ module gl_mgr ( fb_PAINT_X = 10'hXXX; fb_PAINT_Y = 10'hXXX; fb_PAINT_RGB16 = 16'hXXXX; + fb_GL_REQ = 1'b0; + fb_GL_ADDR = 20'hXXXXX; + fb_GL_X = 10'hXXX; + fb_GL_Y = 10'hXXX; rc_addr1 = 8'hXX; rc_data_in1 = 1'bX; rc_we1 = 1'b0; @@ -363,5 +422,21 @@ module gl_mgr ( polygon_en = 1'b0; end + if (GL_CMD == `GL_CMD_IMAGE) begin + image_en = 1'b1; + GL_DONE = image_done; + fb_PAINT_REQ = image_PAINT_REQ; + fb_PAINT_X = image_PAINT_X; + fb_PAINT_Y = image_PAINT_Y; + fb_PAINT_RGB16 = image_PAINT_RGB16; + fb_GL_REQ = image_GL_REQ; + fb_GL_ADDR = image_GL_ADDR; + rc_addr1 = image_RC_ADDR; + rc_data_in1 = image_RC_DATA_WR; + rc_we1 = image_RC_WE; + end else begin + image_en = 1'b0; + end + end endmodule diff --git a/gl/oto_gl_hw.tcl b/gl/oto_gl_hw.tcl index 12db108ece5460b26c313babada69f5d49915508..a5e334b4e9a8a6f73732e5c38e58fa4034c61fb4 100644 --- a/gl/oto_gl_hw.tcl +++ b/gl/oto_gl_hw.tcl @@ -1,12 +1,12 @@ # TCL File Generated by Component Editor 17.1 -# Sun Dec 03 22:29:28 CST 2017 +# Thu Dec 07 23:23:06 CST 2017 # DO NOT MODIFY # # oto_gl "otofpga Graphics Library" v1.0 -# 2017.12.03.22:29:28 -# +# 2017.12.07.23:23:06 +# otofgpa hardware-accelerated graphics painter # # @@ -18,7 +18,7 @@ package require -exact qsys 16.1 # # module oto_gl # -set_module_property DESCRIPTION "" +set_module_property DESCRIPTION "otofgpa hardware-accelerated graphics painter" set_module_property NAME oto_gl set_module_property VERSION 1.0 set_module_property INTERNAL false @@ -53,6 +53,7 @@ add_fileset_file gl_painter_circle.sv SYSTEM_VERILOG PATH painters/gl_painter_ci add_fileset_file gl_painter_polygon.sv SYSTEM_VERILOG PATH painters/gl_painter_polygon.sv add_fileset_file gl_blender.sv SYSTEM_VERILOG PATH utils/gl_blender.sv add_fileset_file gl_line_scanner.sv SYSTEM_VERILOG PATH utils/gl_line_scanner.sv +add_fileset_file gl_painter_image.sv SYSTEM_VERILOG PATH painters/gl_painter_image.sv # diff --git a/gl/painters/gl_painter_image.sv b/gl/painters/gl_painter_image.sv new file mode 100644 index 0000000000000000000000000000000000000000..f81d1b6074c14b37c7f46a7e981c8e853a1db179 --- /dev/null +++ b/gl/painters/gl_painter_image.sv @@ -0,0 +1,149 @@ +module gl_painter_image ( + // Clock + input logic CLOCK, RESET, + + // Arguments + input logic [19:0] IMG_BASE, + input logic [9:0] W, H, + input logic [9:0] X[6], Y[6], + + // Transparency + input logic [15:0] TRANSPARENCY, + + // Status Control + input logic EN, + output logic DONE, + + input logic PAINT_BUFFER, + + // Memory read connection + output logic fb_GL_REQ, + output logic [19:0] fb_GL_ADDR, + input logic [15:0] fb_GL_DATA, + input logic fb_GL_READY, + + // Memory write connection + output logic fb_PAINT_REQ, + output logic [9:0] fb_PAINT_X, fb_PAINT_Y, + output logic [15:0] fb_PAINT_RGB16, + input logic fb_PAINT_READY, + + // Redraw cache connection + output logic [19:0] RC_ADDR, + output logic RC_DATA_WR, + output logic RC_WE, + input logic RC_DATA_RD +); + + logic [2:0] i, i_in; + logic [19:0] img_ptr, img_ptr_in; + logic [9:0] x, y, x_in, y_in; + logic [15:0] color, color_in; + logic paint_req_in, read_req_in; + enum logic[3:0] { + s_idle, s_fetch, s_paint, s_fin + } state, state_next; + + assign fb_PAINT_X = X[i] + x; + assign fb_PAINT_Y = Y[i] + y; + assign fb_PAINT_RGB16 = color; + + assign RC_ADDR = {fb_PAINT_X, fb_PAINT_Y[8:0], PAINT_BUFFER}; + assign RC_DATA_WR = 1'b1; + + assign fb_GL_ADDR = img_ptr; + + always_ff @(posedge CLOCK) begin + if(RESET | ~EN) begin + state <= s_idle; + x <= 0; + y <= 0; + i <= 0; + fb_PAINT_REQ <= 1'b0; + fb_GL_REQ <= 1'b0; + color <= {5'b0, 6'b0, 5'b11111}; + img_ptr <= IMG_BASE; + end else begin + state <= state_next; + x <= x_in; + y <= y_in; + i <= i_in; + fb_PAINT_REQ <= paint_req_in; + fb_GL_REQ <= read_req_in; + color <= color_in; + state <= state_next; + img_ptr <= img_ptr_in; + end + end + + always_comb begin + // Default values + state_next = state; + x_in = x; + y_in = y; + color_in = color; + i_in = i; + DONE = 1'b0; + RC_WE = 1'b0; + paint_req_in = 1'b0; + read_req_in = 1'b0; + img_ptr_in = img_ptr; + + case (state) + s_idle: begin + state_next = s_fetch; + x_in = 0; + y_in = 0; + i_in = 0; + paint_req_in = 1'b0; + read_req_in = 1'b1; + img_ptr_in = IMG_BASE; + end + + s_fetch: begin + if (~fb_GL_READY) begin + // Continue reading + read_req_in = 1'b1; + end else begin + // Done. Save data and start drawing + color_in = fb_GL_DATA; + i_in = 0; + paint_req_in = 1'b1; + state_next = s_paint; + end + end + + s_paint: begin + paint_req_in = 1'b1; + RC_WE = 1'b1; + if(fb_PAINT_READY) begin + // Value written, move to next location + i_in = i + 1; + if (Y[i_in][9] || i_in == 6) begin + // Done. Move to next pixel + x_in = x + 1; + img_ptr_in = img_ptr + 1; + if (x_in == W) begin + // Move to next row + x_in = 0; + y_in = y_in + 1; + if (y_in == H) begin + // Completely done. + paint_req_in = 1'b0; + state_next = s_fin; + DONE = 1'b1; + end + end + end + end + end + + s_fin: begin + DONE = 1'b1; + end + + endcase + + end + +endmodule