Files
Arcade-Athena_MiSTer/rtl/front/AthenaCore_Front_sync.sv

355 lines
9.9 KiB
Systemverilog

//AthenaCore_Front_sync.sv
//Author: @RndMnkIII
//Date: 27/05/2022
`default_nettype none
`timescale 1ns/1ps
module AthenaCore_Front_sync(
input wire VIDEO_RSTn,
input wire clk,
input wire CK1,
//Side SRAM address selector V/C
input wire V_C,
//B address
input wire FRONT_VIDEO_CSn,
input wire [10:0] VA,
input wire [7:0] VD_in,
output logic [7:0] VD_out,
//HACK settings
input wire [7:0] hack_settings,
//hps_io rom interface
input wire [24:0] ioctl_addr,
input wire [7:0] ioctl_data,
input wire ioctl_wr,
//A address
input wire VCKn,
//front SRAM control
input wire VRD,
input wire VDG,
input wire VOE,
input wire VWE,
//clocking
input wire [4:0] FH,
input wire [8:0] FV,
input wire LC,
input wire VLK,
input wire FCK,
input wire H3,
input wire LD,
input wire CK0,
//front data output
output logic [7:0] FD,
output logic [8:0] FL_Y
);
logic [7:0] D0_in, D1_in, D2_in, D3_in;
logic [7:0] Q0, Q1, Q2, Q3;
logic [7:0] D0_out, D1_out, D2_out, D3_out;
logic [7:0] Dreg0, Dreg1, Dreg2, Dreg3;
logic F1B3, F1B2, F1B1, F1B0;
ttl_74139_nodly b2_cpu_pcb(.Enable_bar(FRONT_VIDEO_CSn), .A_2D(VA[1:0]), .Y_2D({F1B3, F1B2, F1B1, F1B0}));
//bus multiplexers between video data common bus and front SRAM ICs.
logic F2_EN; //F10 LS32 UnitA
logic F3_EN; //F10 LS32 UnitB
logic F4_EN; //F10 LS32 UnitC
logic F5_EN; //F10 LS32 UnitD
assign F2_EN =~(F1B0 | VDG);
assign F3_EN =~(F1B1 | VDG);
assign F4_EN =~(F1B2 | VDG);
assign F5_EN =~(F1B3 | VDG);
assign D0_in = (F2_EN && VRD) ? VD_in : 8'hFF;
assign D1_in = (F3_EN && VRD) ? VD_in : 8'hFF;
assign D2_in = (F4_EN && VRD) ? VD_in : 8'hFF;
assign D3_in = (F5_EN && VRD) ? VD_in : 8'hFF;
// DIR=L B->A, DIR=H A->B
// A (VD) -> B(Dx)
logic [10:0] A;
logic B3CSn, B2CSn, B1CSn, B0CSn;
logic d2_dummy;
ttl_74157 #(.DELAY_RISE(0), .DELAY_FALL(0)) d5 (.Enable_bar(1'b0), .Select(V_C), .A_2D({F1B3,VCKn,F1B2,VCKn,F1B1,VCKn,F1B0,VCKn}), .Y({B3CSn, B2CSn, B1CSn, B0CSn}));
ttl_74157 #(.DELAY_RISE(0), .DELAY_FALL(0)) d2 (.Enable_bar(1'b0), .Select(V_C), .A_2D({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,VA[10],1'b0}), .Y({d2_dummy, A[10:8]}));
ttl_74157 #(.DELAY_RISE(0), .DELAY_FALL(0)) d3 (.Enable_bar(1'b0), .Select(V_C), .A_2D({VA[9],1'b0,VA[8],1'b0,VA[7],FH[4],VA[6],FH[3]}), .Y(A[7:4]));
ttl_74157 #(.DELAY_RISE(0), .DELAY_FALL(0)) d4 (.Enable_bar(1'b0), .Select(V_C), .A_2D({VA[5],FH[2],VA[4],FH[1],VA[3],FH[0],VA[2],H3}), .Y(A[3:0]));
//--- HM6116P-3 2Kx8 300ns SRAM x 4 ICs, only used 512bytes per IC ---
//TNKIII only uses VA[10:0] 2Kbytes FRONT RAM space
SRAM_dual_sync #(.ADDR_WIDTH(9)) h2_byte0
(
.ADDR0({VA[10:2]}),
.clk0(clk),
.cen0(~F1B0),
.we0(~VWE),
.DATA0(D0_in),
.Q0(Q0),
.ADDR1({3'b000,FH[4:0],H3}),
.clk1(clk),
.cen1(~VCKn),
.we1(1'b0),
.DATA1(8'hff),
.Q1(Dreg0)
);
SRAM_dual_sync #(.ADDR_WIDTH(9)) h3_byte1
(
.ADDR0({VA[10:2]}),
.clk0(clk),
.cen0(~F1B1),
.we0(~VWE),
.DATA0(D1_in),
.Q0(Q1),
.ADDR1({3'b000,FH[4:0],H3}),
.clk1(clk),
.cen1(~VCKn),
.we1(1'b0),
.DATA1(8'hff),
.Q1(Dreg1)
);
SRAM_dual_sync #(.ADDR_WIDTH(9)) h5_byte2
(
.ADDR0({VA[10:2]}),
.clk0(clk),
.cen0(~F1B2),
.we0(~VWE),
.DATA0(D2_in),
.Q0(Q2),
.ADDR1({3'b000,FH[4:0],H3}),
.clk1(clk),
.cen1(~VCKn),
.we1(1'b0),
.DATA1(8'hff),
.Q1(Dreg2)
);
SRAM_dual_sync #(.ADDR_WIDTH(9)) h6_byte3
(
.ADDR0({VA[10:2]}),
.clk0(clk),
.cen0(~F1B3),
.we0(~VWE),
.DATA0(D3_in),
.Q0(Q3),
.ADDR1({3'b000,FH[4:0],H3}),
.clk1(clk),
.cen1(~VCKn),
.we1(1'b0),
.DATA1(8'hff),
.Q1(Dreg3)
);
assign D0_out = (!VOE) ? Q0 : 8'hff;
assign D1_out = (!VOE) ? Q1 : 8'hff;
assign D2_out = (!VOE) ? Q2 : 8'hff;
assign D3_out = (!VOE) ? Q3 : 8'hff;
assign VD_out = ( (!VRD && F2_EN) ? D0_out : (
(!VRD && F3_EN) ? D1_out : (
(!VRD && F4_EN) ? D2_out : (
(!VRD && F5_EN) ? D3_out : 8'hff
))));
logic [7:0] G2_Q;
//Sprite X offset
ttl_74273_sync g2(.RESETn(VIDEO_RSTn), .CLRn(1'b1), .Clk(clk), .Cen(VLK), .D(Dreg0), .Q(G2_Q));
logic [7:0] Tile_num;
//Sprite Tile Number
ttl_74273_sync g3(.RESETn(VIDEO_RSTn), .CLRn(1'b1), .Clk(clk), .Cen(VLK), .D((!VCKn ? Dreg1 : 8'hff)), .Q(Tile_num));
logic [7:0] Y_offset;
//Sprite Y offset
ttl_74273_sync g4(.RESETn(VIDEO_RSTn), .CLRn(1'b1), .Clk(clk), .Cen(VLK), .D(Dreg2), .Q(Y_offset));
logic [7:0] G5_Q;
//Sprite attributes
ttl_74273_sync g5(.RESETn(VIDEO_RSTn), .CLRn(1'b1), .Clk(clk), .Cen(VLK), .D((!VCKn ? Dreg3 : 8'hff)), .Q(G5_Q));
logic [3:0] Spr_color_bank;
logic X_offset_MSB;
logic Spr_bank; //Athena 1024 tiles
logic Spr_XFlip; //TNKIII
logic Y_offset_MSB;
//G5_Q[6]
//G5_Q[5]
//assign Spr_XFlip = G5_Q[5];
assign X_offset_MSB = ~G5_Q[4];
logic [7:0] X_offset;
genvar i;
generate
for(i=0; i<8; i++) begin : x_offset_gen
assign X_offset[i] = ~G2_Q[i];
end
endgenerate
//TNKIII SPECIFIC
ttl_74174_sync N7
(
.Reset_n(VIDEO_RSTn),
.Clk(clk),
.Cen(FCK),
.Clr_n(1'b1),
.D({G5_Q[7],G5_Q[6],G5_Q[3:0]}),
.Q({FL_Y[8],Spr_bank,Spr_color_bank})
);
ttl_74273_sync f6(.RESETn(VIDEO_RSTn), .CLRn(1'b1), .Clk(clk), .Cen(FCK), .D(Y_offset), .Q(FL_Y[7:0]));
logic [7:0] G7_Q;
ttl_74273_sync g7(.RESETn(VIDEO_RSTn), .CLRn(1'b1), .Clk(clk), .Cen(FCK), .D(Tile_num), .Q(G7_Q));
logic e7_D;
logic e5_cout;
logic [3:0] e5_sum;
assign e7_D = FV[8] ^ X_offset_MSB;
logic e7_C;
assign e7_C = e7_D ^ e5_cout;
logic e4_cout;
ttl_74283_nodly e5 (.A(FV[7:4]), .B(X_offset[7:4]), .C_in(e4_cout), .Sum(e5_sum), .C_out(e5_cout));
logic [3:0] e4_sum;
ttl_74283_nodly e4 (.A(FV[3:0]), .B(X_offset[3:0]), .C_in(1'b1), .Sum(e4_sum), .C_out(e4_cout));
logic e6_B;
assign e6_B = &e5_sum;
logic e8_C;
////////////Hack: insert one clock cycle delay to e7_C,e6_B
reg e7_Cr, e6_Br;
always @(posedge clk) begin
e7_Cr <= e7_C;
e6_Br <= e6_B;
end
assign e8_C = ~(e7_Cr & e6_Br);
logic [4:0] E8_Q;
//logic E8_dummy;
logic SPR_ROM_BANK_MSB;
ttl_74174_sync E8
(
.Reset_n(VIDEO_RSTn),
.Clk(clk),
.Cen(FCK),
.Clr_n(1'b1),
//insert in LSB BIT G5_Q[5] as ROM SPR_BANK MSB
//.D({e8_C,e4_flip,~G5_Q[5]}),
.D({e8_C,e4_sum,G5_Q[5]}), //Athena
.Q({E8_Q,SPR_ROM_BANK_MSB})
);
logic [1:0] M6_dum;
ttl_74174_sync M6
(
.Reset_n(VIDEO_RSTn),
.Clk(clk),
.Cen(LC),
.Clr_n(1'b1),
.D({2'b11,Spr_color_bank}),
.Q({M6_dum,FD[6:3]})
);
assign FD[7] = 1'b0;
//MBM27256-25 250ns 32Kx8x3 FRONT ROMS ---
wire P7_H7_cs = (ioctl_addr >= 25'h50_000) & (ioctl_addr < 25'h58_000);
wire P8_F7_cs = (ioctl_addr >= 25'h60_000) & (ioctl_addr < 25'h68_000);
wire P9_E7_cs = (ioctl_addr >= 25'h70_000) & (ioctl_addr < 25'h78_000);
logic [7:0] H7_D, H7_Dout; //On PCB pulled to Vcc with 4.7Kx8 RA7
// logic HACK_FCK;
// assign HACK_FCK = (hack_settings[0]) ? ~FCK : FCK;
eprom_32K P7_H7
(
.ADDR({SPR_ROM_BANK_MSB,Spr_bank,G7_Q,E8_Q[3:0],FCK}), //HACK SETTTINGS
.CLK(clk),
.DATA(H7_Dout),
.ADDR_DL(ioctl_addr),
.CLK_DL(clk),
.DATA_IN(ioctl_data),
.CS_DL(P7_H7_cs),
.WR(ioctl_wr)
);
assign H7_D = (!E8_Q[4]) ? H7_Dout : 8'hFF;
logic [7:0] F7_D, F7_Dout; //On PCB pulled to Vcc with 4.7Kx8 RA6
eprom_32K P8_F7
(
.ADDR({SPR_ROM_BANK_MSB,Spr_bank,G7_Q,E8_Q[3:0],FCK}), //HACK SETTTINGS
.CLK(clk),
.DATA(F7_Dout),
.ADDR_DL(ioctl_addr),
.CLK_DL(clk),
.DATA_IN(ioctl_data),
.CS_DL(P8_F7_cs),
.WR(ioctl_wr)
);
assign F7_D = (!E8_Q[4]) ? F7_Dout : 8'hFF;
logic [7:0] E7_D,E7_Dout; //On PCB pulled to Vcc with 4.7Kx8 RA5
eprom_32K P9_E7
(
.ADDR({SPR_ROM_BANK_MSB,Spr_bank,G7_Q,E8_Q[3:0],FCK}), //HACK SETTTINGS
.CLK(clk),
.DATA(E7_Dout),
.ADDR_DL(ioctl_addr),
.CLK_DL(clk),
.DATA_IN(ioctl_data),
.CS_DL(P9_E7_cs),
.WR(ioctl_wr)
);
assign E7_D = (!E8_Q[4]) ? E7_Dout : 8'hFF;
// logic LD_reg;
// always @(posedge clk) begin
// LD_reg <= LD;
// end
PLSO_shift g10 (.RESETn(VIDEO_RSTn), .CLK(clk), .CEN(~CK0), .LOADn(LD), .SI(1'b1), .D(H7_D), .SO(FD[0]), .DIR(0)); //Hack CLK should be CK0, HACKED settings DIR
PLSO_shift g9 (.RESETn(VIDEO_RSTn), .CLK(clk), .CEN(~CK0), .LOADn(LD), .SI(1'b1), .D(F7_D), .SO(FD[1]), .DIR(0)); //Hack CLK should be CK0
PLSO_shift g8 (.RESETn(VIDEO_RSTn), .CLK(clk), .CEN(~CK0), .LOADn(LD), .SI(1'b1), .D(E7_D), .SO(FD[2]), .DIR(0)); //Hack CLK should be CK0
endmodule
module PLSO_shift (RESETn, CLK, CEN, LOADn, SI, D, SO, DIR);
input wire RESETn, CLK, CEN, SI, LOADn;
input wire [7:0] D;
output wire SO;
input wire DIR;
reg [7:0] tmp;
reg last_cen;
always @(posedge CLK)
begin
if (!RESETn) begin
tmp <= 0;
last_cen = 1'b1;
end
else begin
last_cen <= CEN;
if (CEN && !last_cen) begin
if (!LOADn) tmp <= D;
else if (DIR) tmp <= {SI, tmp[7:1]};
else tmp <= {tmp[6:0], SI};
end
end
end
assign SO = (DIR) ? tmp[0] : tmp[7];
endmodule