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 ""} { "" "" "" "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\|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\|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 ""} { "" "" "" "*" { } { } 0 21074 "" 0 0 "Design Software" 0 -1 0 ""}
{ "" "" "" "RST" { } { } 0 9999 "" 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 ""} { "" "" "" "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 CDF_FILE jtag.cdf
set_global_assignment -name QIP_FILE sys/sys.qip set_global_assignment -name QIP_FILE sys/sys.qip
set_global_assignment -name QSYS_FILE sys/vip.qsys set_global_assignment -name QSYS_FILE sys/vip.qsys
set_global_assignment -name VHDL_FILE src/t80/T80_Reg.vhd set_global_assignment -name QIP_FILE src/t80/T80.qip
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 VERILOG_FILE src/cpu/zsignals.v 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/zports.v
set_global_assignment -name VERILOG_FILE src/cpu/zmem.v set_global_assignment -name VERILOG_FILE src/cpu/zmem.v

View File

@ -96,7 +96,6 @@ module arbiter(
// TS // TS
input wire [23:0] ts_addr, input wire [23:0] ts_addr,
input wire ts_req, input wire ts_req,
input wire ts_z80_lp,
output wire ts_pre_next, output wire ts_pre_next,
output wire ts_next, output wire ts_next,

View File

@ -256,12 +256,10 @@ wire video_next;
wire video_pre_next; wire video_pre_next;
wire next_video; wire next_video;
wire video_strobe; wire video_strobe;
wire video_next_strobe;
// TS // TS
wire [20:0] ts_addr; wire [20:0] ts_addr;
wire ts_req; wire ts_req;
wire ts_z80_lp;
// IN // IN
wire ts_pre_next; wire ts_pre_next;
@ -518,7 +516,6 @@ arbiter TS07
.video_pre_next(video_pre_next), .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_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_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 .next_vid(next_video), // used for TM prefetch
.cpu_addr({csvrom, 2'b00, cpu_addr_20}), .cpu_addr({csvrom, 2'b00, cpu_addr_20}),
.cpu_wrdata(cpu_do_bus), .cpu_wrdata(cpu_do_bus),
@ -537,7 +534,6 @@ arbiter TS07
.dma_next(dma_next), .dma_next(dma_next),
.ts_addr({3'b000, ts_addr}), .ts_addr({3'b000, ts_addr}),
.ts_req(ts_req), .ts_req(ts_req),
.ts_z80_lp(ts_z80_lp),
.ts_pre_next(ts_pre_next), .ts_pre_next(ts_pre_next),
.ts_next(ts_next), .ts_next(ts_next),
.tm_addr({3'b000, tm_addr}), .tm_addr({3'b000, tm_addr}),
@ -564,7 +560,6 @@ video_top TS08
.hblank(VGA_HBLANK), .hblank(VGA_HBLANK),
.vblank(VGA_VBLANK), .vblank(VGA_VBLANK),
.pix_stb(VGA_CEPIX), .pix_stb(VGA_CEPIX),
.a(cpu_a_bus),
.d(cpu_do_bus), .d(cpu_do_bus),
.zmd(zmd), .zmd(zmd),
.zma(zma), .zma(zma),
@ -607,10 +602,8 @@ video_top TS08
.video_pre_next(video_pre_next), .video_pre_next(video_pre_next),
.next_video(next_video), .next_video(next_video),
.video_strobe(video_strobe), .video_strobe(video_strobe),
.video_next_strobe(video_next_strobe),
.ts_addr(ts_addr), .ts_addr(ts_addr),
.ts_req(ts_req), .ts_req(ts_req),
.ts_z80_lp(ts_z80_lp),
.ts_pre_next(ts_pre_next), .ts_pre_next(ts_pre_next),
.ts_next(ts_next), .ts_next(ts_next),
.tm_addr(tm_addr), .tm_addr(tm_addr),

View File

@ -14,7 +14,7 @@
-- Quartus II generated Memory Initialization File (.mif) -- Quartus II generated Memory Initialization File (.mif)
WIDTH=15; WIDTH=16;
DEPTH=256; DEPTH=256;
ADDRESS_RADIX=HEX; ADDRESS_RADIX=HEX;

View File

@ -1,38 +1,33 @@
// This module fetches video data from DRAM // This module fetches video data from DRAM
module video_fetch ( module video_fetch
(
// clocks // clocks
input wire clk, input wire clk,
// control // control
input wire [3:0] f_sel, input wire [3:0] f_sel,
input wire [1:0] b_sel, input wire [1:0] b_sel,
input wire fetch_stb, input wire fetch_stb,
// video data // video data
output reg [31:0] fetch_data, output reg [31:0] fetch_data,
output reg [31:0] fetch_temp, output reg [31:0] fetch_temp,
// DRAM interface // DRAM interface
input wire video_strobe, input wire video_strobe,
input wire [15:0] video_data input wire [15:0] video_data
); );
// fetching 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 (video_strobe) always @(posedge clk) if (fetch_stb) fetch_data <= fetch_temp;
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;
endmodule endmodule

View File

@ -1,23 +1,28 @@
// This module decodes video modes // This module decodes video modes
module video_mode ( module video_mode
(
// clocks // clocks
input wire clk, f1, c3, input wire clk, f1, c3,
// video config // video config
input wire [7:0] vpage, input wire [7:0] vpage,
input wire [7:0] vconf, input wire [7:0] vconf,
input wire ts_rres_ext,
input wire v60hz, input wire v60hz,
// video parameters & mode controls // video parameters & mode controls
input wire [8:0] gx_offs, input wire [8:0] gx_offs,
output wire [9:0] x_offs_mode, output wire [9:0] x_offs_mode,
output wire [8:0] hpix_beg, output wire [8:0] hpix_beg,
output wire [8:0] hpix_end, output wire [8:0] hpix_end,
output wire [8:0] vpix_beg, output wire [8:0] vpix_beg,
output wire [8:0] vpix_end, 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 [5:0] x_tiles,
output wire [4:0] go_offs, output wire [4:0] go_offs,
output wire [3:0] fetch_sel, output wire [3:0] fetch_sel,
@ -31,202 +36,204 @@ module video_mode (
output wire pix_stb, output wire pix_stb,
output wire fetch_stb, output wire fetch_stb,
// video data // video data
input wire [15:0] txt_char, input wire [15:0] txt_char,
// video counters // video counters
input wire [7:0] cnt_col, input wire [7:0] cnt_col,
input wire [8:0] cnt_row, input wire [8:0] cnt_row,
input wire cptr, input wire cptr,
// DRAM interface // DRAM interface
output wire [20:0] video_addr, output wire [20:0] video_addr,
output wire [ 4:0] video_bw output wire [ 4:0] video_bw
); );
wire [1:0] vmod = vconf[1:0];
wire [1:0] vmod = vconf[1:0]; wire [1:0] rres = vconf[7:6];
wire [1:0] rres = vconf[7:6];
// clocking strobe for pixels (TV) // clocking strobe for pixels (TV)
assign pix_stb = tv_hires ? f1 : c3; assign pix_stb = tv_hires ? f1 : c3;
always @(posedge clk) always @(posedge clk) if (line_start_s) vga_hires <= tv_hires;
if (line_start_s)
vga_hires <= tv_hires;
// Modes // Modes
localparam M_ZX = 2'h0; // ZX localparam M_ZX = 2'h0; // ZX
localparam M_HC = 2'h1; // 16c localparam M_HC = 2'h1; // 16c
localparam M_XC = 2'h2; // 256c localparam M_XC = 2'h2; // 256c
localparam M_TX = 2'h3; // Text localparam M_TX = 2'h3; // Text
// Render modes (affects 'video_render.v') // Render modes (affects 'video_render.v')
localparam R_ZX = 2'h0; localparam R_ZX = 2'h0;
localparam R_HC = 2'h1; localparam R_HC = 2'h1;
localparam R_XC = 2'h2; localparam R_XC = 2'h2;
localparam R_TX = 2'h3; localparam R_TX = 2'h3;
// fetch strobes // fetch strobes
wire ftch[0:3]; wire ftch[0:3];
assign fetch_stb = (pix_start | ftch[render_mode]) && c3; assign fetch_stb = (pix_start | ftch[render_mode]) && c3;
assign ftch[R_ZX] = &fetch_cnt[3:0]; assign ftch[R_ZX] = &fetch_cnt[3:0];
assign ftch[R_HC] = &fetch_cnt[1:0]; assign ftch[R_HC] = &fetch_cnt[1:0];
assign ftch[R_XC] = fetch_cnt[0]; assign ftch[R_XC] = fetch_cnt[0];
assign ftch[R_TX] = &fetch_cnt[3:0]; assign ftch[R_TX] = &fetch_cnt[3:0];
// fetch window // fetch window
wire [4:0] g_offs[0:3]; wire [4:0] g_offs[0:3];
// these values are from a thin air!!! recheck them occasionally! // these values are from a thin air!!! recheck them occasionally!
assign g_offs[M_ZX] = 5'd18; assign g_offs[M_ZX] = 5'd18;
assign g_offs[M_HC] = 5'd6; assign g_offs[M_HC] = 5'd6;
assign g_offs[M_XC] = 5'd4; assign g_offs[M_XC] = 5'd4;
assign g_offs[M_TX] = 5'd10; assign g_offs[M_TX] = 5'd10;
assign go_offs = g_offs[vmod]; assign go_offs = g_offs[vmod];
// fetch selectors // fetch selectors
// Attention: counter is already incremented at the time of video data fetching! // Attention: counter is already incremented at the time of video data fetching!
// wire m_c = (vmod == M_HC) | (vmod == M_XC); // 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}; // 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:7];
wire [3:0] f_sel[0:3]; wire [3:0] f_sel[0:3];
assign f_sel[M_ZX] = {~cptr, ~cptr, cptr, cptr}; assign f_sel[M_ZX] = {~cptr, ~cptr, cptr, cptr};
assign f_sel[M_HC] = {~cptr, ~cptr, 2'b11}; assign f_sel[M_HC] = {~cptr, ~cptr, 2'b11};
assign f_sel[M_XC] = {~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 f_sel[M_TX] = f_txt_sel[cnt_col[1:0]];
assign fetch_sel = f_sel[vmod]; 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]; // wire [1:0] f_bsl[0:7];
// assign f_bsl[M_ZX] = 2'b10; // assign f_bsl[M_ZX] = 2'b10;
// assign f_bsl[M_HC] = 2'b10; // assign f_bsl[M_HC] = 2'b10;
// assign f_bsl[M_XC] = 2'b10; // assign f_bsl[M_XC] = 2'b10;
// assign f_bsl[M_TX] = f_txt_bsl[cnt_col[1:0]]; // assign f_bsl[M_TX] = f_txt_bsl[cnt_col[1:0]];
// assign fetch_bsl = f_bsl[vmod]; // assign fetch_bsl = f_bsl[vmod];
wire [3:0] f_txt_sel[0:3]; wire [3:0] f_txt_sel[0:3];
assign f_txt_sel[1] = 4'b0011; // char assign f_txt_sel[1] = 4'b0011; // char
assign f_txt_sel[2] = 4'b1100; // attr assign f_txt_sel[2] = 4'b1100; // attr
assign f_txt_sel[3] = 4'b0001; // gfx0 assign f_txt_sel[3] = 4'b0001; // gfx0
assign f_txt_sel[0] = 4'b0010; // gfx1 assign f_txt_sel[0] = 4'b0010; // gfx1
wire [1:0] f_txt_bsl[0:3]; wire [1:0] f_txt_bsl[0:3];
assign f_txt_bsl[1] = 2'b10; // char assign f_txt_bsl[1] = 2'b10; // char
assign f_txt_bsl[2] = 2'b10; // attr assign f_txt_bsl[2] = 2'b10; // attr
assign f_txt_bsl[3] = {2{cnt_row[0]}}; // gfx0 assign f_txt_bsl[3] = {2{cnt_row[0]}}; // gfx0
assign f_txt_bsl[0] = {2{cnt_row[0]}}; // gfx1 assign f_txt_bsl[0] = {2{cnt_row[0]}}; // gfx1
// X offset // 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 // DRAM bandwidth usage
localparam BW2 = 2'b00; localparam BW2 = 2'b00;
localparam BW4 = 2'b01; localparam BW4 = 2'b01;
localparam BW8 = 2'b11; localparam BW8 = 2'b11;
localparam BU1 = 3'b001; localparam BU1 = 3'b001;
localparam BU2 = 3'b010; localparam BU2 = 3'b010;
localparam BU4 = 3'b100; localparam BU4 = 3'b100;
// [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2 // [4:3] - total cycles: 11 = 8 / 01 = 4 / 00 = 2
// [2:0] - need cycles // [2:0] - need cycles
wire [4:0] bw[0:3]; wire [4:0] bw[0:3];
assign bw[M_ZX] = {BW8, BU1}; // '1 of 8' (ZX) assign bw[M_ZX] = {BW8, BU1}; // '1 of 8' (ZX)
assign bw[M_HC] = {BW4, BU1}; // '1 of 4' (16c) assign bw[M_HC] = {BW4, BU1}; // '1 of 4' (16c)
assign bw[M_XC] = {BW2, BU1}; // '1 of 2' (256c) assign bw[M_XC] = {BW2, BU1}; // '1 of 2' (256c)
assign bw[M_TX] = {BW8, BU4}; // '4 of 8' (text) assign bw[M_TX] = {BW8, BU4}; // '4 of 8' (text)
assign video_bw = bw[vmod]; assign video_bw = bw[vmod];
// pixelrate // pixelrate
wire [3:0] pixrate = 4'b1000; // change these if you change the modes indexes! wire [3:0] pixrate = 4'b1000; // change these if you change the modes indexes!
assign tv_hires = pixrate[vmod]; assign tv_hires = pixrate[vmod];
// render mode // render mode
// wire [1:0] r_mode[0:7]; // wire [1:0] r_mode[0:7];
wire [1:0] r_mode[0:3]; wire [1:0] r_mode[0:3];
assign r_mode[M_ZX] = R_ZX; assign r_mode[M_ZX] = R_ZX;
assign r_mode[M_HC] = R_HC; assign r_mode[M_HC] = R_HC;
assign r_mode[M_XC] = R_XC; assign r_mode[M_XC] = R_XC;
assign r_mode[M_TX] = R_TX; assign r_mode[M_TX] = R_TX;
assign render_mode = r_mode[vmod]; assign render_mode = r_mode[vmod];
// raster resolution // raster resolution
wire [8:0] hp_beg[0:3]; wire [8:0] hp_beg[0:3];
wire [8:0] hp_end[0:3]; wire [8:0] hp_end[0:3];
wire [8:0] vp_beg[0:3]; wire [8:0] vp_beg[0:3];
wire [8:0] vp_end[0:3]; wire [8:0] vp_end[0:3];
wire [5:0] x_tile[0:3]; wire [5:0] x_tile[0:3];
assign hp_beg[0] = 9'd140; // 256 (88-52-256-52) 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[1] = 9'd108; // 320 (88-20-320-20)
assign hp_beg[2] = 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[3] = 9'd88; // 360 (88-0-360-0)
assign hp_end[0] = 9'd396; // 256 assign hp_end[0] = 9'd396; // 256
assign hp_end[1] = 9'd428; // 320 assign hp_end[1] = 9'd428; // 320
assign hp_end[2] = 9'd428; // 320 assign hp_end[2] = 9'd428; // 320
assign hp_end[3] = 9'd448; // 360 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[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[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[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[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[0] = v60hz ? 9'd238 : 9'd272; // 192
assign vp_end[1] = v60hz ? 9'd242 : 9'd276; // 200 assign vp_end[1] = v60hz ? 9'd242 : 9'd276; // 200
assign vp_end[2] = v60hz ? 9'd262 : 9'd296; // 240 assign vp_end[2] = v60hz ? 9'd262 : 9'd296; // 240
assign vp_end[3] = v60hz ? 9'd262 : 9'd320; // 240/288 assign vp_end[3] = v60hz ? 9'd262 : 9'd320; // 240/288
assign x_tile[0] = 6'd34; // 256 assign x_tile[0] = 6'd34; // 256
assign x_tile[1] = 6'd42; // 320 assign x_tile[1] = 6'd42; // 320
assign x_tile[2] = 6'd42; // 320 assign x_tile[2] = 6'd42; // 320
assign x_tile[3] = 6'd47; // 360 assign x_tile[3] = 6'd47; // 360
assign hpix_beg = hp_beg[rres]; assign hpix_beg = hp_beg[rres];
assign hpix_end = hp_end[rres]; assign hpix_end = hp_end[rres];
assign vpix_beg = vp_beg[rres]; assign vpix_beg = vp_beg[rres];
assign vpix_end = vp_end[rres]; assign vpix_end = vp_end[rres];
assign x_tiles = x_tile[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 // videomode addresses
wire [20:0] v_addr[0:3]; wire [20:0] v_addr[0:3];
assign v_addr[M_ZX] = addr_zx; assign v_addr[M_ZX] = addr_zx;
assign v_addr[M_HC] = addr_16c; assign v_addr[M_HC] = addr_16c;
assign v_addr[M_XC] = addr_256c; assign v_addr[M_XC] = addr_256c;
assign v_addr[M_TX] = addr_text; assign v_addr[M_TX] = addr_text;
assign video_addr = v_addr[vmod]; assign video_addr = v_addr[vmod];
// ZX // ZX
wire [20:0] addr_zx = {vpage, 1'b0, ~cnt_col[0] ? addr_zx_gfx : addr_zx_atr}; 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_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]}; wire [11:0] addr_zx_atr = {3'b110, cnt_row[7:3], cnt_col[4:1]};
// 16c // 16c
wire [20:0] addr_16c = {vpage[7:3], cnt_row, cnt_col[6:0]}; wire [20:0] addr_16c = {vpage[7:3], cnt_row, cnt_col[6:0]};
// 256c // 256c
wire [20:0] addr_256c = {vpage[7:4], cnt_row, cnt_col[7:0]}; wire [20:0] addr_256c = {vpage[7:4], cnt_row, cnt_col[7:0]};
// Textmode // Textmode
wire [20:0] addr_text = {vpage[7:1], addr_tx[cnt_col[1:0]]}; wire [20:0] addr_text = {vpage[7:1], addr_tx[cnt_col[1:0]]};
wire [13:0] addr_tx[0:3]; 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[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[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[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] assign addr_tx[3] = {~vpage[0], 3'b000, (txt_char[15:8]), cnt_row[2:1]}; // char1 graphics, data[15:8]
endmodule endmodule

View File

@ -1,76 +1,68 @@
// This module generates video for DAC // This module generates video for DAC
// MVV corrected 24bpp 24.08.2014 // (c)2015 TSL
module video_out ( module video_out
(
// clocks // clocks
input wire clk, f0, c3, input wire clk, f0, c3,
// video controls // video controls
input wire vga_on, input wire vga_on,
input wire tv_blank, input wire tv_blank,
input wire vga_blank, input wire vga_blank,
input wire [1:0] plex_sel_in, input wire [1:0] plex_sel_in,
// mode controls // mode controls
input wire tv_hires, input wire tv_hires,
input wire vga_hires, input wire vga_hires,
input wire [3:0] palsel, input wire [3:0] palsel,
// Z80 pins // Z80 pins
input wire [14:0] cram_data_in, input wire [15:0] cram_data_in,
input wire [7:0] cram_addr_in, input wire [7:0] cram_addr_in,
input wire cram_we, input wire cram_we,
// video data // video data
input wire [7:0] vplex_in, //<====== INPUT input wire [7:0] vplex_in,
input wire [7:0] vgaplex, //<====== INPUT VGA input wire [7:0] vgaplex,
output wire [7:0] vred, output wire [7:0] vred,
output wire [7:0] vgrn, output wire [7:0] vgrn,
output wire [7:0] vblu, output wire [7:0] vblu,
//--------------------- output wire vdac_mode
output wire [3:0] tst
); );
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 // TV/VGA mux
reg [7:0] vplex; 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 [7:0] plex = vga_on ? vgaplex : vplex;
wire plex_sel = vga_on ? plex_sel_in[0] : plex_sel_in[1]; wire plex_sel = vga_on ? plex_sel_in[0] : plex_sel_in[1];
wire hires = vga_on ? vga_hires : tv_hires; 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] 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), .clock (clk),
.address_a(cram_addr_in), .address_a(cram_addr_in),
.data_a (cram_data_in), .data_a (cram_data_in),
.wren_a (cram_we), .wren_a (cram_we),
.address_b(vdata), //-<INPUT .address_b(vdata),
.q_b (vpixel) .q_b (vpixel)
); );
//=============VPIXEL=================================
reg blank; reg blank;
always @(posedge clk) blank <= vga_on ? vga_blank : tv_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 vred = {vpix[14:10], vpix[14:12]};
assign vgrn = {vpix[ 9: 5], vpix[ 9: 7]}; assign vgrn = {vpix[ 9: 5], vpix[ 9: 7]};
assign vblu = {vpix[ 4: 0], vpix[ 4: 2]}; assign vblu = {vpix[ 4: 0], vpix[ 4: 2]};
assign vdac_mode = vpixel[15];
endmodule endmodule

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@ module video_top
output wire [7:0] vred, output wire [7:0] vred,
output wire [7:0] vgrn, output wire [7:0] vgrn,
output wire [7:0] vblu, output wire [7:0] vblu,
output wire vdac_mode,
// video syncs // video syncs
output wire hsync, output wire hsync,
@ -25,7 +26,6 @@ module video_top
output wire pix_stb, output wire pix_stb,
// Z80 controls // Z80 controls
input wire [15:0] a,
input wire [ 7:0] d, input wire [ 7:0] d,
input wire [15:0] zmd, input wire [15:0] zmd,
input wire [ 7:0] zma, input wire [ 7:0] zma,
@ -74,10 +74,8 @@ module video_top
input wire video_pre_next, input wire video_pre_next,
input wire next_video, input wire next_video,
input wire video_strobe, input wire video_strobe,
input wire video_next_strobe,
output wire [20:0] ts_addr, output wire [20:0] ts_addr,
output wire ts_req, output wire ts_req,
output wire ts_z80_lp,
input wire ts_pre_next, input wire ts_pre_next,
input wire ts_next, input wire ts_next,
output wire [20:0] tm_addr, output wire [20:0] tm_addr,
@ -87,14 +85,10 @@ module video_top
// video controls // video controls
input wire cfg_60hz, input wire cfg_60hz,
input wire sync_pol, input wire sync_pol,
input wire vga_on, input wire vga_on
output wire [3:0] tst
); );
assign ts_z80_lp = tsconf[4];
// video config // video config
wire [7:0] vpage; // re-latched at line_start wire [7:0] vpage; // re-latched at line_start
wire [7:0] vconf; // wire [7:0] vconf; //
@ -116,6 +110,10 @@ wire [8:0] hpix_beg;
wire [8:0] hpix_end; wire [8:0] hpix_end;
wire [8:0] vpix_beg; wire [8:0] vpix_beg;
wire [8:0] vpix_end; 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 [5:0] x_tiles;
wire [9:0] x_offs_mode; wire [9:0] x_offs_mode;
wire [4:0] go_offs; wire [4:0] go_offs;
@ -123,12 +121,9 @@ wire [1:0] render_mode;
wire tv_hires; wire tv_hires;
wire vga_hires; wire vga_hires;
wire v60hz; wire v60hz;
//===zx-evo-fpga-564db5e984ef ===
wire nogfx = vconf[5]; wire nogfx = vconf[5];
wire notsu = vconf[4]; wire notsu = vconf[4];
wire gfxovr = vconf[3]; wire gfxovr = vconf[3];
//wire gfxovr;
//===============================
wire tv_hblank; wire tv_hblank;
wire tv_vblank; wire tv_vblank;
wire vga_hblank; wire vga_hblank;
@ -142,6 +137,7 @@ wire [3:0] scnt;
wire [8:0] lcount; wire [8:0] lcount;
// synchro // synchro
wire frame_start;
wire pix_start; wire pix_start;
wire tv_pix_start; wire tv_pix_start;
wire vga_pix_start; wire vga_pix_start;
@ -151,6 +147,7 @@ wire v_pf;
wire hpix; wire hpix;
wire vpix; wire vpix;
wire hvpix; wire hvpix;
wire hvtspix;
wire flash; wire flash;
// fetcher // fetcher
@ -177,9 +174,6 @@ wire [3:0] tsr_pal;
wire tsr_rdy; wire tsr_rdy;
// TS-line // 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 [8:0] ts_waddr;
wire [7:0] ts_wdata; wire [7:0] ts_wdata;
wire ts_we; wire ts_we;
@ -189,7 +183,8 @@ wire [8:0] ts_raddr;
wire [9:0] vga_cnt_in; wire [9:0] vga_cnt_in;
wire [9:0] vga_cnt_out; wire [9:0] vga_cnt_out;
video_ports video_ports ( video_ports video_ports
(
.clk (clk), .clk (clk),
.d (d), .d (d),
.res (res), .res (res),
@ -232,6 +227,7 @@ video_ports video_ports (
.palsel (palsel), .palsel (palsel),
.hint_beg (hint_beg), .hint_beg (hint_beg),
.vint_beg (vint_beg), .vint_beg (vint_beg),
.int_start (0),
.tsconf (tsconf), .tsconf (tsconf),
.tmpage (tmpage), .tmpage (tmpage),
.t0gpage (t0gpage), .t0gpage (t0gpage),
@ -240,7 +236,8 @@ video_ports video_ports (
); );
video_mode video_mode ( video_mode video_mode
(
.clk (clk), .clk (clk),
.f1 (f1), .f1 (f1),
.c3 (c3), .c3 (c3),
@ -254,10 +251,15 @@ video_mode video_mode (
.txt_char (fetch_temp[15:0]), .txt_char (fetch_temp[15:0]),
.gx_offs (gx_offs), .gx_offs (gx_offs),
.x_offs_mode (x_offs_mode), .x_offs_mode (x_offs_mode),
.ts_rres_ext (tsconf[0]),
.hpix_beg (hpix_beg), .hpix_beg (hpix_beg),
.hpix_end (hpix_end), .hpix_end (hpix_end),
.vpix_beg (vpix_beg), .vpix_beg (vpix_beg),
.vpix_end (vpix_end), .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), .x_tiles (x_tiles),
.go_offs (go_offs), .go_offs (go_offs),
.cnt_col (cnt_col), .cnt_col (cnt_col),
@ -274,7 +276,8 @@ video_mode video_mode (
); );
video_sync video_sync ( video_sync video_sync
(
.clk (clk), .clk (clk),
.f1 (f1), .f1 (f1),
.c0 (c0), .c0 (c0),
@ -284,6 +287,10 @@ video_sync video_sync (
.hpix_end (hpix_end), .hpix_end (hpix_end),
.vpix_beg (vpix_beg), .vpix_beg (vpix_beg),
.vpix_end (vpix_end), .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), .go_offs (go_offs),
.x_offs (x_offs_mode[1:0]), .x_offs (x_offs_mode[1:0]),
.y_offs_wr (gy_offsl_wr || gy_offsh_wr), .y_offs_wr (gy_offsl_wr || gy_offsh_wr),
@ -311,12 +318,14 @@ video_sync video_sync (
.ts_start (ts_start), .ts_start (ts_start),
.cstart (x_offs_mode[9:2]), .cstart (x_offs_mode[9:2]),
.rstart (gy_offs), .rstart (gy_offs),
.frame_start (frame_start),
.int_start (int_start), .int_start (int_start),
.v_pf (v_pf), .v_pf (v_pf),
.hpix (hpix), .hpix (hpix),
.v_ts (v_ts), .v_ts (v_ts),
.vpix (vpix), .vpix (vpix),
.hvpix (hvpix), .hvpix (hvpix),
.hvtspix (hvtspix),
.nogfx (nogfx), .nogfx (nogfx),
.cfg_60hz (cfg_60hz), .cfg_60hz (cfg_60hz),
.sync_pol (sync_pol), .sync_pol (sync_pol),
@ -327,7 +336,8 @@ video_sync video_sync (
); );
video_fetch video_fetch ( video_fetch video_fetch
(
.clk (clk), .clk (clk),
.f_sel (fetch_sel), .f_sel (fetch_sel),
.b_sel (fetch_bsl), .b_sel (fetch_bsl),
@ -338,7 +348,8 @@ video_fetch video_fetch (
.video_data (dram_rdata) .video_data (dram_rdata)
); );
video_ts video_ts ( video_ts video_ts
(
.clk (clk), .clk (clk),
.start (ts_start), .start (ts_start),
.line (lcount), .line (lcount),
@ -378,8 +389,8 @@ video_ts video_ts (
.sfile_we (sfile_we) .sfile_we (sfile_we)
); );
video_ts_render video_ts_render
video_ts_render video_ts_render ( (
.clk (clk), .clk (clk),
.reset (ts_start), .reset (ts_start),
@ -406,10 +417,12 @@ video_ts_render video_ts_render (
); );
video_render video_render ( video_render video_render
(
.clk (clk), .clk (clk),
.c1 (c1), .c1 (c1),
.hvpix (hvpix), .hvpix (hvpix),
.hvtspix (hvtspix),
.nogfx (nogfx), .nogfx (nogfx),
.notsu (notsu), .notsu (notsu),
.gfxovr (gfxovr), .gfxovr (gfxovr),
@ -424,7 +437,8 @@ video_render video_render (
.vplex_out (vplex) .vplex_out (vplex)
); );
video_out video_out ( video_out video_out
(
.clk (clk), .clk (clk),
.f0 (f0), .f0 (f0),
.c3 (c3), .c3 (c3),
@ -436,14 +450,14 @@ video_out video_out (
.tv_hires (tv_hires), .tv_hires (tv_hires),
.vga_hires (vga_hires), .vga_hires (vga_hires),
.cram_addr_in (zma), .cram_addr_in (zma),
.cram_data_in (zmd[14:0]), .cram_data_in (zmd[15:0]),
.cram_we (cram_we), .cram_we (cram_we),
.vplex_in (vplex), .vplex_in (vplex),
.vgaplex (vgaplex), .vgaplex (vgaplex),
.vred (vred), .vred (vred),
.vgrn (vgrn), .vgrn (vgrn),
.vblu (vblu), .vblu (vblu),
.tst (tst) .vdac_mode (vdac_mode)
); );
assign hblank = vga_on ? vga_hblank : tv_hblank; assign hblank = vga_on ? vga_hblank : tv_hblank;
@ -453,12 +467,12 @@ assign vblank = vga_on ? vga_vblank : tv_vblank;
// (2 altdprams) // (2 altdprams)
wire tl_act0 = lcount[0]; wire tl_act0 = lcount[0];
wire tl_act1 = ~lcount[0]; wire tl_act1 = ~lcount[0];
wire [8:0] ts_waddr0 = tl_act0 ? ts_raddr : ts_waddr; wire [8:0] ts_waddr0 = tl_act0 ? ts_raddr : ts_waddr;
wire [7:0] ts_wdata0 = tl_act0 ? 8'd0 : ts_wdata; wire [7:0] ts_wdata0 = tl_act0 ? 8'd0 : ts_wdata;
wire ts_we0 = tl_act0 ? c3 : ts_we; wire ts_we0 = tl_act0 ? c3 : ts_we;
wire [8:0] ts_waddr1 = tl_act1 ? ts_raddr : ts_waddr; wire [8:0] ts_waddr1 = tl_act1 ? ts_raddr : ts_waddr;
wire [7:0] ts_wdata1 = tl_act1 ? 8'd0 : ts_wdata; wire [7:0] ts_wdata1 = tl_act1 ? 8'd0 : ts_wdata;
wire ts_we1 = tl_act1 ? c3 : ts_we; wire ts_we1 = tl_act1 ? c3 : ts_we;
wire [7:0] ts_rdata = tl_act0 ? ts_rdata0 : ts_rdata1; wire [7:0] ts_rdata = tl_act0 ? ts_rdata0 : ts_rdata1;
wire [7:0] ts_rdata0, ts_rdata1; wire [7:0] ts_rdata0, ts_rdata1;

View File

@ -59,319 +59,296 @@ module video_ts
output wire [20:0] dram_addr, output wire [20:0] dram_addr,
output wire dram_req, output wire dram_req,
input wire dram_next, input wire dram_next,
input wire [15:0] dram_rdata, input wire [15:0] dram_rdata
output wire [2:0] tst
); );
// config // config
wire s_en = tsconf[7]; wire s_en = tsconf[7];
wire t1_en = tsconf[6]; wire t1_en = tsconf[6];
wire t0_en = tsconf[5]; wire t0_en = tsconf[5];
wire t1z_en = tsconf[3]; wire t1z_en = tsconf[3];
wire t0z_en = tsconf[2]; wire t0z_en = tsconf[2];
// TS renderer interface // TS renderer interface
assign tsr_go = sprite_go || tile_go; assign tsr_go = sprite_go || tile_go;
assign tsr_x = sprites ? sprites_x : tile_x; assign tsr_x = sprites ? sprites_x : tile_x;
assign tsr_xs = sprites ? sprites_xs : 3'd0; assign tsr_xs = sprites ? sprites_xs : 3'd0;
assign tsr_xf = sprites ? sprites_xf : t_xflp; assign tsr_xf = sprites ? sprites_xf : t_xflp;
assign tsr_page = sprites ? sgpage : tile_page; assign tsr_page = sprites ? sgpage : tile_page;
assign tsr_line = sprites ? sprites_line : tile_line; assign tsr_line = sprites ? sprites_line : tile_line;
assign tsr_addr = sprites ? sprites_addr : tile_addr; assign tsr_addr = sprites ? sprites_addr : tile_addr;
assign tsr_pal = sprites ? s_pal : tile_pal; assign tsr_pal = sprites ? s_pal : tile_pal;
// Layer selectors control // Layer selectors control
// DEBUG !!! localparam LAYERS = 6; // Total number of layers to process
assign tst = lyr; localparam TM = 0; // Individual layers
reg [2:0] lyr; localparam S0 = 1;
always@* localparam T0 = 2;
// if (layer_active[S0]) localparam S1 = 3;
// lyr = 2; localparam T1 = 4;
// else if (layer_active[S1]) localparam S2 = 5;
// 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 wire tmap = layer_active[TM];
localparam TM = 0; // Individual layers wire sprites = layer_active[S0] || layer_active[S1] || layer_active[S2];
localparam S0 = 1; wire tiles = layer_active[T0] || layer_active[T1];
localparam T0 = 2;
localparam S1 = 3;
localparam T1 = 4;
localparam S2 = 5;
wire tmap = layer_active[TM]; reg [LAYERS-1:0] layer;
wire sprites = layer_active[S0] || layer_active[S1] || layer_active[S2]; always @(posedge clk)
wire tiles = layer_active[T0] || layer_active[T1]; if (start)
layer <= 1;
else if (|(layer & layer_skip))
layer <= {layer[LAYERS-2:0], 1'b0};
reg [LAYERS-1:0] layer; reg [LAYERS-1:0] layer_active;
always @(posedge clk) always @(posedge clk)
if (start) if (start)
layer <= 1; layer_active <= 0;
else if (|(layer & layer_skip)) else
layer <= {layer[LAYERS-2:0], 1'b0}; layer_active <= layer & ~layer_skip;
reg [LAYERS-1:0] layer_active; wire [LAYERS-1:0] layer_enabled = {s_en, t1_en, s_en, t0_en, s_en, t1_en || t0_en};
always @(posedge clk) wire [LAYERS-1:0] layer_allowed = {{5{v_ts}}, v_pf};
if (start) wire [LAYERS-1:0] layer_end = {spr_end[2], tile_end[1], spr_end[1], tile_end[0], spr_end[0], tm_end};
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}; reg [LAYERS-1:0] layer_skip;
wire [LAYERS-1:0] layer_allowed = {{5{v_ts}}, v_pf}; always @(posedge clk)
wire [LAYERS-1:0] layer_end = {spr_end[2], tile_end[1], spr_end[1], tile_end[0], spr_end[0], tm_end}; if (start)
layer_skip <= ~(layer_enabled & layer_allowed);
reg [LAYERS-1:0] layer_skip; else
always @(posedge clk) layer_skip <= layer_skip | layer_end;
if (start)
layer_skip <= ~(layer_enabled & layer_allowed);
else
layer_skip <= layer_skip | layer_end;
// --- Tile map prefetch --- // --- Tile map prefetch ---
// DRAM controls // 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_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; assign dram_req = tmap;
// TMB control // 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] 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 [8:0] tm_line = line + 9'd16;
wire [2:0] tm_b_line = tm_line[2:0]; 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 [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 [2:0] tm_num = tm_x[2:0];
wire tm_layer = tm_x[3]; wire tm_layer = tm_x[3];
// internal layers control // internal layers control
wire tm_end = tm_x == (t1_en ? 5'd16 : 5'd8); wire tm_end = tm_x == (t1_en ? 5'd16 : 5'd8);
wire tm_next = dram_next && tmap; wire tm_next = dram_next && tmap;
reg [1:0] m_layer; reg [1:0] m_layer;
always @(posedge clk) always @(posedge clk)
if (start) if (start)
m_layer <= 2'b1; m_layer <= 2'b1;
else if (tm_end) else if (tm_end)
m_layer <= {m_layer[0], 1'b0}; m_layer <= {m_layer[0], 1'b0};
// tilemap X coordinate // tilemap X coordinate
reg [4:0] tm_x; reg [4:0] tm_x;
always @(posedge clk) always @(posedge clk)
if (start) if (start)
tm_x <= t0_en ? 5'd0 : 5'd8; tm_x <= t0_en ? 5'd0 : 5'd8;
else if (tm_next) else if (tm_next)
tm_x <= tm_x + 5'd1; tm_x <= tm_x + 5'd1;
// --- Tiles --- // --- Tiles ---
// tile descriptor fields // tile descriptor fields
wire [11:0] t_tnum = tmb_rdata[11:0]; wire [11:0] t_tnum = tmb_rdata[11:0];
wire [1:0] t_pal = tmb_rdata[13:12]; wire [1:0] t_pal = tmb_rdata[13:12];
wire t_xflp = tmb_rdata[14]; wire t_xflp = tmb_rdata[14];
wire t_yflp = tmb_rdata[15]; wire t_yflp = tmb_rdata[15];
// TSR control // TSR control
wire [7:0] tile_page = t_sel ? t0gpage : t1gpage; 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 [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 [5:0] tile_addr = t_tnum[5:0];
wire [8:0] tile_x = {(tx - 6'd1), 3'd0} - tx_offs[2: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}; wire [3:0] tile_pal = {t_sel ? t0_palsel : t1_palsel, t_pal};
// TMB control // TMB control
wire [8:0] tmb_raddr = {t_line[4:3], tx + tx_offs[8:3], ~t_sel}; wire [8:0] tmb_raddr = {t_line[4:3], tx + tx_offs[8:3], ~t_sel};
// layer parameter selectors // layer parameter selectors
wire [8:0] tx_offs = t_sel ? t0x_offs : t1x_offs; 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 [3:0] ty_offs = t_sel ? t0y_offs[2:0] : t1y_offs[2:0];
wire t_sel = t_layer[0]; wire t_sel = t_layer[0];
// internal layers control // internal layers control
wire [1:0] tile_end = {2{t_layer_end}} & t_layer[1:0]; wire [1:0] tile_end = {2{t_layer_end}} & t_layer[1:0];
wire t_layer_end = tx == num_tiles; wire t_layer_end = tx == num_tiles;
wire t_layer_start = start || t_layer_end; wire t_layer_start = start || t_layer_end;
reg [1:0] t_layer; reg [1:0] t_layer;
always @(posedge clk) always @(posedge clk)
if (start) if (start)
t_layer <= t0_en ? 2'b01 : 2'b10; t_layer <= t0_en ? 2'b01 : 2'b10;
else if (t_layer_end) else if (t_layer_end)
t_layer <= {t_layer[0], 1'b0}; t_layer <= {t_layer[0], 1'b0};
// TMBUF control // TMBUF control
// condition write to tx write to tm_valid // condition write to tx write to tm_valid
// t_layer_start 0 TM_PRE_VALID // t_layer_start 0 TM_PRE_VALID
// tm_pre_valid tx+1 TM_VALID // tm_pre_valid tx+1 TM_VALID
// tile_skip tx+1 - // tile_skip tx+1 -
// tile_go tx+1 TM_VALID // tile_go tx+1 TM_VALID
// tile_wait tx-1 TM_PRE_VALID // tile_wait tx-1 TM_PRE_VALID
localparam TM_PRE_VALID = 2'b01; localparam TM_PRE_VALID = 2'b01;
localparam TM_VALID = 2'b10; localparam TM_VALID = 2'b10;
wire tile_go = tile_good && tsr_allowed; wire tile_go = tile_good && tsr_allowed;
wire tile_wait = tile_good && !tsr_allowed; wire tile_wait = tile_good && !tsr_allowed;
wire tile_good = tm_valid && tile_valid; wire tile_good = tm_valid && tile_valid;
wire tile_skip = tm_valid && !tile_valid; wire tile_skip = tm_valid && !tile_valid;
wire tsr_allowed = tiles && tsr_rdy; wire tsr_allowed = tiles && tsr_rdy;
wire tile_valid = |t_tnum || (t_sel ? t0z_en : t1z_en); wire tile_valid = |t_tnum || (t_sel ? t0z_en : t1z_en);
wire tm_pre_valid = tm_valid_r[0]; wire tm_pre_valid = tm_valid_r[0];
wire tm_valid = tm_valid_r[1]; wire tm_valid = tm_valid_r[1];
reg [1:0] tm_valid_r; reg [1:0] tm_valid_r;
always @(posedge clk) always @(posedge clk)
if (t_layer_start || tile_wait) if (t_layer_start || tile_wait)
tm_valid_r <= TM_PRE_VALID; tm_valid_r <= TM_PRE_VALID;
else if (tm_pre_valid || tile_go) else if (tm_pre_valid || tile_go)
tm_valid_r <= TM_VALID; tm_valid_r <= TM_VALID;
reg [5:0] tx; reg [5:0] tx;
always @(posedge clk) always @(posedge clk)
if (t_layer_start) if (t_layer_start)
tx <= 6'd0; tx <= 6'd0;
else if (tm_pre_valid || tile_skip || tile_go) else if (tm_pre_valid || tile_skip || tile_go)
tx <= tx + 6'd1; tx <= tx + 6'd1;
else if (tile_wait) else if (tile_wait)
tx <= tx - 6'd1; tx <= tx - 6'd1;
// tile Y geometry // tile Y geometry
wire [4:0] t_line = line[4:0] + ty_offs; wire [4:0] t_line = line[4:0] + ty_offs;
// --- Sprites --- // --- Sprites ---
// sprite descriptor fields // sprite descriptor fields
// R0 // R0
wire [8:0] s_ycrd = sfile_rdata[8:0]; wire [8:0] s_ycrd = sfile_rdata[8:0];
wire [2:0] s_ysz = sfile_rdata[11:9]; wire [2:0] s_ysz = sfile_rdata[11:9];
wire s_act = sfile_rdata[13]; wire s_act = sfile_rdata[13];
wire s_leap = sfile_rdata[14]; wire s_leap = sfile_rdata[14];
wire s_yflp = sfile_rdata[15]; wire s_yflp = sfile_rdata[15];
// R1 // R1
wire [8:0] s_xcrd = sfile_rdata[8:0]; wire [8:0] s_xcrd = sfile_rdata[8:0];
wire [2:0] s_xsz = sfile_rdata[11:9]; wire [2:0] s_xsz = sfile_rdata[11:9];
wire s_xflp = sfile_rdata[15]; wire s_xflp = sfile_rdata[15];
// R2 // R2
wire [11:0] s_tnum = sfile_rdata[11:0]; wire [11:0] s_tnum = sfile_rdata[11:0];
wire [3:0] s_pal = sfile_rdata[15:12]; wire [3:0] s_pal = sfile_rdata[15:12];
// TSR control // TSR control
reg [8:0] sprites_x; reg [8:0] sprites_x;
reg [2:0] sprites_xs; reg [2:0] sprites_xs;
reg sprites_xf; reg sprites_xf;
wire [5:0] sprites_addr = s_tnum[5:0]; wire [5:0] sprites_addr = s_tnum[5:0];
// internal layers control // internal layers control
wire [2:0] spr_end = ({3{s_layer_end}} & s_layer[2:0]) | {3{sprites_last}}; 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 s_layer_end = (sr0_valid && !spr_valid && s_leap) || (sprite_go && s_leap_r);
wire sprites_last = sreg == 8'd255; wire sprites_last = sreg == 8'd255;
reg [2:0] s_layer; reg [2:0] s_layer;
always @(posedge clk) always @(posedge clk)
if (start) if (start)
s_layer <= 3'b1; s_layer <= 3'b1;
else if (s_layer_end) else if (s_layer_end)
s_layer <= {s_layer[1:0], 1'b0}; s_layer <= {s_layer[1:0], 1'b0};
// SFile registers control // SFile registers control
// condition write to sreg write to sr_valid action // condition write to sreg write to sr_valid action
// start 0 SR0_PRE_VALID Start // start 0 SR0_PRE_VALID Start
// sr0_pre_valid sreg+3 SR0_VALID SR0 pre-read // sr0_pre_valid sreg+3 SR0_VALID SR0 pre-read
// sr0_valid && !spr_valid sreg+3 - Skip sprite // sr0_valid && !spr_valid sreg+3 - Skip sprite
// sr0_valid && spr_valid sreg-2 SR1_PRE_VALID SR1 pre-read // sr0_valid && spr_valid sreg-2 SR1_PRE_VALID SR1 pre-read
// sr1_pre_valid sreg+1 SR1_VALID SR1 read // sr1_pre_valid sreg+1 SR1_VALID SR1 read
// sr1_valid sreg+1 SR2_VALID SR2 pre-read // sr1_valid sreg+1 SR2_VALID SR2 pre-read
// sr2_valid && !tsr_rdy - - Wait for TSR ready // sr2_valid && !tsr_rdy - - Wait for TSR ready
// sr2_valid && tsr_rdy sreg+1 SR0_PRE_VALID Next sprite // sr2_valid && tsr_rdy sreg+1 SR0_PRE_VALID Next sprite
// sprites_last - NONE_VALID End // sprites_last - NONE_VALID End
localparam NONE_VALID = 5'b00000; localparam NONE_VALID = 5'b00000;
localparam SR0_PRE_VALID = 5'b00001; localparam SR0_PRE_VALID = 5'b00001;
localparam SR0_VALID = 5'b00010; localparam SR0_VALID = 5'b00010;
localparam SR1_PRE_VALID = 5'b00100; localparam SR1_PRE_VALID = 5'b00100;
localparam SR1_VALID = 5'b01000; localparam SR1_VALID = 5'b01000;
localparam SR2_VALID = 5'b10000; localparam SR2_VALID = 5'b10000;
wire sprite_go = sr2_valid && sprites && tsr_rdy; // kick to renderer wire sprite_go = sr2_valid && sprites && tsr_rdy; // kick to renderer
wire spr_valid = s_visible && s_act; wire spr_valid = s_visible && s_act;
wire sr0_pre_valid = sr_valid[0]; wire sr0_pre_valid = sr_valid[0];
wire sr0_valid = sr_valid[1]; wire sr0_valid = sr_valid[1];
wire sr1_pre_valid = sr_valid[2]; wire sr1_pre_valid = sr_valid[2];
wire sr1_valid = sr_valid[3]; wire sr1_valid = sr_valid[3];
wire sr2_valid = sr_valid[4]; wire sr2_valid = sr_valid[4];
reg [4:0] sr_valid; reg [4:0] sr_valid;
always @(posedge clk) always @(posedge clk)
if (start) if (start)
sr_valid <= SR0_PRE_VALID; sr_valid <= SR0_PRE_VALID;
else if (sprites_last) else if (sprites_last)
sr_valid <= NONE_VALID; sr_valid <= NONE_VALID;
else if (sr0_pre_valid) else if (sr0_pre_valid)
sr_valid <= SR0_VALID; sr_valid <= SR0_VALID;
else if (sr0_valid && spr_valid) else if (sr0_valid && spr_valid)
sr_valid <= SR1_PRE_VALID; sr_valid <= SR1_PRE_VALID;
else if (sr1_pre_valid) else if (sr1_pre_valid)
sr_valid <= SR1_VALID; sr_valid <= SR1_VALID;
else if (sr1_valid) else if (sr1_valid)
sr_valid <= SR2_VALID; sr_valid <= SR2_VALID;
else if (sprite_go) else if (sprite_go)
sr_valid <= SR0_PRE_VALID; sr_valid <= SR0_PRE_VALID;
reg [7:0] sreg; reg [7:0] sreg;
always @(posedge clk) always @(posedge clk)
if (start) if (start)
sreg <= 8'd0; sreg <= 8'd0;
else if (sr0_pre_valid) else if (sr0_pre_valid)
sreg <= sreg + 8'd3; sreg <= sreg + 8'd3;
else if (sr0_valid) else if (sr0_valid)
sreg <= spr_valid ? (sreg - 8'd2) : (sreg + 8'd3); sreg <= spr_valid ? (sreg - 8'd2) : (sreg + 8'd3);
else if (sr1_pre_valid || sprite_go) else if (sr1_pre_valid || sprite_go)
sreg <= sreg + 8'd1; sreg <= sreg + 8'd1;
// SFile control // SFile control
reg [5:0] s_bmline_offset_r; reg [5:0] s_bmline_offset_r;
reg s_leap_r; reg s_leap_r;
always @(posedge clk) always @(posedge clk) begin
if (sr0_valid)
begin begin
if (sr0_valid) s_leap_r <= s_leap;
begin s_bmline_offset_r <= s_bmline_offset;
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
end end
// sprite Y geometry if (sr1_valid)
wire [8:0] s_line = line - s_ycrd; // visible line of sprite in current video line begin
wire s_visible = (s_line <= s_ymax); // check if sprite line is within Y size sprites_x <= s_xcrd;
wire [5:0] s_ymax = {s_ysz, 3'b111}; 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; // sprite Y geometry
wire [5:0] s_bmline_offset = s_yflp ? (s_ymax - s_line[5:0]) : s_line[5:0]; 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 // SFile

View File

@ -15,12 +15,12 @@
// after TS request recognized and processed by DRAM controller. // after TS request recognized and processed by DRAM controller.
// It is recommended to assert 'tsr_go' at 'c2'. // It is recommended to assert 'tsr_go' at 'c2'.
module video_ts_render ( module video_ts_render
(
// clocks // clocks
input wire clk, input wire clk,
// controls // controls
input wire reset, // line start strobe, inits the machine 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' 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 input wire [ 3:0] pal, // palette selector, bits[7:4] of CRAM address
output wire mem_rdy, // ready to receive new task output wire mem_rdy, // ready to receive new task
// TS-Line interface // TS-Line interface
output reg [ 8:0] ts_waddr, output reg [ 8:0] ts_waddr,
output wire [ 7:0] ts_wdata, output wire [ 7:0] ts_wdata,
output wire ts_we, output wire ts_we,
// DRAM interface // DRAM interface
output wire [20:0] dram_addr, output wire [20:0] dram_addr,
output wire dram_req, output wire dram_req,
input wire [15:0] dram_rdata, input wire [15:0] dram_rdata,
input wire dram_pre_next, input wire dram_pre_next,
input wire dram_next input wire dram_next
); );
// DRAM request // DRAM request
assign dram_req = tsr_go || !mem_rdy; assign dram_req = tsr_go || !mem_rdy;
// DRAM addressing // DRAM addressing
assign dram_addr = tsr_go ? addr_in : addr_next; assign dram_addr = tsr_go ? addr_in : addr_next;
wire [20:0] addr_in = {addr_offset, addr, 1'b0}; wire [20:0] addr_in = {addr_offset, addr, 1'b0};
wire [13:0] addr_offset = {page[7:3], line}; wire [13:0] addr_offset = {page[7:3], line};
wire [20:0] addr_next = {addr_reg[20:7], addr_reg[6:0] + dram_next}; 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 // as renderer can't move outside the single bitmap line, only 7 bits are processed
reg [20:0] addr_reg; reg [20:0] addr_reg;
always @(posedge clk) always @(posedge clk) addr_reg <= dram_addr;
addr_reg <= dram_addr;
// DRAM cycles counter // DRAM cycles counter
assign mem_rdy = cyc[4]; assign mem_rdy = cyc[4];
reg [4:0] cyc; reg [4:0] cyc;
always @(posedge clk) always @(posedge clk)
if (reset) if (reset)
cyc <= 5'b10000; cyc <= 5'b10000;
else if (tsr_go) else if (tsr_go)
cyc <= {1'b0, x_size, 1'b1}; cyc <= {1'b0, x_size, 1'b1};
else if (dram_pre_next) else if (dram_pre_next)
cyc <= cyc - 5'd1; cyc <= cyc - 5'd1;
// DRAM data fetching // DRAM data fetching
reg [15:0] data; reg [15:0] data;
always @(posedge clk) always @(posedge clk) if (dram_next) data <= dram_rdata;
if (dram_next)
data <= dram_rdata;
// pixel render counter // pixel render counter
assign ts_we = render_on && |pix; // write signal for TS-line assign ts_we = render_on && |pix; // write signal for TS-line
wire render_on = !cnt[2]; wire render_on = !cnt[2];
reg [2:0] cnt; reg [2:0] cnt;
always @(posedge clk) always @(posedge clk)
if (reset) if (reset)
cnt <= 3'b100; cnt <= 3'b100;
else if (dram_next) else if (dram_next)
cnt <= 3'b000; cnt <= 3'b000;
else if (render_on) else if (render_on)
cnt <= cnt + 3'd1; cnt <= cnt + 3'd1;
// renderer reload // renderer reload
reg tsr_rld; reg tsr_rld;
always @(posedge clk) always @(posedge clk)
if (reset) if (reset)
tsr_rld <= 1'b0; tsr_rld <= 1'b0;
else if (tsr_go) else if (tsr_go)
tsr_rld <= 1'b1; tsr_rld <= 1'b1;
else if (dram_next) else if (dram_next)
tsr_rld <= 1'b0; tsr_rld <= 1'b0;
// delayed values // delayed values
reg [8:0] x_coord_d; reg [8:0] x_coord_d;
reg [3:0] pal_d; reg [3:0] pal_d;
reg flip_d; reg flip_d;
always @(posedge clk) always @(posedge clk)
if (tsr_go) if (tsr_go)
begin begin
x_coord_d <= x_coord + (flip ? {x_size, 3'b111} : 6'd0); x_coord_d <= x_coord + (flip ? {x_size, 3'b111} : 6'd0);
pal_d <= pal; pal_d <= pal;
flip_d <= flip; flip_d <= flip;
end end
// TS-line address // TS-line address
wire [8:0] ts_waddr_mx = tsr_rld_stb ? x_coord_d : (render_on ? x_next : ts_waddr); 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 [8:0] x_next = ts_waddr + {{8{flip_r}}, 1'b1};
wire tsr_rld_stb = tsr_rld && dram_next; wire tsr_rld_stb = tsr_rld && dram_next;
always @(posedge clk) always @(posedge clk) ts_waddr <= ts_waddr_mx;
ts_waddr <= ts_waddr_mx;
reg [3:0] pal_r; reg [3:0] pal_r;
reg flip_r; reg flip_r;
always @(posedge clk) always @(posedge clk)
if (tsr_rld_stb) if (tsr_rld_stb)
begin begin
pal_r <= pal_d; pal_r <= pal_d;
flip_r <= flip_d; flip_r <= flip_d;
end end
// renderer mux // renderer mux
assign ts_wdata = {pal_r, pix}; assign ts_wdata = {pal_r, pix};
wire [3:0] pix = pix_m[cnt[1:0]]; wire [3:0] pix = pix_m[cnt[1:0]];
wire [3:0] pix_m[0:3]; wire [3:0] pix_m[0:3];
assign pix_m[0] = data[7:4]; assign pix_m[0] = data[7:4];
assign pix_m[1] = data[3:0]; assign pix_m[1] = data[3:0];
assign pix_m[2] = data[15:12]; assign pix_m[2] = data[15:12];
assign pix_m[3] = data[11:8]; assign pix_m[3] = data[11:8];
endmodule endmodule