diff --git a/rtl/fx_ga.sv b/rtl/fx_ga.sv index ec6d9d8..30396a8 100644 --- a/rtl/fx_ga.sv +++ b/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 diff --git a/rtl/mach.sv b/rtl/mach.sv index 9d46e73..0633677 100644 --- a/rtl/mach.sv +++ b/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); diff --git a/rtl/tb/pcfx_top_tb.sv b/rtl/tb/pcfx_top_tb.sv index b99c24e..ff5fe87 100644 --- a/rtl/tb/pcfx_top_tb.sv +++ b/rtl/tb/pcfx_top_tb.sv @@ -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 diff --git a/rtl/tb/pcfx_top_tb.verilator.gtkw b/rtl/tb/pcfx_top_tb.verilator.gtkw index 4143941..56cfb84 100644 --- a/rtl/tb/pcfx_top_tb.verilator.gtkw +++ b/rtl/tb/pcfx_top_tb.verilator.gtkw @@ -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 diff --git a/rtl/v810 b/rtl/v810 index d2f672d..06e987a 160000 --- a/rtl/v810 +++ b/rtl/v810 @@ -1 +1 @@ -Subproject commit d2f672d65baba3b840954e1d28459634d6cd0e00 +Subproject commit 06e987a7048d9a689f56405f0449ef5cf0e2bfcc