/**
*	osu!fpga
*
*	An osu!-like rhythm game on DE2-115
*
*	See README for more information
*
*	Copyright (c) 2017 by Fang Lu and Xutao J. Jiang. See LICENSE file
*
*/

`include "gl/gl_def_cmd.sv"

module osu_fpga_toplevel (
	// Clock
	input logic CLOCK_50,

	// Buttons & LEDs
	input logic [1:0] KEY,
	input logic [17:0] SW,
	output logic [7:0] LEDG,
	output logic [17:0] LEDR,
	output logic [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7,

	// DRAM
	output logic [12:0] DRAM_ADDR,
	output logic [1:0] DRAM_BA,
	output logic DRAM_CAS_N, DRAM_CKE, DRAM_CS_N,
	inout wire [31:0] DRAM_DQ,
	output logic [3:0] DRAM_DQM,
	output logic DRAM_RAS_N, DRAM_WE_N, DRAM_CLK,

	// SRAM
	output logic [19:0] SRAM_ADDR,
	inout wire [15:0] SRAM_DQ,
	output logic SRAM_UB_N, SRAM_LB_N, SRAM_CE_N, SRAM_OE_N, SRAM_WE_N,

	// Flash
	output logic [22:0] FL_ADDR,
	inout wire [7:0] FL_DQ,
	output logic FL_CE_N, FL_OE_N, FL_WE_N, FL_RESET_N, FL_WP_N,
	input logic FL_RY,

	// sdcard

	// PS/2
	inout wire PS2_KBCLK, PS2_KBDAT,

	// HPI (USB)
	inout wire [15:0] OTG_DATA,
	output logic [1:0] OTG_ADDR,
	output logic OTG_CS_N, OTG_OE_N, OTG_WE_N, OTG_RST_N,
	input logic[1:0] OTG_INT,

	// VGA
	output logic VGA_CLK,
	output logic [7:0] VGA_R, VGA_G, VGA_B,
	output logic VGA_SYNC_N, VGA_BLANK_N, VGA_VS, VGA_HS,

	// Audio
	// Debug GPIO
	inout wire [35:0] GPIO
);
	// Synchronizers
	logic Reset_h, Clk;
	always_ff @ (posedge CLOCK_50) begin
		Reset_h <= ~(KEY[0]);        // The push buttons are active low
	end

	logic[3:0] GL_CMD /*synthesis keep*/;
	logic[31:0] GL_ARG1, GL_ARG2, GL_ARG3, GL_ARG4;
	logic[31:0] GL_ARG5, GL_ARG6, GL_ARG7, GL_ARG8;
	logic GL_EXEC, GL_FRAME_FINISHED, GL_DONE;
	assign LEDG[0] = GL_FRAME_FINISHED;
	gl_mgr test(
		.CLOCK            (CLOCK_50),
		.RESET            (Reset_h),
		.GL_TIMEOUT       (LEDR[17]),
		.GL_FRAME_FINISHED(GL_FRAME_FINISHED),
		.GL_DONE          (GL_DONE),
		.GL_DRAWTIME      (LEDR[9:0]),
		.AVL_REQ          (1'b0),
		.AVL_ADDR         (),
		.AVL_DATA         (),
		.AVL_READY        (),
		.AVL_PLT_RD       (1'b0),
		.AVL_PLT_WR       (1'b0),
		.AVL_PLT_INDEX    (),
		.AVL_PLT_RD_COLOR (),
		.AVL_PLT_WR_COLOR (),
		.GPIO             (GPIO),
	.*);

	enum logic[3:0] {
		s_idle, s_paint
	} state, state_next /*synthesis keep*/;

	always_ff @(posedge CLOCK_50) begin
		if(Reset_h) begin
			state <= s_idle;
		end else begin
			state <= state_next;
		end
	end

	always_comb begin
		state_next = state;
		GL_ARG1 = 32'h0;
		GL_ARG2 = 32'h0;
		GL_ARG3 = 32'h0;
		GL_ARG4 = 32'h0;
		GL_ARG5 = 32'h0;
		GL_ARG6 = 32'h0;
		GL_ARG7 = 32'h0;
		GL_ARG8 = 32'h0;
		GL_EXEC = 1'b0;
		case (state)
			s_idle: begin
				GL_CMD = `GL_CMD_FIN;
				if(GL_FRAME_FINISHED) begin
					state_next = s_paint;
				end
			end
			s_paint: begin
				GL_CMD = `GL_CMD_RECT;
				GL_ARG1 = {12'h0, 10'd020, 10'd0};
				GL_ARG2 = {12'h0, 10'd400, 10'd50};
				GL_ARG3 = {5'b01100, 6'b110011, 5'b11111, 5'b01100, 6'b110011, 5'b11111};
				GL_EXEC = 1'b1;
				if (GL_DONE) begin
					state_next = s_idle;
				end
			end
		endcase
	end

    /*
	// Additional wires for Flash
	assign FL_WP_N = 1'b1;

	// HPI wrapper
    logic [1:0] hpi_addr;
    logic [15:0] hpi_data_in, hpi_data_out;
    logic hpi_r, hpi_w, hpi_cs;
	hpi_io_intf hpi_io_inst(
		.Clk(CLOCK_50),
		.Reset(Reset_h),
		// signals connected to NIOS II
		.from_sw_address(hpi_addr),
		.from_sw_data_in(hpi_data_in),
		.from_sw_data_out(hpi_data_out),
		.from_sw_r(hpi_r),
		.from_sw_w(hpi_w),
		.from_sw_cs(hpi_cs),
		// signals connected to EZ-OTG chip
		.OTG_DATA(OTG_DATA),
		.OTG_ADDR(OTG_ADDR),
		.OTG_RD_N(OTG_OE_N),
		.OTG_WR_N(OTG_WE_N),
		.OTG_CS_N(OTG_CS_N),
		.OTG_RST_N(OTG_RST_N)
	);

	// Hex drivers
	logic [31:0] hex_export;
	hexdriver hexdrv7(.In(hex_export[31:28]), .Out(HEX7));
	hexdriver hexdrv6(.In(hex_export[27:24]), .Out(HEX6));
	hexdriver hexdrv5(.In(hex_export[23:20]), .Out(HEX5));
	hexdriver hexdrv4(.In(hex_export[19:16]), .Out(HEX4));
	hexdriver hexdrv3(.In(hex_export[15:12]), .Out(HEX3));
	hexdriver hexdrv2(.In(hex_export[11:8]), .Out(HEX2));
	hexdriver hexdrv1(.In(hex_export[7:4]), .Out(HEX1));
	hexdriver hexdrv0(.In(hex_export[3:0]), .Out(HEX0));

	// Main Program (SoC)
	otogame main_soc (
		// Clock
		.clk_clk(CLOCK_50),
		.reset_reset_n(~Reset_h),
		// DRAM
		.sdram_wire_addr(DRAM_ADDR),
		.sdram_wire_ba(DRAM_BA),
		.sdram_wire_cas_n(DRAM_CAS_N),
		.sdram_wire_cke(DRAM_CKE),
		.sdram_wire_cs_n(DRAM_CS_N),
		.sdram_wire_dq(DRAM_DQ),
		.sdram_wire_dqm(DRAM_DQM),
		.sdram_wire_ras_n(DRAM_RAS_N),
		.sdram_wire_we_n(DRAM_WE_N),
		.sdram_clk_clk(DRAM_CLK),
		// Flash
		.flash_conn_ADDR(FL_ADDR),
		.flash_conn_DQ(FL_DQ),
		.flash_conn_CE_N(FL_CE_N),
		.flash_conn_OE_N(FL_OE_N),
		.flash_conn_WE_N(FL_WE_N),
		.flash_conn_RST_N(FL_RESET_N),
		// PS/2
		.ps2_data_export(PS2_KBDAT),
		.ps2_clk_export(PS2_KBCLK),
		// USB
		.otg_hpi_address_export(hpi_addr),
		.otg_hpi_data_in_port(hpi_data_in),
		.otg_hpi_data_out_port(hpi_data_out),
		.otg_hpi_cs_export(hpi_cs),
		.otg_hpi_r_export(hpi_r),
		.otg_hpi_w_export(hpi_w),
		// LEDs
		.hex_export(hex_export),
		.ledr_export(LEDR),
		.ledg_export(LEDG)
	);
	*/

endmodule