mirror of
https://github.com/MiSTer-devel/PCFX_MiSTer.git
synced 2026-05-31 03:04:28 +00:00
Add 4 I/O wait states; fix HuC6270 BUSY_N and CPU_CE use
HuC6270 signals are now more closely aligned with how huc6280.vhd uses them. This fixes a freeze on entering the backup memory screen.
This commit is contained in:
54
rtl/fx_ga.sv
54
rtl/fx_ga.sv
@@ -47,6 +47,7 @@ module fx_ga
|
||||
// Device control
|
||||
output WRn,
|
||||
output RDn,
|
||||
output VDC_CPU_CE,
|
||||
input VDC0_BUSYn,
|
||||
input VDC1_BUSYn,
|
||||
input MMC_BUSYn,
|
||||
@@ -77,7 +78,7 @@ assign READYn = unk_cen & ROM_READYn & RAM_READYn & io_readyn;
|
||||
assign SZRQn = ~unk_cen | (ROM_CEn & IO_CEn);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Address decoder / device control
|
||||
// Address decoder
|
||||
|
||||
// Assert A[1] for upper-halfword or -byte access to 16-bit memory /
|
||||
// IO, i.e., if one or both of BEn[3:2] are asserted.
|
||||
@@ -101,16 +102,63 @@ assign VDC0_CSn = ~(~IO_CEn & (A[27:8] == 20'h00004)); // HuC6270 #0
|
||||
assign VDC1_CSn = ~(~IO_CEn & (A[27:8] == 20'h00005)); // HuC6270 #1
|
||||
assign MMC_CSn = ~(~IO_CEn & (A[27:8] == 20'h00006)); // HuC6272
|
||||
|
||||
assign WRn = IO_CEn | DAn | RW;
|
||||
assign RDn = IO_CEn | DAn | ~RW;
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// I/O device control
|
||||
|
||||
logic io_wait;
|
||||
logic [2:0] io_wait_cnt;
|
||||
logic vdc_busy_end;
|
||||
|
||||
assign WRn = IO_CEn | vdc_busy_end | DAn | RW;
|
||||
assign RDn = IO_CEn | vdc_busy_end | DAn | ~RW;
|
||||
|
||||
// FXGABOAD says: "Write access to normal I/O requires six cycles," or
|
||||
// 4 wait states. Assume that read access does, too.
|
||||
//
|
||||
// TODO: Implement Huc* write buffer.
|
||||
|
||||
always @(posedge CLK) if (CE) begin
|
||||
if (~RESn) begin
|
||||
io_wait_cnt <= '0;
|
||||
end
|
||||
else begin
|
||||
if (io_wait) // I/O cycle in progress
|
||||
io_wait_cnt <= io_wait_cnt - 1'd1;
|
||||
else if (~IO_CEn & ~BCYSTn) // New I/O cycle start
|
||||
io_wait_cnt <= 3'd4;
|
||||
end
|
||||
end
|
||||
|
||||
assign io_wait = |io_wait_cnt;
|
||||
|
||||
always @* begin
|
||||
if (~VDC0_CSn) io_readyn = ~VDC0_BUSYn;
|
||||
else if (~VDC1_CSn) io_readyn = ~VDC1_BUSYn;
|
||||
else if (~MMC_CSn) io_readyn = ~MMC_BUSYn;
|
||||
else io_readyn = IO_CEn;
|
||||
|
||||
io_readyn |= io_wait;
|
||||
end
|
||||
|
||||
// huc6270.vhd inputs a signal that never existed in actual hardware:
|
||||
// the internal clock enable of the CPU. It uses this to determine
|
||||
// when the I/O bus cycle completes. (Actual HW would instead use the
|
||||
// de-assertion of RDn / WRn for this purpose.)
|
||||
assign VDC_CPU_CE = CE & ~io_readyn;
|
||||
|
||||
// huc6270.vhd assumes that, when it de-asserts BUSYn, RDn / WRn will
|
||||
// de-assert in the next clock cycle, regardless of CE. But, CPU will
|
||||
// only act on BUSYn and then change RDn / WRn on CE. This workaround
|
||||
// de-asserts RDn / WRn early, then resets when DAn de-asserts (CPU
|
||||
// ends bus cycle).
|
||||
wire vdc_busy = ~io_wait & (~VDC0_BUSYn | ~VDC1_BUSYn);
|
||||
logic vdc_busy_d;
|
||||
always @(posedge CLK) begin
|
||||
vdc_busy_d <= vdc_busy;
|
||||
vdc_busy_end <= (vdc_busy_end | (vdc_busy_d & ~vdc_busy)) & ~(~RESn | DAn);
|
||||
end
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Register interface
|
||||
|
||||
|
||||
14
rtl/mach.sv
14
rtl/mach.sv
@@ -112,6 +112,7 @@ wire vram1_we;
|
||||
logic ga_wrn, ga_rdn;
|
||||
logic ga_csn;
|
||||
logic [15:0] ga_do;
|
||||
logic vdc_cpu_ce;
|
||||
|
||||
logic pce, pce_negedge;
|
||||
logic hs_posedge, hs_negedge;
|
||||
@@ -208,6 +209,7 @@ fx_ga ga
|
||||
|
||||
.WRn(ga_wrn),
|
||||
.RDn(ga_rdn),
|
||||
.VDC_CPU_CE(vdc_cpu_ce),
|
||||
.VDC0_BUSYn(vdc0_busyn),
|
||||
.VDC1_BUSYn(vdc1_busyn),
|
||||
.MMC_BUSYn(mmc_busyn),
|
||||
@@ -262,7 +264,7 @@ huc6270 vdc0
|
||||
.CLK(CLK),
|
||||
.RST_N(RESn),
|
||||
.CLR_MEM('0),
|
||||
.CPU_CE(CE),
|
||||
.CPU_CE(vdc_cpu_ce),
|
||||
|
||||
.BYTEWORD('0),
|
||||
.A({mem16_a[2], 1'b0}),
|
||||
@@ -316,7 +318,7 @@ huc6270 vdc1
|
||||
.CLK(CLK),
|
||||
.RST_N(RESn),
|
||||
.CLR_MEM('0),
|
||||
.CPU_CE(CE),
|
||||
.CPU_CE(vdc_cpu_ce),
|
||||
|
||||
.BYTEWORD('0),
|
||||
.A({mem16_a[2], 1'b0}),
|
||||
@@ -527,12 +529,18 @@ assign VID_PCE = pce;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
always @(posedge CLK) if (1 && CE) begin
|
||||
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 (~cpu_bcystn & ~cpu_mrqn &
|
||||
((cpu_a == 32'hFFFFFF90) | (cpu_a == 32'hFFFFFFD0)))
|
||||
$finish(1);
|
||||
end
|
||||
|
||||
always @(sram_cen)
|
||||
$display("!! %t: sram_cen=%x", $realtime, sram_cen);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ initial begin
|
||||
$dumpvars();
|
||||
`else
|
||||
$dumpfile("pcfx_top_tb.verilator.fst");
|
||||
#(0e3) $dumpvars();
|
||||
#(4800e3) $dumpvars();
|
||||
`endif
|
||||
end
|
||||
|
||||
@@ -271,8 +271,8 @@ initial #0 begin
|
||||
end
|
||||
|
||||
initial begin
|
||||
#(418e3) ;
|
||||
//repeat (15) #(1000e3) ;
|
||||
repeat (5) #(1000e3) ;
|
||||
#(100e3) ;
|
||||
//$writememh("vram0.hex", pcfx_top.mach.vram0.mem);
|
||||
//$writememh("vram1.hex", pcfx_top.mach.vram1.mem);
|
||||
//$writememh("vce_cp.hex", pcfx_top.mach.vce.cpram.mem);
|
||||
@@ -285,18 +285,18 @@ initial if (1) begin
|
||||
|
||||
$display("Pressing JP1.Left...");
|
||||
hmi.jp1.l = '1;
|
||||
#(2600e3) hmi.jp1.l = '0;
|
||||
#(1300e3) hmi.jp1.l = '0;
|
||||
#(40e3);
|
||||
|
||||
$display("Pressing JP1.Up...");
|
||||
hmi.jp1.u = '1;
|
||||
#(40e3) hmi.jp1.u = '0;
|
||||
#(80e3);
|
||||
#(40e3);
|
||||
|
||||
$display("Pressing JP1.Run...");
|
||||
hmi.jp1.run = '1;
|
||||
#(40e3) hmi.jp1.run = '0;
|
||||
#(80e3);
|
||||
#(40e3);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI
|
||||
[*] Sun Jan 4 05:13:07 2026
|
||||
[*] Mon Jan 12 04:51:09 2026
|
||||
[*]
|
||||
[dumpfile] "/Users/dhunter/src/mister/PCFX_MiSTer/rtl/tb/pcfx_top_tb.verilator.fst"
|
||||
[dumpfile_mtime] "Sun Jan 4 05:08:23 2026"
|
||||
[dumpfile_size] 26093463
|
||||
[dumpfile_mtime] "Mon Jan 12 01:43:43 2026"
|
||||
[dumpfile_size] 27041171
|
||||
[savefile] "/Users/dhunter/src/mister/PCFX_MiSTer/rtl/tb/pcfx_top_tb.verilator.gtkw"
|
||||
[timestart] 0
|
||||
[timestart] 4825000000
|
||||
[size] 1334 601
|
||||
[pos] -1 -1
|
||||
*-26.078840 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
*-27.020149 5046407940 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
[markername] AA
|
||||
[markername] BB
|
||||
[markername] CC
|
||||
@@ -51,14 +51,13 @@ pcfx_top_tb.pcfx_top.mach.cpu_d_i[31:0]
|
||||
pcfx_top_tb.pcfx_top.mach.cpu_d_o[31:0]
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.cpu_rw
|
||||
pcfx_top_tb.pcfx_top.mach.cpu_readyn
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.mem16_a[31:0]
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.ram_cen
|
||||
pcfx_top_tb.pcfx_top.mach.rom_cen
|
||||
@29
|
||||
pcfx_top_tb.pcfx_top.mach.sram_cen
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.io_cen
|
||||
pcfx_top_tb.pcfx_top.mach.ga_rdn
|
||||
pcfx_top_tb.pcfx_top.mach.ga_wrn
|
||||
@@ -69,18 +68,32 @@ pcfx_top_tb.pcfx_top.mach.cpu.INT
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.cpu.eu.pc[31:0]
|
||||
pcfx_top_tb.pcfx_top.mach.cpu.eu.idex_pc[31:0]
|
||||
pcfx_top_tb.pcfx_top.mach.cpu.eu.idex_ir[31:0]
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.cpu.SZRQn
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.cpu.eu.DA[31:0]
|
||||
@100000028
|
||||
pcfx_top_tb.pcfx_top.mach.cpu.mem.ebst[2:0]
|
||||
@200
|
||||
-ga
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.ga.MRQn
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.ga.isr[6:0]
|
||||
@c00022
|
||||
pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
@800200
|
||||
@28
|
||||
(0)pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
(1)pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
(2)pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
(3)pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
(4)pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
(5)pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
(6)pcfx_top_tb.pcfx_top.mach.ga.imr[6:0]
|
||||
@1401200
|
||||
-group_end
|
||||
@c00200
|
||||
-kpc0
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.ga.kpc0.KP_LATCH
|
||||
@@ -96,7 +109,7 @@ pcfx_top_tb.pcfx_top.mach.ga.kpc0.DO[15:0]
|
||||
pcfx_top_tb.pcfx_top.mach.ga.kpc0.ios
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.ga.kpc0.data_sr[31:0]
|
||||
@1000200
|
||||
@1401200
|
||||
-kpc0
|
||||
@200
|
||||
-mmc
|
||||
@@ -161,15 +174,31 @@ pcfx_top_tb.pcfx_top.mach.scsi_cd.CD_DATA_END
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.vdc0.IRQ_N
|
||||
pcfx_top_tb.pcfx_top.mach.vdc0.CS_N
|
||||
pcfx_top_tb.pcfx_top.mach.vdc0.BUSY_N
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.vdc0.AR[4:0]
|
||||
pcfx_top_tb.pcfx_top.mach.vdc0.VD[8:0]
|
||||
@200
|
||||
-vdc1
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.CPU_CE
|
||||
@29
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.CS_N
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.A[1:0]
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.BUSY_N
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.AR[4:0]
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.RD_N
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.WR_N
|
||||
@22
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.VD[8:0]
|
||||
@28
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.CPU_BUSY
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.CPURD_PEND
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.CPURD_PEND2
|
||||
pcfx_top_tb.pcfx_top.mach.vdc1.CPURD_EXEC
|
||||
@200
|
||||
-vce
|
||||
@28
|
||||
|
||||
2
rtl/v810
2
rtl/v810
Submodule rtl/v810 updated: d2f672d65b...06e987a704
Reference in New Issue
Block a user