From 93f35af5ea946c20602233d2533c182b840cca2a Mon Sep 17 00:00:00 2001 From: sorgelig Date: Wed, 22 Aug 2018 04:10:49 +0800 Subject: [PATCH] Update the video to latest version. --- TSConf-lite.srf | 2 + TSConf.qsf | 7 +- src/memory/arbiter.v | 1 - src/tsconf.v | 7 - src/video/video_cram.mif | 560 ++++++++++++++++++------------------ src/video/video_fetch.v | 51 ++-- src/video/video_mode.v | 293 ++++++++++--------- src/video/video_out.v | 72 +++-- src/video/video_ports.v | 258 ++++++++--------- src/video/video_render.v | 93 +++--- src/video/video_sync.v | 257 ++++++++--------- src/video/video_top.v | 114 ++++---- src/video/video_ts.v | 485 +++++++++++++++---------------- src/video/video_ts_render.v | 149 +++++----- 14 files changed, 1139 insertions(+), 1210 deletions(-) diff --git a/TSConf-lite.srf b/TSConf-lite.srf index 8f27398..f8ac6db 100644 --- a/TSConf-lite.srf +++ b/TSConf-lite.srf @@ -20,6 +20,8 @@ { "" "" "" "LOCKED port on the PLL is not properly connected on instance \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} { "" "" "" "Inferred RAM node \"emu:emu\|tsconf:tsconf\|gs:U15\|T80s:z80_unit\|T80:u0\|T80_Reg:Regs\|RegsH_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} { "" "" "" "Inferred RAM node \"emu:emu\|tsconf:tsconf\|gs:U15\|T80s:z80_unit\|T80:u0\|T80_Reg:Regs\|RegsL_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|tsconf:tsconf\|T80s:CPU\|T80:u0\|T80_Reg:Regs\|RegsH_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|tsconf:tsconf\|T80s:CPU\|T80:u0\|T80_Reg:Regs\|RegsL_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} { "" "" "" "*" { } { } 0 21074 "" 0 0 "Design Software" 0 -1 0 ""} { "" "" "" "RST" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} { "" "" "" "sysmem_HPS_fpga_interfaces.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} diff --git a/TSConf.qsf b/TSConf.qsf index 6813a4c..2c173e4 100644 --- a/TSConf.qsf +++ b/TSConf.qsf @@ -361,12 +361,7 @@ set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl" set_global_assignment -name CDF_FILE jtag.cdf set_global_assignment -name QIP_FILE sys/sys.qip set_global_assignment -name QSYS_FILE sys/vip.qsys -set_global_assignment -name VHDL_FILE src/t80/T80_Reg.vhd -set_global_assignment -name VHDL_FILE src/t80/T80_Pack.vhd -set_global_assignment -name VHDL_FILE src/t80/T80_MCode.vhd -set_global_assignment -name VHDL_FILE src/t80/T80_ALU.vhd -set_global_assignment -name VHDL_FILE src/t80/T80.vhd -set_global_assignment -name VHDL_FILE src/t80/T80s.vhd +set_global_assignment -name QIP_FILE src/t80/T80.qip set_global_assignment -name VERILOG_FILE src/cpu/zsignals.v set_global_assignment -name VERILOG_FILE src/cpu/zports.v set_global_assignment -name VERILOG_FILE src/cpu/zmem.v diff --git a/src/memory/arbiter.v b/src/memory/arbiter.v index 81bb18d..17c4f97 100644 --- a/src/memory/arbiter.v +++ b/src/memory/arbiter.v @@ -96,7 +96,6 @@ module arbiter( // TS input wire [23:0] ts_addr, input wire ts_req, - input wire ts_z80_lp, output wire ts_pre_next, output wire ts_next, diff --git a/src/tsconf.v b/src/tsconf.v index fc0c7dd..2a5bd8a 100644 --- a/src/tsconf.v +++ b/src/tsconf.v @@ -256,12 +256,10 @@ wire video_next; wire video_pre_next; wire next_video; wire video_strobe; -wire video_next_strobe; // TS wire [20:0] ts_addr; wire ts_req; -wire ts_z80_lp; // IN wire ts_pre_next; @@ -518,7 +516,6 @@ arbiter TS07 .video_pre_next(video_pre_next), .video_next(video_next), // (c2) at this signal video_addr may be changed; it is one clock leading the video_strobe .video_strobe(video_strobe), // (c3) one-cycle strobe meaning that video_data is available - .video_next_strobe(video_next_strobe), .next_vid(next_video), // used for TM prefetch .cpu_addr({csvrom, 2'b00, cpu_addr_20}), .cpu_wrdata(cpu_do_bus), @@ -537,7 +534,6 @@ arbiter TS07 .dma_next(dma_next), .ts_addr({3'b000, ts_addr}), .ts_req(ts_req), - .ts_z80_lp(ts_z80_lp), .ts_pre_next(ts_pre_next), .ts_next(ts_next), .tm_addr({3'b000, tm_addr}), @@ -564,7 +560,6 @@ video_top TS08 .hblank(VGA_HBLANK), .vblank(VGA_VBLANK), .pix_stb(VGA_CEPIX), - .a(cpu_a_bus), .d(cpu_do_bus), .zmd(zmd), .zma(zma), @@ -607,10 +602,8 @@ video_top TS08 .video_pre_next(video_pre_next), .next_video(next_video), .video_strobe(video_strobe), - .video_next_strobe(video_next_strobe), .ts_addr(ts_addr), .ts_req(ts_req), - .ts_z80_lp(ts_z80_lp), .ts_pre_next(ts_pre_next), .ts_next(ts_next), .tm_addr(tm_addr), diff --git a/src/video/video_cram.mif b/src/video/video_cram.mif index b92597d..90ba69b 100644 --- a/src/video/video_cram.mif +++ b/src/video/video_cram.mif @@ -1,280 +1,280 @@ --- Copyright (C) 1991-2007 Altera Corporation --- Your use of Altera Corporation's design tools, logic functions --- and other software and tools, and its AMPP partner logic --- functions, and any output files from any of the foregoing --- (including device programming or simulation files), and any --- associated documentation or information are expressly subject --- to the terms and conditions of the Altera Program License --- Subscription Agreement, Altera MegaCore Function License --- Agreement, or other applicable license agreement, including, --- without limitation, that your use is for the sole purpose of --- programming logic devices manufactured by Altera and sold by --- Altera or its authorized distributors. Please refer to the --- applicable agreement for further details. - --- Quartus II generated Memory Initialization File (.mif) - -WIDTH=15; -DEPTH=256; - -ADDRESS_RADIX=HEX; -DATA_RADIX=HEX; - -CONTENT BEGIN - 000 : 0000; - 001 : 0008; - 002 : 0010; - 003 : 0018; - 004 : 2000; - 005 : 2008; - 006 : 2010; - 007 : 2018; - 008 : 4000; - 009 : 4008; - 00A : 4010; - 00B : 4018; - 00C : 6000; - 00D : 6008; - 00E : 6010; - 00F : 6018; - 010 : 0100; - 011 : 0108; - 012 : 0110; - 013 : 0118; - 014 : 2100; - 015 : 2108; - 016 : 2110; - 017 : 2118; - 018 : 4100; - 019 : 4108; - 01A : 4110; - 01B : 4118; - 01C : 6100; - 01D : 6108; - 01E : 6110; - 01F : 6118; - 020 : 0200; - 021 : 0208; - 022 : 0210; - 023 : 0218; - 024 : 2200; - 025 : 2208; - 026 : 2210; - 027 : 2218; - 028 : 4200; - 029 : 4208; - 02A : 4210; - 02B : 4218; - 02C : 6200; - 02D : 6208; - 02E : 6210; - 02F : 6218; - 030 : 0300; - 031 : 0308; - 032 : 0310; - 033 : 0318; - 034 : 2300; - 035 : 2308; - 036 : 2310; - 037 : 2318; - 038 : 4300; - 039 : 4308; - 03A : 4310; - 03B : 4318; - 03C : 6300; - 03D : 6308; - 03E : 6310; - 03F : 6318; - 040 : 0000; - 041 : 0010; - 042 : 4000; - 043 : 4010; - 044 : 0200; - 045 : 0210; - 046 : 4200; - 047 : 4210; - 048 : 2108; - 049 : 0018; - 04A : 6000; - 04B : 6018; - 04C : 0300; - 04D : 0318; - 04E : 6300; - 04F : 6318; - 050 : 0000; - 051 : 0010; - 052 : 4000; - 053 : 4010; - 054 : 0200; - 055 : 0210; - 056 : 4200; - 057 : 4210; - 058 : 0000; - 059 : 0018; - 05A : 6000; - 05B : 6018; - 05C : 0300; - 05D : 0318; - 05E : 6300; - 05F : 6318; - 060 : 0000; - 061 : 0010; - 062 : 4000; - 063 : 4010; - 064 : 0200; - 065 : 0210; - 066 : 4200; - 067 : 4210; - 068 : 2108; - 069 : 0018; - 06A : 6000; - 06B : 6018; - 06C : 0300; - 06D : 0318; - 06E : 6300; - 06F : 6318; - 070 : 0000; - 071 : 0010; - 072 : 4000; - 073 : 4010; - 074 : 0200; - 075 : 0210; - 076 : 4200; - 077 : 4210; - 078 : 0000; - 079 : 0018; - 07A : 6000; - 07B : 6018; - 07C : 0300; - 07D : 0318; - 07E : 6300; - 07F : 6318; - 080 : 0000; - 081 : 0010; - 082 : 4000; - 083 : 4010; - 084 : 0200; - 085 : 0210; - 086 : 4200; - 087 : 4210; - 088 : 2108; - 089 : 0018; - 08A : 6000; - 08B : 6018; - 08C : 0300; - 08D : 0318; - 08E : 6300; - 08F : 6318; - 090 : 0000; - 091 : 0010; - 092 : 4000; - 093 : 4010; - 094 : 0200; - 095 : 0210; - 096 : 4200; - 097 : 4210; - 098 : 0000; - 099 : 0018; - 09A : 6000; - 09B : 6018; - 09C : 0300; - 09D : 0318; - 09E : 6300; - 09F : 6318; - 0A0 : 0000; - 0A1 : 0010; - 0A2 : 4000; - 0A3 : 4010; - 0A4 : 0200; - 0A5 : 0210; - 0A6 : 4200; - 0A7 : 4210; - 0A8 : 2108; - 0A9 : 0018; - 0AA : 6000; - 0AB : 6018; - 0AC : 0300; - 0AD : 0318; - 0AE : 6300; - 0AF : 6318; - 0B0 : 0000; - 0B1 : 0010; - 0B2 : 4000; - 0B3 : 4010; - 0B4 : 0200; - 0B5 : 0210; - 0B6 : 4200; - 0B7 : 4210; - 0B8 : 0000; - 0B9 : 0018; - 0BA : 6000; - 0BB : 6018; - 0BC : 0300; - 0BD : 0318; - 0BE : 6300; - 0BF : 6318; - 0C0 : 0000; - 0C1 : 0010; - 0C2 : 4000; - 0C3 : 4010; - 0C4 : 0200; - 0C5 : 0210; - 0C6 : 4200; - 0C7 : 4210; - 0C8 : 2108; - 0C9 : 0018; - 0CA : 6000; - 0CB : 6018; - 0CC : 0300; - 0CD : 0318; - 0CE : 6300; - 0CF : 6318; - 0D0 : 0000; - 0D1 : 0010; - 0D2 : 4000; - 0D3 : 4010; - 0D4 : 0200; - 0D5 : 0210; - 0D6 : 4200; - 0D7 : 4210; - 0D8 : 0000; - 0D9 : 0018; - 0DA : 6000; - 0DB : 6018; - 0DC : 0300; - 0DD : 0318; - 0DE : 6300; - 0DF : 6318; - 0E0 : 0000; - 0E1 : 0010; - 0E2 : 4000; - 0E3 : 4010; - 0E4 : 0200; - 0E5 : 0210; - 0E6 : 4200; - 0E7 : 4210; - 0E8 : 2108; - 0E9 : 0018; - 0EA : 6000; - 0EB : 6018; - 0EC : 0300; - 0ED : 0318; - 0EE : 6300; - 0EF : 6318; - 0F0 : 0000; - 0F1 : 0010; - 0F2 : 4000; - 0F3 : 4010; - 0F4 : 0200; - 0F5 : 0210; - 0F6 : 4200; - 0F7 : 4210; - 0F8 : 0000; - 0F9 : 0018; - 0FA : 6000; - 0FB : 6018; - 0FC : 0300; - 0FD : 0318; - 0FE : 6300; - 0FF : 6318; -END; +-- Copyright (C) 1991-2007 Altera Corporation +-- Your use of Altera Corporation's design tools, logic functions +-- and other software and tools, and its AMPP partner logic +-- functions, and any output files from any of the foregoing +-- (including device programming or simulation files), and any +-- associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License +-- Subscription Agreement, Altera MegaCore Function License +-- Agreement, or other applicable license agreement, including, +-- without limitation, that your use is for the sole purpose of +-- programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the +-- applicable agreement for further details. + +-- Quartus II generated Memory Initialization File (.mif) + +WIDTH=16; +DEPTH=256; + +ADDRESS_RADIX=HEX; +DATA_RADIX=HEX; + +CONTENT BEGIN + 000 : 0000; + 001 : 0008; + 002 : 0010; + 003 : 0018; + 004 : 2000; + 005 : 2008; + 006 : 2010; + 007 : 2018; + 008 : 4000; + 009 : 4008; + 00A : 4010; + 00B : 4018; + 00C : 6000; + 00D : 6008; + 00E : 6010; + 00F : 6018; + 010 : 0100; + 011 : 0108; + 012 : 0110; + 013 : 0118; + 014 : 2100; + 015 : 2108; + 016 : 2110; + 017 : 2118; + 018 : 4100; + 019 : 4108; + 01A : 4110; + 01B : 4118; + 01C : 6100; + 01D : 6108; + 01E : 6110; + 01F : 6118; + 020 : 0200; + 021 : 0208; + 022 : 0210; + 023 : 0218; + 024 : 2200; + 025 : 2208; + 026 : 2210; + 027 : 2218; + 028 : 4200; + 029 : 4208; + 02A : 4210; + 02B : 4218; + 02C : 6200; + 02D : 6208; + 02E : 6210; + 02F : 6218; + 030 : 0300; + 031 : 0308; + 032 : 0310; + 033 : 0318; + 034 : 2300; + 035 : 2308; + 036 : 2310; + 037 : 2318; + 038 : 4300; + 039 : 4308; + 03A : 4310; + 03B : 4318; + 03C : 6300; + 03D : 6308; + 03E : 6310; + 03F : 6318; + 040 : 0000; + 041 : 0010; + 042 : 4000; + 043 : 4010; + 044 : 0200; + 045 : 0210; + 046 : 4200; + 047 : 4210; + 048 : 2108; + 049 : 0018; + 04A : 6000; + 04B : 6018; + 04C : 0300; + 04D : 0318; + 04E : 6300; + 04F : 6318; + 050 : 0000; + 051 : 0010; + 052 : 4000; + 053 : 4010; + 054 : 0200; + 055 : 0210; + 056 : 4200; + 057 : 4210; + 058 : 0000; + 059 : 0018; + 05A : 6000; + 05B : 6018; + 05C : 0300; + 05D : 0318; + 05E : 6300; + 05F : 6318; + 060 : 0000; + 061 : 0010; + 062 : 4000; + 063 : 4010; + 064 : 0200; + 065 : 0210; + 066 : 4200; + 067 : 4210; + 068 : 2108; + 069 : 0018; + 06A : 6000; + 06B : 6018; + 06C : 0300; + 06D : 0318; + 06E : 6300; + 06F : 6318; + 070 : 0000; + 071 : 0010; + 072 : 4000; + 073 : 4010; + 074 : 0200; + 075 : 0210; + 076 : 4200; + 077 : 4210; + 078 : 0000; + 079 : 0018; + 07A : 6000; + 07B : 6018; + 07C : 0300; + 07D : 0318; + 07E : 6300; + 07F : 6318; + 080 : 0000; + 081 : 0010; + 082 : 4000; + 083 : 4010; + 084 : 0200; + 085 : 0210; + 086 : 4200; + 087 : 4210; + 088 : 2108; + 089 : 0018; + 08A : 6000; + 08B : 6018; + 08C : 0300; + 08D : 0318; + 08E : 6300; + 08F : 6318; + 090 : 0000; + 091 : 0010; + 092 : 4000; + 093 : 4010; + 094 : 0200; + 095 : 0210; + 096 : 4200; + 097 : 4210; + 098 : 0000; + 099 : 0018; + 09A : 6000; + 09B : 6018; + 09C : 0300; + 09D : 0318; + 09E : 6300; + 09F : 6318; + 0A0 : 0000; + 0A1 : 0010; + 0A2 : 4000; + 0A3 : 4010; + 0A4 : 0200; + 0A5 : 0210; + 0A6 : 4200; + 0A7 : 4210; + 0A8 : 2108; + 0A9 : 0018; + 0AA : 6000; + 0AB : 6018; + 0AC : 0300; + 0AD : 0318; + 0AE : 6300; + 0AF : 6318; + 0B0 : 0000; + 0B1 : 0010; + 0B2 : 4000; + 0B3 : 4010; + 0B4 : 0200; + 0B5 : 0210; + 0B6 : 4200; + 0B7 : 4210; + 0B8 : 0000; + 0B9 : 0018; + 0BA : 6000; + 0BB : 6018; + 0BC : 0300; + 0BD : 0318; + 0BE : 6300; + 0BF : 6318; + 0C0 : 0000; + 0C1 : 0010; + 0C2 : 4000; + 0C3 : 4010; + 0C4 : 0200; + 0C5 : 0210; + 0C6 : 4200; + 0C7 : 4210; + 0C8 : 2108; + 0C9 : 0018; + 0CA : 6000; + 0CB : 6018; + 0CC : 0300; + 0CD : 0318; + 0CE : 6300; + 0CF : 6318; + 0D0 : 0000; + 0D1 : 0010; + 0D2 : 4000; + 0D3 : 4010; + 0D4 : 0200; + 0D5 : 0210; + 0D6 : 4200; + 0D7 : 4210; + 0D8 : 0000; + 0D9 : 0018; + 0DA : 6000; + 0DB : 6018; + 0DC : 0300; + 0DD : 0318; + 0DE : 6300; + 0DF : 6318; + 0E0 : 0000; + 0E1 : 0010; + 0E2 : 4000; + 0E3 : 4010; + 0E4 : 0200; + 0E5 : 0210; + 0E6 : 4200; + 0E7 : 4210; + 0E8 : 2108; + 0E9 : 0018; + 0EA : 6000; + 0EB : 6018; + 0EC : 0300; + 0ED : 0318; + 0EE : 6300; + 0EF : 6318; + 0F0 : 0000; + 0F1 : 0010; + 0F2 : 4000; + 0F3 : 4010; + 0F4 : 0200; + 0F5 : 0210; + 0F6 : 4200; + 0F7 : 4210; + 0F8 : 0000; + 0F9 : 0018; + 0FA : 6000; + 0FB : 6018; + 0FC : 0300; + 0FD : 0318; + 0FE : 6300; + 0FF : 6318; +END; diff --git a/src/video/video_fetch.v b/src/video/video_fetch.v index 63d9b39..7eba80b 100644 --- a/src/video/video_fetch.v +++ b/src/video/video_fetch.v @@ -1,38 +1,33 @@ // This module fetches video data from DRAM -module video_fetch ( - -// clocks +module video_fetch +( + // clocks input wire clk, - -// control - input wire [3:0] f_sel, - input wire [1:0] b_sel, - input wire fetch_stb, - -// video data - output reg [31:0] fetch_data, + + // control + input wire [3:0] f_sel, + input wire [1:0] b_sel, + input wire fetch_stb, + + // video data + output reg [31:0] fetch_data, output reg [31:0] fetch_temp, - -// DRAM interface + + // DRAM interface input wire video_strobe, input wire [15:0] video_data - ); - // fetching data - - always @(posedge clk) if (video_strobe) - begin - if (f_sel[0]) fetch_temp[ 7: 0] <= b_sel[0] ? video_data[15:8] : video_data[ 7:0]; - if (f_sel[1]) fetch_temp[15: 8] <= b_sel[1] ? video_data[15:8] : video_data[ 7:0]; - if (f_sel[2]) fetch_temp[23:16] <= video_data[ 7:0]; - if (f_sel[3]) fetch_temp[31:24] <= video_data[15:8]; - end - - - always @(posedge clk) if (fetch_stb) - fetch_data <= fetch_temp; +always @(posedge clk) if (video_strobe) +begin + if (f_sel[0]) fetch_temp[ 7: 0] <= b_sel[0] ? video_data[15:8] : video_data[ 7:0]; + if (f_sel[1]) fetch_temp[15: 8] <= b_sel[1] ? video_data[15:8] : video_data[ 7:0]; + if (f_sel[2]) fetch_temp[23:16] <= video_data[ 7:0]; + if (f_sel[3]) fetch_temp[31:24] <= video_data[15:8]; +end -endmodule \ No newline at end of file +always @(posedge clk) if (fetch_stb) fetch_data <= fetch_temp; + +endmodule diff --git a/src/video/video_mode.v b/src/video/video_mode.v index 19abc63..fb182ee 100644 --- a/src/video/video_mode.v +++ b/src/video/video_mode.v @@ -1,23 +1,28 @@ // This module decodes video modes -module video_mode ( - -// clocks +module video_mode +( + // clocks input wire clk, f1, c3, -// video config + // video config input wire [7:0] vpage, input wire [7:0] vconf, + input wire ts_rres_ext, input wire v60hz, -// video parameters & mode controls + // video parameters & mode controls input wire [8:0] gx_offs, output wire [9:0] x_offs_mode, output wire [8:0] hpix_beg, output wire [8:0] hpix_end, output wire [8:0] vpix_beg, output wire [8:0] vpix_end, + output wire [8:0] hpix_beg_ts, + output wire [8:0] hpix_end_ts, + output wire [8:0] vpix_beg_ts, + output wire [8:0] vpix_end_ts, output wire [5:0] x_tiles, output wire [4:0] go_offs, output wire [3:0] fetch_sel, @@ -31,202 +36,204 @@ module video_mode ( output wire pix_stb, output wire fetch_stb, -// video data + // video data input wire [15:0] txt_char, -// video counters - input wire [7:0] cnt_col, - input wire [8:0] cnt_row, - input wire cptr, + // video counters + input wire [7:0] cnt_col, + input wire [8:0] cnt_row, + input wire cptr, -// DRAM interface - output wire [20:0] video_addr, - output wire [ 4:0] video_bw + // DRAM interface + output wire [20:0] video_addr, + output wire [ 4:0] video_bw ); - - wire [1:0] vmod = vconf[1:0]; - wire [1:0] rres = vconf[7:6]; +wire [1:0] vmod = vconf[1:0]; +wire [1:0] rres = vconf[7:6]; // clocking strobe for pixels (TV) - assign pix_stb = tv_hires ? f1 : c3; +assign pix_stb = tv_hires ? f1 : c3; - always @(posedge clk) - if (line_start_s) - vga_hires <= tv_hires; +always @(posedge clk) if (line_start_s) vga_hires <= tv_hires; // Modes - localparam M_ZX = 2'h0; // ZX - localparam M_HC = 2'h1; // 16c - localparam M_XC = 2'h2; // 256c - localparam M_TX = 2'h3; // Text +localparam M_ZX = 2'h0; // ZX +localparam M_HC = 2'h1; // 16c +localparam M_XC = 2'h2; // 256c +localparam M_TX = 2'h3; // Text // Render modes (affects 'video_render.v') - localparam R_ZX = 2'h0; - localparam R_HC = 2'h1; - localparam R_XC = 2'h2; - localparam R_TX = 2'h3; +localparam R_ZX = 2'h0; +localparam R_HC = 2'h1; +localparam R_XC = 2'h2; +localparam R_TX = 2'h3; // fetch strobes - wire ftch[0:3]; - assign fetch_stb = (pix_start | ftch[render_mode]) && c3; - assign ftch[R_ZX] = &fetch_cnt[3:0]; - assign ftch[R_HC] = &fetch_cnt[1:0]; - assign ftch[R_XC] = fetch_cnt[0]; - assign ftch[R_TX] = &fetch_cnt[3:0]; +wire ftch[0:3]; +assign fetch_stb = (pix_start | ftch[render_mode]) && c3; +assign ftch[R_ZX] = &fetch_cnt[3:0]; +assign ftch[R_HC] = &fetch_cnt[1:0]; +assign ftch[R_XC] = fetch_cnt[0]; +assign ftch[R_TX] = &fetch_cnt[3:0]; // fetch window - wire [4:0] g_offs[0:3]; - // these values are from a thin air!!! recheck them occasionally! - assign g_offs[M_ZX] = 5'd18; - assign g_offs[M_HC] = 5'd6; - assign g_offs[M_XC] = 5'd4; - assign g_offs[M_TX] = 5'd10; - assign go_offs = g_offs[vmod]; +wire [4:0] g_offs[0:3]; +// these values are from a thin air!!! recheck them occasionally! +assign g_offs[M_ZX] = 5'd18; +assign g_offs[M_HC] = 5'd6; +assign g_offs[M_XC] = 5'd4; +assign g_offs[M_TX] = 5'd10; +assign go_offs = g_offs[vmod]; // fetch selectors // Attention: counter is already incremented at the time of video data fetching! - // wire m_c = (vmod == M_HC) | (vmod == M_XC); - // assign fetch_sel = vmod == M_TX ? f_txt_sel[cnt_col[1:0]] : {~cptr, ~cptr, cptr | m_c, cptr | m_c}; +// wire m_c = (vmod == M_HC) | (vmod == M_XC); +// assign fetch_sel = vmod == M_TX ? f_txt_sel[cnt_col[1:0]] : {~cptr, ~cptr, cptr | m_c, cptr | m_c}; - // wire [3:0] f_sel[0:7]; - wire [3:0] f_sel[0:3]; - assign f_sel[M_ZX] = {~cptr, ~cptr, cptr, cptr}; - assign f_sel[M_HC] = {~cptr, ~cptr, 2'b11}; - assign f_sel[M_XC] = {~cptr, ~cptr, 2'b11}; - assign f_sel[M_TX] = f_txt_sel[cnt_col[1:0]]; - assign fetch_sel = f_sel[vmod]; +// wire [3:0] f_sel[0:7]; +wire [3:0] f_sel[0:3]; +assign f_sel[M_ZX] = {~cptr, ~cptr, cptr, cptr}; +assign f_sel[M_HC] = {~cptr, ~cptr, 2'b11}; +assign f_sel[M_XC] = {~cptr, ~cptr, 2'b11}; +assign f_sel[M_TX] = f_txt_sel[cnt_col[1:0]]; +assign fetch_sel = f_sel[vmod]; - assign fetch_bsl = (vmod == M_TX) ? f_txt_bsl[cnt_col[1:0]] : 2'b10; +assign fetch_bsl = (vmod == M_TX) ? f_txt_bsl[cnt_col[1:0]] : 2'b10; - // wire [1:0] f_bsl[0:7]; - // assign f_bsl[M_ZX] = 2'b10; - // assign f_bsl[M_HC] = 2'b10; - // assign f_bsl[M_XC] = 2'b10; - // assign f_bsl[M_TX] = f_txt_bsl[cnt_col[1:0]]; - // assign fetch_bsl = f_bsl[vmod]; +// wire [1:0] f_bsl[0:7]; +// assign f_bsl[M_ZX] = 2'b10; +// assign f_bsl[M_HC] = 2'b10; +// assign f_bsl[M_XC] = 2'b10; +// assign f_bsl[M_TX] = f_txt_bsl[cnt_col[1:0]]; +// assign fetch_bsl = f_bsl[vmod]; - wire [3:0] f_txt_sel[0:3]; - assign f_txt_sel[1] = 4'b0011; // char - assign f_txt_sel[2] = 4'b1100; // attr - assign f_txt_sel[3] = 4'b0001; // gfx0 - assign f_txt_sel[0] = 4'b0010; // gfx1 +wire [3:0] f_txt_sel[0:3]; +assign f_txt_sel[1] = 4'b0011; // char +assign f_txt_sel[2] = 4'b1100; // attr +assign f_txt_sel[3] = 4'b0001; // gfx0 +assign f_txt_sel[0] = 4'b0010; // gfx1 - wire [1:0] f_txt_bsl[0:3]; - assign f_txt_bsl[1] = 2'b10; // char - assign f_txt_bsl[2] = 2'b10; // attr - assign f_txt_bsl[3] = {2{cnt_row[0]}}; // gfx0 - assign f_txt_bsl[0] = {2{cnt_row[0]}}; // gfx1 +wire [1:0] f_txt_bsl[0:3]; +assign f_txt_bsl[1] = 2'b10; // char +assign f_txt_bsl[2] = 2'b10; // attr +assign f_txt_bsl[3] = {2{cnt_row[0]}}; // gfx0 +assign f_txt_bsl[0] = {2{cnt_row[0]}}; // gfx1 // X offset - assign x_offs_mode = {vmod == M_XC ? {gx_offs[8:1], 1'b0} : {1'b0, gx_offs[8:1]}, gx_offs[0]}; +assign x_offs_mode = {vmod == M_XC ? {gx_offs[8:1], 1'b0} : {1'b0, gx_offs[8:1]}, gx_offs[0]}; // DRAM bandwidth usage - localparam BW2 = 2'b00; - localparam BW4 = 2'b01; - localparam BW8 = 2'b11; +localparam BW2 = 2'b00; +localparam BW4 = 2'b01; +localparam BW8 = 2'b11; - localparam BU1 = 3'b001; - localparam BU2 = 3'b010; - localparam BU4 = 3'b100; +localparam BU1 = 3'b001; +localparam BU2 = 3'b010; +localparam BU4 = 3'b100; - // [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2 - // [2:0] - need cycles - wire [4:0] bw[0:3]; - assign bw[M_ZX] = {BW8, BU1}; // '1 of 8' (ZX) - assign bw[M_HC] = {BW4, BU1}; // '1 of 4' (16c) - assign bw[M_XC] = {BW2, BU1}; // '1 of 2' (256c) - assign bw[M_TX] = {BW8, BU4}; // '4 of 8' (text) - assign video_bw = bw[vmod]; +// [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2 +// [2:0] - need cycles +wire [4:0] bw[0:3]; +assign bw[M_ZX] = {BW8, BU1}; // '1 of 8' (ZX) +assign bw[M_HC] = {BW4, BU1}; // '1 of 4' (16c) +assign bw[M_XC] = {BW2, BU1}; // '1 of 2' (256c) +assign bw[M_TX] = {BW8, BU4}; // '4 of 8' (text) +assign video_bw = bw[vmod]; // pixelrate - wire [3:0] pixrate = 4'b1000; // change these if you change the modes indexes! - assign tv_hires = pixrate[vmod]; +wire [3:0] pixrate = 4'b1000; // change these if you change the modes indexes! +assign tv_hires = pixrate[vmod]; // render mode - // wire [1:0] r_mode[0:7]; - wire [1:0] r_mode[0:3]; - assign r_mode[M_ZX] = R_ZX; - assign r_mode[M_HC] = R_HC; - assign r_mode[M_XC] = R_XC; - assign r_mode[M_TX] = R_TX; - assign render_mode = r_mode[vmod]; +// wire [1:0] r_mode[0:7]; +wire [1:0] r_mode[0:3]; +assign r_mode[M_ZX] = R_ZX; +assign r_mode[M_HC] = R_HC; +assign r_mode[M_XC] = R_XC; +assign r_mode[M_TX] = R_TX; +assign render_mode = r_mode[vmod]; // raster resolution - wire [8:0] hp_beg[0:3]; - wire [8:0] hp_end[0:3]; - wire [8:0] vp_beg[0:3]; - wire [8:0] vp_end[0:3]; - wire [5:0] x_tile[0:3]; +wire [8:0] hp_beg[0:3]; +wire [8:0] hp_end[0:3]; +wire [8:0] vp_beg[0:3]; +wire [8:0] vp_end[0:3]; +wire [5:0] x_tile[0:3]; - assign hp_beg[0] = 9'd140; // 256 (88-52-256-52) - assign hp_beg[1] = 9'd108; // 320 (88-20-320-20) - assign hp_beg[2] = 9'd108; // 320 (88-20-320-20) - assign hp_beg[3] = 9'd88; // 360 (88-0-360-0) +assign hp_beg[0] = 9'd140; // 256 (88-52-256-52) +assign hp_beg[1] = 9'd108; // 320 (88-20-320-20) +assign hp_beg[2] = 9'd108; // 320 (88-20-320-20) +assign hp_beg[3] = 9'd88; // 360 (88-0-360-0) - assign hp_end[0] = 9'd396; // 256 - assign hp_end[1] = 9'd428; // 320 - assign hp_end[2] = 9'd428; // 320 - assign hp_end[3] = 9'd448; // 360 +assign hp_end[0] = 9'd396; // 256 +assign hp_end[1] = 9'd428; // 320 +assign hp_end[2] = 9'd428; // 320 +assign hp_end[3] = 9'd448; // 360 - assign vp_beg[0] = v60hz ? 9'd046 : 9'd080; // 192 (22-24-192-24)/(32-48-192-48) (blank-border-pixels-border) - assign vp_beg[1] = v60hz ? 9'd042 : 9'd076; // 200 (22-20-200-20)/(32-44-200-44) - assign vp_beg[2] = v60hz ? 9'd022 : 9'd056; // 240 (22-0-240-0)/(32-24-240-24) - assign vp_beg[3] = v60hz ? 9'd022 : 9'd032; // 288 (22-0-240-0)/(32-0-288-0) +assign vp_beg[0] = v60hz ? 9'd046 : 9'd080; // 192 (22-24-192-24)/(32-48-192-48) (blank-border-pixels-border) +assign vp_beg[1] = v60hz ? 9'd042 : 9'd076; // 200 (22-20-200-20)/(32-44-200-44) +assign vp_beg[2] = v60hz ? 9'd022 : 9'd056; // 240 (22-0-240-0)/(32-24-240-24) +assign vp_beg[3] = v60hz ? 9'd022 : 9'd032; // 288 (22-0-240-0)/(32-0-288-0) - assign vp_end[0] = v60hz ? 9'd238 : 9'd272; // 192 - assign vp_end[1] = v60hz ? 9'd242 : 9'd276; // 200 - assign vp_end[2] = v60hz ? 9'd262 : 9'd296; // 240 - assign vp_end[3] = v60hz ? 9'd262 : 9'd320; // 240/288 +assign vp_end[0] = v60hz ? 9'd238 : 9'd272; // 192 +assign vp_end[1] = v60hz ? 9'd242 : 9'd276; // 200 +assign vp_end[2] = v60hz ? 9'd262 : 9'd296; // 240 +assign vp_end[3] = v60hz ? 9'd262 : 9'd320; // 240/288 - assign x_tile[0] = 6'd34; // 256 - assign x_tile[1] = 6'd42; // 320 - assign x_tile[2] = 6'd42; // 320 - assign x_tile[3] = 6'd47; // 360 - - assign hpix_beg = hp_beg[rres]; - assign hpix_end = hp_end[rres]; - assign vpix_beg = vp_beg[rres]; - assign vpix_end = vp_end[rres]; - assign x_tiles = x_tile[rres]; +assign x_tile[0] = 6'd34; // 256 +assign x_tile[1] = 6'd42; // 320 +assign x_tile[2] = 6'd42; // 320 +assign x_tile[3] = 6'd47; // 360 +assign hpix_beg = hp_beg[rres]; +assign hpix_end = hp_end[rres]; +assign vpix_beg = vp_beg[rres]; +assign vpix_end = vp_end[rres]; + +assign hpix_beg_ts = ts_rres_ext ? hp_beg[3] : hp_beg[rres]; +assign hpix_end_ts = ts_rres_ext ? hp_end[3] : hp_end[rres]; +assign vpix_beg_ts = ts_rres_ext ? vp_beg[3] : vp_beg[rres]; +assign vpix_end_ts = ts_rres_ext ? vp_end[3] : vp_end[rres]; + +assign x_tiles = ts_rres_ext ? x_tile[3] : x_tile[rres]; // videomode addresses - wire [20:0] v_addr[0:3]; - assign v_addr[M_ZX] = addr_zx; - assign v_addr[M_HC] = addr_16c; - assign v_addr[M_XC] = addr_256c; - assign v_addr[M_TX] = addr_text; - assign video_addr = v_addr[vmod]; +wire [20:0] v_addr[0:3]; +assign v_addr[M_ZX] = addr_zx; +assign v_addr[M_HC] = addr_16c; +assign v_addr[M_XC] = addr_256c; +assign v_addr[M_TX] = addr_text; +assign video_addr = v_addr[vmod]; - // ZX - wire [20:0] addr_zx = {vpage, 1'b0, ~cnt_col[0] ? addr_zx_gfx : addr_zx_atr}; - wire [11:0] addr_zx_gfx = {cnt_row[7:6], cnt_row[2:0], cnt_row[5:3], cnt_col[4:1]}; - wire [11:0] addr_zx_atr = {3'b110, cnt_row[7:3], cnt_col[4:1]}; +// ZX +wire [20:0] addr_zx = {vpage, 1'b0, ~cnt_col[0] ? addr_zx_gfx : addr_zx_atr}; +wire [11:0] addr_zx_gfx = {cnt_row[7:6], cnt_row[2:0], cnt_row[5:3], cnt_col[4:1]}; +wire [11:0] addr_zx_atr = {3'b110, cnt_row[7:3], cnt_col[4:1]}; - // 16c - wire [20:0] addr_16c = {vpage[7:3], cnt_row, cnt_col[6:0]}; +// 16c +wire [20:0] addr_16c = {vpage[7:3], cnt_row, cnt_col[6:0]}; - // 256c - wire [20:0] addr_256c = {vpage[7:4], cnt_row, cnt_col[7:0]}; +// 256c +wire [20:0] addr_256c = {vpage[7:4], cnt_row, cnt_col[7:0]}; - // Textmode - wire [20:0] addr_text = {vpage[7:1], addr_tx[cnt_col[1:0]]}; - wire [13:0] addr_tx[0:3]; - assign addr_tx[0] = {vpage[0], cnt_row[8:3], 1'b0, cnt_col[7:2]}; // char codes, data[15:0] - assign addr_tx[1] = {vpage[0], cnt_row[8:3], 1'b1, cnt_col[7:2]}; // char attributes, data[31:16] - assign addr_tx[2] = {~vpage[0], 3'b000, (txt_char[7:0]), cnt_row[2:1]}; // char0 graphics, data[7:0] - assign addr_tx[3] = {~vpage[0], 3'b000, (txt_char[15:8]), cnt_row[2:1]}; // char1 graphics, data[15:8] +// Textmode +wire [20:0] addr_text = {vpage[7:1], addr_tx[cnt_col[1:0]]}; +wire [13:0] addr_tx[0:3]; +assign addr_tx[0] = {vpage[0], cnt_row[8:3], 1'b0, cnt_col[7:2]}; // char codes, data[15:0] +assign addr_tx[1] = {vpage[0], cnt_row[8:3], 1'b1, cnt_col[7:2]}; // char attributes, data[31:16] +assign addr_tx[2] = {~vpage[0], 3'b000, (txt_char[7:0]), cnt_row[2:1]}; // char0 graphics, data[7:0] +assign addr_tx[3] = {~vpage[0], 3'b000, (txt_char[15:8]), cnt_row[2:1]}; // char1 graphics, data[15:8] endmodule diff --git a/src/video/video_out.v b/src/video/video_out.v index 3da696b..0ba9fcb 100644 --- a/src/video/video_out.v +++ b/src/video/video_out.v @@ -1,76 +1,68 @@ // This module generates video for DAC -// MVV corrected 24bpp 24.08.2014 +// (c)2015 TSL -module video_out ( - -// clocks +module video_out +( + // clocks input wire clk, f0, c3, -// video controls + // video controls input wire vga_on, input wire tv_blank, - input wire vga_blank, + input wire vga_blank, input wire [1:0] plex_sel_in, -// mode controls + // mode controls input wire tv_hires, input wire vga_hires, input wire [3:0] palsel, -// Z80 pins - input wire [14:0] cram_data_in, - input wire [7:0] cram_addr_in, + // Z80 pins + input wire [15:0] cram_data_in, + input wire [7:0] cram_addr_in, input wire cram_we, -// video data - input wire [7:0] vplex_in, //<====== INPUT - input wire [7:0] vgaplex, //<====== INPUT VGA - - output wire [7:0] vred, + // video data + input wire [7:0] vplex_in, + input wire [7:0] vgaplex, + output wire [7:0] vred, output wire [7:0] vgrn, output wire [7:0] vblu, - //--------------------- - output wire [3:0] tst + output wire vdac_mode ); -assign tst[0] = clk; ////phase[0]; -assign tst[1] = cram_we; //phase[1]; -assign tst[2] = cram_addr_in[0]; // -assign tst[3] = cram_data_in[0]; //pwm[3][{phase, 1'b0}]; //!pwm[igrn][{phase, 1'b1}]; - // TV/VGA mux reg [7:0] vplex; -always @(posedge clk) if (c3) vplex <= vplex_in; +always @(posedge clk) if (c3) vplex <= vplex_in; -wire [7:0] plex = vga_on ? vgaplex : vplex; -wire plex_sel = vga_on ? plex_sel_in[0] : plex_sel_in[1]; -wire hires = vga_on ? vga_hires : tv_hires; -wire [7:0] vdata = hires ? {palsel, plex_sel ? plex[3:0] : plex[7:4]} : plex; +wire [7:0] plex = vga_on ? vgaplex : vplex; +wire plex_sel = vga_on ? plex_sel_in[0] : plex_sel_in[1]; +wire hires = vga_on ? vga_hires : tv_hires; +wire [7:0] vdata = hires ? {palsel, plex_sel ? plex[3:0] : plex[7:4]} : plex; -// CRAM ===================================================================== -wire [14:0] vpixel; -dpram #(.DATAWIDTH(15), .ADDRWIDTH(8), .MEM_INIT_FILE("src/video/video_cram.mif")) video_cram +// CRAM +wire [15:0] vpixel; +dpram #(.DATAWIDTH(16), .ADDRWIDTH(8), .MEM_INIT_FILE("src/video/video_cram.mif")) video_cram ( .clock (clk), .address_a(cram_addr_in), .data_a (cram_data_in), .wren_a (cram_we), - .address_b(vdata), //-= HSYNC_BEG) && (hcount < HSYNC_END); - wire vs = (vcount >= vsync_beg) && (vcount < vsync_end); +wire hs = (hcount >= HSYNC_BEG) && (hcount < HSYNC_END); +wire vs = (vcount >= vsync_beg) && (vcount < vsync_end); - assign tv_hblank = (hcount > HBLNK_BEG) && (hcount <= HBLNK_END); - assign tv_vblank = (vcount >= vblnk_beg) && (vcount < vblnk_end); +assign tv_hblank = (hcount > HBLNK_BEG) && (hcount <= HBLNK_END); +assign tv_vblank = (vcount >= vblnk_beg) && (vcount < vblnk_end); - wire vga_hblank1 = (cnt_out > 9'd359); - always @(posedge clk) if (f1) // fix me - bydlocode !!! - vga_hblank <= vga_hblank1; +wire vga_hblank1 = (cnt_out > 9'd359); +always @(posedge clk) if (f1) vga_hblank <= vga_hblank1; - wire hs_vga = ((hcount >= HSYNCV_BEG) && (hcount < HSYNCV_END)) || - ((hcount >= (HSYNCV_BEG + HPERIOD/2)) && (hcount < (HSYNCV_END + HPERIOD/2))); +wire hs_vga = ((hcount >= HSYNCV_BEG) && (hcount < HSYNCV_END)) || + ((hcount >= (HSYNCV_BEG + HPERIOD/2)) && (hcount < (HSYNCV_END + HPERIOD/2))); - wire vga_pix_start = ((hcount == (HBLNKV_END)) || (hcount == (HBLNKV_END + HPERIOD/2))); +wire vga_pix_start = ((hcount == (HBLNKV_END)) || (hcount == (HBLNKV_END + HPERIOD/2))); - assign vga_line = (hcount >= HPERIOD/2); +assign vga_line = (hcount >= HPERIOD/2); - assign hvpix = hpix && vpix; +assign hvpix = hpix && vpix; - assign hpix = (hcount >= hpix_beg) && (hcount < hpix_end); +assign hpix = (hcount >= hpix_beg) && (hcount < hpix_end); - assign vpix = (vcount >= vpix_beg) && (vcount < vpix_end); // vertical pixels window - assign v_ts = (vcount >= (vpix_beg - 1)) && (vcount < (vpix_end - 1)); // vertical TS window - assign v_pf = (vcount >= (vpix_beg - 17)) && (vcount < (vpix_end - 9)); // vertical tilemap prefetch window +assign vpix = (vcount >= vpix_beg) && (vcount < vpix_end); + +assign hvtspix = htspix && vtspix; +wire htspix = (hcount >= hpix_beg_ts) && (hcount < hpix_end_ts); +wire vtspix = (vcount >= vpix_beg_ts) && (vcount < vpix_end_ts); + +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) video_go <= (hcount >= (hpix_beg - go_offs - x_offs)) && (hcount < (hpix_end - go_offs - x_offs + 4)) && vpix && !nogfx; - wire line_start = hcount == (HPERIOD - 1); - assign line_start_s = line_start && c3; - wire line_start2 = hcount == (HSYNC_END - 1); - 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 - 1); - assign ts_start = c3 && ts_start_coarse; - assign int_start = (hcount == {hint_beg, 1'b0}) && (vcount == vint_beg) && c0; +wire line_start = hcount == (HPERIOD - 1); +assign line_start_s = line_start && c3; +wire line_start2 = hcount == (HSYNC_END - 1); +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; +always @(posedge clk) if (line_start_s) vga_vblank <= tv_vblank; - always @(posedge clk) if (line_start_s) // fix me - bydlocode !!! - vga_vblank <= tv_vblank; - - - always @(posedge clk) - begin - hsync <= sync_pol ^ (vga_on ? hs_vga : hs); - vsync <= sync_pol ^ vs; - csync <= ~(vs ^ hs); - end - +always @(posedge clk) begin + hsync <= sync_pol ^ (vga_on ? hs_vga : hs); + vsync <= sync_pol ^ vs; + csync <= ~(vs ^ hs); +end endmodule diff --git a/src/video/video_top.v b/src/video/video_top.v index 206f1a2..750e208 100644 --- a/src/video/video_top.v +++ b/src/video/video_top.v @@ -2,7 +2,7 @@ // This module is a video top-level -module video_top +module video_top ( // clocks input wire clk, @@ -15,17 +15,17 @@ module video_top output wire [7:0] vred, output wire [7:0] vgrn, output wire [7:0] vblu, + output wire vdac_mode, // video syncs output wire hsync, output wire vsync, output wire csync, output wire hblank, - output wire vblank, - output wire pix_stb, + output wire vblank, + output wire pix_stb, // Z80 controls - input wire [15:0] a, input wire [ 7:0] d, input wire [15:0] zmd, input wire [ 7:0] zma, @@ -74,10 +74,8 @@ module video_top input wire video_pre_next, input wire next_video, input wire video_strobe, - input wire video_next_strobe, output wire [20:0] ts_addr, output wire ts_req, - output wire ts_z80_lp, input wire ts_pre_next, input wire ts_next, output wire [20:0] tm_addr, @@ -87,14 +85,10 @@ module video_top // video controls input wire cfg_60hz, input wire sync_pol, - input wire vga_on, - - output wire [3:0] tst + input wire vga_on ); -assign ts_z80_lp = tsconf[4]; - // video config wire [7:0] vpage; // re-latched at line_start wire [7:0] vconf; // @@ -116,6 +110,10 @@ wire [8:0] hpix_beg; wire [8:0] hpix_end; wire [8:0] vpix_beg; wire [8:0] vpix_end; +wire [8:0] hpix_beg_ts; +wire [8:0] hpix_end_ts; +wire [8:0] vpix_beg_ts; +wire [8:0] vpix_end_ts; wire [5:0] x_tiles; wire [9:0] x_offs_mode; wire [4:0] go_offs; @@ -123,16 +121,13 @@ wire [1:0] render_mode; wire tv_hires; wire vga_hires; wire v60hz; -//===zx-evo-fpga-564db5e984ef === wire nogfx = vconf[5]; wire notsu = vconf[4]; wire gfxovr = vconf[3]; -//wire gfxovr; -//=============================== wire tv_hblank; -wire tv_vblank; -wire vga_hblank; -wire vga_vblank; +wire tv_vblank; +wire vga_hblank; +wire vga_vblank; // counters wire [7:0] cnt_col; @@ -142,6 +137,7 @@ wire [3:0] scnt; wire [8:0] lcount; // synchro +wire frame_start; wire pix_start; wire tv_pix_start; wire vga_pix_start; @@ -151,6 +147,7 @@ wire v_pf; wire hpix; wire vpix; wire hvpix; +wire hvtspix; wire flash; // fetcher @@ -177,9 +174,6 @@ wire [3:0] tsr_pal; wire tsr_rdy; // TS-line -// wire [8:0] ts_waddr = a[8:0]; -// wire [7:0] ts_wdata = {d[7:1], 1'b1}; -// wire ts_we = c3; wire [8:0] ts_waddr; wire [7:0] ts_wdata; wire ts_we; @@ -189,7 +183,8 @@ wire [8:0] ts_raddr; wire [9:0] vga_cnt_in; wire [9:0] vga_cnt_out; -video_ports video_ports ( +video_ports video_ports +( .clk (clk), .d (d), .res (res), @@ -232,6 +227,7 @@ video_ports video_ports ( .palsel (palsel), .hint_beg (hint_beg), .vint_beg (vint_beg), + .int_start (0), .tsconf (tsconf), .tmpage (tmpage), .t0gpage (t0gpage), @@ -240,7 +236,8 @@ video_ports video_ports ( ); -video_mode video_mode ( +video_mode video_mode +( .clk (clk), .f1 (f1), .c3 (c3), @@ -254,10 +251,15 @@ video_mode video_mode ( .txt_char (fetch_temp[15:0]), .gx_offs (gx_offs), .x_offs_mode (x_offs_mode), + .ts_rres_ext (tsconf[0]), .hpix_beg (hpix_beg), .hpix_end (hpix_end), .vpix_beg (vpix_beg), .vpix_end (vpix_end), + .hpix_beg_ts (hpix_beg_ts), + .hpix_end_ts (hpix_end_ts), + .vpix_beg_ts (vpix_beg_ts), + .vpix_end_ts (vpix_end_ts), .x_tiles (x_tiles), .go_offs (go_offs), .cnt_col (cnt_col), @@ -274,7 +276,8 @@ video_mode video_mode ( ); -video_sync video_sync ( +video_sync video_sync +( .clk (clk), .f1 (f1), .c0 (c0), @@ -284,6 +287,10 @@ video_sync video_sync ( .hpix_end (hpix_end), .vpix_beg (vpix_beg), .vpix_end (vpix_end), + .hpix_beg_ts (hpix_beg_ts), + .hpix_end_ts (hpix_end_ts), + .vpix_beg_ts (vpix_beg_ts), + .vpix_end_ts (vpix_end_ts), .go_offs (go_offs), .x_offs (x_offs_mode[1:0]), .y_offs_wr (gy_offsl_wr || gy_offsh_wr), @@ -294,8 +301,8 @@ video_sync video_sync ( .vsync (vsync), .csync (csync), .tv_hblank (tv_hblank), - .tv_vblank (tv_vblank), - .vga_hblank (vga_hblank), + .tv_vblank (tv_vblank), + .vga_hblank (vga_hblank), .vga_vblank (vga_vblank), .vga_cnt_in (vga_cnt_in), .vga_cnt_out (vga_cnt_out), @@ -311,23 +318,26 @@ video_sync video_sync ( .ts_start (ts_start), .cstart (x_offs_mode[9:2]), .rstart (gy_offs), + .frame_start (frame_start), .int_start (int_start), .v_pf (v_pf), .hpix (hpix), .v_ts (v_ts), .vpix (vpix), .hvpix (hvpix), + .hvtspix (hvtspix), .nogfx (nogfx), .cfg_60hz (cfg_60hz), .sync_pol (sync_pol), .v60hz (v60hz), - .vga_on (vga_on), + .vga_on (vga_on), .video_go (video_go), .video_pre_next(video_pre_next) ); -video_fetch video_fetch ( +video_fetch video_fetch +( .clk (clk), .f_sel (fetch_sel), .b_sel (fetch_bsl), @@ -338,7 +348,8 @@ video_fetch video_fetch ( .video_data (dram_rdata) ); -video_ts video_ts ( +video_ts video_ts +( .clk (clk), .start (ts_start), .line (lcount), @@ -378,8 +389,8 @@ video_ts video_ts ( .sfile_we (sfile_we) ); - -video_ts_render video_ts_render ( +video_ts_render video_ts_render +( .clk (clk), .reset (ts_start), @@ -406,10 +417,12 @@ video_ts_render video_ts_render ( ); -video_render video_render ( +video_render video_render +( .clk (clk), .c1 (c1), .hvpix (hvpix), + .hvtspix (hvtspix), .nogfx (nogfx), .notsu (notsu), .gfxovr (gfxovr), @@ -424,45 +437,46 @@ video_render video_render ( .vplex_out (vplex) ); -video_out video_out ( +video_out video_out +( .clk (clk), .f0 (f0), .c3 (c3), .vga_on (vga_on), .tv_blank (tv_hblank|tv_vblank), - .vga_blank (vga_hblank|vga_vblank), + .vga_blank (vga_hblank|vga_vblank), .palsel (palsel[3:0]), .plex_sel_in ({h1, f1}), .tv_hires (tv_hires), .vga_hires (vga_hires), .cram_addr_in (zma), - .cram_data_in (zmd[14:0]), + .cram_data_in (zmd[15:0]), .cram_we (cram_we), .vplex_in (vplex), .vgaplex (vgaplex), - .vred (vred), - .vgrn (vgrn), + .vred (vred), + .vgrn (vgrn), .vblu (vblu), - .tst (tst) + .vdac_mode (vdac_mode) ); - + assign hblank = vga_on ? vga_hblank : tv_hblank; -assign vblank = vga_on ? vga_vblank : tv_vblank; +assign vblank = vga_on ? vga_vblank : tv_vblank; // 2 buffers: 512 pixels * 8 bits (9x8) - used as bitmap buffer for TS overlay over graphics // (2 altdprams) wire tl_act0 = lcount[0]; wire tl_act1 = ~lcount[0]; -wire [8:0] ts_waddr0 = tl_act0 ? ts_raddr : ts_waddr; -wire [7:0] ts_wdata0 = tl_act0 ? 8'd0 : ts_wdata; -wire ts_we0 = tl_act0 ? c3 : ts_we; -wire [8:0] ts_waddr1 = tl_act1 ? ts_raddr : ts_waddr; -wire [7:0] ts_wdata1 = tl_act1 ? 8'd0 : ts_wdata; -wire ts_we1 = tl_act1 ? c3 : ts_we; +wire [8:0] ts_waddr0 = tl_act0 ? ts_raddr : ts_waddr; +wire [7:0] ts_wdata0 = tl_act0 ? 8'd0 : ts_wdata; +wire ts_we0 = tl_act0 ? c3 : ts_we; +wire [8:0] ts_waddr1 = tl_act1 ? ts_raddr : ts_waddr; +wire [7:0] ts_wdata1 = tl_act1 ? 8'd0 : ts_wdata; +wire ts_we1 = tl_act1 ? c3 : ts_we; wire [7:0] ts_rdata = tl_act0 ? ts_rdata0 : ts_rdata1; wire [7:0] ts_rdata0, ts_rdata1; -dpram #(.ADDRWIDTH(9)) video_tsline0 +dpram #(.ADDRWIDTH(9)) video_tsline0 ( .clock (clk), .address_a (ts_waddr0), @@ -470,9 +484,9 @@ dpram #(.ADDRWIDTH(9)) video_tsline0 .wren_a (ts_we0), .address_b (ts_raddr), .q_b (ts_rdata0) -); +); -dpram #(.ADDRWIDTH(9)) video_tsline1 +dpram #(.ADDRWIDTH(9)) video_tsline1 ( .clock (clk), .address_a (ts_waddr1), @@ -484,7 +498,7 @@ dpram #(.ADDRWIDTH(9)) video_tsline1 // 2 lines * 512 pix * 8 bit (10x8) - used for VGA doubler // (1 altdpram) -dpram #(.ADDRWIDTH(10)) video_vmem +dpram #(.ADDRWIDTH(10)) video_vmem ( .clock (clk), .address_a (vga_cnt_in), @@ -492,7 +506,7 @@ dpram #(.ADDRWIDTH(10)) video_vmem .wren_a (c3), .address_b (vga_cnt_out), .q_b (vgaplex) -); +); endmodule diff --git a/src/video/video_ts.v b/src/video/video_ts.v index 383fd22..065f189 100644 --- a/src/video/video_ts.v +++ b/src/video/video_ts.v @@ -59,319 +59,296 @@ module video_ts output wire [20:0] dram_addr, output wire dram_req, input wire dram_next, - input wire [15:0] dram_rdata, - - output wire [2:0] tst + input wire [15:0] dram_rdata ); // config - wire s_en = tsconf[7]; - wire t1_en = tsconf[6]; - wire t0_en = tsconf[5]; - wire t1z_en = tsconf[3]; - wire t0z_en = tsconf[2]; +wire s_en = tsconf[7]; +wire t1_en = tsconf[6]; +wire t0_en = tsconf[5]; +wire t1z_en = tsconf[3]; +wire t0z_en = tsconf[2]; // TS renderer interface - assign tsr_go = sprite_go || tile_go; - assign tsr_x = sprites ? sprites_x : tile_x; - assign tsr_xs = sprites ? sprites_xs : 3'd0; - assign tsr_xf = sprites ? sprites_xf : t_xflp; - assign tsr_page = sprites ? sgpage : tile_page; - assign tsr_line = sprites ? sprites_line : tile_line; - assign tsr_addr = sprites ? sprites_addr : tile_addr; - assign tsr_pal = sprites ? s_pal : tile_pal; +assign tsr_go = sprite_go || tile_go; +assign tsr_x = sprites ? sprites_x : tile_x; +assign tsr_xs = sprites ? sprites_xs : 3'd0; +assign tsr_xf = sprites ? sprites_xf : t_xflp; +assign tsr_page = sprites ? sgpage : tile_page; +assign tsr_line = sprites ? sprites_line : tile_line; +assign tsr_addr = sprites ? sprites_addr : tile_addr; +assign tsr_pal = sprites ? s_pal : tile_pal; // Layer selectors control - // DEBUG !!! - assign tst = lyr; - reg [2:0] lyr; - always@* - // if (layer_active[S0]) - // lyr = 2; - // else if (layer_active[S1]) - // lyr = 6; - // else if (layer_active[S2]) - // lyr = 4; - // else if (layer_active[TM]) - // lyr = 1; - // else if (layer_active[T0]) - // lyr = 3; - // else if (layer_active[T1]) - // lyr = 5; - // else lyr = 0; - lyr = 0; - // lyr = sr_valid; +localparam LAYERS = 6; // Total number of layers to process +localparam TM = 0; // Individual layers +localparam S0 = 1; +localparam T0 = 2; +localparam S1 = 3; +localparam T1 = 4; +localparam S2 = 5; - localparam LAYERS = 6; // Total number of layers to process - localparam TM = 0; // Individual layers - localparam S0 = 1; - localparam T0 = 2; - localparam S1 = 3; - localparam T1 = 4; - localparam S2 = 5; +wire tmap = layer_active[TM]; +wire sprites = layer_active[S0] || layer_active[S1] || layer_active[S2]; +wire tiles = layer_active[T0] || layer_active[T1]; - wire tmap = layer_active[TM]; - wire sprites = layer_active[S0] || layer_active[S1] || layer_active[S2]; - wire tiles = layer_active[T0] || layer_active[T1]; +reg [LAYERS-1:0] layer; +always @(posedge clk) + if (start) + layer <= 1; + else if (|(layer & layer_skip)) + layer <= {layer[LAYERS-2:0], 1'b0}; - reg [LAYERS-1:0] layer; - always @(posedge clk) - if (start) - layer <= 1; - else if (|(layer & layer_skip)) - layer <= {layer[LAYERS-2:0], 1'b0}; +reg [LAYERS-1:0] layer_active; +always @(posedge clk) + if (start) + layer_active <= 0; + else + layer_active <= layer & ~layer_skip; - reg [LAYERS-1:0] layer_active; - always @(posedge clk) - if (start) - layer_active <= 0; - else - layer_active <= layer & ~layer_skip; +wire [LAYERS-1:0] layer_enabled = {s_en, t1_en, s_en, t0_en, s_en, t1_en || t0_en}; +wire [LAYERS-1:0] layer_allowed = {{5{v_ts}}, v_pf}; +wire [LAYERS-1:0] layer_end = {spr_end[2], tile_end[1], spr_end[1], tile_end[0], spr_end[0], tm_end}; - wire [LAYERS-1:0] layer_enabled = {s_en, t1_en, s_en, t0_en, s_en, t1_en || t0_en}; - wire [LAYERS-1:0] layer_allowed = {{5{v_ts}}, v_pf}; - wire [LAYERS-1:0] layer_end = {spr_end[2], tile_end[1], spr_end[1], tile_end[0], spr_end[0], tm_end}; - - reg [LAYERS-1:0] layer_skip; - always @(posedge clk) - if (start) - layer_skip <= ~(layer_enabled & layer_allowed); - else - layer_skip <= layer_skip | layer_end; +reg [LAYERS-1:0] layer_skip; +always @(posedge clk) + if (start) + layer_skip <= ~(layer_enabled & layer_allowed); + else + layer_skip <= layer_skip | layer_end; // --- Tile map prefetch --- - // DRAM controls - assign dram_addr = {tmpage, tm_b_row, tm_layer, tm_b_line, tm_num}; // 20:13 - page, 12:7 - row, 6 - layer, 5:0 - column (burst number : number in burst) - assign dram_req = tmap; +// DRAM controls +assign dram_addr = {tmpage, tm_b_row, tm_layer, tm_b_line, tm_num}; // 20:13 - page, 12:7 - row, 6 - layer, 5:0 - column (burst number : number in burst) +assign dram_req = tmap; - // TMB control - wire [8:0] tmb_waddr = {tm_line[4:3], tm_b_line, tm_num, tm_layer}; // 8:7 - buffer #, 6:4 - burst number (of 8 bursts), 3:1 - number in burst (8 tiles per burst), 0 - layer - wire [8:0] tm_line = line + 9'd16; - wire [2:0] tm_b_line = tm_line[2:0]; - wire [5:0] tm_b_row = tm_line[8:3] + (tm_layer ? t1y_offs[8:3] : t0y_offs[8:3]); - wire [2:0] tm_num = tm_x[2:0]; - wire tm_layer = tm_x[3]; + // TMB control +wire [8:0] tmb_waddr = {tm_line[4:3], tm_b_line, tm_num, tm_layer}; // 8:7 - buffer #, 6:4 - burst number (of 8 bursts), 3:1 - number in burst (8 tiles per burst), 0 - layer +wire [8:0] tm_line = line + 9'd16; +wire [2:0] tm_b_line = tm_line[2:0]; +wire [5:0] tm_b_row = tm_line[8:3] + (tm_layer ? t1y_offs[8:3] : t0y_offs[8:3]); +wire [2:0] tm_num = tm_x[2:0]; +wire tm_layer = tm_x[3]; - // internal layers control - wire tm_end = tm_x == (t1_en ? 5'd16 : 5'd8); - wire tm_next = dram_next && tmap; +// internal layers control +wire tm_end = tm_x == (t1_en ? 5'd16 : 5'd8); +wire tm_next = dram_next && tmap; - reg [1:0] m_layer; - always @(posedge clk) - if (start) - m_layer <= 2'b1; - else if (tm_end) - m_layer <= {m_layer[0], 1'b0}; +reg [1:0] m_layer; +always @(posedge clk) + if (start) + m_layer <= 2'b1; + else if (tm_end) + m_layer <= {m_layer[0], 1'b0}; - // tilemap X coordinate - reg [4:0] tm_x; - always @(posedge clk) - if (start) - tm_x <= t0_en ? 5'd0 : 5'd8; - else if (tm_next) - tm_x <= tm_x + 5'd1; +// tilemap X coordinate +reg [4:0] tm_x; +always @(posedge clk) + if (start) + tm_x <= t0_en ? 5'd0 : 5'd8; + else if (tm_next) + tm_x <= tm_x + 5'd1; // --- Tiles --- - // tile descriptor fields - wire [11:0] t_tnum = tmb_rdata[11:0]; - wire [1:0] t_pal = tmb_rdata[13:12]; - wire t_xflp = tmb_rdata[14]; - wire t_yflp = tmb_rdata[15]; +// tile descriptor fields +wire [11:0] t_tnum = tmb_rdata[11:0]; +wire [1:0] t_pal = tmb_rdata[13:12]; +wire t_xflp = tmb_rdata[14]; +wire t_yflp = tmb_rdata[15]; - // TSR control - wire [7:0] tile_page = t_sel ? t0gpage : t1gpage; - wire [8:0] tile_line = {t_tnum[11:6], (t_line[2:0] ^ {3{t_yflp}})}; - wire [5:0] tile_addr = t_tnum[5:0]; - wire [8:0] tile_x = {(tx - 6'd1), 3'd0} - tx_offs[2:0]; - wire [3:0] tile_pal = {t_sel ? t0_palsel : t1_palsel, t_pal}; +// TSR control +wire [7:0] tile_page = t_sel ? t0gpage : t1gpage; +wire [8:0] tile_line = {t_tnum[11:6], (t_line[2:0] ^ {3{t_yflp}})}; +wire [5:0] tile_addr = t_tnum[5:0]; +wire [8:0] tile_x = {(tx - 6'd1), 3'd0} - tx_offs[2:0]; +wire [3:0] tile_pal = {t_sel ? t0_palsel : t1_palsel, t_pal}; - // TMB control - wire [8:0] tmb_raddr = {t_line[4:3], tx + tx_offs[8:3], ~t_sel}; +// TMB control +wire [8:0] tmb_raddr = {t_line[4:3], tx + tx_offs[8:3], ~t_sel}; - // layer parameter selectors - wire [8:0] tx_offs = t_sel ? t0x_offs : t1x_offs; - wire [3:0] ty_offs = t_sel ? t0y_offs[2:0] : t1y_offs[2:0]; - wire t_sel = t_layer[0]; +// layer parameter selectors +wire [8:0] tx_offs = t_sel ? t0x_offs : t1x_offs; +wire [3:0] ty_offs = t_sel ? t0y_offs[2:0] : t1y_offs[2:0]; +wire t_sel = t_layer[0]; - // internal layers control - wire [1:0] tile_end = {2{t_layer_end}} & t_layer[1:0]; - wire t_layer_end = tx == num_tiles; - wire t_layer_start = start || t_layer_end; +// internal layers control +wire [1:0] tile_end = {2{t_layer_end}} & t_layer[1:0]; +wire t_layer_end = tx == num_tiles; +wire t_layer_start = start || t_layer_end; - reg [1:0] t_layer; - always @(posedge clk) - if (start) - t_layer <= t0_en ? 2'b01 : 2'b10; - else if (t_layer_end) - t_layer <= {t_layer[0], 1'b0}; +reg [1:0] t_layer; +always @(posedge clk) + if (start) + t_layer <= t0_en ? 2'b01 : 2'b10; + else if (t_layer_end) + t_layer <= {t_layer[0], 1'b0}; - // TMBUF control - // condition write to tx write to tm_valid - // t_layer_start 0 TM_PRE_VALID - // tm_pre_valid tx+1 TM_VALID - // tile_skip tx+1 - - // tile_go tx+1 TM_VALID - // tile_wait tx-1 TM_PRE_VALID +// TMBUF control + // condition write to tx write to tm_valid + // t_layer_start 0 TM_PRE_VALID + // tm_pre_valid tx+1 TM_VALID + // tile_skip tx+1 - + // tile_go tx+1 TM_VALID + // tile_wait tx-1 TM_PRE_VALID - localparam TM_PRE_VALID = 2'b01; - localparam TM_VALID = 2'b10; +localparam TM_PRE_VALID = 2'b01; +localparam TM_VALID = 2'b10; - wire tile_go = tile_good && tsr_allowed; - wire tile_wait = tile_good && !tsr_allowed; - wire tile_good = tm_valid && tile_valid; - wire tile_skip = tm_valid && !tile_valid; - wire tsr_allowed = tiles && tsr_rdy; - wire tile_valid = |t_tnum || (t_sel ? t0z_en : t1z_en); +wire tile_go = tile_good && tsr_allowed; +wire tile_wait = tile_good && !tsr_allowed; +wire tile_good = tm_valid && tile_valid; +wire tile_skip = tm_valid && !tile_valid; +wire tsr_allowed = tiles && tsr_rdy; +wire tile_valid = |t_tnum || (t_sel ? t0z_en : t1z_en); - wire tm_pre_valid = tm_valid_r[0]; - wire tm_valid = tm_valid_r[1]; +wire tm_pre_valid = tm_valid_r[0]; +wire tm_valid = tm_valid_r[1]; - reg [1:0] tm_valid_r; - always @(posedge clk) - if (t_layer_start || tile_wait) - tm_valid_r <= TM_PRE_VALID; - else if (tm_pre_valid || tile_go) - tm_valid_r <= TM_VALID; +reg [1:0] tm_valid_r; +always @(posedge clk) + if (t_layer_start || tile_wait) + tm_valid_r <= TM_PRE_VALID; + else if (tm_pre_valid || tile_go) + tm_valid_r <= TM_VALID; - reg [5:0] tx; - always @(posedge clk) - if (t_layer_start) - tx <= 6'd0; - else if (tm_pre_valid || tile_skip || tile_go) - tx <= tx + 6'd1; - else if (tile_wait) - tx <= tx - 6'd1; +reg [5:0] tx; +always @(posedge clk) + if (t_layer_start) + tx <= 6'd0; + else if (tm_pre_valid || tile_skip || tile_go) + tx <= tx + 6'd1; + else if (tile_wait) + tx <= tx - 6'd1; - // tile Y geometry - wire [4:0] t_line = line[4:0] + ty_offs; +// tile Y geometry +wire [4:0] t_line = line[4:0] + ty_offs; // --- Sprites --- - // sprite descriptor fields - // R0 - wire [8:0] s_ycrd = sfile_rdata[8:0]; - wire [2:0] s_ysz = sfile_rdata[11:9]; - wire s_act = sfile_rdata[13]; - wire s_leap = sfile_rdata[14]; - wire s_yflp = sfile_rdata[15]; - // R1 - wire [8:0] s_xcrd = sfile_rdata[8:0]; - wire [2:0] s_xsz = sfile_rdata[11:9]; - wire s_xflp = sfile_rdata[15]; - // R2 - wire [11:0] s_tnum = sfile_rdata[11:0]; - wire [3:0] s_pal = sfile_rdata[15:12]; +// sprite descriptor fields +// R0 +wire [8:0] s_ycrd = sfile_rdata[8:0]; +wire [2:0] s_ysz = sfile_rdata[11:9]; +wire s_act = sfile_rdata[13]; +wire s_leap = sfile_rdata[14]; +wire s_yflp = sfile_rdata[15]; +// R1 +wire [8:0] s_xcrd = sfile_rdata[8:0]; +wire [2:0] s_xsz = sfile_rdata[11:9]; +wire s_xflp = sfile_rdata[15]; +// R2 +wire [11:0] s_tnum = sfile_rdata[11:0]; +wire [3:0] s_pal = sfile_rdata[15:12]; - // TSR control - reg [8:0] sprites_x; - reg [2:0] sprites_xs; - reg sprites_xf; - wire [5:0] sprites_addr = s_tnum[5:0]; +// TSR control +reg [8:0] sprites_x; +reg [2:0] sprites_xs; +reg sprites_xf; +wire [5:0] sprites_addr = s_tnum[5:0]; - // internal layers control - wire [2:0] spr_end = ({3{s_layer_end}} & s_layer[2:0]) | {3{sprites_last}}; - wire s_layer_end = (sr0_valid && !spr_valid && s_leap) || (sprite_go && s_leap_r); - wire sprites_last = sreg == 8'd255; +// internal layers control +wire [2:0] spr_end = ({3{s_layer_end}} & s_layer[2:0]) | {3{sprites_last}}; +wire s_layer_end = (sr0_valid && !spr_valid && s_leap) || (sprite_go && s_leap_r); +wire sprites_last = sreg == 8'd255; - reg [2:0] s_layer; - always @(posedge clk) - if (start) - s_layer <= 3'b1; - else if (s_layer_end) - s_layer <= {s_layer[1:0], 1'b0}; +reg [2:0] s_layer; +always @(posedge clk) + if (start) + s_layer <= 3'b1; + else if (s_layer_end) + s_layer <= {s_layer[1:0], 1'b0}; - // SFile registers control - // condition write to sreg write to sr_valid action - // start 0 SR0_PRE_VALID Start - // sr0_pre_valid sreg+3 SR0_VALID SR0 pre-read - // sr0_valid && !spr_valid sreg+3 - Skip sprite - // sr0_valid && spr_valid sreg-2 SR1_PRE_VALID SR1 pre-read - // sr1_pre_valid sreg+1 SR1_VALID SR1 read - // sr1_valid sreg+1 SR2_VALID SR2 pre-read - // sr2_valid && !tsr_rdy - - Wait for TSR ready - // sr2_valid && tsr_rdy sreg+1 SR0_PRE_VALID Next sprite - // sprites_last - NONE_VALID End +// SFile registers control + // condition write to sreg write to sr_valid action + // start 0 SR0_PRE_VALID Start + // sr0_pre_valid sreg+3 SR0_VALID SR0 pre-read + // sr0_valid && !spr_valid sreg+3 - Skip sprite + // sr0_valid && spr_valid sreg-2 SR1_PRE_VALID SR1 pre-read + // sr1_pre_valid sreg+1 SR1_VALID SR1 read + // sr1_valid sreg+1 SR2_VALID SR2 pre-read + // sr2_valid && !tsr_rdy - - Wait for TSR ready + // sr2_valid && tsr_rdy sreg+1 SR0_PRE_VALID Next sprite + // sprites_last - NONE_VALID End - localparam NONE_VALID = 5'b00000; - localparam SR0_PRE_VALID = 5'b00001; - localparam SR0_VALID = 5'b00010; - localparam SR1_PRE_VALID = 5'b00100; - localparam SR1_VALID = 5'b01000; - localparam SR2_VALID = 5'b10000; +localparam NONE_VALID = 5'b00000; +localparam SR0_PRE_VALID = 5'b00001; +localparam SR0_VALID = 5'b00010; +localparam SR1_PRE_VALID = 5'b00100; +localparam SR1_VALID = 5'b01000; +localparam SR2_VALID = 5'b10000; - wire sprite_go = sr2_valid && sprites && tsr_rdy; // kick to renderer - wire spr_valid = s_visible && s_act; +wire sprite_go = sr2_valid && sprites && tsr_rdy; // kick to renderer +wire spr_valid = s_visible && s_act; - wire sr0_pre_valid = sr_valid[0]; - wire sr0_valid = sr_valid[1]; - wire sr1_pre_valid = sr_valid[2]; - wire sr1_valid = sr_valid[3]; - wire sr2_valid = sr_valid[4]; +wire sr0_pre_valid = sr_valid[0]; +wire sr0_valid = sr_valid[1]; +wire sr1_pre_valid = sr_valid[2]; +wire sr1_valid = sr_valid[3]; +wire sr2_valid = sr_valid[4]; - reg [4:0] sr_valid; - always @(posedge clk) - if (start) - sr_valid <= SR0_PRE_VALID; - else if (sprites_last) - sr_valid <= NONE_VALID; - else if (sr0_pre_valid) - sr_valid <= SR0_VALID; - else if (sr0_valid && spr_valid) - sr_valid <= SR1_PRE_VALID; - else if (sr1_pre_valid) - sr_valid <= SR1_VALID; - else if (sr1_valid) - sr_valid <= SR2_VALID; - else if (sprite_go) - sr_valid <= SR0_PRE_VALID; +reg [4:0] sr_valid; +always @(posedge clk) + if (start) + sr_valid <= SR0_PRE_VALID; + else if (sprites_last) + sr_valid <= NONE_VALID; + else if (sr0_pre_valid) + sr_valid <= SR0_VALID; + else if (sr0_valid && spr_valid) + sr_valid <= SR1_PRE_VALID; + else if (sr1_pre_valid) + sr_valid <= SR1_VALID; + else if (sr1_valid) + sr_valid <= SR2_VALID; + else if (sprite_go) + sr_valid <= SR0_PRE_VALID; - reg [7:0] sreg; - always @(posedge clk) - if (start) - sreg <= 8'd0; - else if (sr0_pre_valid) - sreg <= sreg + 8'd3; - else if (sr0_valid) - sreg <= spr_valid ? (sreg - 8'd2) : (sreg + 8'd3); - else if (sr1_pre_valid || sprite_go) - sreg <= sreg + 8'd1; +reg [7:0] sreg; +always @(posedge clk) + if (start) + sreg <= 8'd0; + else if (sr0_pre_valid) + sreg <= sreg + 8'd3; + else if (sr0_valid) + sreg <= spr_valid ? (sreg - 8'd2) : (sreg + 8'd3); + else if (sr1_pre_valid || sprite_go) + sreg <= sreg + 8'd1; - // SFile control - reg [5:0] s_bmline_offset_r; - reg s_leap_r; +// SFile control +reg [5:0] s_bmline_offset_r; +reg s_leap_r; - always @(posedge clk) +always @(posedge clk) begin + if (sr0_valid) begin - if (sr0_valid) - begin - s_leap_r <= s_leap; - s_bmline_offset_r <= s_bmline_offset; - end - - if (sr1_valid) - begin - sprites_x <= s_xcrd; - sprites_xs <= s_xsz; - sprites_xf <= s_xflp; - end + s_leap_r <= s_leap; + s_bmline_offset_r <= s_bmline_offset; end - // sprite Y geometry - wire [8:0] s_line = line - s_ycrd; // visible line of sprite in current video line - wire s_visible = (s_line <= s_ymax); // check if sprite line is within Y size - wire [5:0] s_ymax = {s_ysz, 3'b111}; + if (sr1_valid) + begin + sprites_x <= s_xcrd; + sprites_xs <= s_xsz; + sprites_xf <= s_xflp; + end +end - wire [8:0] sprites_line = {s_tnum[11:6], 3'b0} + s_bmline_offset_r; - wire [5:0] s_bmline_offset = s_yflp ? (s_ymax - s_line[5:0]) : s_line[5:0]; +// sprite Y geometry +wire [8:0] s_line = line - s_ycrd; // visible line of sprite in current video line +wire s_visible = (s_line <= s_ymax); // check if sprite line is within Y size +wire [5:0] s_ymax = {s_ysz, 3'b111}; + +wire [8:0] sprites_line = {s_tnum[11:6], 3'b0} + s_bmline_offset_r; +wire [5:0] s_bmline_offset = s_yflp ? (s_ymax - s_line[5:0]) : s_line[5:0]; // SFile diff --git a/src/video/video_ts_render.v b/src/video/video_ts_render.v index 4066a36..ae6f991 100644 --- a/src/video/video_ts_render.v +++ b/src/video/video_ts_render.v @@ -15,12 +15,12 @@ // after TS request recognized and processed by DRAM controller. // It is recommended to assert 'tsr_go' at 'c2'. -module video_ts_render ( - -// clocks +module video_ts_render +( + // clocks input wire clk, -// controls + // controls input wire reset, // line start strobe, inits the machine input wire [ 8:0] x_coord, // address in TS-line where render to, auto-flipped to match 'flip' times 'x_size' @@ -34,122 +34,117 @@ module video_ts_render ( input wire [ 3:0] pal, // palette selector, bits[7:4] of CRAM address output wire mem_rdy, // ready to receive new task -// TS-Line interface + // TS-Line interface output reg [ 8:0] ts_waddr, output wire [ 7:0] ts_wdata, output wire ts_we, -// DRAM interface + // DRAM interface output wire [20:0] dram_addr, output wire dram_req, input wire [15:0] dram_rdata, input wire dram_pre_next, input wire dram_next - ); // DRAM request - assign dram_req = tsr_go || !mem_rdy; +assign dram_req = tsr_go || !mem_rdy; // DRAM addressing - assign dram_addr = tsr_go ? addr_in : addr_next; - wire [20:0] addr_in = {addr_offset, addr, 1'b0}; - wire [13:0] addr_offset = {page[7:3], line}; - wire [20:0] addr_next = {addr_reg[20:7], addr_reg[6:0] + dram_next}; - // as renderer can't move outside the single bitmap line, only 7 bits are processed +assign dram_addr = tsr_go ? addr_in : addr_next; +wire [20:0] addr_in = {addr_offset, addr, 1'b0}; +wire [13:0] addr_offset = {page[7:3], line}; +wire [20:0] addr_next = {addr_reg[20:7], addr_reg[6:0] + dram_next}; +// as renderer can't move outside the single bitmap line, only 7 bits are processed - reg [20:0] addr_reg; - always @(posedge clk) - addr_reg <= dram_addr; +reg [20:0] addr_reg; +always @(posedge clk) addr_reg <= dram_addr; // DRAM cycles counter - assign mem_rdy = cyc[4]; +assign mem_rdy = cyc[4]; - reg [4:0] cyc; - always @(posedge clk) - if (reset) - cyc <= 5'b10000; - else if (tsr_go) - cyc <= {1'b0, x_size, 1'b1}; - else if (dram_pre_next) - cyc <= cyc - 5'd1; +reg [4:0] cyc; +always @(posedge clk) + if (reset) + cyc <= 5'b10000; + else if (tsr_go) + cyc <= {1'b0, x_size, 1'b1}; + else if (dram_pre_next) + cyc <= cyc - 5'd1; // DRAM data fetching - reg [15:0] data; - always @(posedge clk) - if (dram_next) - data <= dram_rdata; +reg [15:0] data; +always @(posedge clk) if (dram_next) data <= dram_rdata; // pixel render counter - assign ts_we = render_on && |pix; // write signal for TS-line - wire render_on = !cnt[2]; +assign ts_we = render_on && |pix; // write signal for TS-line +wire render_on = !cnt[2]; - reg [2:0] cnt; - always @(posedge clk) - if (reset) - cnt <= 3'b100; - else if (dram_next) - cnt <= 3'b000; - else if (render_on) - cnt <= cnt + 3'd1; +reg [2:0] cnt; +always @(posedge clk) + if (reset) + cnt <= 3'b100; + else if (dram_next) + cnt <= 3'b000; + else if (render_on) + cnt <= cnt + 3'd1; // renderer reload - reg tsr_rld; - always @(posedge clk) - if (reset) - tsr_rld <= 1'b0; - else if (tsr_go) - tsr_rld <= 1'b1; - else if (dram_next) - tsr_rld <= 1'b0; +reg tsr_rld; +always @(posedge clk) + if (reset) + tsr_rld <= 1'b0; + else if (tsr_go) + tsr_rld <= 1'b1; + else if (dram_next) + tsr_rld <= 1'b0; // delayed values - reg [8:0] x_coord_d; - reg [3:0] pal_d; - reg flip_d; - always @(posedge clk) - if (tsr_go) - begin - x_coord_d <= x_coord + (flip ? {x_size, 3'b111} : 6'd0); - pal_d <= pal; - flip_d <= flip; - end +reg [8:0] x_coord_d; +reg [3:0] pal_d; +reg flip_d; +always @(posedge clk) + if (tsr_go) + begin + x_coord_d <= x_coord + (flip ? {x_size, 3'b111} : 6'd0); + pal_d <= pal; + flip_d <= flip; + end // TS-line address - wire [8:0] ts_waddr_mx = tsr_rld_stb ? x_coord_d : (render_on ? x_next : ts_waddr); - wire [8:0] x_next = ts_waddr + {{8{flip_r}}, 1'b1}; - wire tsr_rld_stb = tsr_rld && dram_next; +wire [8:0] ts_waddr_mx = tsr_rld_stb ? x_coord_d : (render_on ? x_next : ts_waddr); +wire [8:0] x_next = ts_waddr + {{8{flip_r}}, 1'b1}; +wire tsr_rld_stb = tsr_rld && dram_next; - always @(posedge clk) - ts_waddr <= ts_waddr_mx; +always @(posedge clk) ts_waddr <= ts_waddr_mx; - reg [3:0] pal_r; - reg flip_r; - always @(posedge clk) - if (tsr_rld_stb) - begin - pal_r <= pal_d; - flip_r <= flip_d; - end +reg [3:0] pal_r; +reg flip_r; +always @(posedge clk) + if (tsr_rld_stb) + begin + pal_r <= pal_d; + flip_r <= flip_d; + end // renderer mux - assign ts_wdata = {pal_r, pix}; - wire [3:0] pix = pix_m[cnt[1:0]]; +assign ts_wdata = {pal_r, pix}; +wire [3:0] pix = pix_m[cnt[1:0]]; - wire [3:0] pix_m[0:3]; - assign pix_m[0] = data[7:4]; - assign pix_m[1] = data[3:0]; - assign pix_m[2] = data[15:12]; - assign pix_m[3] = data[11:8]; +wire [3:0] pix_m[0:3]; +assign pix_m[0] = data[7:4]; +assign pix_m[1] = data[3:0]; +assign pix_m[2] = data[15:12]; +assign pix_m[3] = data[11:8]; endmodule