Update the video to latest version.

This commit is contained in:
sorgelig
2018-08-22 04:10:49 +08:00
parent 7ee1d8a53f
commit 93f35af5ea
14 changed files with 1139 additions and 1210 deletions

View File

@ -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 ""}

View File

@ -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

View File

@ -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,

View File

@ -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),

View File

@ -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;

View File

@ -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
always @(posedge clk) if (fetch_stb) fetch_data <= fetch_temp;
endmodule

View File

@ -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

View File

@ -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), //-<INPUT
.q_b (vpixel)
.address_b(vdata),
.q_b (vpixel)
);
//=============VPIXEL=================================
reg blank;
always @(posedge clk) blank <= vga_on ? vga_blank : tv_blank;
wire [14:0] vpix = blank ? 15'b0 : vpixel; //OK for Spectrum mode // 5 bits for every color
wire [14:0] vpix = blank ? 15'b0 : vpixel[14:0];
assign vred = {vpix[14:10], vpix[14:12]};
assign vgrn = {vpix[ 9: 5], vpix[ 9: 7]};
assign vblu = {vpix[ 4: 0], vpix[ 4: 2]};
assign vgrn = {vpix[ 9: 5], vpix[ 9: 7]};
assign vblu = {vpix[ 4: 0], vpix[ 4: 2]};
assign vdac_mode = vpixel[15];
endmodule

View File

@ -1,44 +1,45 @@
// This module latches all port parameters for video from Z80
module video_ports (
// clocks
module video_ports
(
// clocks
input wire clk,
input wire [ 7:0] d,
input wire res,
input wire int_start,
input wire line_start_s,
input wire res,
input wire int_start,
input wire line_start_s,
// port write strobes
input wire zborder_wr,
input wire border_wr,
input wire zvpage_wr,
input wire vpage_wr,
input wire vconf_wr,
input wire gx_offsl_wr,
input wire gx_offsh_wr,
input wire gy_offsl_wr,
input wire gy_offsh_wr,
input wire t0x_offsl_wr,
input wire t0x_offsh_wr,
input wire t0y_offsl_wr,
input wire t0y_offsh_wr,
input wire t1x_offsl_wr,
input wire t1x_offsh_wr,
input wire t1y_offsl_wr,
input wire t1y_offsh_wr,
input wire tsconf_wr,
input wire palsel_wr,
input wire tmpage_wr,
input wire t0gpage_wr,
input wire t1gpage_wr,
input wire sgpage_wr,
input wire hint_beg_wr ,
input wire vint_begl_wr,
input wire vint_begh_wr,
// port write strobes
input wire zborder_wr,
input wire border_wr,
input wire zvpage_wr,
input wire vpage_wr,
input wire vconf_wr,
input wire gx_offsl_wr,
input wire gx_offsh_wr,
input wire gy_offsl_wr,
input wire gy_offsh_wr,
input wire t0x_offsl_wr,
input wire t0x_offsh_wr,
input wire t0y_offsl_wr,
input wire t0y_offsh_wr,
input wire t1x_offsl_wr,
input wire t1x_offsh_wr,
input wire t1y_offsl_wr,
input wire t1y_offsh_wr,
input wire tsconf_wr,
input wire palsel_wr,
input wire tmpage_wr,
input wire t0gpage_wr,
input wire t1gpage_wr,
input wire sgpage_wr,
input wire hint_beg_wr ,
input wire vint_begl_wr,
input wire vint_begh_wr,
// video parameters
// video parameters
output reg [7:0] border,
output reg [7:0] vpage,
output reg [7:0] vconf,
@ -56,118 +57,93 @@ module video_ports (
output reg [7:0] t0gpage,
output reg [7:0] t1gpage,
output reg [7:0] sgpage
);
);
reg [7:0] vpage_r;
reg [7:0] vconf_r;
reg [7:0] t0gpage_r;
reg [7:0] t1gpage_r;
reg [8:0] gx_offs_r;
reg [8:0] t0x_offs_r;
reg [8:0] t1x_offs_r;
reg [7:0] palsel_r;
reg [7:0] vpage_r;
reg [7:0] vconf_r;
reg [7:0] t0gpage_r;
reg [7:0] t1gpage_r;
reg [8:0] gx_offs_r;
reg [8:0] t0x_offs_r;
reg [8:0] t1x_offs_r;
reg [7:0] palsel_r;
wire [8:0] vint_beg_inc = vint_beg + vint_inc;
wire [8:0] vint_beg_next = {(vint_beg_inc[8:6] == 3'b101) ? 3'b0 : vint_beg_inc[8:6], vint_beg_inc[5:0]}; // if over 319 lines, decrement 320
reg [3:0] vint_inc;
always @(posedge clk)
if (res)
begin
vint_beg <= 9'd0;
vint_inc <= 4'b0;
end
else if (vint_begl_wr)
vint_beg[7:0] <= d;
//vint_beg[7:0] <= 8'd0; //--- мигает vint_beg[8] <= 1'b0; //----
//vint_beg[7:0] <= 8'd10; //---мигает vint_beg[8] <= 1'b0; //----
//vint_beg[7:0] <= 8'd20; //---мигает vint_beg[8] <= 1'b0; //----
//vint_beg[7:0] <= 8'd50;--- нет картинки
//vint_beg[7:0] <= 8'd255;
else if (vint_begh_wr)
begin
vint_beg[8] <= d[0];
//vint_beg[8] <= 1'b0; //----
vint_inc <= d[7:4];
end
else if (int_start)
vint_beg <= vint_beg_next;
always @(posedge clk)
if (res)
begin
vpage_r <= 8'h05;
vconf_r <= 8'h00;
gx_offs_r <= 9'b0;
palsel_r <= 8'h0F;
gy_offs <= 9'b0;
tsconf <= 8'b0;
hint_beg <= 8'd1;
end
wire [8:0] vint_beg_inc = vint_beg + vint_inc;
wire [8:0] vint_beg_next = {(vint_beg_inc[8:6] == 3'b101) ? 3'b0 : vint_beg_inc[8:6], vint_beg_inc[5:0]}; // if over 319 lines, decrement 320
reg [3:0] vint_inc;
always @(posedge clk) begin
if (res) begin
vint_beg <= 9'd0;
vint_inc <= 4'b0;
end
else if (vint_begl_wr) vint_beg[7:0] <= d;
else if (vint_begh_wr) begin
vint_beg[8] <= d[0];
vint_inc <= d[7:4];
end
else if (int_start) vint_beg <= vint_beg_next;
end
else
begin
if (zborder_wr ) border <= {5'b11110, d[2:0]};
if (border_wr ) border <= d;
if (gy_offsl_wr ) gy_offs[7:0] <= d;
if (gy_offsh_wr ) gy_offs[8] <= d[0];
if (t0y_offsl_wr) t0y_offs[7:0] <= d;
if (t0y_offsh_wr) t0y_offs[8] <= d[0];
if (t1y_offsl_wr) t1y_offs[7:0] <= d;
if (t1y_offsh_wr) t1y_offs[8] <= d[0];
if (tsconf_wr ) tsconf <= d;
if (tmpage_wr ) tmpage <= d;
if (sgpage_wr ) sgpage <= d;
if (hint_beg_wr ) hint_beg <= d;
if (zvpage_wr ) vpage_r <= {6'b000001, d[3], 1'b1};
if (vpage_wr ) vpage_r <= d;
if (vconf_wr ) vconf_r <= d;
if (gx_offsl_wr ) gx_offs_r[7:0] <= d;
if (gx_offsh_wr ) gx_offs_r[8] <= d[0];
if (palsel_wr ) palsel_r <= d;
if (t0x_offsl_wr) t0x_offs_r[7:0] <= d;
if (t0x_offsh_wr) t0x_offs_r[8] <= d[0];
if (t1x_offsl_wr) t1x_offs_r[7:0] <= d;
if (t1x_offsh_wr) t1x_offs_r[8] <= d[0];
if (t0gpage_wr ) t0gpage_r <= d;
if (t1gpage_wr ) t1gpage_r <= d;
// if (t0x_offsl_wr) t0x_offs[7:0] <= d;
// if (t0x_offsh_wr) t0x_offs[8] <= d[0];
// if (t1x_offsl_wr) t1x_offs[7:0] <= d;
// if (t1x_offsh_wr) t1x_offs[8] <= d[0];
// if (t0gpage_wr ) t0gpage <= d;
// if (t1gpage_wr ) t1gpage <= d;
end
always @(posedge clk) begin
if (res) begin
vpage_r <= 8'h05;
vconf_r <= 8'h00;
gx_offs_r <= 9'b0;
palsel_r <= 8'h0F;
gy_offs <= 9'b0;
tsconf <= 8'b0;
hint_beg <= 8'd1;
end
else begin
if (zborder_wr ) border <= {palsel[3:0], 1'b0, d[2:0]};
if (border_wr ) border <= d;
if (gy_offsl_wr ) gy_offs[7:0] <= d;
if (gy_offsh_wr ) gy_offs[8] <= d[0];
if (t0y_offsl_wr) t0y_offs[7:0] <= d;
if (t0y_offsh_wr) t0y_offs[8] <= d[0];
if (t1y_offsl_wr) t1y_offs[7:0] <= d;
if (t1y_offsh_wr) t1y_offs[8] <= d[0];
if (tsconf_wr ) tsconf <= d;
if (tmpage_wr ) tmpage <= d;
if (sgpage_wr ) sgpage <= d;
if (hint_beg_wr ) hint_beg <= d;
if (zvpage_wr ) vpage_r <= {6'b000001, d[3], 1'b1};
if (vpage_wr ) vpage_r <= d;
if (vconf_wr ) vconf_r <= d;
if (gx_offsl_wr ) gx_offs_r[7:0] <= d;
if (gx_offsh_wr ) gx_offs_r[8] <= d[0];
if (palsel_wr ) palsel_r <= d;
if (t0x_offsl_wr) t0x_offs_r[7:0] <= d;
if (t0x_offsh_wr) t0x_offs_r[8] <= d[0];
if (t1x_offsl_wr) t1x_offs_r[7:0] <= d;
if (t1x_offsh_wr) t1x_offs_r[8] <= d[0];
if (t0gpage_wr ) t0gpage_r <= d;
if (t1gpage_wr ) t1gpage_r <= d;
end
end
// latching regs at line start, delaying hires for 1 line
always @(posedge clk)
if (res)
begin
vpage <= 8'h05;
vconf <= 8'h00;
gx_offs <= 9'b0;
palsel <= 8'h0F;
end
always @(posedge clk) begin
if (res)
begin
vpage <= 8'h05;
vconf <= 8'h00;
gx_offs <= 9'b0;
palsel <= 8'h0F;
end
else if (zvpage_wr) vpage <= {6'b000001, d[3], 1'b1};
else if (line_start_s) begin
vpage <= vpage_r;
vconf <= vconf_r;
gx_offs <= gx_offs_r;
palsel <= palsel_r;
t0x_offs <= t0x_offs_r;
t1x_offs <= t1x_offs_r;
t0gpage <= t0gpage_r;
t1gpage <= t1gpage_r;
end
end
else if (zvpage_wr)
vpage <= {6'b000001, d[3], 1'b1};
else if (line_start_s)
begin
vpage <= vpage_r;
vconf <= vconf_r;
gx_offs <= gx_offs_r;
palsel <= palsel_r;
t0x_offs <= t0x_offs_r;
t1x_offs <= t1x_offs_r;
t0gpage <= t0gpage_r;
t1gpage <= t1gpage_r;
end
endmodule
endmodule

View File

@ -1,12 +1,13 @@
// This module renders video data for output
module video_render (
// clocks
module video_render
(
// clocks
input wire clk, c1,
// video controls
// video controls
input wire hvpix,
input wire hvtspix,
input wire nogfx,
input wire notsu,
input wire gfxovr,
@ -15,71 +16,69 @@ module video_render (
input wire [3:0] psel,
input wire [3:0] palsel,
// mode controls
// mode controls
input wire [1:0] render_mode,
// video data
// video data
input wire [31:0] data,
input wire [ 7:0] border_in,
input wire [ 7:0] tsdata_in,
output wire [ 7:0] vplex_out
);
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;
// ZX graphics
wire [15:0] zx_gfx = data[15: 0];
wire [15:0] zx_atr = data[31:16];
wire zx_dot = zx_gfx[{psel[3], ~psel[2:0]}];
wire [7:0] zx_attr = ~psel[3] ? zx_atr[7:0] : zx_atr[15:8];
wire [7:0] zx_pix = {palsel, zx_attr[6], zx_dot ^ (flash & zx_attr[7]) ? zx_attr[2:0] : zx_attr[5:3]};
wire [15:0] zx_gfx = data[15: 0];
wire [15:0] zx_atr = data[31:16];
wire zx_dot = zx_gfx[{psel[3], ~psel[2:0]}];
wire [7:0] zx_attr = ~psel[3] ? zx_atr[7:0] : zx_atr[15:8];
wire [7:0] zx_pix = {palsel, zx_attr[6], zx_dot ^ (flash & zx_attr[7]) ? zx_attr[2:0] : zx_attr[5:3]};
// text graphics
// (it uses common renderer with ZX, but different attributes)
wire [7:0] tx_pix = {palsel, zx_dot ? zx_attr[3:0] : zx_attr[7:4]};
wire [7:0] tx_pix = {palsel, zx_dot ? zx_attr[3:0] : zx_attr[7:4]};
// 16c graphics
wire [3:0] hc_dot[0:3];
assign hc_dot[0] = data[ 7: 4];
assign hc_dot[1] = data[ 3: 0];
assign hc_dot[2] = data[15:12];
assign hc_dot[3] = data[11: 8];
wire [7:0] hc_pix = {palsel, hc_dot[psel[1:0]]};
wire [3:0] hc_dot[0:3];
assign hc_dot[0] = data[ 7: 4];
assign hc_dot[1] = data[ 3: 0];
assign hc_dot[2] = data[15:12];
assign hc_dot[3] = data[11: 8];
wire [7:0] hc_pix = {palsel, hc_dot[psel[1:0]]};
// 256c graphics
wire [7:0] xc_dot[0:1];
assign xc_dot[0] = data[ 7: 0];
assign xc_dot[1] = data[15: 8];
wire [7:0] xc_pix = xc_dot[psel[0]];
wire [7:0] xc_dot[0:1];
assign xc_dot[0] = data[ 7: 0];
assign xc_dot[1] = data[15: 8];
wire [7:0] xc_pix = xc_dot[psel[0]];
// mode selects
wire [7:0] pix[0:3];
assign pix[R_ZX] = zx_pix; // ZX
assign pix[R_HC] = hc_pix; // 16c
assign pix[R_XC] = xc_pix; // 256c
assign pix[R_TX] = tx_pix; // text
wire pixv[0:3];
assign pixv[R_ZX] = zx_dot ^ (flash & zx_attr[7]);
assign pixv[R_HC] = |hc_dot[psel[1:0]];
assign pixv[R_XC] = |xc_dot[psel[0]];
assign pixv[R_TX] = zx_dot;
wire [7:0] pix[0:3];
assign pix[R_ZX] = zx_pix; // ZX
assign pix[R_HC] = hc_pix; // 16c
assign pix[R_XC] = xc_pix; // 256c
assign pix[R_TX] = tx_pix; // text
wire pixv[0:3];
assign pixv[R_ZX] = zx_dot ^ (flash & zx_attr[7]);
assign pixv[R_HC] = |hc_dot[psel[1:0]];
assign pixv[R_XC] = |xc_dot[psel[0]];
assign pixv[R_TX] = zx_dot;
// video plex muxer
wire tsu_visible = (|tsdata_in[3:0] && !notsu);
wire gfx_visible = (pixv[render_mode] && !nogfx);
wire [7:0] video1 = tsu_visible ? tsdata_in : (nogfx ? border_in : pix[render_mode]);
wire [7:0] video2 = gfx_visible ? pix[render_mode] : (tsu_visible ? tsdata_in : border_in);
wire [7:0] video = !hvpix ? border_in : (gfxovr ? video2 : video1);
assign vplex_out = hires ? {temp, video[3:0]} : video; // in hi-res plex contains two pixels 4 bits each
wire tsu_visible = (|tsdata_in[3:0] && !notsu);
wire gfx_visible = (pixv[render_mode] && !nogfx);
wire [7:0] video1 = tsu_visible ? tsdata_in : (nogfx ? border_in : pix[render_mode]);
wire [7:0] video2 = gfx_visible ? pix[render_mode] : (tsu_visible ? tsdata_in : border_in);
wire [7:0] video = hvpix ? (gfxovr ? video2 : video1) : ((hvtspix && tsu_visible) ? tsdata_in : border_in);
assign vplex_out = hires ? {temp, video[3:0]} : video; // in hi-res plex contains two pixels 4 bits each
reg [3:0] temp;
always @(posedge clk) if (c1)
temp <= video[3:0];
reg [3:0] temp;
always @(posedge clk) if (c1) temp <= video[3:0];
endmodule

View File

@ -2,29 +2,33 @@
// This module generates all video raster signals
module video_sync (
// clocks
module video_sync
(
// clocks
input wire clk, f1, c0, c1, c3, pix_stb,
// video parameters
// 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,
input wire [8:0] rstart,
// video syncs
// video syncs
output reg hsync,
output reg vsync,
output reg csync,
// video controls
// video controls
input wire cfg_60hz,
input wire sync_pol,
input wire vga_on,
@ -35,6 +39,7 @@ module video_sync (
output wire vpix,
output wire v_ts,
output wire hvpix,
output wire hvtspix,
output wire tv_hblank,
output wire tv_vblank,
output reg vga_hblank,
@ -47,7 +52,7 @@ module video_sync (
output wire frame,
output wire flash,
// video counters
// video counters
output wire [9:0] vga_cnt_in,
output wire [9:0] vga_cnt_out,
output wire [8:0] ts_raddr,
@ -57,172 +62,152 @@ module video_sync (
output reg cptr,
output reg [3:0] scnt,
// DRAM
// DRAM
input wire video_pre_next,
output reg video_go,
// ZX controls
// 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 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;
localparam VBLNK_END_50 = 9'd32;
localparam VPERIOD_50 = 9'd320;
localparam VSYNC_BEG_50 = 9'd08;
localparam VSYNC_END_50 = 9'd11;
localparam VBLNK_BEG_50 = 9'd00;
localparam VBLNK_END_50 = 9'd32;
localparam VPERIOD_50 = 9'd320;
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;
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;
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;
// counters
reg [8:0] hcount = 0;
reg [8:0] vcount = 0;
reg [8:0] cnt_out = 0;
reg [8:0] hcount = 0;
reg [8:0] vcount = 0;
reg [8:0] cnt_out = 0;
// horizontal TV (7 MHz)
always @(posedge clk) if (c3)
hcount <= line_start ? 9'b0 : hcount + 9'b1;
// 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;
// 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;
// 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
// 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
else
if (video_pre_next)
begin
cnt_col <= cnt_col + 8'b1;
cptr <= ~cptr;
end
end
// row address for DRAM
always @(posedge clk) begin 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;
end
// row address for DRAM
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) scnt <= pix_start ? 4'b0 : scnt + 4'b1; // f1 or c3
assign vga_cnt_in = {vcount[0], hcount - HBLNK_END};
assign vga_cnt_out = {~vcount[0], cnt_out};
// pixel counter
always @(posedge clk) if (pix_stb) // f1 or c3
scnt <= pix_start ? 4'b0 : scnt + 4'b1;
assign vga_cnt_in = {vcount[0], hcount - HBLNK_END};
assign vga_cnt_out = {~vcount[0], cnt_out};
// TS-line counter
assign ts_raddr = hcount - hpix_beg;
always @(posedge clk)
if (ts_start_coarse)
lcount <= vcount - vpix_beg + 9'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
reg y_offs_wr_r;
always @(posedge clk)
if (y_offs_wr)
y_offs_wr_r <= 1'b1;
else
if (line_start_s)
y_offs_wr_r <= 1'b0;
reg y_offs_wr_r;
always @(posedge clk) begin
if (y_offs_wr) y_offs_wr_r <= 1'b1;
else if (line_start_s) y_offs_wr_r <= 1'b0;
end
// 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
v60hz <= !cfg_60hz; // re-sync of 60Hz mode selector
flash_ctr <= flash_ctr + 5'b1;
end
reg [4:0] flash_ctr;
assign frame = flash_ctr[0];
assign flash = flash_ctr[4];
always @(posedge clk) begin
if (frame_start && c3) begin
v60hz <= !cfg_60hz; // re-sync of 60Hz mode selector
flash_ctr <= flash_ctr + 5'b1;
end
end
// sync strobes
wire hs = (hcount >= 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

View File

@ -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

View File

@ -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

View File

@ -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