From f4d9ab55193dac5d0689bef0831802afe7b8837a Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sat, 31 Jul 2021 14:05:30 +0200 Subject: [PATCH] Gyruss: make it fully synchronous --- Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv | 12 +- Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv | 118 +++++++++++-------- Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv | 98 ++++++++------- 3 files changed, 130 insertions(+), 98 deletions(-) diff --git a/Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv index 3fc12647..3eaa7bb7 100644 --- a/Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv +++ b/Arcade_MiST/Konami Gyruss/rtl/Gyruss_CPU.sv @@ -666,13 +666,15 @@ wire cs_linebuffer, sprite_flip; wire [5:0] k503_R; k503 u9F ( + .clk(clk_49m), + .clk_en(cen_6m), .OB(spriteram_reg[7:0]), .VCNT(vcnt_lat), .H4(h_cnt[2]), - .H8(0), + .H8(1'b0), .LD(h_cnt[1:0] != 2'b11), .OCS(cs_linebuffer), - .OFLP(sprite_flip), + .NE83(sprite_flip), .R(k503_R) ); assign spriterom_A[5] = k503_R[5]; @@ -819,11 +821,11 @@ wire [4:0] sprite_D; wire sprite_lbuff_sel, sprite_lbuff_dec0, sprite_lbuff_dec1; k502 u6B ( - .RESET(1), .CK1(clk_49m), + .CK1_EN(cen_12m), .CK2(clk_49m), - .CEN(cen_6m), - .LD0(h_cnt[2:0] == 3'b000), + .CK2_EN(cen_6m), + .LD0(h_cnt[2:0] != 3'b111), .H2(h_cnt[1]), .H256(h_cnt[8]), .SPAL(sprite_lut_D), diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv index 717c4cee..81bed0a7 100644 --- a/Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv +++ b/Arcade_MiST/Konami Gyruss/rtl/custom/k502.sv @@ -2,7 +2,8 @@ // // SystemVerilog implementation of the Konami 502 custom chip, used for // generating sprites on a number of '80s Konami arcade PCBs -// Copyright (C) 2020, 2021 Ace +// +// Copyright (C) 2020 Ace // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -29,7 +30,7 @@ _| |_ SPLB(0) |_|1 28|_| VCC _| |_ -SPLB(1) |_|2 27|_| RESET +SPLB(1) |_|2 27|_| ? _| |_ SPLB(2) |_|3 26|_| SPLB(4) _| |_ @@ -62,10 +63,10 @@ Note: The SPLB pins are bidirectional - this model splits these pins into separa module k502 ( - input RESET, input CK1, + input CK1_EN, input CK2, - input CEN, //Set to 1 if using this code to replace a real 502 + input CK2_EN, input LD0, input H2, input H256, @@ -81,39 +82,57 @@ module k502 //As the Konami 502 doesn't have a dedicated input for bit 2 of the horizontal counter (H4), generate //this signal internally by dividing H2 by 2 reg h2_div = 0; +`ifdef SIM always_ff @(posedge H2) begin h2_div <= ~h2_div; end -wire h4 = h2_div; - -//Latch H256 on rising edge of LD0 and delay by one cycle (set to 0 if 502 is held in reset) -reg h256_lat = 0; -always_ff @(posedge LD0 or negedge RESET) begin - if(!RESET) - h256_lat <= 0; - else - h256_lat <= H256; -end -reg h256_dly = 0; -always_ff @(posedge h256_lat or negedge RESET) begin - if(!RESET) - h256_dly <= 0; - else - h256_dly <= ~h256_dly; -end - -//Generate OSEL, OLD and OCLR -reg [1:0] osel_reg; -always_ff @(negedge H2 or negedge RESET) begin - if(!RESET) - osel_reg <= 2'b00; - else begin - if(!h4) - osel_reg[1] <= h256_dly; - else - osel_reg[0] <= osel_reg[1]; +`else +reg h2_d; +always @(posedge CK2) begin + if (CK2_EN) begin + h2_d <= H2; + if (h2_d & H2) h2_div <= !h2_div; // falling edge of H2 end end +`endif +wire h4 = h2_div; + +reg h256_lat = 0; +reg h256_dly = 0; +`ifdef SIM +//Latch H256 on rising edge of LD0 and delay by one cycle +always_ff @(posedge LD0) begin + h256_lat <= H256; +end +always_ff @(posedge h256_lat) begin + h256_dly <= ~h256_dly; +end +`else +always @(posedge CK2) begin + if (CK2_EN & !LD0) begin + h256_lat <= H256; + if (!h256_lat & H256) h256_dly <= ~h256_dly; + end +end +`endif +//Generate OSEL, OLD and OCLR +reg [1:0] osel_reg; +`ifdef SIM +always_ff @(negedge H2) begin + if(!h4) + osel_reg[1] <= h256_dly; + else + osel_reg[0] <= osel_reg[1]; +end +`else +assign osel_reg[1] = h256_dly; +always @(posedge CK2) begin + if (CK2_EN & h2_d & H2) begin // falling edge of H2 + if(!h4) osel_reg[0] <= osel_reg[1]; + end +end +`endif + assign OLD = ~osel_reg[1]; assign OSEL = osel_reg[0]; assign OCLR = ~osel_reg[0]; @@ -121,23 +140,22 @@ assign OCLR = ~osel_reg[0]; //Multiplex incoming line buffer RAM data wire [3:0] lbuff_Dmux = OCLR ? SPLBi[3:0] : SPLBi[7:4]; -//Latch incoming line buffer RAM data on the falling edge of CK1 +//Latch incoming line buffer RAM data on the rising edge of CK1 reg [7:0] lbuff_lat; -always_ff @(negedge CK1) begin - if(!RESET) - lbuff_lat <= 8'd0; - else if(CEN) - lbuff_lat <= SPLBi; -end - -//Latch multiplexed line buffer RAM data on the falling edge of CK2 reg [3:0] lbuff_mux_lat; -always_ff @(negedge CK2) begin - if(!RESET) - lbuff_mux_lat <= 4'd0; - else if(CEN) - lbuff_mux_lat <= lbuff_Dmux; +`ifdef SIM +always_ff @(posedge CK1) begin + lbuff_lat <= SPLBi; + lbuff_mux_lat <= lbuff_Dmux; end +`else +always_ff @(posedge CK1) begin + if (CK1_EN) begin + lbuff_lat <= SPLBi; + lbuff_mux_lat <= lbuff_Dmux; + end +end +`endif //Assign sprite data output assign COL[4] = ~(|lbuff_mux_lat[3:0]); @@ -150,10 +168,14 @@ wire sprite_pal_sel1 = (~lbuff_lat[3] & ~lbuff_lat[2] & ~lbuff_lat[1] & ~lbuff_l //Multiplex sprite data from line buffer with palette data (lower 4 bits) wire [7:0] sprite_pal_mux; -assign sprite_pal_mux[3:0] = osel_reg[0] ? (sprite_pal_sel1 ? SPAL : SPLBi[3:0]) : 4'h0; +assign sprite_pal_mux[3:0] = osel_reg[0] ? + (sprite_pal_sel1 ? SPAL : SPLBi[3:0]): + 4'h0; //Multiplex sprite data from line buffer with palette data (upper 4 bits) -assign sprite_pal_mux[7:4] = ~osel_reg[0] ? (sprite_pal_sel2 ? SPAL : SPLBi[7:4]) : 4'h0; +assign sprite_pal_mux[7:4] = ~osel_reg[0] ? + (sprite_pal_sel2 ? SPAL : SPLBi[7:4]): + 4'h0; //Output data to sprite line buffer assign SPLBo = sprite_pal_mux; diff --git a/Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv b/Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv index bf464503..fd2c632c 100644 --- a/Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv +++ b/Arcade_MiST/Konami Gyruss/rtl/custom/k503.sv @@ -2,7 +2,8 @@ // // SystemVerilog implementation of the Konami 503 custom chip, used by // several Konami arcade PCBs for handling sprite data -// Copyright (C) 2020, 2021 Ace +// +// Copyright (C) 2020 Ace // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -25,29 +26,29 @@ //============================================================================ //Chip pinout: -/* _____________ +/* _____________ _| |_ OB(7) |_|1 40|_| VCC _| |_ -OB(6) |_|2 39|_| VCNT(7) +OB(6) |_|2 39|_| V128 _| |_ -OB(5) |_|3 38|_| VCNT(6) +OB(5) |_|3 38|_| V64 _| |_ -OB(4) |_|4 37|_| VCNT(5) +OB(4) |_|4 37|_| V32 _| |_ -OB(3) |_|5 36|_| VCNT(4) +OB(3) |_|5 36|_| V16 _| |_ -OB(2) |_|6 35|_| VCNT(3) +OB(2) |_|6 35|_| V8 _| |_ -OB(1) |_|7 34|_| VCNT(2) +OB(1) |_|7 34|_| V4 _| |_ -OB(0) |_|8 33|_| VCNT(1) +OB(0) |_|8 33|_| V2 _| |_ -R(5) |_|9 32|_| VCNT(0) +R(5) |_|9 32|_| V1 _| |_ R(4) |_|10 31|_| NC _| |_ -R(3) |_|11 30|_| OFLP +R(3) |_|11 30|_| NE83 _| |_ R(2) |_|12 29|_| OCS _| |_ @@ -71,49 +72,56 @@ GND |_|20 21|_| NC module k503 ( - input [7:0] OB, //Sprite data input - input [7:0] VCNT, //Vertical counter input - input H4, H8, //Horizontal counter bits 2 (H4) and 3 (H8) - input LD, //LD input (pulses low when bits 0 and 1 of the horizontal counter are both 1) - output OCS, //Sprite line buffer chip select output - output OFLP, //Sprite flip output - output ODAT, //Signal to latch upper bits of sprite address - output OCOL, //Signal to load addresses for sprite line buffer - output [5:0] R //Lower 6 bits of sprite address + input clk, + input clk_en, + input [7:0] OB, + input [7:0] VCNT, + input H4, H8, + input LD, + output OCS, + output NE83, + output ODAT, OCOL, + output [5:0] R ); -//Sum sprite bits with vertical counter -wire [7:0] sprite_sum = OB + VCNT; +//Sum object bits with vertical counter +wire [7:0] obj_sum = OB + VCNT; -//Sprite select signal -wire sprite_sel = ~(&sprite_sum[7:4]); +//Control signal for object enable output +wire obj_ctl = ~(&obj_sum[7:4]); -//Sprite flip control -reg hflip, vflip; -always_ff @(posedge H4) begin - hflip <= OB[6]; - vflip <= OB[7]; +//Sprite control +wire sprite_ctrl = ~(~LD & ~H4 & ~H8) /* synthesis keep */; +reg ob6_lat, ob7_lat; +always_ff @(posedge clk) begin + if (clk_en & ~sprite_ctrl) begin + ob6_lat <= OB[6]; + ob7_lat <= OB[7]; + end end -//Latch sprite information -reg [6:0] sprite; -always_ff @(negedge H4) begin - sprite <= {sprite_sel, hflip, vflip, sprite_sum[3:0]}; +//Latch object information +reg [6:0] obj; +always_ff @(posedge clk) begin + if (clk_en & ~objdata) + obj <= {obj_ctl, ob6_lat, ob7_lat, obj_sum[3:0]}; end -wire sprite_vflip = sprite[4]; -assign OFLP = sprite[5]; -assign OCS = sprite[6]; +wire obj_dat = obj[4]; +assign NE83 = obj[5]; +assign OCS = obj[6]; -//Assign OCOL (sprite color) and ODAT (sprite data) outputs -assign OCOL = ({H8, H4, LD} != 3'b100); -assign ODAT = ({H8, H4, LD} != 3'b010); +//Assign OCOL and ODAT outputs +assign OCOL = ~(~LD & ~H4 & H8); +wire objdata = ~(~LD & H4 & ~H8) /* synthesis keep */; +assign ODAT = objdata; //XOR final output for R -assign R[5] = (sprite[3] ^ sprite_vflip); -assign R[4] = (OFLP ^ H8); -assign R[3] = (OFLP ^ ~H4); -assign R[2] = (sprite[2] ^ sprite_vflip); -assign R[1] = (sprite[1] ^ sprite_vflip); -assign R[0] = (sprite[0] ^ sprite_vflip); +assign R[5] = (obj[3] ^ obj_dat); +assign R[4] = (NE83 ^ H8); +assign R[3] = (NE83 ^ ~H4); +assign R[2] = (obj[2] ^ obj_dat); +assign R[1] = (obj[1] ^ obj_dat); +assign R[0] = (obj[0] ^ obj_dat); endmodule +