//=============================================================================== // FPGA GALAXIAN TOP // // Version : 2.50 // // Copyright(c) 2004 Katsumi Degawa , All rights reserved // // Important ! // // This program is freeware for non-commercial use. // An author does no guarantee about this program. // You can use this under your own risk. // // 2004- 4-30 galaxian modify by K.DEGAWA // 2004- 5- 6 first release. // 2004- 8-23 Improvement with T80-IP. // 2004- 9-18 The description of ALTERA(CYCLONE) and XILINX(SPARTAN2E) was made one. // 2004- 9-22 The problem which missile didn't sometimes come out from was improved. //================================================================================ `include "src/mc_conf.v" module mc_top( // FPGA_USE I_CLK_125M, `ifdef PSPAD_USE // PS_PAD interface psCLK, psSEL, psTXD, psRXD, `endif // INPORT SW IF I_PSW, // SOUND OUT O_SOUND_OUT_L, O_SOUND_OUT_R, // VGA (VIDEO) IF O_VGA_R, O_VGA_G, O_VGA_B, O_VGA_H_SYNCn, O_VGA_V_SYNCn ); // FPGA_USE input I_CLK_125M; // CPU ADDRESS BUS wire [15:0]W_A; // CPU IF wire W_CPU_RDn; wire W_CPU_WRn; wire W_CPU_MREQn; wire W_CPU_RFSHn; wire W_CPU_BUSAKn; wire W_CPU_IORQn; wire W_CPU_M1n; wire W_CPU_CLK; wire W_CPU_HRDWR_RESETn; wire W_CPU_WAITn; wire W_CPU_NMIn; `ifdef PSPAD_USE // PS_PAD interface input psRXD; output psTXD,psCLK,psSEL; `endif // INPORT SW IF input [8:0]I_PSW; // SOUND OUT output O_SOUND_OUT_L; output O_SOUND_OUT_R; // VGA (VIDEO) IF output [3:0]O_VGA_R; output [3:0]O_VGA_G; output [3:0]O_VGA_B; output O_VGA_H_SYNCn; output O_VGA_V_SYNCn; wire W_RESETn = |(~I_PSW[8:5]); //------ CLOCK GEN --------------------------- wire I_CLK_18432M; wire W_CLK_12M,WB_CLK_12M; wire W_CLK_6M,WB_CLK_6M; wire W_STARS_CLK; mc_dcm clockgen( .CLKIN_IN(I_CLK_125M), .RST_IN(! W_RESETn), .CLKFX_OUT(I_CLK_18432M) ); //------ H&V COUNTER ------------------------- wire [8:0]W_H_CNT; wire [7:0]W_V_CNT; wire W_H_BL; wire W_V_BLn; wire W_C_BLn; wire W_H_SYNC; wire W_V_SYNC; //------ CPU RAM ---------------------------- wire [7:0]W_CPU_RAM_DO; //------ ADDRESS DECDER ---------------------- wire W_CPU_ROM_CSn; wire W_CPU_RAM_RDn; wire W_CPU_RAM_WRn; wire W_CPU_RAM_CSn; wire W_OBJ_RAM_RDn; wire W_OBJ_RAM_WRn; wire W_OBJ_RAM_RQn; wire W_VID_RAM_RDn; wire W_VID_RAM_WRn; wire W_SW0_OEn; wire W_SW1_OEn; wire W_DIP_OEn; wire W_WDR_OEn; wire W_LAMP_WEn; wire W_SOUND_WEn; wire W_PITCHn; wire W_H_FLIP; wire W_V_FLIP; wire W_BD_G; wire W_STARS_ON; wire W_VID_RDn = W_OBJ_RAM_RDn & W_VID_RAM_RDn ; wire W_SW_OEn = W_SW0_OEn & W_SW1_OEn & W_DIP_OEn ; //------- INPORT ----------------------------- wire [7:0]W_SW_DO; //------- VIDEO ----------------------------- wire [7:0]W_VID_DO; //-------------------------------------------- mc_clock MC_CLK( .I_CLK_18M(I_CLK_18432M), .O_CLK_12M(WB_CLK_12M), .O_CLK_06M(WB_CLK_6M) ); `ifdef DEVICE_CYCLONE assign W_CLK_12M = WB_CLK_12M; assign W_CLK_6M = WB_CLK_6M; `endif `ifdef DEVICE_SPARTAN2E BUFG BUFG_12MHz( .I(WB_CLK_12M),.O(W_CLK_12M) ); BUFG BUFG_6MHz ( .I(WB_CLK_6M ),.O(W_CLK_6M ) ); `endif //--- DATA I/F ------------------------------------- reg [7:0]W_CPU_ROM_DO; wire [7:0]W_CPU_ROM_DOB = W_CPU_ROM_CSn ? 8'h00: W_CPU_ROM_DO ; wire [7:0]W_BDO = W_SW_DO | W_VID_DO | W_CPU_RAM_DO | W_CPU_ROM_DOB ; wire [7:0]W_BDI; //--- CPU I/F ------------------------------------- reg [3:0]rst_count; always@(posedge W_H_CNT[0] or negedge W_RESETn) begin if(! W_RESETn) rst_count <= 0; else begin if( rst_count == 15) rst_count <= rst_count; else rst_count <= rst_count+1; end end assign W_CPU_RESETn = W_RESETn; assign W_CPU_CLK = W_H_CNT[0]; Z80IP CPU( .CLK(W_CPU_CLK), .RESET_N(W_CPU_RESETn), .INT_N(1'b1), .NMI_N(W_CPU_NMIn), .ADRS(W_A), .DOUT(W_BDI), .DINP(W_BDO), .M1_N(), .MREQ_N(W_CPU_MREQn), .IORQ_N(), .RD_N(W_CPU_RDn ), .WR_N(W_CPU_WRn ), .WAIT_N(W_CPU_WAITn), .BUSWO(), .RFSH_N(W_CPU_RFSHn), .HALT_N() ); wire W_CPU_RAM_CLK = W_CLK_12M & ~W_CPU_RAM_CSn; mc_cpu_ram MC_CPU_RAM( .I_CLK(W_CPU_RAM_CLK), .I_ADDR(W_A[9:0]), .I_D(W_BDI), .I_WE(~W_CPU_WRn), .I_OE(~W_CPU_RAM_RDn ), .O_D(W_CPU_RAM_DO) ); mc_adec MC_ADEC( .I_CLK_12M(W_CLK_12M), .I_CLK_6M(W_CLK_6M), .I_CPU_CLK(W_H_CNT[0]), .I_RSTn(W_RESETn), .I_CPU_A(W_A), .I_CPU_D(W_BDI[0]), .I_MREQn(W_CPU_MREQn), .I_RFSHn(W_CPU_RFSHn), .I_RDn(W_CPU_RDn), .I_WRn(W_CPU_WRn), .I_H_BL(W_H_BL), .I_V_BLn(W_V_BLn), .O_WAITn(W_CPU_WAITn), .O_NMIn(W_CPU_NMIn), .O_CPU_ROM_CSn(W_CPU_ROM_CSn), .O_CPU_RAM_RDn(W_CPU_RAM_RDn), .O_CPU_RAM_WRn(W_CPU_RAM_WRn), .O_CPU_RAM_CSn(W_CPU_RAM_CSn), .O_OBJ_RAM_RDn(W_OBJ_RAM_RDn), .O_OBJ_RAM_WRn(W_OBJ_RAM_WRn), .O_OBJ_RAM_RQn(W_OBJ_RAM_RQn), .O_VID_RAM_RDn(W_VID_RAM_RDn), .O_VID_RAM_WRn(W_VID_RAM_WRn), .O_SW0_OEn(W_SW0_OEn), .O_SW1_OEn(W_SW1_OEn), .O_DIP_OEn(W_DIP_OEn), .O_WDR_OEn(W_WDR_OEn), .O_LAMP_WEn(W_LAMP_WEn), .O_SOUND_WEn(W_SOUND_WEn), .O_PITCHn(W_PITCHn), .O_H_FLIP(W_H_FLIP), .O_V_FLIP(W_V_FLIP), .O_BD_G(W_BD_G), .O_STARS_ON(W_STARS_ON) ); //-------- SOUND I/F ----------------------------- //--- Parts 9L --------- reg [7:0]W_9L_Q; always@(posedge W_CLK_12M or negedge W_RESETn) begin if(W_RESETn == 1'b0)begin W_9L_Q <= 0; end else begin if(W_SOUND_WEn == 1'b0)begin case(W_A[2:0]) 3'h0 : W_9L_Q[0] <= W_BDI[0]; 3'h1 : W_9L_Q[1] <= W_BDI[0]; 3'h2 : W_9L_Q[2] <= W_BDI[0]; 3'h3 : W_9L_Q[3] <= W_BDI[0]; 3'h4 : W_9L_Q[4] <= W_BDI[0]; 3'h5 : W_9L_Q[5] <= W_BDI[0]; 3'h6 : W_9L_Q[6] <= W_BDI[0]; 3'h7 : W_9L_Q[7] <= W_BDI[0]; endcase end end end wire W_VOL1 = W_9L_Q[6]; wire W_VOL2 = W_9L_Q[7]; wire W_FIRE = W_9L_Q[5]; wire W_HIT = W_9L_Q[3]; wire W_FS3 = W_9L_Q[2]; wire W_FS2 = W_9L_Q[1]; wire W_FS1 = W_9L_Q[0]; //--------------------------------------------------- //---- CPU DATA WATCH ------------------------------- wire ZMWR = W_CPU_MREQn | W_CPU_WRn ; reg [1:0]on_game; always @(posedge W_CPU_CLK) begin if(~ZMWR)begin if(W_A == 16'h4007)begin if(W_BDI == 8'h00) on_game[0] <= 1; else on_game[0] <= 0; end if(W_A == 16'h4005)begin if(W_BDI == 8'h03 || W_BDI == 8'h04 ) on_game[1] <= 1; else on_game[1] <= 0; end end end `ifdef PSPAD_USE reg died; always @(posedge W_CPU_CLK) begin if(~ZMWR)begin if(W_A == 16'h4206)begin if(W_BDI == 8'h00) died <= 0; else died <= 1; end end end //---- PS_PAD Interface ----------------------------- wire [8:0]ps_PSW; wire VIB_SW = died & (&on_game[1:0]); fpga_arcade_if pspad( .CLK_18M432(I_CLK_18432M), .I_RSTn(W_RESETn), .psCLK(psCLK), .psSEL(psSEL), .psTXD(psTXD), .psRXD(psRXD), .ps_PSW(ps_PSW), .I_VIB_SW(VIB_SW) ); `endif //---- SW Interface --------------------------------- `ifdef PSPAD_USE wire L1 = I_PSW[2] & ps_PSW[2]; wire R1 = I_PSW[3] & ps_PSW[3]; wire U1 = I_PSW[0]; wire D1 = I_PSW[1]; wire J1 = I_PSW[4] & ps_PSW[8]; wire S1 = (U1|J1) & ps_PSW[6]; wire S2 = (D1|J1) & ps_PSW[7]; wire C1 = (L1|R1|U1|~D1) & ps_PSW[4]; `else wire L1 = ! I_PSW[2]; wire R1 = ! I_PSW[3]; wire U1 = ! I_PSW[0]; wire D1 = ! I_PSW[1]; wire J1 = ! I_PSW[4]; wire S1 = ! I_PSW[5]; wire S2 = ! I_PSW[7]; wire C1 = ! I_PSW[6]; `endif wire C2 = ! I_PSW[8]; wire L2 = L1; wire R2 = R1; wire U2 = U1; wire D2 = D1; wire J2 = J1; mc_inport MC_INPORT( .I_COIN1(~C1), // ACTIVE HI .I_COIN2(~C2), // ACTIVE HI .I_1P_LE(~L1), // ACTIVE HI .I_1P_RI(~R1), // ACTIVE HI .I_1P_SH(~J1), // ACTIVE HI .I_2P_LE(~L2), // ACTIVE HI .I_2P_RI(~R2), // ACTIVE HI .I_2P_SH(~J2), // ACTIVE HI .I_1P_START(~S1), // ACTIVE HI .I_2P_START(~S2), // ACTIVE HI .I_SW0_OEn(W_SW0_OEn), .I_SW1_OEn(W_SW1_OEn), .I_DIP_OEn(W_DIP_OEn), .O_D(W_SW_DO) ); //----------------------------------------------------------------------------- //------- ROM ------------------------------------------------------- reg [18:0]ROM_A; wire [18:0]W_WAV_A0,W_WAV_A1,W_WAV_A2; reg [7:0]W_WAV_D0,W_WAV_D1,W_WAV_D2; wire [7:0]ROM_D; galaxian_roms ROMS( .I_ROM_CLK(W_CLK_12M), .I_ADDR({3'h0,W_A[15:0]}), .O_DATA(ROM_D) ); always@(posedge W_CLK_12M) begin W_CPU_ROM_DO <= ROM_D; end //----------------------------------------------------------------------------- wire W_V_BL2n; mc_hv_count MC_HV( .I_CLK(WB_CLK_6M), .I_RSTn(W_RESETn), .O_H_CNT(W_H_CNT), .O_H_SYNC(W_H_SYNC), .O_H_BL(W_H_BL), .O_V_CNT(W_V_CNT), .O_V_SYNC(W_V_SYNC), .O_V_BL2n(W_V_BL2n), .O_V_BLn(W_V_BLn), .O_C_BLn(W_C_BLn) ); //------ VIDEO ----------------------------- wire W_8HF; wire W_1VF; wire W_C_BLnX; wire W_256HnX; wire W_MISSILEn; wire W_SHELLn; wire [1:0]W_VID; wire [2:0]W_COL; mc_video MC_VID( .I_CLK_18M(I_CLK_18432M), .I_CLK_12M(W_CLK_12M), .I_CLK_6M(W_CLK_6M), .I_H_CNT(W_H_CNT), .I_V_CNT(W_V_CNT), .I_H_FLIP(W_H_FLIP), .I_V_FLIP(W_V_FLIP), .I_V_BLn(W_V_BLn), .I_C_BLn(W_C_BLn), .I_A(W_A[9:0]), .I_OBJ_SUB_A(3'b000), .I_BD(W_BDI), .I_OBJ_RAM_RQn(W_OBJ_RAM_RQn), .I_OBJ_RAM_RDn(W_OBJ_RAM_RDn), .I_OBJ_RAM_WRn(W_OBJ_RAM_WRn), .I_VID_RAM_RDn(W_VID_RAM_RDn), .I_VID_RAM_WRn(W_VID_RAM_WRn), .O_C_BLnX(W_C_BLnX), .O_8HF(W_8HF), .O_256HnX(W_256HnX), .O_1VF(W_1VF), .O_MISSILEn(W_MISSILEn), .O_SHELLn(W_SHELLn), .O_BD(W_VID_DO), .O_VID(W_VID), .O_COL(W_COL) ); wire W_C_BLX; wire W_STARS_OFFn; wire [2:0]W_VIDEO_R; wire [2:0]W_VIDEO_G; wire [1:0]W_VIDEO_B; mc_col_pal MC_COL_PAL( .I_CLK_12M(W_CLK_12M), .I_CLK_6M(W_CLK_6M), .I_VID(W_VID), .I_COL(W_COL), .I_C_BLnX(W_C_BLnX), .O_C_BLX(W_C_BLX), .O_STARS_OFFn(W_STARS_OFFn), .O_R(W_VIDEO_R), .O_G(W_VIDEO_G), .O_B(W_VIDEO_B) ); wire [2:0]W_STARS_R; wire [2:0]W_STARS_G; wire [1:0]W_STARS_B; mc_stars MC_STARS( .I_CLK_18M(I_CLK_18432M), `ifdef DEVICE_CYCLONE .I_CLK_6M(~WB_CLK_6M), `endif `ifdef DEVICE_SPARTAN2E .I_CLK_6M(WB_CLK_6M), `endif .I_H_FLIP(W_H_FLIP), .I_V_SYNC(W_V_SYNC), .I_8HF(W_8HF), .I_256HnX(W_256HnX), .I_1VF(W_1VF), .I_2V(W_V_CNT[1]), .I_STARS_ON(W_STARS_ON), .I_STARS_OFFn(W_STARS_OFFn), .O_R(W_STARS_R), .O_G(W_STARS_G), .O_B(W_STARS_B), .O_NOISE() ); wire [2:0]W_R; wire [2:0]W_G; wire [1:0]W_B; mc_vedio_mix MIX( .I_VID_R(W_VIDEO_R), .I_VID_G(W_VIDEO_G), .I_VID_B(W_VIDEO_B), .I_STR_R(W_STARS_R), .I_STR_G(W_STARS_G), .I_STR_B(W_STARS_B), .I_C_BLnXX(~W_C_BLX), .I_C_BLX(W_C_BLX | ~W_V_BL2n), .I_MISSILEn(W_MISSILEn), .I_SHELLn(W_SHELLn), .O_R(W_R), .O_G(W_G), .O_B(W_B) ); wire [2:0]W_VGA_R; wire [2:0]W_VGA_G; wire [1:0]W_VGA_B; `ifdef VGA_USE mc_vga_if VGA( // input .I_CLK_1(W_CLK_6M), .I_CLK_2(W_CLK_12M), .I_R(W_R), .I_G(W_G), .I_B(W_B), .I_H_SYNC(W_H_SYNC), .I_V_SYNC(W_V_SYNC), // output .O_R(W_VGA_R), .O_G(W_VGA_G), .O_B(W_VGA_B), .O_H_SYNCn(O_VGA_H_SYNCn), .O_V_SYNCn(O_VGA_V_SYNCn) ); `else assign W_VGA_R[2:0] = W_R; assign W_VGA_G[2:0] = W_G; assign W_VGA_B[1:0] = W_B; //assign O_VGA_H_SYNCn = W_H_SYNC | W_V_SYNC ; // AKIDUKI LCD USED assign O_VGA_H_SYNCn = ~W_H_SYNC ; assign O_VGA_V_SYNCn = ~W_V_SYNC ; `endif assign O_VGA_R[3:0] = {W_VGA_R[0], W_VGA_R[1], W_VGA_R[2], 1'b0}; assign O_VGA_G[3:0] = {W_VGA_G[0], W_VGA_G[1], W_VGA_G[2], 1'b0}; assign O_VGA_B[3:0] = {W_VGA_B[0], W_VGA_B[1], 2'b0}; wire [7:0]W_SDAT_A; mc_sound_a MC_SOUND_A( .I_CLK_12M(W_CLK_12M), .I_CLK_6M(W_CLK_6M), .I_H_CNT1(W_H_CNT[1]), .I_BD(W_BDI), .I_PITCHn(W_PITCHn), .I_VOL1(W_VOL1), .I_VOL2(W_VOL2), .O_SDAT(W_SDAT_A), .O_DO() ); wire [7:0]W_SDAT_B; mc_sound_b MC_SOUND_B( .I_CLK1(I_CLK_18432M), .I_CLK2(W_CLK_6M), .I_RSTn(rst_count[3]), .I_SW({&on_game[1:0],W_HIT,W_FIRE}), .O_WAV_A0(W_WAV_A0), .O_WAV_A1(W_WAV_A1), .O_WAV_A2(W_WAV_A2), .I_WAV_D0(W_WAV_D0), .I_WAV_D1(W_WAV_D1), .I_WAV_D2(W_WAV_D2), .O_SDAT(W_SDAT_B) ); wire W_DAC_A; wire W_DAC_B; assign O_SOUND_OUT_L = W_DAC_A; assign O_SOUND_OUT_R = W_DAC_B; dac wav_dac_a( .Clk(I_CLK_18432M), .Reset(~W_RESETn), .DACin(W_SDAT_A), .DACout(W_DAC_A) ); dac wav_dac_b( .Clk(I_CLK_18432M), .Reset(~W_RESETn), .DACin(W_SDAT_B), .DACout(W_DAC_B) ); endmodule