Skip to content
Snippets Groups Projects
gl_painter_image.sv 3.3 KiB
Newer Older
Fang Lu's avatar
Fang Lu committed
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;
Fang Lu's avatar
Fang Lu committed
					if (color_in == TRANSPARENCY) begin
						// Skip the 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.
								state_next = s_fin;
								DONE = 1'b1;
							end
						end
					end else begin
						// Paint the pixel
						i_in = 0;
						paint_req_in = 1'b1;
						state_next = s_paint;
					end
Fang Lu's avatar
Fang Lu committed
				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
Fang Lu's avatar
Fang Lu committed
						// Done. Fetch next pixel
						paint_req_in = 1'b0;
Fang Lu's avatar
Fang Lu committed
						x_in = x + 1;
						img_ptr_in = img_ptr + 1;
Fang Lu's avatar
Fang Lu committed
						state_next = s_fetch;
						read_req_in = 1'b1;
Fang Lu's avatar
Fang Lu committed
						if (x_in == W) begin
							// Move to next row
							x_in = 0;
							y_in = y_in + 1;
							if (y_in == H) begin
								// Completely done.
								state_next = s_fin;
								DONE = 1'b1;
							end
						end
					end
				end
			end

			s_fin: begin
				DONE = 1'b1;
			end

		endcase

	end

endmodule