//============================================================================
//  Vectrex !
//============================================================================

module emu
(
	//Master input clock
	input 	      CLK_50M,
	input 	      CLK_50M2,

	//Async reset from top-level module.
	//Can be used as initial reset.
	input 	      RESET,

	//Must be passed to hps_io module
	inout [37:0]  HPS_BUS,

	//Base video clock. Usually equals to CLK_SYS.
	output 	      CLK_VIDEO,

	//Multiple resolutions are supported using different CE_PIXEL rates.
	//Must be based on CLK_VIDEO
	output 	      CE_PIXEL,

	//Video aspect ratio for HDMI. Most retro systems have ratio 4:3.
	output [7:0]  VIDEO_ARX,
	output [7:0]  VIDEO_ARY,

	output [7:0]  VGA_R,
	output [7:0]  VGA_G,
	output [7:0]  VGA_B,
	output 	      VGA_HS,
	output 	      VGA_VS,
	output 	      VGA_DE, // = ~(VBlank | HBlank)
    
	output [15:0] SPOT_X,
	output [15:0] SPOT_Y,
	output  [7:0] SPOT_Z,
	output        SPOT_EN,
	output        SPOT_CLK,
	
	output 	      LED_USER, // 1 - ON, 0 - OFF.

	// b[1]: 0 - LED status is system status ORed with b[0]
	//       1 - LED status is controled solely by b[0]
	// hint: supply 2'b00 to let the system control the LED.
	output [1:0]  LED_POWER,
	output [1:0]  LED_DISK,

        output [3:0]  TESTLEDS,

	output [15:0] AUDIO_L,
	output [15:0] AUDIO_R,
	output 	      AUDIO_S, // 1 - signed audio samples, 0 - unsigned
	input 	      TAPE_IN,

	//DDR3 RAM interface
	output 	      ddram1_clk,
	input 	      ddram1_waitrequest,
	output [7:0]  ddram1_burstcount,
	output [29:0] ddram1_address,
	input [31:0]  ddram1_readdata,
	input 	      ddram1_readdatavalid,
	output 	      ddram1_read,
	output [31:0] ddram1_writedata,
	output [3:0]  ddram1_byteenable,
	output 	      ddram1_write,

	//DDR3 RAM interface
	output 	      ddram2_clk,
	input 	      ddram2_waitrequest,
	output [7:0]  ddram2_burstcount,
	output [29:0] ddram2_address,
	input [31:0]  ddram2_readdata,
	input 	      ddram2_readdatavalid,
	output 	      ddram2_read,
	output [31:0] ddram2_writedata,
	output [3:0]  ddram2_byteenable,
	output 	      ddram2_write,

	//DDR3 RAM interface
	output 	      ddram3_clk,
	input 	      ddram3_waitrequest,
	output [7:0]  ddram3_burstcount,
	output [29:0] ddram3_address,
	input [31:0]  ddram3_readdata,
	input 	      ddram3_readdatavalid,
	output 	      ddram3_read,
	output [31:0] ddram3_writedata,
	output [3:0]  ddram3_byteenable,
	output 	      ddram3_write,

	//SDRAM interface with lower latency
	output 	      SDRAM_CLK,
	output 	      SDRAM_CKE,
	output [12:0] SDRAM_A,
	output [1:0]  SDRAM_BA,
	inout [15:0]  SDRAM_DQ,
	output 	      SDRAM_DQML,
	output 	      SDRAM_DQMH,
	output 	      SDRAM_nCS,
	output 	      SDRAM_nCAS,
	output 	      SDRAM_nRAS,
	output 	      SDRAM_nWE
);

   assign {SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = 6'b111111;
   assign SDRAM_DQ = 'Z;
   assign SDRAM_CLK = 0;
   assign SDRAM_CKE = 0;

   assign VIDEO_ARX = status[1] ? 8'd16 : 8'd4;
   assign VIDEO_ARY = status[1] ? 8'd9  : 8'd3;

   
   assign LED_DISK  = 0;
   assign LED_POWER = 0;
   assign LED_USER  = 0;

`include "build_id.v"
   localparam CONF_STR = {
			  "VECTREX;;",
			  "F,BIN;",
			  "-;",
			  "O1,Swap joysticks,No,Yes;",
			  "-;",
			  "O46,Persistance,3,4,5,6,7,0,1,2;",
			  "O79,Phosphor,0,1,2,3,4,5,6,7;",
			  "OAC,Lumi,8,7,6,5,4,3,2,1;",
			  "O23,Shape,0,1,2,3;",
			  "OE,Rotation,0,90;",
			  "OD,Antialiasing,Yes,No;",
			  "J1,A,B,C,D;",
			  "V,v1.00.",`BUILD_DATE
			  };
   
   wire [31:0] 	      status;
   wire [1:0] 	      buttons;
   wire [15:0] 	      joystick_0;
   wire [15:0] 	      joystick_1;
   wire [15:0] 	      joystick_analog_0;
   wire [15:0] 	      joystick_analog_1;
   wire 	      ioctl_download;
   wire 	      ioctl_wr;
   wire [24:0] 	      ioctl_addr;
   wire [15:0] 	      ioctl_data;
   reg 		      ioctl_wait;
   wire 	      forced_scandoubler;
   
   hps_io #(.STRLEN($size(CONF_STR)>>3), .PS2DIV(1000), .WIDE(1)) hps_io
     (
      .clk_sys(clk_sys),
      .HPS_BUS(HPS_BUS),

      .conf_str(CONF_STR),
      .joystick_0(joystick_0),
      .joystick_1(joystick_1),
      .joystick_analog_0(joystick_analog_0),
      .joystick_analog_1(joystick_analog_1),
      .buttons(buttons),
      .status(status),
      .forced_scandoubler(forced_scandoubler),

      .ioctl_download(ioctl_download),
      .ioctl_wr(ioctl_wr),
      .ioctl_addr(ioctl_addr),
      .ioctl_dout(ioctl_data),
      .ioctl_wait(ioctl_wait),
      
      // ps2 keyboard emulation
      .ps2_kbd_clk(),
      .ps2_kbd_data(),
      
      .ps2_kbd_led_use(0),
      .ps2_kbd_led_status(0)
      );

   wire [3:0] left_udlr;
   wire [3:0] right_udlr;
   wire       pause;
   	
   assign left_udlr  = {joystick_0[3],joystick_0[2],joystick_0[1],joystick_0[0]};
   assign right_udlr = {joystick_1[3],joystick_1[2],joystick_1[1],joystick_1[0]};
   
   wire [7:0] left_x,left_y,right_x,right_y;
	
   assign left_x = joystick_analog_0[15:8];
   assign left_y = joystick_analog_0[7:0];
   
   assign right_x = joystick_analog_1[15:8];
   assign right_y = joystick_analog_1[7:0];

   assign pause = joystick_0[4] | joystick_1[4];
   
   ///////////////////////////////////////////////////
   wire clksys,clkvid,hdmi_clk;
   wire clk_sys, clk_ram, locked;
   
   pll pll
     (
      .refclk(CLK_50M),
      .rst(0),
      .outclk_0(clksys), // 99MHz
      .outclk_1(clkvid), // 66MHz
      .locked(locked)
      );

      
    pll_hdmi pll_hdmi
      (
       .refclk(CLK_50M2),
       .rst(reset),
       .outclk_0(hdmi_clk) // 74.25MHz
      );

   assign CLK_VIDEO = clkvid;
 //assign CLK_VIDEO = hdmi_clk;
   assign clk_sys = clksys;
   
   ///////////////////////////////////////////////////
   
   wire reset = RESET|buttons[1];
   
   assign CE_PIXEL = 1'b1;
   wire [15:0] sound;
   
   assign AUDIO_L=sound;
   assign AUDIO_R=sound;
   assign AUDIO_S=1;

   vec_core i_vec_core
     (
      .sound(sound),
      
      .left_udlr(status[1]?left_udlr:right_udlr),
      .left_x(status[1]?left_x:right_x),
      .left_y(status[1]?left_y:right_y),

      .right_udlr(status[1]?right_udlr:left_udlr),
      .right_x(status[1]?right_x:left_x),
      .right_y(status[1]?right_y:left_y),

      .pause(pause),
      
      .vga_r   (VGA_R),
      .vga_g   (VGA_G),
      .vga_b   (VGA_B),
      .vga_de  (VGA_DE),
      .vga_hsyn(VGA_HS),
      .vga_vsyn(VGA_VS),
      .vga_clk (CLK_VIDEO),
      .vga_en  (CE_PIXEL),
      
      .spot_x  (SPOT_X),
      .spot_y  (SPOT_Y),
      .spot_z  (SPOT_Z),
      .spot_en (SPOT_EN),
      .spot_clk(SPOT_CLK),
      
      .status(status),
      .testleds(TESTLEDS),
      
      // Draw Interface
      .avl_clk           (ddram1_clk),
      .avl_waitrequest   (ddram1_waitrequest),
      .avl_readdata      (ddram1_readdata),
      .avl_readdatavalid (ddram1_readdatavalid),
      .avl_burstcount    (ddram1_burstcount),
      .avl_writedata     (ddram1_writedata),
      .avl_address       (ddram1_address),
      .avl_write         (ddram1_write),
      .avl_read          (ddram1_read),
      .avl_byteenable    (ddram1_byteenable),

      // Framebuffer
      .vid_clk           (ddram2_clk),
      .vid_waitrequest   (ddram2_waitrequest),
      .vid_readdata      (ddram2_readdata),
      .vid_readdatavalid (ddram2_readdatavalid),
      .vid_burstcount    (ddram2_burstcount),
      .vid_writedata     (ddram2_writedata),
      .vid_address       (ddram2_address),
      .vid_write         (ddram2_write),
      .vid_read          (ddram2_read),
      .vid_byteenable    (ddram2_byteenable),

      // ROM
      .rom_clk           (ddram3_clk),
      .rom_waitrequest   (ddram3_waitrequest),
      .rom_readdata      (ddram3_readdata),
      .rom_readdatavalid (ddram3_readdatavalid),
      .rom_burstcount    (ddram3_burstcount),
      .rom_writedata     (ddram3_writedata),
      .rom_address       (ddram3_address),
      .rom_write         (ddram3_write),
      .rom_read          (ddram3_read),
      .rom_byteenable    (ddram3_byteenable),

      //
      .host_download     (ioctl_download),
      .host_wr           (ioctl_wr),
      .host_addr         (ioctl_addr),
      .host_data         (ioctl_data),
      .host_wait         (ioctl_wait),
      .clksys            (clksys),
      .reset_na          (~(reset|ioctl_download))
      );

endmodule
