Fix HGC border display by calculating HBlank timing on correct clock domain

- Add std_hsyncwidth and vblank_border outputs to HGC module for border detection
- Connect CRTC hsync_width register (R3) to enable dynamic sync width detection
- Update HGC H_SYNCWIDTH to standard value (4'd15) per Hercules specifications
- Extend Peripherals.sv to multiplex HGC timing signals with CGA
- Fix critical bug: HBlank_fixed was calculated only in CGA clock domain
  In HGC mode, it was desynchronized, causing shifted display instead of proper border
- Add HBlank_fixed_hgc calculated on clk_57_272 (HGC clock) for correct timing
- Update LHBL logic to use appropriate HBlank_fixed for each video mode
- Border now properly reduces visible area in HGC mode with correct synchronization
This commit is contained in:
Aitor Gómez García
2026-01-23 13:42:04 +01:00
parent 6decefa0f8
commit ebbecd6712
3 changed files with 33 additions and 8 deletions

17
PCXT.sv
View File

@@ -1518,7 +1518,9 @@ module emu
wire HBlank_VGA;
reg [10:0] HBlank_counter = 0;
reg [10:0] HBlank_counter_hgc = 0;
reg HBlank_fixed = 1'b1;
reg HBlank_fixed_hgc = 1'b1;
reg [1:0] HSync_del = 1'b11;
reg [1:0] HSync_del_hgc = 1'b11;
localparam integer MDA_VSYNC_DELAY = 19;
@@ -1564,7 +1566,18 @@ module emu
HBlank_del_hgc <= {HBlank_del_hgc[23:0], HBlank};
HSync_del_hgc <= {HSync_del_hgc[0], HSync};
if (HSync_del_hgc == 2'b01)
begin
VSync_line <= {VSync_line[MDA_VSYNC_DELAY-1:0], VSync};
HBlank_counter_hgc <= 0;
HBlank_fixed_hgc <= 1'b1;
end
else
begin
if (HBlank_counter_hgc == (std_hsyncwidth ? 120 : 143))
HBlank_fixed_hgc <= 1'b0;
else
HBlank_counter_hgc <= HBlank_counter_hgc + 1;
end
end
end
@@ -1622,8 +1635,8 @@ module emu
assign CE_PIXEL = ce_pixel;
*/
wire LHBL = (~swap_video_eff && border_video_ff) ? HBlank_fixed : HBlank_VGA;
wire LVBL = (~swap_video_eff && border_video_ff) ? (std_hsyncwidth ? VGA_VBlank_border : VBlank) : VBlank;
wire LHBL = (border_video_ff) ? (swap_video_eff ? HBlank_fixed_hgc : HBlank_fixed) : HBlank_VGA;
wire LVBL = (border_video_ff) ? (std_hsyncwidth ? VGA_VBlank_border : VBlank) : VBlank;
wire VSync_hgc = VSync_line[MDA_VSYNC_DELAY];
wire pre2x_LHBL, pre2x_LVBL;

View File

@@ -1199,7 +1199,7 @@ end
.hgc_rgb(hgc_rgb)
);
hgc hgc1
hgc hgc1
(
.clk (clk_vga_hgc),
.bus_a (hgc_io_address_2),
@@ -1223,8 +1223,10 @@ end
.de_o (de_o_hgc),
.grph_mode (hgc_grph_mode),
.grph_page (hgc_grph_page),
.std_hsyncwidth (std_hsyncwidth_hgc),
.vblank_border (vblank_border_hgc),
.hercules_hw (hercules_hw)
);
always_ff @(posedge clock)
@@ -1258,6 +1260,8 @@ end
wire VGA_VBlank_border_raw;
wire std_hsyncwidth_raw;
wire tandy_color_16_raw;
wire std_hsyncwidth_hgc;
wire vblank_border_hgc;
// Sets up the card to generate a video signal
// that will work with a standard VGA monitor
@@ -1275,8 +1279,8 @@ end
wire composite_cga = tandy_video_en ? (swap_video ? ~composite : composite) : composite;
assign VGA_VBlank_border = `ENABLE_CGA ? VGA_VBlank_border_raw : 1'b0;
assign std_hsyncwidth = `ENABLE_CGA ? std_hsyncwidth_raw : 1'b0;
assign VGA_VBlank_border = `ENABLE_CGA ? VGA_VBlank_border_raw : (`ENABLE_HGC ? vblank_border_hgc : 1'b0);
assign std_hsyncwidth = `ENABLE_CGA ? std_hsyncwidth_raw : (`ENABLE_HGC ? std_hsyncwidth_hgc : 1'b0);
assign tandy_color_16 = `ENABLE_CGA ? tandy_color_16_raw : 1'b0;

View File

@@ -38,11 +38,14 @@ module hgc(
output intensity,
output grph_mode,
output grph_page,
output std_hsyncwidth,
output vblank_border,
input hercules_hw
);
parameter HGC_70HZ = 1;
parameter BLINK_MAX = 0;
localparam STD_HSYNCWIDTH = 4'd15;
parameter IO_BASE_ADDR = 16'h3b0; // HGC is 3B0, CGA is 3D0
wire crtc_cs;
@@ -80,6 +83,7 @@ module hgc(
wire[4:0] clkdiv;
wire crtc_clk;
wire[7:0] ram_1_d;
wire[3:0] hsync_width_crtc;
reg[23:0] blink_counter;
reg blink;
@@ -154,6 +158,10 @@ module hgc(
assign video_enabled = hgc_control_reg[3];
assign grph_mode = hgc_control_reg[1];
// Standard sync width detection
assign std_hsyncwidth = (hsync_width_crtc == STD_HSYNCWIDTH);
assign vblank_border = vblank;
// Hsync only present when video is enabled
assign hsync = video_enabled & hsync_int;
@@ -193,7 +201,7 @@ module hgc(
.MA(crtc_addr),
.RA(row_addr),
.hsync_width()
.hsync_width(hsync_width_crtc)
);
@@ -201,7 +209,7 @@ module hgc(
defparam crtc.H_TOTAL = 8'd99;
defparam crtc.H_DISP = 8'd80;
defparam crtc.H_SYNCPOS = 8'd82;
defparam crtc.H_SYNCWIDTH = 4'd12;
defparam crtc.H_SYNCWIDTH = 4'd15;
defparam crtc.V_TOTAL = 7'd31;
defparam crtc.V_TOTALADJ = 5'd1;
defparam crtc.V_DISP = 7'd25;