`include "tune.v" // This module generates video raster signals module video_sync ( // clocks input wire clk, f1, c0, c3, pix_stb, // video parameters input wire [8:0] hpix_beg, input wire [8:0] hpix_end, input wire [8:0] vpix_beg, input wire [8:0] vpix_end, input wire [8:0] hpix_beg_ts, input wire [8:0] hpix_end_ts, input wire [8:0] vpix_beg_ts, input wire [8:0] vpix_end_ts, input wire [4:0] go_offs, input wire [1:0] x_offs, input wire [7:0] hint_beg, input wire [8:0] vint_beg, input wire [7:0] cstart, input wire [8:0] rstart, // video syncs output reg hsync, output reg vsync, output reg csync, // video controls input wire cfg_60hz, input wire vga_on, output reg v60hz = 0, input wire nogfx, output wire v_pf, output wire hpix, output wire vpix, output wire v_ts, output wire hvpix, output wire hvtspix, output wire tv_blank, output wire vga_blank, output wire vga_line, output wire frame_start, output wire line_start_s, output wire pix_start, output wire ts_start, output wire frame, output wire flash, // video counters output wire [9:0] vga_cnt_in, output wire [9:0] vga_cnt_out, output wire [8:0] ts_raddr, output reg [8:0] lcount = 0, output reg [7:0] cnt_col = 0, output reg [8:0] cnt_row = 0, output reg cptr = 0, output reg [3:0] scnt = 0, `ifdef PENT_312 output wire [4:0] hcnt, output wire upper8, `endif // DRAM input wire video_pre_next, output reg video_go = 0, // ZX controls input wire y_offs_wr, output wire int_start ); localparam HSYNC_BEG = 9'd11; localparam HSYNC_END = 9'd43; localparam HBLNK_BEG = 9'd00; localparam HBLNK_END = 9'd88; localparam HSYNCV_BEG = 9'd5; localparam HSYNCV_END = 9'd31; localparam HBLNKV_END = 9'd42; localparam HPERIOD = 9'd448; localparam VSYNC_BEG_50 = 9'd08; localparam VSYNC_END_50 = 9'd11; localparam VBLNK_BEG_50 = 9'd00; `ifdef PENT_312 localparam VBLNK_END_50 = 9'd24; localparam VPERIOD_50 = 9'd312; `else localparam VBLNK_END_50 = 9'd32; localparam VPERIOD_50 = 9'd320; `endif localparam VSYNC_BEG_60 = 9'd04; localparam VSYNC_END_60 = 9'd07; localparam VBLNK_BEG_60 = 9'd00; localparam VBLNK_END_60 = 9'd22; localparam VPERIOD_60 = 9'd262; wire [8:0] vsync_beg = v60hz ? VSYNC_BEG_60 : VSYNC_BEG_50; wire [8:0] vsync_end = v60hz ? VSYNC_END_60 : VSYNC_END_50; wire [8:0] vblnk_beg = v60hz ? VBLNK_BEG_60 : VBLNK_BEG_50; wire [8:0] vblnk_end = v60hz ? VBLNK_END_60 : VBLNK_END_50; wire [8:0] vperiod = v60hz ? VPERIOD_60 : VPERIOD_50; `ifdef PENT_312 assign hcnt = hcount[4:0]; assign upper8 = vcount < 8; `endif reg [8:0] hcount = 0; reg [8:0] vcount = 0; reg [8:0] cnt_out = 0; reg vga_hblank = 0; reg vga_vblank = 0; wire line_start = hcount == (HPERIOD - 1); wire line_start2 = hcount == (HSYNC_END - 1); assign line_start_s = line_start && c3; assign frame_start = line_start && (vcount == (vperiod - 1)); wire vis_start = line_start && (vcount == (vblnk_end - 1)); assign pix_start = hcount == (hpix_beg - x_offs - 1); wire ts_start_coarse = hcount == (hpix_beg_ts - 1); assign ts_start = c3 && ts_start_coarse; assign int_start = (hcount == {hint_beg, 1'b0}) && (vcount == vint_beg) && c0; wire vga_pix_start = ((hcount == (HBLNKV_END)) || (hcount == (HBLNKV_END + HPERIOD/2))); wire hs_vga = ((hcount >= HSYNCV_BEG) && (hcount < HSYNCV_END)) || ((hcount >= (HSYNCV_BEG + HPERIOD/2)) && (hcount < (HSYNCV_END + HPERIOD/2))); assign vga_line = (hcount >= HPERIOD/2); wire hs = (hcount >= HSYNC_BEG) && (hcount < HSYNC_END); wire vs = (vcount >= vsync_beg) && (vcount < vsync_end); assign vga_cnt_in = {vcount[0], hcount - HBLNK_END}; assign vga_cnt_out = {~vcount[0], cnt_out}; wire tv_hblank = (hcount > HBLNK_BEG) && (hcount <= HBLNK_END); wire tv_vblank = (vcount >= vblnk_beg) && (vcount < vblnk_end); assign vga_blank = vga_hblank || vga_vblank; assign tv_blank = tv_hblank || tv_vblank; // horizontal TV (7 MHz) always @(posedge clk) if (c3) hcount <= line_start ? 9'b0 : hcount + 9'b1; // vertical TV (15.625 kHz) always @(posedge clk) if (line_start_s) vcount <= (vcount == (vperiod - 1)) ? 9'b0 : vcount + 9'b1; // horizontal VGA (14MHz) always @(posedge clk) if (f1) cnt_out <= vga_pix_start && c3 ? 9'b0 : cnt_out + 9'b1; // column address for DRAM always @(posedge clk) begin if (line_start2) begin cnt_col <= cstart; cptr <= 1'b0; end else if (video_pre_next) begin cnt_col <= cnt_col + 8'b1; cptr <= ~cptr; end end // row address for DRAM reg y_offs_wr_r; always @(posedge clk) if (c3) if (vis_start || (line_start && y_offs_wr_r)) cnt_row <= rstart; else if (line_start && vpix) cnt_row <= cnt_row + 9'b1; // pixel counter always @(posedge clk) if (pix_stb) // f1 or c3 scnt <= pix_start ? 4'b0 : scnt + 4'b1; // TS-line counter assign ts_raddr = hcount - hpix_beg_ts; always @(posedge clk) if (ts_start_coarse) lcount <= vcount - vpix_beg_ts + 9'b1; // Y offset re-latch trigger always @(posedge clk) if (y_offs_wr) y_offs_wr_r <= 1'b1; else if (line_start_s) y_offs_wr_r <= 1'b0; // FLASH generator reg [4:0] flash_ctr; assign frame = flash_ctr[0]; assign flash = flash_ctr[4]; always @(posedge clk) if (frame_start && c3) begin flash_ctr <= flash_ctr + 5'b1; // re-sync 60Hz mode selector `ifdef FORCE_60HZ v60hz <= 1'b1; `elsif ENABLE_60HZ v60hz <= !cfg_60hz; `else v60hz <= 1'b0; `endif end // sync strobes wire vga_hblank1 = (cnt_out > 9'd359); always @(posedge clk) if (f1) // fix me - bydlocode !!! vga_hblank <= vga_hblank1; assign hvpix = hpix && vpix; assign hpix = (hcount >= hpix_beg) && (hcount < hpix_end); assign vpix = (vcount >= vpix_beg) && (vcount < vpix_end); wire htspix = (hcount >= hpix_beg_ts) && (hcount < hpix_end_ts); wire vtspix = (vcount >= vpix_beg_ts) && (vcount < vpix_end_ts); assign hvtspix = htspix && vtspix; assign v_ts = (vcount >= (vpix_beg_ts - 1)) && (vcount < (vpix_end_ts - 1)); // vertical TS window assign v_pf = (vcount >= (vpix_beg_ts - 17)) && (vcount < (vpix_end_ts - 9)); // vertical tilemap prefetch window always @(posedge clk) video_go <= (hcount >= (hpix_beg - go_offs - x_offs)) && (hcount < (hpix_end - go_offs - x_offs + 4)) && vpix && !nogfx; always @(posedge clk) if (line_start_s) // fix me - bydlocode !!! vga_vblank <= tv_vblank; always @(posedge clk) begin hsync <= vga_on ? hs_vga : hs; vsync <= vs; csync <= ~(vs ^ hs); end endmodule