mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-02-05 07:44:46 +00:00
Gyruss: make it fully synchronous
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user