mirror of
https://github.com/MiSTer-devel/PCFX_MiSTer.git
synced 2026-04-19 03:04:49 +00:00
580 lines
12 KiB
Systemverilog
580 lines
12 KiB
Systemverilog
// Computer assembly
|
|
//
|
|
// Copyright (c) 2025-2026 David Hunter
|
|
//
|
|
// This program is GPL licensed. See COPYING for the full license.
|
|
|
|
/* verilator lint_off PINMISSING */
|
|
|
|
import core_pkg::*;
|
|
|
|
module mach
|
|
(
|
|
input CLK,
|
|
input CE,
|
|
input RESn,
|
|
|
|
output CPU_BCYSTn,
|
|
|
|
output [19:0] ROM_A,
|
|
input [15:0] ROM_DO,
|
|
output ROM_CEn,
|
|
input ROM_READYn,
|
|
|
|
output [20:0] RAM_A,
|
|
output [31:0] RAM_DI,
|
|
input [31:0] RAM_DO,
|
|
output RAM_CEn,
|
|
output RAM_WEn,
|
|
output [3:0] RAM_BEn,
|
|
input RAM_READYn,
|
|
|
|
output [14:0] SRAM_A,
|
|
output [7:0] SRAM_DI,
|
|
input [7:0] SRAM_DO,
|
|
output SRAM_CEn,
|
|
output SRAM_WEn,
|
|
input SRAM_READYn,
|
|
|
|
output [26:1] MCP_A,
|
|
output [7:0] MCP_DI,
|
|
input [7:0] MCP_DO,
|
|
output MCP_CSn,
|
|
output MCP_RDn,
|
|
output MCP_WRn,
|
|
input MCP_READYn,
|
|
|
|
input hmi_t HMI,
|
|
|
|
output [31:0] A,
|
|
output reg ERROR,
|
|
|
|
output VID_PCE,
|
|
output [7:0] VID_Y,
|
|
output [7:0] VID_U,
|
|
output [7:0] VID_V,
|
|
output VID_VSn,
|
|
output VID_HSn,
|
|
output VID_VBL,
|
|
output VID_HBL
|
|
);
|
|
|
|
wire [31:0] cpu_a;
|
|
logic [31:0] cpu_d_i;
|
|
wire [31:0] cpu_d_o;
|
|
wire [3:0] cpu_ben;
|
|
wire [1:0] cpu_st;
|
|
wire cpu_dan;
|
|
wire cpu_mrqn;
|
|
wire cpu_rw;
|
|
wire cpu_bcystn;
|
|
wire cpu_readyn;
|
|
wire cpu_szrqn;
|
|
logic cpu_int;
|
|
logic [3:0] cpu_intvn;
|
|
logic cpu_nmin;
|
|
|
|
logic rom_cen;
|
|
logic [15:0] rom_do;
|
|
logic rom_readyn;
|
|
|
|
logic ram_cen;
|
|
wire [31:0] ram_do;
|
|
logic ram_readyn;
|
|
|
|
logic sram_cen;
|
|
wire [7:0] sram_do;
|
|
logic sram_readyn;
|
|
|
|
logic mcp_csn;
|
|
wire [7:0] mcp_do;
|
|
logic mcp_readyn;
|
|
|
|
logic a1_16;
|
|
logic [31:0] mem16_a;
|
|
|
|
logic io_cen;
|
|
logic [15:0] io_do;
|
|
wire [3:0] io_int;
|
|
|
|
logic unk_cen;
|
|
|
|
logic vce_csn;
|
|
logic [15:0] vce_do;
|
|
|
|
logic vdc0_csn;
|
|
logic vdc0_busyn;
|
|
logic vdc0_irqn;
|
|
logic [15:0] vdc0_do;
|
|
logic [8:0] vdc0_vd;
|
|
|
|
wire [15:0] vram0_a;
|
|
wire [15:0] vram0_di, vram0_do;
|
|
wire vram0_we;
|
|
|
|
logic vdc1_csn;
|
|
logic vdc1_busyn;
|
|
logic vdc1_irqn;
|
|
logic [15:0] vdc1_do;
|
|
logic [8:0] vdc1_vd;
|
|
|
|
wire [15:0] vram1_a;
|
|
wire [15:0] vram1_di, vram1_do;
|
|
wire vram1_we;
|
|
|
|
logic ga_wrn, ga_rdn;
|
|
logic ga_csn;
|
|
logic [15:0] ga_do;
|
|
logic vdc_cpu_ce;
|
|
|
|
logic dck70, dck70_negedge;
|
|
logic hs_posedge, hs_negedge;
|
|
logic vs_posedge, vs_negedge;
|
|
|
|
wire mmc_csn;
|
|
logic mmc_busyn;
|
|
wire mmc_irqn;
|
|
wire [15:0] mmc_do;
|
|
wire [7:0] mmc_scsi_do;
|
|
wire mmc_scsi_doe;
|
|
|
|
logic [7:0] scsi_data;
|
|
wire scsi_atnn, scsi_bsyn, scsi_ackn, scsi_rstn, scsi_msgn,
|
|
scsi_seln, scsi_cdn, scsi_reqn, scsi_ion;
|
|
|
|
wire [7:0] scsi_cd_do;
|
|
logic [7:0] scsi_cd_status;
|
|
logic scsi_cd_stat_get;
|
|
logic [95:0] scsi_cd_command;
|
|
wire scsi_cd_comm_send;
|
|
logic [7:0] scsi_cd_cd_data;
|
|
logic scsi_cd_cd_wr;
|
|
logic scsi_cd_cd_data_end;
|
|
|
|
wire [1:0] kp_latch;
|
|
wire [1:0] kp_clk;
|
|
wire [1:0] kp_rw;
|
|
wire [1:0] kp_din;
|
|
wire [1:0] kp_dout;
|
|
|
|
v810 cpu
|
|
(
|
|
.RESn(RESn),
|
|
.CLK(CLK),
|
|
.CE(CE),
|
|
|
|
.A(cpu_a),
|
|
.D_I(cpu_d_i),
|
|
.D_O(cpu_d_o),
|
|
.BEn(cpu_ben),
|
|
.ST(cpu_st),
|
|
.DAn(cpu_dan),
|
|
.MRQn(cpu_mrqn),
|
|
.RW(cpu_rw),
|
|
.BCYSTn(cpu_bcystn),
|
|
.READYn(cpu_readyn),
|
|
.SZRQn(cpu_szrqn),
|
|
|
|
.INT(cpu_int),
|
|
.INTVn(cpu_intvn),
|
|
.NMIn(cpu_nmin)
|
|
);
|
|
|
|
assign io_int[0] = '0; //huc6273_int;
|
|
assign io_int[1] = ~vdc1_irqn;
|
|
assign io_int[2] = ~mmc_irqn;
|
|
assign io_int[3] = ~vdc0_irqn;
|
|
|
|
fx_ga ga
|
|
(
|
|
.RESn(RESn),
|
|
.CLK(CLK),
|
|
.CE(CE),
|
|
|
|
.A(cpu_a),
|
|
.DI(cpu_d_o[15:0]),
|
|
.DO(ga_do),
|
|
.BEn(cpu_ben),
|
|
.ST(cpu_st),
|
|
.DAn(cpu_dan),
|
|
.MRQn(cpu_mrqn),
|
|
.RW(cpu_rw),
|
|
.BCYSTn(cpu_bcystn),
|
|
.READYn(cpu_readyn),
|
|
.SZRQn(cpu_szrqn),
|
|
|
|
.A1_16(a1_16),
|
|
.ROM_CEn(rom_cen),
|
|
.RAM_CEn(ram_cen),
|
|
.SRAM_CEn(sram_cen),
|
|
.MCP_CSn(mcp_csn),
|
|
.IO_CEn(io_cen),
|
|
|
|
.FX_GA_CSn(ga_csn),
|
|
.PSG_CSn(),
|
|
.VPU_CSn(),
|
|
.VCE_CSn(vce_csn),
|
|
.VDC0_CSn(vdc0_csn),
|
|
.VDC1_CSn(vdc1_csn),
|
|
.MMC_CSn(mmc_csn),
|
|
|
|
.ROM_READYn(rom_readyn),
|
|
.RAM_READYn(ram_readyn),
|
|
.SRAM_READYn(sram_readyn),
|
|
.MCP_READYn(mcp_readyn),
|
|
|
|
.WRn(ga_wrn),
|
|
.RDn(ga_rdn),
|
|
.VDC_CPU_CE(vdc_cpu_ce),
|
|
.VDC0_BUSYn(vdc0_busyn),
|
|
.VDC1_BUSYn(vdc1_busyn),
|
|
.MMC_BUSYn(mmc_busyn),
|
|
|
|
.DINT(io_int),
|
|
|
|
.CINT(cpu_int),
|
|
.CINTVn(cpu_intvn),
|
|
.CNMIn(cpu_nmin),
|
|
|
|
.KP_LATCH(kp_latch),
|
|
.KP_CLK(kp_clk),
|
|
.KP_RW(kp_rw),
|
|
.KP_DIN(kp_din),
|
|
.KP_DOUT(kp_dout)
|
|
);
|
|
|
|
huc6261 vce
|
|
(
|
|
.RESn(RESn),
|
|
.CLK(CLK),
|
|
.CE(CE), // TODO: Divide .CE by 5 for 5MHz pixel clock
|
|
|
|
.CSn(vce_csn),
|
|
.WRn(ga_wrn),
|
|
.RDn(ga_rdn),
|
|
.A2(mem16_a[2]),
|
|
.DI(cpu_d_o[15:0]),
|
|
.DO(vce_do),
|
|
|
|
.DCK70(dck70),
|
|
.DCK70_NEGEDGE(dck70_negedge),
|
|
.HSYNC_POSEDGE(hs_posedge),
|
|
.HSYNC_NEGEDGE(hs_negedge),
|
|
.VSYNC_POSEDGE(vs_posedge),
|
|
.VSYNC_NEGEDGE(vs_negedge),
|
|
|
|
.VDC0_VD(vdc0_vd),
|
|
.VDC1_VD(vdc1_vd),
|
|
|
|
.Y(VID_Y),
|
|
.U(VID_U),
|
|
.V(VID_V),
|
|
.VSn(VID_VSn),
|
|
.HSn(VID_HSn),
|
|
.VBL(VID_VBL),
|
|
.HBL(VID_HBL)
|
|
);
|
|
|
|
huc6270 vdc0
|
|
(
|
|
.CLK(CLK),
|
|
.RST_N(RESn),
|
|
.CLR_MEM('0),
|
|
.CPU_CE(vdc_cpu_ce),
|
|
|
|
.BYTEWORD('0),
|
|
.A({mem16_a[2], 1'b0}),
|
|
.DI(cpu_d_o[15:0]),
|
|
.DO(vdc0_do),
|
|
.CS_N(vdc0_csn),
|
|
.WR_N(ga_wrn),
|
|
.RD_N(ga_rdn),
|
|
.BUSY_N(vdc0_busyn),
|
|
.IRQ_N(vdc0_irqn),
|
|
|
|
.DCK_CE(dck70),
|
|
.DCK_CE_F(dck70_negedge),
|
|
.HSYNC_F(hs_negedge),
|
|
.HSYNC_R(hs_posedge),
|
|
.VSYNC_F(vs_negedge),
|
|
.VSYNC_R(vs_posedge),
|
|
.VD(vdc0_vd),
|
|
.BORDER(),
|
|
.GRID(),
|
|
.SP64('0),
|
|
|
|
.RAM_A(vram0_a),
|
|
.RAM_DI(vram0_di),
|
|
.RAM_DO(vram0_do),
|
|
.RAM_WE(vram0_we),
|
|
|
|
.BG_EN('1),
|
|
.SPR_EN('1)
|
|
);
|
|
|
|
dpram #(.addr_width(16), .data_width(16), .disable_value(0)) vram0
|
|
(
|
|
.clock(CLK),
|
|
.address_a(vram0_a),
|
|
.data_a(vram0_do),
|
|
.enable_a('1),
|
|
.wren_a(vram0_we),
|
|
.q_a(vram0_di),
|
|
.cs_a('1),
|
|
.address_b('0),
|
|
.data_b('0),
|
|
.enable_b('1),
|
|
.wren_b('0),
|
|
.q_b(),
|
|
.cs_b('1)
|
|
);
|
|
|
|
huc6270 vdc1
|
|
(
|
|
.CLK(CLK),
|
|
.RST_N(RESn),
|
|
.CLR_MEM('0),
|
|
.CPU_CE(vdc_cpu_ce),
|
|
|
|
.BYTEWORD('0),
|
|
.A({mem16_a[2], 1'b0}),
|
|
.DI(cpu_d_o[15:0]),
|
|
.DO(vdc1_do),
|
|
.CS_N(vdc1_csn),
|
|
.WR_N(ga_wrn),
|
|
.RD_N(ga_rdn),
|
|
.BUSY_N(vdc1_busyn),
|
|
.IRQ_N(vdc1_irqn),
|
|
|
|
.DCK_CE(dck70),
|
|
.DCK_CE_F(dck70_negedge),
|
|
.HSYNC_F(hs_negedge),
|
|
.HSYNC_R(hs_posedge),
|
|
.VSYNC_F(vs_negedge),
|
|
.VSYNC_R(vs_posedge),
|
|
.VD(vdc1_vd),
|
|
.BORDER(),
|
|
.GRID(),
|
|
.SP64('0),
|
|
|
|
.RAM_A(vram1_a),
|
|
.RAM_DI(vram1_di),
|
|
.RAM_DO(vram1_do),
|
|
.RAM_WE(vram1_we),
|
|
|
|
.BG_EN('1),
|
|
.SPR_EN('1)
|
|
);
|
|
|
|
dpram #(.addr_width(16), .data_width(16), .disable_value(0)) vram1
|
|
(
|
|
.clock(CLK),
|
|
.address_a(vram1_a),
|
|
.data_a(vram1_do),
|
|
.enable_a('1),
|
|
.wren_a(vram1_we),
|
|
.q_a(vram1_di),
|
|
.cs_a('1),
|
|
.address_b('0),
|
|
.data_b('0),
|
|
.enable_b('1),
|
|
.wren_b('0),
|
|
.q_b(),
|
|
.cs_b('1)
|
|
);
|
|
|
|
huc6272 mmc
|
|
(
|
|
.CLK(CLK),
|
|
.RESn(RESn),
|
|
.CE(CE),
|
|
|
|
.A(mem16_a[2:1]),
|
|
.DI(cpu_d_o[15:0]),
|
|
.DO(mmc_do),
|
|
.CSn(mmc_csn),
|
|
.WRn(ga_wrn),
|
|
.RDn(ga_rdn),
|
|
.BUSYn(mmc_busyn),
|
|
.IRQn(mmc_irqn),
|
|
|
|
.SCSI_DI(scsi_data),
|
|
.SCSI_DO(mmc_scsi_do),
|
|
.SCSI_DOE(mmc_scsi_doe),
|
|
.SCSI_ATNn(scsi_atnn),
|
|
.SCSI_BSYn(scsi_bsyn),
|
|
.SCSI_ACKn(scsi_ackn),
|
|
.SCSI_RSTn(scsi_rstn),
|
|
.SCSI_MSGn(scsi_msgn),
|
|
.SCSI_SELn(scsi_seln),
|
|
.SCSI_CDn(scsi_cdn),
|
|
.SCSI_REQn(scsi_reqn),
|
|
.SCSI_IOn(scsi_ion)
|
|
);
|
|
|
|
// SCSI <-> CD bridge
|
|
scsi scsi_cd
|
|
(
|
|
.RESET_N(RESn),
|
|
.CLK(CLK),
|
|
.DBI(scsi_data),
|
|
.DBO(scsi_cd_do),
|
|
.SEL_N(scsi_seln),
|
|
.ACK_N(scsi_ackn),
|
|
.RST_N(scsi_rstn),
|
|
.BSY_N(scsi_bsyn),
|
|
.REQ_N(scsi_reqn),
|
|
.MSG_N(scsi_msgn),
|
|
.CD_N(scsi_cdn),
|
|
.IO_N(scsi_ion),
|
|
.STATUS(scsi_cd_status),
|
|
.MESSAGE('0),
|
|
.STAT_GET(scsi_cd_stat_get),
|
|
.COMMAND(scsi_cd_command),
|
|
.COMM_SEND(scsi_cd_comm_send),
|
|
.DOUT_REQ('0),
|
|
.DOUT(),
|
|
.DOUT_SEND(),
|
|
.CD_DATA(scsi_cd_cd_data),
|
|
.CD_WR(scsi_cd_cd_wr),
|
|
.CD_DATA_END(scsi_cd_cd_data_end),
|
|
.STOP_CD_SND(),
|
|
.DBG_DATAIN_CNT()
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// CPU memory / I/O bus
|
|
|
|
always @* begin
|
|
if (~rom_cen)
|
|
cpu_d_i = {16'b0, rom_do};
|
|
else if (~ram_cen)
|
|
cpu_d_i = ram_do;
|
|
else if (~sram_cen)
|
|
cpu_d_i = {24'b0, sram_do};
|
|
else if (~mcp_csn)
|
|
cpu_d_i = {24'b0, mcp_do};
|
|
else if (~io_cen)
|
|
cpu_d_i = {16'b0, io_do};
|
|
else
|
|
cpu_d_i = '0;
|
|
end
|
|
|
|
always @* begin
|
|
if (~vce_csn)
|
|
io_do = vce_do;
|
|
else if (~vdc0_csn)
|
|
io_do = vdc0_do;
|
|
else if (~vdc1_csn)
|
|
io_do = vdc1_do;
|
|
else if (~ga_csn)
|
|
io_do = ga_do;
|
|
else if (~mmc_csn)
|
|
io_do = mmc_do;
|
|
else
|
|
io_do = '0;
|
|
end
|
|
|
|
assign rom_do = ROM_DO;
|
|
assign rom_readyn = rom_cen | ROM_READYn;
|
|
|
|
assign ram_do = RAM_DO;
|
|
assign ram_readyn = ram_cen | RAM_READYn;
|
|
|
|
assign sram_do = SRAM_DO;
|
|
assign sram_readyn = sram_cen | SRAM_READYn;
|
|
|
|
assign mcp_do = MCP_DO;
|
|
assign mcp_readyn = mcp_csn | MCP_READYn;
|
|
|
|
assign mem16_a = {cpu_a[31:2], a1_16, 1'b0};
|
|
|
|
assign CPU_BCYSTn = cpu_bcystn;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Core memory interface
|
|
|
|
assign ROM_CEn = rom_cen;
|
|
assign ROM_A = mem16_a[19:0];
|
|
|
|
assign RAM_CEn = ram_cen;
|
|
assign RAM_A = cpu_a[20:0];
|
|
assign RAM_DI = cpu_d_o;
|
|
assign RAM_WEn = ram_cen | cpu_rw;
|
|
assign RAM_BEn = cpu_ben;
|
|
|
|
assign SRAM_CEn = sram_cen;
|
|
assign SRAM_A = mem16_a[15:1];
|
|
assign SRAM_DI = cpu_d_o[7:0];
|
|
assign SRAM_WEn = sram_cen | cpu_rw;
|
|
|
|
assign MCP_CSn = mcp_csn;
|
|
assign MCP_A = mem16_a[26:1];
|
|
assign MCP_DI = cpu_d_o[7:0];
|
|
assign MCP_RDn = mcp_csn | ~cpu_rw;
|
|
assign MCP_WRn = mcp_csn | cpu_rw;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// SCSI interface
|
|
|
|
assign scsi_data = mmc_scsi_doe ? mmc_scsi_do : scsi_cd_do;
|
|
|
|
fake_cd fake_cd
|
|
(
|
|
.CLK(CLK),
|
|
.RESn(RESn),
|
|
|
|
.STAT_GET(scsi_cd_stat_get),
|
|
.COMMAND(scsi_cd_command),
|
|
.COMM_SEND(scsi_cd_comm_send),
|
|
.STATUS(scsi_cd_status),
|
|
.CD_DATA(scsi_cd_cd_data),
|
|
.CD_WR(scsi_cd_cd_wr)
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// K-port interface
|
|
|
|
hmi2kp hmi2kp
|
|
(
|
|
.CLK(CLK),
|
|
.RESn(RESn),
|
|
|
|
.HMI(HMI),
|
|
|
|
.KP_LATCH(kp_latch),
|
|
.KP_CLK(kp_clk),
|
|
.KP_RW(kp_rw),
|
|
.KP_DIN(kp_din),
|
|
.KP_DOUT(kp_dout)
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
assign A = cpu_a;
|
|
assign VID_PCE = dck70;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
always @(posedge CLK) if (0 && CE) begin
|
|
if (~io_cen & ~cpu_dan)
|
|
$display("%t: %x %s %x", $realtime,A, (cpu_rw ? "R" : "w"),
|
|
(cpu_rw ? cpu_d_i[15:0] : cpu_d_o[15:0]));
|
|
end
|
|
|
|
always @(posedge CLK) if (1 && CE) begin
|
|
if (~RESn) begin
|
|
ERROR <= '0;
|
|
end
|
|
else begin
|
|
if (~cpu_bcystn & ~cpu_mrqn &
|
|
((cpu_a == 32'hFFFFFF90) | (cpu_a == 32'hFFFFFFD0)))
|
|
ERROR <= '1;
|
|
end
|
|
end
|
|
|
|
always @(posedge ERROR)
|
|
$finish(1);
|
|
|
|
endmodule
|