diff --git a/rtl/huc6272.sv b/rtl/huc6272.sv index f74f9c8..87eb64f 100644 --- a/rtl/huc6272.sv +++ b/rtl/huc6272.sv @@ -94,15 +94,16 @@ logic scsi_int_req_act; rf_bgm_t rf_bgm; -logic [3:0] mpa; -logic [8:0] mpd; -logic mpwr_pend, mpwr; -logic mpsw; +logic mpwr_pend; +logic [18:1] vid_ma_a; +logic [15:0] vid_ma_di, vid_ma_do; +logic [1:0] vid_ma_be; +logic vid_ma_wr, vid_ma_req, vid_ma_ack; logic [18:1] vid_mb_a; logic [15:0] vid_mb_di, vid_mb_do; logic [1:0] vid_mb_be; -logic vid_mb_wr, vid_mb_req, vidMb_ack; +logic vid_mb_wr, vid_mb_req, vid_mb_ack; ////////////////////////////////////////////////////////////////////// // CPU memory / I/O bus interface @@ -126,7 +127,6 @@ always @(posedge CLK) if (CE) begin scsi_dma_mode <= '0; rf_bgm <= '0; mpwr_pend <= '0; - mpwr <= '0; end else begin if (~CSn & ~WRn) begin @@ -169,13 +169,13 @@ always @(posedge CLK) if (CE) begin rf_bgm.rsw <= DI[12]; end 7'h13: begin - mpa <= DI[3:0]; + rf_bgm.mpwa <= DI[3:0]; end 7'h14: begin - mpd <= DI[8:0]; + rf_bgm.mpwd <= DI[8:0]; mpwr_pend <= '1; end - 7'h15: mpsw <= DI[0]; + 7'h15: rf_bgm.mpsw <= DI[0]; 7'h16: rf_bgm.sub_wrap <= DI[3:0]; 7'h20: rf_bgm.bgp[0].bat <= DI[7:0]; 7'h21: rf_bgm.bgp[0].cg <= DI[7:0]; @@ -227,11 +227,11 @@ always @(posedge CLK) if (CE) begin else begin if (mpwr_pend) begin mpwr_pend <= '0; - mpwr <= '1; + rf_bgm.mpwr <= '1; end - else if (mpwr) begin - mpwr <= '0; - mpa <= mpa + 1'd1; + else if (rf_bgm.mpwr) begin + rf_bgm.mpwr <= '0; + rf_bgm.mpwa <= rf_bgm.mpwa + 1'd1; end end end @@ -319,13 +319,13 @@ huc6272_dmc dmca .CE(CE), .RESn(RESn), - .A('0), - .DI(), - .DO('0), - .BE('0), - .WR('0), - .REQ('0), - .ACK(), + .A(vid_ma_a), + .DI(vid_ma_di), + .DO(vid_ma_do), + .BE(vid_ma_be), + .WR(vid_ma_wr), + .REQ(vid_ma_req), + .ACK(vid_ma_ack), .R_DI(RA_DI), .R_DO(RA_DO), @@ -372,13 +372,13 @@ huc6272_video video .rf_bgm(rf_bgm), - .MA_A(), - .MA_DI('0), - .MA_DO(), - .MA_BE(), - .MA_WR(), - .MA_REQ(), - .MA_ACK(), + .MA_A(vid_ma_a), + .MA_DI(vid_ma_di), + .MA_DO(vid_ma_do), + .MA_BE(vid_ma_be), + .MA_WR(vid_ma_wr), + .MA_REQ(vid_ma_req), + .MA_ACK(vid_ma_ack), .MB_A(vid_mb_a), .MB_DI(vid_mb_di), @@ -475,4 +475,5 @@ endmodule `include "huc6272_dmc.sv" `include "huc6272_video.sv" +`include "huc6272_fetch.sv" `include "huc6272_bgm.sv" diff --git a/rtl/huc6272_bgm.sv b/rtl/huc6272_bgm.sv index 37c2561..105466b 100644 --- a/rtl/huc6272_bgm.sv +++ b/rtl/huc6272_bgm.sv @@ -14,22 +14,35 @@ module huc6272_bgm // Register file input rf_bgm_t rf_bgm, + // Render control interface input DCK, + input FETCH, input RENDER, input [9:0] RENDER_BG_COL, - input MBA1, - input [15:0] MBD, - input MBACK, - + input MDSA, + input [1:0] MDLA, + input [15:0] MDA, + input MDSB, + input [1:0] MDLB, + input [15:0] MDB, + output [23:0] PD, output PDE ); +wire cgbank = rf_bgm.bgp[LAYER].cg[7]; wire format_clr_16m = ((rf_bgm.bgp[LAYER].format == BGF_INT_DOT_16M) | (rf_bgm.bgp[LAYER].format == BGF_EXT_BLK_16M) | (rf_bgm.bgp[LAYER].format == BGF_EXT_DOT_16M)); +logic mds; +logic [15:0] md; + +assign mds = cgbank ? MDSB : MDSA; +assign mdl = cgbank ? MDLB : MDLA; +assign md = cgbank ? MDB : MDA; + logic cgfce; logic [15:0] cgrd_in; logic [31:0] cgrd; @@ -40,7 +53,7 @@ logic cgpdeo; wire cgrce = DCK; always @(posedge CLK) - cgfce <= MBACK; + cgfce <= mds & (mdl == LAYER); always @(posedge CLK) begin if (~RESn) begin @@ -49,15 +62,18 @@ always @(posedge CLK) begin cgrd_in <= '0; end else if (cgfce) begin - cgra <= MBA1; - cgrd_in <= MBD; + cgra <= ~cgra; + cgrd_in <= md; if (format_clr_16m) begin - if (MBA1) - cgrd <= {cgrd_in, MBD}; + if (cgra) + cgrd <= {cgrd_in, md}; end else cgrd <= {16'b0, cgrd_in}; end + else if (~(FETCH | RENDER)) begin + cgra <= '0; + end end always @* begin diff --git a/rtl/huc6272_fetch.sv b/rtl/huc6272_fetch.sv new file mode 100644 index 0000000..a1c4dd2 --- /dev/null +++ b/rtl/huc6272_fetch.sv @@ -0,0 +1,110 @@ +// HuC6272 (KING) video fetch engine, one bank +// +// Copyright (c) 2026 David Hunter +// +// This program is GPL licensed. See COPYING for the full license. + +module huc6272_fetch + ( + input CLK, + input CE, + input RESn, + + // Register file + input rf_bgm_t rf_bgm, + + // Render control interface + input DCK, // pixel clock enable + input FETCH, + input [9:0] FETCH_BG_ROW, + input [9:0] FETCH_BG_COL, + + // Microprogram data store interface + input mpd_t MPRBUF, + + // Memory client interface + output [18:1] M_A, + input [15:0] M_DI, + output [15:0] M_DO, + output [1:0] M_BE, + output M_WR, + output M_REQ, + input M_ACK, + + // Fetched CG data + output MDS, + output [1:0] MDL, + output [15:0] MD + ); + +////////////////////////////////////////////////////////////////////// +// Microprogram engine + +mpd_t mpe_d; +logic [18:1] mpe_ra; +logic mpe_ren; +logic [1:0] mpe_layer; + +assign mpe_d = FETCH ? MPRBUF : 9'h100; + +function [18:1] mpe_addr(mpd_t mpd); +logic [7:0] base; +rf_bgp_t bgp; + bgp = get_bgp(mpd.layer); + mpe_addr = '0; + if (~mpd.nop) begin + mpe_addr[16:10] = mpd.bat ? bgp.bat[6:0] : bgp.cg[6:0]; // [7] is A/-B + if (mpd.bat) + ; // TODO + else // CG + mpe_addr += {FETCH_BG_ROW[7:0], FETCH_BG_COL[7:3], mpd.cgoff}; + end +endfunction + +always @(posedge CLK) begin + mpe_ren <= ~mpe_d.nop; + mpe_layer <= mpe_d.layer; + mpe_ra <= mpe_addr(mpe_d); +end + +////////////////////////////////////////////////////////////////////// +// Bank A/B memory client interface + +logic mtrg, mreq, mack; +logic [1:0] mdl; +logic [18:1] ma, ma_d; +logic [15:0] md; + +assign ma = mpe_ra; +assign mtrg = mpe_ren & FETCH & DCK; +assign mack = M_REQ & M_ACK; + +always @(posedge CLK) begin + if (~RESn) begin + ma_d <= '0; + mdl <= '0; + md <= '0; + mreq <= '0; + end + else begin + mreq <= M_REQ & ~M_ACK; + + if (mtrg) begin + ma_d <= ma; + mdl <= mpe_layer; + end + if (mack) + md <= M_DI; + end +end + +assign M_A = ma; +assign M_BE = '1; +assign M_WR = '0; +assign M_REQ = mreq | mtrg; + +assign MDS = mack; +assign MDL = mdl; +assign MD = md; + +endmodule diff --git a/rtl/huc6272_types.svh b/rtl/huc6272_types.svh index 6b6313b..a717c6a 100644 --- a/rtl/huc6272_types.svh +++ b/rtl/huc6272_types.svh @@ -29,9 +29,22 @@ typedef struct packed { } rf_bgp_t; typedef struct packed { + logic [3:0] mpwa; + logic [8:0] mpwd; + logic mpwr; + logic mpsw; rf_bgp_t [4] bgp; logic rsw; logic sub_wrap; logic [7:0] sub_bat0, sub_cg0; logic [3:0] size_sub_m0, size_sub_n0; } rf_bgm_t; + +typedef struct packed { + logic nop; + logic [1:0] layer; + logic rotate; + logic bat; // BAT / -CG + logic ext; // EXT / -INT + logic [2:0] cgoff; // CG offset +} mpd_t; diff --git a/rtl/huc6272_video.sv b/rtl/huc6272_video.sv index a592876..94c3df9 100644 --- a/rtl/huc6272_video.sv +++ b/rtl/huc6272_video.sv @@ -44,6 +44,16 @@ module huc6272_video logic [9:0] row, col; +function rf_bgp_t get_bgp(input [1:0] layer); + case (layer) + 2'd0: get_bgp = rf_bgm.bgp[0]; + 2'd1: get_bgp = rf_bgm.bgp[1]; + 2'd2: get_bgp = rf_bgm.bgp[2]; + 2'd3: get_bgp = rf_bgm.bgp[3]; + default: get_bgp = 'X; + endcase +endfunction + ////////////////////////////////////////////////////////////////////// // Video counter @@ -98,36 +108,83 @@ wire [9:0] render_bg_row = row - RENDER_ROW_START; wire [9:0] render_bg_col = col - RENDER_COL_START; ////////////////////////////////////////////////////////////////////// -// Bank A/B memory client interfaces +// Microprogram data store -logic mbtrg, mbreq, mback; -logic [18:1] mba, mba_d; -logic [15:0] mbd; +mpd_t mpd [2][8]; +mpd_t mprbufa, mprbufb; +logic [2:0] mpra; -assign mba = {fetch_bg_row[7:0], fetch_bg_col[7:0]}; -assign mbtrg = fetch & DCK; -assign mback = MB_REQ & MB_ACK; +assign mpra = fetch ? fetch_bg_col[2:0] : '0; always @(posedge CLK) begin - if (~RESn) begin - mba_d <= '0; - mbd <= '0; - mbreq <= '0; - end - else begin - mbreq <= MB_REQ & ~MB_ACK; - - if (mbtrg) - mba_d <= mba; - if (mback) - mbd <= MB_DI; - end + mprbufa <= mpd[0][mpra]; + mprbufb <= mpd[1][mpra]; + if (rf_bgm.mpwr) + mpd[rf_bgm.mpwa[3]][rf_bgm.mpwa[2:0]] <= rf_bgm.mpwd; end -assign MB_A = mba; -assign MB_BE = '1; -assign MB_WR = '0; -assign MB_REQ = mbreq | mbtrg; +////////////////////////////////////////////////////////////////////// +// Bank A/B microprogram engine and memory client interfaces + +logic mdsa, mdsb; +logic [1:0] mdla, mdlb; +logic [15:0] mda, mdb; + +huc6272_fetch vfea + ( + .CLK(CLK), + .CE(CE), + .RESn(RESn), + + .rf_bgm(rf_bgm), + + .DCK(DCK), + .FETCH(fetch), + .FETCH_BG_ROW(fetch_bg_row), + .FETCH_BG_COL(fetch_bg_col), + + .MPRBUF(mprbufa), + + .M_A(MA_A), + .M_DI(MA_DI), + .M_DO(MA_DO), + .M_BE(MA_BE), + .M_WR(MA_WR), + .M_REQ(MA_REQ), + .M_ACK(MA_ACK), + + .MDS(mdsa), + .MDL(mdla), + .MD(mda) + ); + +huc6272_fetch vfeb + ( + .CLK(CLK), + .CE(CE), + .RESn(RESn), + + .rf_bgm(rf_bgm), + + .DCK(DCK), + .FETCH(fetch), + .FETCH_BG_ROW(fetch_bg_row), + .FETCH_BG_COL(fetch_bg_col), + + .MPRBUF(mprbufb), + + .M_A(MB_A), + .M_DI(MB_DI), + .M_DO(MB_DO), + .M_BE(MB_BE), + .M_WR(MB_WR), + .M_REQ(MB_REQ), + .M_ACK(MB_ACK), + + .MDS(mdsb), + .MDL(mdlb), + .MD(mdb) + ); ////////////////////////////////////////////////////////////////////// // BG pipelines @@ -144,12 +201,16 @@ huc6272_bgm #(0) bg0 .rf_bgm(rf_bgm), .DCK(DCK), + .FETCH(fetch), .RENDER(render), .RENDER_BG_COL(render_bg_col), - .MBA1(mba_d[1]), - .MBD(mbd), - .MBACK(mback), + .MDSA(mdsa), + .MDLA(mdla), + .MDA(mda), + .MDSB(mdsb), + .MDLB(mdlb), + .MDB(mdb), .PD(bg0_pd), .PDE(bg0_pde) diff --git a/rtl/tb/huc6272_video_tb.gtkw b/rtl/tb/huc6272_video_tb.gtkw index 906791e..f6ea0bc 100644 --- a/rtl/tb/huc6272_video_tb.gtkw +++ b/rtl/tb/huc6272_video_tb.gtkw @@ -1,15 +1,15 @@ [*] [*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI -[*] Sun Mar 15 21:23:29 2026 +[*] Mon Mar 16 04:44:30 2026 [*] [dumpfile] "/Users/dhunter/src/mister/PCFX_MiSTer/rtl/tb/huc6272_video_tb.vcd" -[dumpfile_mtime] "Sun Mar 15 21:23:23 2026" -[dumpfile_size] 5946693 +[dumpfile_mtime] "Mon Mar 16 04:43:58 2026" +[dumpfile_size] 6247181 [savefile] "/Users/dhunter/src/mister/PCFX_MiSTer/rtl/tb/huc6272_video_tb.gtkw" -[timestart] 0 +[timestart] 558159 [size] 1333 600 [pos] -1 -1 -*-17.200001 13280 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 +*-9.200001 559380 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 @@ -55,25 +55,48 @@ huc6272_video_tb.dut.video.fetch @24 huc6272_video_tb.dut.video.fetch_bg_row[9:0] huc6272_video_tb.dut.video.fetch_bg_col[9:0] -@28 -huc6272_video_tb.dut.video.mbtrg -huc6272_video_tb.dut.video.mback +@c00200 +-vfea @22 -huc6272_video_tb.dut.video.mba[18:1] -huc6272_video_tb.dut.video.mba_d[18:1] -huc6272_video_tb.dut.video.mbd[15:0] +huc6272_video_tb.dut.video.vfea.mpe_ra[18:1] +huc6272_video_tb.dut.video.vfea.mpe_d[8:0] +@28 +huc6272_video_tb.dut.video.vfea.mtrg +huc6272_video_tb.dut.video.vfea.mack +@22 +huc6272_video_tb.dut.video.vfea.ma[18:1] +huc6272_video_tb.dut.video.vfea.MD[15:0] +@28 +huc6272_video_tb.dut.video.vfea.MDL[1:0] +@1401200 +-vfea +@800200 +-vfeb +@22 +huc6272_video_tb.dut.video.vfeb.mpe_ra[18:1] +huc6272_video_tb.dut.video.vfeb.mpe_d[8:0] +@28 +huc6272_video_tb.dut.video.vfeb.mtrg +huc6272_video_tb.dut.video.vfeb.mack +@22 +huc6272_video_tb.dut.video.vfeb.ma[18:1] +huc6272_video_tb.dut.video.vfeb.MD[15:0] +@28 +huc6272_video_tb.dut.video.vfeb.MDL[1:0] +@1000200 +-vfeb @800200 -bg0 -@29 -huc6272_video_tb.dut.video.bg0.cgfce @28 +huc6272_video_tb.dut.video.bg0.cgfce huc6272_video_tb.dut.video.bg0.cgra @22 huc6272_video_tb.dut.video.bg0.cgrd[31:0] @28 huc6272_video_tb.dut.video.render -@24 +@25 huc6272_video_tb.dut.video.render_bg_row[9:0] +@24 huc6272_video_tb.dut.video.render_bg_col[9:0] @22 huc6272_video_tb.dut.video.bg0.cgpd[23:0]