diff --git a/PCXT.qsf b/PCXT.qsf
index 96ec8fd..7e70785 100644
--- a/PCXT.qsf
+++ b/PCXT.qsf
@@ -290,6 +290,10 @@ set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_
set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_signal_integrity
set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_boundary_scan
set_global_assignment -name EDA_RUN_TOOL_AUTOMATICALLY OFF -section_id eda_simulation
+set_global_assignment -name VERILOG_FILE rtl/video/mda_sequencer.v
+set_global_assignment -name VERILOG_FILE rtl/video/mda_pixel.v
+set_global_assignment -name VERILOG_FILE rtl/video/mda_attrib.v
+set_global_assignment -name VERILOG_FILE rtl/video/mda.v
set_global_assignment -name VERILOG_FILE rtl/uart/uart.v
set_global_assignment -name QIP_FILE rtl/uart/uart.qip
set_global_assignment -name VHDL_FILE rtl/uart/gh_uart_Tx_8bit.vhd
@@ -403,4 +407,5 @@ set_global_assignment -name SYSTEMVERILOG_FILE PCXT.sv
set_global_assignment -name SIP_FILE pll.sip
set_global_assignment -name QIP_FILE rtl/pll.qip
set_global_assignment -name SIP_FILE rtl/pll.sip
+set_global_assignment -name VERILOG_FILE rtl/video/mda_vgaport.v
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
\ No newline at end of file
diff --git a/PCXT.sv b/PCXT.sv
index 2e274db..40c0ac0 100644
--- a/PCXT.sv
+++ b/PCXT.sv
@@ -211,7 +211,9 @@ localparam CONF_STR = {
"-;",
"OA,Adlib,On,Invisible;",
"-;",
- "O12,Video,Color,Green,Amber,B/W;",
+ "O4,Video Output,Tandy/CGA,MDA;",
+ "O12,CGA RGB,Color,Green,Amber,B/W;",
+ "O56,MDA RGB,Green,Amber,B/W;",
"O89,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];",
//"O78,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
"-;",
@@ -314,7 +316,7 @@ wire pll_locked;
wire clk_100;
wire clk_28_636;
-wire clk_25;
+wire clk_56_875;
reg clk_14_318 = 1'b0;
//reg clk_7_16 = 1'b0;
wire clk_4_77;
@@ -329,6 +331,7 @@ pll pll
.outclk_1(clk_28_636),
.outclk_2(clk_uart),
.outclk_3(cen_opl2),
+ .outclk_4(clk_56_875),
.locked(pll_locked)
);
@@ -468,8 +471,9 @@ always @(posedge clk_4_77)
logic [7:0] port_b_out;
logic [7:0] port_c_in;
- logic [7:0] sw = 8'b00101101; // PCXT DIP Switches
+ reg [7:0] sw;
+ assign sw = status[4] ? 8'b00111101 : 8'b00101101; // PCXT DIP Switches (MDA or CGA 80)
assign port_c_in[3:0] = port_b_out[3] ? sw[7:4] : sw[3:0];
CHIPSET u_CHIPSET (
@@ -486,8 +490,12 @@ always @(posedge clk_4_77)
.processor_ready (processor_ready),
.interrupt_to_cpu (interrupt_to_cpu),
.splashscreen (splashscreen),
- .clk_vga (clk_28_636),
+ .video_output (status[4]),
+ .clk_vga_cga (clk_28_636),
.enable_cga (1'b1),
+ .clk_vga_mda (clk_56_875),
+ .enable_mda (1'b1),
+ .mda_rgb (status[6:5]),
.de_o (VGA_DE),
.VGA_R (r),
.VGA_G (g),
@@ -617,7 +625,7 @@ always @(posedge clk_4_77)
);
*/
- always @ (status[2:1], r, g, b) begin
+ always @ (status[2:1], r, g, b) begin
case(status[2:1])
// Verde
2'b01 : begin
@@ -646,9 +654,9 @@ always @(posedge clk_4_77)
endcase
end
- assign VGA_R = {raux, 2'b0};
- assign VGA_G = {gaux, 2'b0};
- assign VGA_B = {baux, 2'b0};
+ assign VGA_R = {status[4] ? r : raux, 2'b0};
+ assign VGA_G = {status[4] ? g : gaux, 2'b0};
+ assign VGA_B = {status[4] ? b : baux, 2'b0};
/*
// SRAM management
diff --git a/SW/splash.txt b/SW/splash.txt
index 115f40f..6b83835 100644
--- a/SW/splash.txt
+++ b/SW/splash.txt
@@ -5,7 +5,7 @@
(_()((_|(_|_)) (_(_())/((_|()\ (_)) )\_____((_)(_(_())
| \/ |(_) __||_ _(_)) ((_) | _ ((/ __\ \/ /|_ _|
| |\/| || \__ \ | | / -_)| '_| | _/| (__ > < | |
- |_| |_||_|___/ |_| \___||_| |_| \___/_/\_\ |_| 07/06/2022
+ |_| |_||_|___/ |_| \___||_| |_| \___/_/\_\ |_| 13/06/2022
Port by @spark2k06, @naeloob
diff --git a/releases/PCXT_20220613.rbf b/releases/PCXT_20220613.rbf
new file mode 100644
index 0000000..5010b32
Binary files /dev/null and b/releases/PCXT_20220613.rbf differ
diff --git a/rtl/KFPC-XT/HDL/Chipset.sv b/rtl/KFPC-XT/HDL/Chipset.sv
index b28099b..37d499d 100644
--- a/rtl/KFPC-XT/HDL/Chipset.sv
+++ b/rtl/KFPC-XT/HDL/Chipset.sv
@@ -18,8 +18,12 @@ module CHIPSET (
// SplashScreen
input logic splashscreen,
// VGA
- input logic clk_vga,
+ input logic video_output,
+ input logic clk_vga_cga,
input logic enable_cga,
+ input logic clk_vga_mda,
+ input logic enable_mda,
+ input logic [1:0] mda_rgb,
output logic de_o,
output logic [5:0] VGA_R,
output logic [5:0] VGA_G,
@@ -182,9 +186,13 @@ module CHIPSET (
.dma_chip_select_n (dma_chip_select_n),
.dma_page_chip_select_n (dma_page_chip_select_n),
.splashscreen (splashscreen),
- .clk_vga (clk_vga),
+ .video_output (video_output),
+ .clk_vga_cga (clk_vga_cga),
.enable_cga (enable_cga),
+ .clk_vga_mda (clk_vga_mda),
+ .enable_mda (enable_mda),
.de_o (de_o),
+ .mda_rgb (mda_rgb),
.VGA_R (VGA_R),
.VGA_G (VGA_G),
.VGA_B (VGA_B),
diff --git a/rtl/KFPC-XT/HDL/Peripherals.sv b/rtl/KFPC-XT/HDL/Peripherals.sv
index 90001d9..516768c 100644
--- a/rtl/KFPC-XT/HDL/Peripherals.sv
+++ b/rtl/KFPC-XT/HDL/Peripherals.sv
@@ -18,8 +18,12 @@ module PERIPHERALS #(
// SplashScreen
input logic splashscreen,
// VGA
- input logic clk_vga,
+ input logic video_output,
+ input logic clk_vga_cga,
input logic enable_cga,
+ input logic clk_vga_mda,
+ input logic enable_mda,
+ input logic [1:0] mda_rgb,
output logic de_o,
output logic [5:0] VGA_R,
output logic [5:0] VGA_G,
@@ -108,7 +112,7 @@ module PERIPHERALS #(
wire tandy_chip_select_n = ~(address[15:3] == (16'h00c0 >> 3)); // 0xc0 - 0xc7
wire opl_chip_select_n = ~(address[15:1] == (16'h0388 >> 1)); // 0x388 .. 0x389
wire cga_chip_select_n = ~(enable_cga & (address[19:14] == 6'b1011_10)); // B8000 - BFFFF (32 KB)
- wire mda_chip_select_n = ~(enable_cga & (address[19:14] == 6'b1011_00)); // B0000 - B7FFF (32 KB)
+ wire mda_chip_select_n = ~(enable_mda & (address[19:14] == 6'b1011_00)); // B0000 - B7FFF (32 KB)
wire rom_select_n = ~(address[19:16] == 4'b1111); // F0000 - FFFFF (64 KB)
wire ram_select_n = ~(address[19:18] == 2'b00); // 00000 - 3FFFF (256 KB)
wire uart_cs = ({address[15:3], 3'd0} == 16'h03F8);
@@ -377,21 +381,84 @@ module PERIPHERALS #(
uart_readdata <= uart_readdata;
end
+ reg [5:0] R_CGA;
+ reg [5:0] G_CGA;
+ reg [5:0] B_CGA;
+ reg HSYNC_CGA;
+ reg VSYNC_CGA;
- wire VRAM_ENABLE;
- wire [18:0] VRAM_ADDR;
- wire [7:0] VRAM_DOUT;
- wire CRTC_OE;
- wire [7:0] CRTC_DOUT;
-
+ reg [5:0] R_MDA;
+ reg [5:0] G_MDA;
+ reg [5:0] B_MDA;
+ reg HSYNC_MDA;
+ reg VSYNC_MDA;
+
+ reg de_o_cga;
+ reg de_o_mda;
+
+ wire[3:0] video_cga;
+ wire[3:0] video_mda;
+
+ assign VGA_R = video_output ? R_MDA : R_CGA;
+ assign VGA_G = video_output ? G_MDA : G_CGA;
+ assign VGA_B = video_output ? B_MDA : B_CGA;
+ assign VGA_HSYNC = video_output ? HSYNC_MDA : HSYNC_CGA;
+ assign VGA_VSYNC = video_output ? VSYNC_MDA : VSYNC_CGA;
+ assign de_o = video_output ? de_o_mda : de_o_cga;
+
+ wire MDA_VRAM_ENABLE;
+ wire [18:0] MDA_VRAM_ADDR;
+ wire [7:0] MDA_VRAM_DOUT;
+ wire MDA_CRTC_OE;
+ wire [7:0] MDA_CRTC_DOUT;
+
+ wire intensity;
+
+
+
+ mda_vgaport vga_mda (
+ .clk(clk_vga_mda),
+ .video(video_mda),
+ .intensity(intensity),
+ .red(R_MDA),
+ .green(G_MDA),
+ .blue(B_MDA),
+ .mda_rgb(mda_rgb)
+ );
+
+ mda mda1 (
+ .clk (clk_vga_mda),
+ .bus_a (address[15:0]),
+ .bus_ior_l (io_read_n),
+ .bus_iow_l (io_write_n),
+ .bus_memr_l (1'd0),
+ .bus_memw_l (1'd0),
+ .bus_d (internal_data_bus),
+ .bus_out (MDA_CRTC_DOUT),
+ .bus_dir (MDA_CRTC_OE),
+ .bus_aen (address_enable_n),
+ .ram_we_l (MDA_VRAM_ENABLE),
+ .ram_a (MDA_VRAM_ADDR),
+ .ram_d (MDA_VRAM_DOUT),
+ .hsync (HSYNC_MDA),
+ .vsync (VSYNC_MDA),
+ .intensity (intensity),
+ .video (video_mda),
+ .de_o (de_o_mda)
+ );
+
+
+ wire CGA_VRAM_ENABLE;
+ wire [18:0] CGA_VRAM_ADDR;
+ wire [7:0] CGA_VRAM_DOUT;
+ wire CGA_CRTC_OE;
+ wire [7:0] CGA_CRTC_DOUT;
+
// Sets up the card to generate a video signal
// that will work with a standard VGA monitor
// connected to the VGA port.
parameter MDA_70HZ = 0;
-
- wire[3:0] vga_video;
- wire[3:0] video;
-
+
// wire composite_on;
wire thin_font;
@@ -401,61 +468,79 @@ module PERIPHERALS #(
// Thin font switch (TODO: switchable with Keyboard shortcut)
assign thin_font = 1'b0; // Default: No thin font
+
+
// CGA digital to analog converter
- cga_vgaport vga (
- .clk(clk_vga),
-// .video(vga_video),
- .video(video), //Mister Test without Scandouble
- .red(VGA_R),
- .green(VGA_G),
- .blue(VGA_B)
+ cga_vgaport vga_cga (
+ .clk(clk_vga_cga),
+ .video(video_cga),
+ .red(R_CGA),
+ .green(G_CGA),
+ .blue(B_CGA)
);
cga cga1 (
- .clk (clk_vga),
+ .clk (clk_vga_cga),
.bus_a (address[15:0]),
.bus_ior_l (io_read_n),
.bus_iow_l (io_write_n),
.bus_memr_l (1'd0),
.bus_memw_l (1'd0),
.bus_d (internal_data_bus),
- .bus_out (CRTC_DOUT),
- .bus_dir (CRTC_OE),
+ .bus_out (CGA_CRTC_DOUT),
+ .bus_dir (CGA_CRTC_OE),
.bus_aen (address_enable_n),
- .ram_we_l (VRAM_ENABLE),
- .ram_a (VRAM_ADDR),
- .ram_d (VRAM_DOUT),
-// .dbl_hsync (VGA_HSYNC),
- .hsync (VGA_HSYNC), //Mister Test without Scandouble
- .vsync (VGA_VSYNC),
- .de_o (de_o),
- .video (video),
-// .dbl_video (vga_video),
-// .comp_video (comp_video),
+ .ram_we_l (CGA_VRAM_ENABLE),
+ .ram_a (CGA_VRAM_ADDR),
+ .ram_d (CGA_VRAM_DOUT),
+ .hsync (HSYNC_CGA),
+ .vsync (VSYNC_CGA),
+ .de_o (de_o_cga),
+ .video (video_cga),
.splashscreen (splashscreen),
.thin_font (thin_font)
);
-
+
defparam cga1.BLINK_MAX = 24'd4772727;
+ defparam mda1.BLINK_MAX = 24'd9100000;
wire [7:0] ram_cpu_dout;
wire [7:0] bios_cpu_dout;
- wire [7:0] vram_cpu_dout;
+ wire [7:0] cga_vram_cpu_dout;
+ wire [7:0] mda_vram_cpu_dout;
- vram vram
+ vram cga_vram
(
.clka (clock),
- .ena (~address_enable_n && (~mda_chip_select_n || ~cga_chip_select_n)),
+ .ena (~address_enable_n && ~cga_chip_select_n),
.wea (~memory_write_n),
.addra (address[14:0]),
.dina (internal_data_bus),
- .douta (vram_cpu_dout),
- .clkb (clk_vga),
+ .douta (cga_vram_cpu_dout),
+ .clkb (clk_vga_cga),
.web (1'b0),
- .enb (VRAM_ENABLE),
- .addrb (VRAM_ADDR[14:0]),
+ .enb (CGA_VRAM_ENABLE),
+ .addrb (CGA_VRAM_ADDR[14:0]),
.dinb (8'h0),
- .doutb (VRAM_DOUT)
+ .doutb (CGA_VRAM_DOUT)
);
+
+
+ vram mda_vram
+ (
+ .clka (clock),
+ .ena (~address_enable_n && ~mda_chip_select_n),
+ .wea (~memory_write_n),
+ .addra (address[14:0]),
+ .dina (internal_data_bus),
+ .douta (mda_vram_cpu_dout),
+ .clkb (clk_vga_mda),
+ .web (1'b0),
+ .enb (MDA_VRAM_ENABLE),
+ .addrb (MDA_VRAM_ADDR[14:0]),
+ .dinb (8'h0),
+ .doutb (MDA_VRAM_DOUT)
+ );
+
ram #(.AW(18)) mram
@@ -528,9 +613,13 @@ module PERIPHERALS #(
data_bus_out_from_chipset = 1'b1;
data_bus_out = ppi_data_bus_out;
end
- else if ((~cga_chip_select_n || ~mda_chip_select_n) && (~memory_read_n)) begin
+ else if ((~cga_chip_select_n) && (~memory_read_n)) begin
data_bus_out_from_chipset = 1'b1;
- data_bus_out = vram_cpu_dout;
+ data_bus_out = cga_vram_cpu_dout;
+ end
+ else if ((~mda_chip_select_n) && (~memory_read_n)) begin
+ data_bus_out_from_chipset = 1'b1;
+ data_bus_out = mda_vram_cpu_dout;
end
else if ((~rom_select_n) && (~memory_read_n)) begin
data_bus_out_from_chipset = 1'b1;
@@ -540,9 +629,13 @@ module PERIPHERALS #(
data_bus_out_from_chipset = 1'b1;
data_bus_out = ram_cpu_dout;
end
- else if (CRTC_OE) begin
+ else if (CGA_CRTC_OE) begin
data_bus_out_from_chipset = 1'b1;
- data_bus_out = CRTC_DOUT;
+ data_bus_out = CGA_CRTC_DOUT;
+ end
+ else if (MDA_CRTC_OE) begin
+ data_bus_out_from_chipset = 1'b1;
+ data_bus_out = MDA_CRTC_DOUT;
end
else if ((~opl_chip_select_n) && (~io_read_n)) begin
data_bus_out_from_chipset = 1'b1;
diff --git a/rtl/pll.qip b/rtl/pll.qip
index 6128d73..35bf73b 100644
--- a/rtl/pll.qip
+++ b/rtl/pll.qip
@@ -37,8 +37,8 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz"
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::NA==::TnVtYmVyIE9mIENsb2Nrcw=="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::NA==::bnVtYmVyX29mX2Nsb2Nrcw=="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::NQ==::TnVtYmVyIE9mIENsb2Nrcw=="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::NQ==::bnVtYmVyX29mX2Nsb2Nrcw=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp"
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp"
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ=="
@@ -91,11 +91,11 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0"
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy"
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::NC43NzY=::RGVzaXJlZCBGcmVxdWVuY3k="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::NTYuODc1::RGVzaXJlZCBGcmVxdWVuY3k="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ=="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MTY=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ=="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MTQ=::QWN0dWFsIERpdmlkZSBGYWN0b3I="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ="
@@ -270,7 +270,7 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::My41ODc0NDMgTUh6::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz"
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::NTcuMTQyODU3IE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0"
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU="
@@ -355,12 +355,12 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMw==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMw=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMw==::ZmFsc2U=::Y19jbnRfYnlwYXNzX2VuMw=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMw==::dHJ1ZQ==::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMw=="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2NA==::MQ==::Y19jbnRfaGlfZGl2NA=="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2NA==::MQ==::Y19jbnRfbG9fZGl2NA=="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2NA==::Nw==::Y19jbnRfaGlfZGl2NA=="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2NA==::Nw==::Y19jbnRfbG9fZGl2NA=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDQ=::MQ==::Y19jbnRfcHJzdDQ="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q0::MA==::Y19jbnRfcGhfbXV4X3Byc3Q0"
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNA==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNA=="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNA==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNA=="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNA==::ZmFsc2U=::Y19jbnRfYnlwYXNzX2VuNA=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNA==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNA=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2NQ==::MQ==::Y19jbnRfaGlfZGl2NQ=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2NQ==::MQ==::Y19jbnRfbG9fZGl2NQ=="
@@ -463,8 +463,8 @@ set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAM
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX2ZiY2xrX211eF8y::bV9jbnQ=::cGxsX2ZiY2xrX211eF8y"
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX21fY250X2luX3NyYw==::cGhfbXV4X2Nsaw==::cGxsX21fY250X2luX3NyYw=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3NsZl9yc3Q=::dHJ1ZQ==::cGxsX3NsZl9yc3Q="
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTIgSGkgRGl2aWRlLEMtQ291bnRlci0yIExvdyBEaXZpZGUsQy1Db3VudGVyLTIgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0yIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTIgSW5wdXQgU291cmNlLEMtQ291bnRlci0yIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTMgSGkgRGl2aWRlLEMtQ291bnRlci0zIExvdyBEaXZpZGUsQy1Db3VudGVyLTMgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0zIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTMgSW5wdXQgU291cmNlLEMtQ291bnRlci0zIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTMgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz"
-set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::OCw4LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSw0LDQsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsMTQsMTQsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsMjE3LDIxNywxLDAscGhfbXV4X2NsayxmYWxzZSxmYWxzZSwxMTIsMTExLDEsMCxwaF9tdXhfY2xrLGZhbHNlLHRydWUsMSwyMCw0MDAwLDgwMC4wIE1IeiwxLG5vbmUsZ2xiLG1fY250LHBoX211eF9jbGssdHJ1ZQ==::UGFyYW1ldGVyIFZhbHVlcw=="
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTIgSGkgRGl2aWRlLEMtQ291bnRlci0yIExvdyBEaXZpZGUsQy1Db3VudGVyLTIgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0yIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTIgSW5wdXQgU291cmNlLEMtQ291bnRlci0yIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTMgSGkgRGl2aWRlLEMtQ291bnRlci0zIExvdyBEaXZpZGUsQy1Db3VudGVyLTMgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0zIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTMgSW5wdXQgU291cmNlLEMtQ291bnRlci0zIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTMgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTQgSGkgRGl2aWRlLEMtQ291bnRlci00IExvdyBEaXZpZGUsQy1Db3VudGVyLTQgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci00IFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTQgSW5wdXQgU291cmNlLEMtQ291bnRlci00IEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTQgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz"
+set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::OCw4LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSw0LDQsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsMTQsMTQsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsMjE3LDIxNywxLDAscGhfbXV4X2NsayxmYWxzZSxmYWxzZSwxMTIsMTExLDEsMCxwaF9tdXhfY2xrLGZhbHNlLHRydWUsNyw3LDEsMCxwaF9tdXhfY2xrLGZhbHNlLGZhbHNlLDEsMjAsNDAwMCw4MDAuMCBNSHosMSxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw=="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc="
set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u"
diff --git a/rtl/pll.v b/rtl/pll.v
index 80aa30b..7c9675d 100644
--- a/rtl/pll.v
+++ b/rtl/pll.v
@@ -12,6 +12,7 @@ module pll (
output wire outclk_1, // outclk1.clk
output wire outclk_2, // outclk2.clk
output wire outclk_3, // outclk3.clk
+ output wire outclk_4, // outclk4.clk
output wire locked, // locked.export
input wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll
output wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll
@@ -24,6 +25,7 @@ module pll (
.outclk_1 (outclk_1), // outclk1.clk
.outclk_2 (outclk_2), // outclk2.clk
.outclk_3 (outclk_3), // outclk3.clk
+ .outclk_4 (outclk_4), // outclk4.clk
.locked (locked), // locked.export
.reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll
.reconfig_from_pll (reconfig_from_pll) // reconfig_from_pll.reconfig_from_pll
@@ -71,7 +73,7 @@ endmodule
// Retrieval info:
// Retrieval info:
// Retrieval info:
-// Retrieval info:
+// Retrieval info:
// Retrieval info:
// Retrieval info:
// Retrieval info:
@@ -112,7 +114,7 @@ endmodule
// Retrieval info:
// Retrieval info:
// Retrieval info:
-// Retrieval info:
+// Retrieval info:
// Retrieval info:
// Retrieval info:
// Retrieval info:
diff --git a/rtl/pll/pll_0002.v b/rtl/pll/pll_0002.v
index 415f92f..7d2fefe 100644
--- a/rtl/pll/pll_0002.v
+++ b/rtl/pll/pll_0002.v
@@ -19,6 +19,9 @@ module pll_0002(
// interface 'outclk3'
output wire outclk_3,
+ // interface 'outclk4'
+ output wire outclk_4,
+
// interface 'locked'
output wire locked,
@@ -35,7 +38,7 @@ module pll_0002(
.pll_fractional_cout(32),
.pll_dsm_out_sel("1st_order"),
.operation_mode("direct"),
- .number_of_clocks(4),
+ .number_of_clocks(5),
.output_clock_frequency0("100.000000 MHz"),
.phase_shift0("0 ps"),
.duty_cycle0(50),
@@ -48,7 +51,7 @@ module pll_0002(
.output_clock_frequency3("3.587443 MHz"),
.phase_shift3("0 ps"),
.duty_cycle3(50),
- .output_clock_frequency4("0 MHz"),
+ .output_clock_frequency4("57.142857 MHz"),
.phase_shift4("0 ps"),
.duty_cycle4(50),
.output_clock_frequency5("0 MHz"),
@@ -128,12 +131,12 @@ module pll_0002(
.c_cnt_in_src3("ph_mux_clk"),
.c_cnt_bypass_en3("false"),
.c_cnt_odd_div_duty_en3("true"),
- .c_cnt_hi_div4(1),
- .c_cnt_lo_div4(1),
+ .c_cnt_hi_div4(7),
+ .c_cnt_lo_div4(7),
.c_cnt_prst4(1),
.c_cnt_ph_mux_prst4(0),
.c_cnt_in_src4("ph_mux_clk"),
- .c_cnt_bypass_en4("true"),
+ .c_cnt_bypass_en4("false"),
.c_cnt_odd_div_duty_en4("false"),
.c_cnt_hi_div5(1),
.c_cnt_lo_div5(1),
@@ -238,7 +241,7 @@ module pll_0002(
.pll_slf_rst("true")
) altera_pll_i (
.rst (rst),
- .outclk ({outclk_3, outclk_2, outclk_1, outclk_0}),
+ .outclk ({outclk_4, outclk_3, outclk_2, outclk_1, outclk_0}),
.locked (locked),
.reconfig_to_pll (reconfig_to_pll),
.fboutclk ( ),
diff --git a/rtl/video/mda.hex b/rtl/video/mda.hex
new file mode 100644
index 0000000..bd2ab58
--- /dev/null
+++ b/rtl/video/mda.hex
@@ -0,0 +1 @@
+00 00 00 00 00 00 00 00 00 00 7E 81 A5 81 81 BD 00 00 7E FF DB FF FF C3 00 00 00 36 7F 7F 7F 7F 00 00 00 08 1C 3E 7F 3E 00 00 18 3C 3C E7 E7 E7 00 00 18 3C 7E FF FF 7E 00 00 00 00 00 18 3C 3C FF FF FF FF FF E7 C3 C3 00 00 00 00 3C 66 42 42 FF FF FF FF C3 99 BD BD 00 00 0F 07 0D 19 3C 66 00 00 3C 66 66 66 3C 18 00 00 3F 33 3F 30 30 30 00 00 7F 63 7F 63 63 63 00 00 18 18 DB 3C E7 3C 00 00 40 60 70 7C 7F 7C 00 00 01 03 07 1F 7F 1F 00 00 18 3C 7E 18 18 18 00 00 33 33 33 33 33 33 00 00 7F DB DB DB 7B 1B 00 3E 63 30 1C 36 63 63 00 00 00 00 00 00 00 00 00 00 18 3C 7E 18 18 18 00 00 18 3C 7E 18 18 18 00 00 18 18 18 18 18 18 00 00 00 00 0C 06 7F 06 00 00 00 00 18 30 7F 30 00 00 00 00 00 60 60 60 00 00 00 00 24 66 FF 66 00 00 00 08 1C 1C 3E 3E 00 00 00 7F 7F 3E 3E 1C 00 00 00 00 00 00 00 00 00 00 18 3C 3C 3C 18 18 00 63 63 63 22 00 00 00 00 00 36 36 7F 36 36 36 0C 0C 3E 63 61 60 3E 03 00 00 00 00 61 63 06 0C 00 00 1C 36 36 1C 3B 6E 00 30 30 30 60 00 00 00 00 00 0C 18 30 30 30 30 00 00 18 0C 06 06 06 06 00 00 00 00 66 3C FF 3C 00 00 00 18 18 18 FF 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 01 03 06 0C 18 30 00 00 3E 63 67 6F 7B 73 00 00 0C 1C 3C 0C 0C 0C 00 00 3E 63 03 06 0C 18 00 00 3E 63 03 03 1E 03 00 00 06 0E 1E 36 66 7F 00 00 7F 60 60 60 7E 03 00 00 1C 30 60 60 7E 63 00 00 7F 63 03 06 0C 18 00 00 3E 63 63 63 3E 63 00 00 3E 63 63 63 3F 03 00 00 00 18 18 00 00 00 00 00 00 18 18 00 00 00 00 00 06 0C 18 30 60 30 00 00 00 00 00 7E 00 00 00 00 60 30 18 0C 06 0C 00 00 3E 63 63 06 0C 0C 00 00 3E 63 63 6F 6F 6F 00 00 08 1C 36 63 63 7F 00 00 7E 33 33 33 3E 33 00 00 1E 33 61 60 60 60 00 00 7C 36 33 33 33 33 00 00 7F 33 31 34 3C 34 00 00 7F 33 31 34 3C 34 00 00 1E 33 61 60 60 6F 00 00 63 63 63 63 7F 63 00 00 3C 18 18 18 18 18 00 00 0F 06 06 06 06 06 00 00 73 33 36 36 3C 36 00 00 78 30 30 30 30 30 00 00 C3 E7 FF DB C3 C3 00 00 63 73 7B 7F 6F 67 00 00 1C 36 63 63 63 63 00 00 7E 33 33 33 3E 30 00 00 3E 63 63 63 63 6B 00 00 7E 33 33 33 3E 36 00 00 3E 63 63 30 1C 06 00 00 FF DB 99 18 18 18 00 00 63 63 63 63 63 63 00 00 C3 C3 C3 C3 C3 C3 00 00 C3 C3 C3 C3 DB DB 00 00 C3 C3 66 3C 18 3C 00 00 C3 C3 C3 66 3C 18 00 00 FF C3 86 0C 18 30 00 00 3C 30 30 30 30 30 00 00 40 60 70 38 1C 0E 00 00 3C 0C 0C 0C 0C 0C 08 1C 36 63 00 00 00 00 00 00 00 00 00 00 00 00 18 18 0C 00 00 00 00 00 00 00 00 00 00 3C 06 3E 00 00 70 30 30 3C 36 33 00 00 00 00 00 3E 63 60 00 00 0E 06 06 1E 36 66 00 00 00 00 00 3E 63 7F 00 00 1C 36 32 30 7C 30 00 00 00 00 00 3B 66 66 00 00 70 30 30 36 3B 33 00 00 0C 0C 00 1C 0C 0C 00 00 06 06 00 0E 06 06 00 00 70 30 30 33 36 3C 00 00 1C 0C 0C 0C 0C 0C 00 00 00 00 00 E6 FF DB 00 00 00 00 00 6E 33 33 00 00 00 00 00 3E 63 63 00 00 00 00 00 6E 33 33 00 00 00 00 00 3B 66 66 00 00 00 00 00 6E 3B 33 00 00 00 00 00 3E 63 38 00 00 08 18 18 7E 18 18 00 00 00 00 00 66 66 66 00 00 00 00 00 C3 C3 C3 00 00 00 00 00 C3 C3 DB 00 00 00 00 00 63 36 1C 00 00 00 00 00 63 63 63 00 00 00 00 00 7F 66 0C 00 00 0E 18 18 18 70 18 00 00 18 18 18 18 00 18 00 00 70 18 18 18 0E 18 00 00 3B 6E 00 00 00 00 00 00 00 00 08 1C 36 63 00 00 1E 33 61 60 60 61 00 00 66 66 00 66 66 66 00 06 0C 18 00 3E 63 7F 00 08 1C 36 00 3C 06 3E 00 00 66 66 00 3C 06 3E 00 30 18 0C 00 3C 06 3E 00 1C 36 1C 00 3C 06 3E 00 00 00 00 3C 66 60 66 00 08 1C 36 00 3E 63 7F 00 00 66 66 00 3E 63 7F 00 30 18 0C 00 3E 63 7F 00 00 66 66 00 38 18 18 00 18 3C 66 00 38 18 18 00 60 30 18 00 38 18 18 00 63 63 08 1C 36 63 63 1C 36 1C 00 1C 36 63 63 0C 18 30 00 7F 33 30 3E 00 00 00 00 6E 3B 1B 7E 00 00 1F 36 66 66 7F 66 00 08 1C 36 00 3E 63 63 00 00 63 63 00 3E 63 63 00 30 18 0C 00 3E 63 63 00 18 3C 66 00 66 66 66 00 30 18 0C 00 66 66 66 00 00 63 63 00 63 63 63 00 63 63 1C 36 63 63 63 00 63 63 00 63 63 63 63 00 18 18 7E C3 C0 C0 C3 00 1C 36 32 30 78 30 30 00 00 C3 66 3C 18 FF 18 00 FC 66 66 7C 62 66 6F 00 0E 1B 18 18 18 7E 18 00 0C 18 30 00 3C 06 3E 00 0C 18 30 00 38 18 18 00 0C 18 30 00 3E 63 63 00 0C 18 30 00 66 66 66 00 00 3B 6E 00 6E 33 33 3B 6E 00 63 73 7B 7F 6F 00 3C 6C 6C 3E 00 7E 00 00 38 6C 6C 38 00 7C 00 00 00 18 18 00 18 18 30 00 00 00 00 00 00 7F 60 00 00 00 00 00 00 7F 03 00 60 E0 63 66 6C 18 30 00 60 E0 63 66 6C 18 33 00 00 18 18 00 18 18 3C 00 00 00 00 1B 36 6C 36 00 00 00 00 6C 36 1B 36 11 44 11 44 11 44 11 44 55 AA 55 AA 55 AA 55 AA DD 77 DD 77 DD 77 DD 77 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 F8 18 18 18 18 18 F8 18 F8 36 36 36 36 36 36 36 F6 00 00 00 00 00 00 00 FE 00 00 00 00 00 F8 18 F8 36 36 36 36 36 F6 06 F6 36 36 36 36 36 36 36 36 00 00 00 00 00 FE 06 F6 36 36 36 36 36 F6 06 FE 36 36 36 36 36 36 36 FE 18 18 18 18 18 F8 18 F8 00 00 00 00 00 00 00 F8 18 18 18 18 18 18 18 1F 18 18 18 18 18 18 18 FF 00 00 00 00 00 00 00 FF 18 18 18 18 18 18 18 1F 00 00 00 00 00 00 00 FF 18 18 18 18 18 18 18 FF 18 18 18 18 18 1F 18 1F 36 36 36 36 36 36 36 37 36 36 36 36 36 37 30 3F 00 00 00 00 00 3F 30 37 36 36 36 36 36 F7 00 FF 00 00 00 00 00 FF 00 F7 36 36 36 36 36 37 30 37 00 00 00 00 00 FF 00 FF 36 36 36 36 36 F7 00 F7 18 18 18 18 18 FF 00 FF 36 36 36 36 36 36 36 FF 00 00 00 00 00 FF 00 FF 00 00 00 00 00 00 00 FF 36 36 36 36 36 36 36 3F 18 18 18 18 18 1F 18 1F 00 00 00 00 00 1F 18 1F 00 00 00 00 00 00 00 3F 36 36 36 36 36 36 36 FF 18 18 18 18 18 FF 18 FF 18 18 18 18 18 18 18 F8 00 00 00 00 00 00 00 1F FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 FF F0 F0 F0 F0 F0 F0 F0 F0 0F 0F 0F 0F 0F 0F 0F 0F FF FF FF FF FF FF FF 00 00 00 00 00 00 3B 6E 6C 00 00 00 00 3E 63 7E 63 00 00 7F 63 63 60 60 60 00 00 00 00 7F 36 36 36 00 00 7F 63 30 18 0C 18 00 00 00 00 00 3F 6C 6C 00 00 00 00 33 33 33 33 00 00 00 00 3B 6E 0C 0C 00 00 7E 18 3C 66 66 66 00 00 1C 36 63 63 7F 63 00 00 1C 36 63 63 63 36 00 00 1E 30 18 0C 3E 66 00 00 00 00 00 7E DB DB 00 00 03 06 7E DB DB F3 00 00 1C 30 60 60 7C 60 00 00 00 3E 63 63 63 63 00 00 00 7F 00 00 7F 00 00 00 18 18 18 FF 18 18 00 00 30 18 0C 06 0C 18 00 00 0C 18 30 60 30 18 00 00 0E 1B 1B 18 18 18 18 18 18 18 18 18 18 18 00 00 18 18 00 00 FF 00 00 00 00 00 3B 6E 00 3B 00 38 6C 6C 38 00 00 00 00 00 00 00 00 00 18 18 00 00 00 00 00 00 00 18 00 0F 0C 0C 0C 0C 0C EC 00 D8 6C 6C 6C 6C 6C 00 00 70 D8 30 60 C8 F8 00 00 00 00 00 3E 3E 3E 3E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 99 81 7E 00 00 00 00 00 E7 FF 7E 00 00 00 00 00 3E 1C 08 00 00 00 00 00 1C 08 00 00 00 00 00 00 18 18 3C 00 00 00 00 00 18 18 3C 00 00 00 00 00 18 00 00 00 00 00 00 00 E7 FF FF FF FF FF 00 00 66 3C 00 00 00 00 00 00 99 C3 FF FF FF FF 00 00 66 66 3C 00 00 00 00 00 7E 18 18 00 00 00 00 00 70 F0 E0 00 00 00 00 00 67 E7 E6 C0 00 00 00 00 DB 18 18 00 00 00 00 00 70 60 40 00 00 00 00 00 07 03 01 00 00 00 00 00 7E 3C 18 00 00 00 00 00 00 33 33 00 00 00 00 00 1B 1B 1B 00 00 00 00 00 36 1C 06 63 3E 00 00 00 7F 7F 7F 00 00 00 00 00 7E 3C 18 7E 00 00 00 00 18 18 18 00 00 00 00 00 7E 3C 18 00 00 00 00 00 0C 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 7F 00 00 00 00 00 00 00 24 00 00 00 00 00 00 00 7F 7F 00 00 00 00 00 00 1C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 18 00 00 00 00 00 00 00 00 00 00 00 00 00 7F 36 36 00 00 00 00 00 43 63 3E 0C 0C 00 00 00 18 33 63 00 00 00 00 00 66 66 3B 00 00 00 00 00 00 00 00 00 00 00 00 00 30 18 0C 00 00 00 00 00 06 0C 18 00 00 00 00 00 66 00 00 00 00 00 00 00 18 18 00 00 00 00 00 00 18 18 18 30 00 00 00 00 00 00 00 00 00 00 00 00 00 18 18 00 00 00 00 00 60 40 00 00 00 00 00 00 63 63 3E 00 00 00 00 00 0C 0C 3F 00 00 00 00 00 30 63 7F 00 00 00 00 00 03 63 3E 00 00 00 00 00 06 06 0F 00 00 00 00 00 03 63 3E 00 00 00 00 00 63 63 3E 00 00 00 00 00 18 18 18 00 00 00 00 00 63 63 3E 00 00 00 00 00 03 06 3C 00 00 00 00 00 18 18 00 00 00 00 00 00 18 18 30 00 00 00 00 00 18 0C 06 00 00 00 00 00 7E 00 00 00 00 00 00 00 18 30 60 00 00 00 00 00 00 0C 0C 00 00 00 00 00 6E 60 3E 00 00 00 00 00 63 63 63 00 00 00 00 00 33 33 7E 00 00 00 00 00 61 33 1E 00 00 00 00 00 33 36 7C 00 00 00 00 00 31 33 7F 00 00 00 00 00 30 30 78 00 00 00 00 00 63 33 1D 00 00 00 00 00 63 63 63 00 00 00 00 00 18 18 3C 00 00 00 00 00 66 66 3C 00 00 00 00 00 36 33 73 00 00 00 00 00 31 33 7F 00 00 00 00 00 C3 C3 C3 00 00 00 00 00 63 63 63 00 00 00 00 00 63 36 1C 00 00 00 00 00 30 30 78 00 00 00 00 00 6F 3E 06 07 00 00 00 00 33 33 73 00 00 00 00 00 63 63 3E 00 00 00 00 00 18 18 3C 00 00 00 00 00 63 63 3E 00 00 00 00 00 66 3C 18 00 00 00 00 00 FF 66 66 00 00 00 00 00 66 C3 C3 00 00 00 00 00 18 18 3C 00 00 00 00 00 61 C3 FF 00 00 00 00 00 30 30 3C 00 00 00 00 00 07 03 01 00 00 00 00 00 0C 0C 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 66 66 3B 00 00 00 00 00 33 33 6E 00 00 00 00 00 60 63 3E 00 00 00 00 00 66 66 3B 00 00 00 00 00 60 63 3E 00 00 00 00 00 30 30 78 00 00 00 00 00 66 3E 06 66 3C 00 00 00 33 33 73 00 00 00 00 00 0C 0C 1E 00 00 00 00 00 06 06 66 66 3C 00 00 00 36 33 73 00 00 00 00 00 0C 0C 1E 00 00 00 00 00 DB DB DB 00 00 00 00 00 33 33 33 00 00 00 00 00 63 63 3E 00 00 00 00 00 33 3E 30 30 78 00 00 00 66 3E 06 06 0F 00 00 00 30 30 78 00 00 00 00 00 0E 63 3E 00 00 00 00 00 18 1B 0E 00 00 00 00 00 66 66 3B 00 00 00 00 00 66 3C 18 00 00 00 00 00 DB FF 66 00 00 00 00 00 1C 36 63 00 00 00 00 00 63 3F 03 06 3C 00 00 00 18 33 7F 00 00 00 00 00 18 18 0E 00 00 00 00 00 18 18 18 00 00 00 00 00 18 18 70 00 00 00 00 00 00 00 00 00 00 00 00 00 63 7F 00 00 00 00 00 00 33 1E 06 03 3E 00 00 00 66 66 3B 00 00 00 00 00 60 63 3E 00 00 00 00 00 66 66 3B 00 00 00 00 00 66 66 3B 00 00 00 00 00 66 66 3B 00 00 00 00 00 66 66 3B 00 00 00 00 00 3C 0C 06 3C 00 00 00 00 60 63 3E 00 00 00 00 00 60 63 3E 00 00 00 00 00 60 63 3E 00 00 00 00 00 18 18 3C 00 00 00 00 00 18 18 3C 00 00 00 00 00 18 18 3C 00 00 00 00 00 7F 63 63 00 00 00 00 00 7F 63 63 00 00 00 00 00 30 33 7F 00 00 00 00 00 D8 DC 77 00 00 00 00 00 66 66 67 00 00 00 00 00 63 63 3E 00 00 00 00 00 63 63 3E 00 00 00 00 00 63 63 3E 00 00 00 00 00 66 66 3B 00 00 00 00 00 66 66 3B 00 00 00 00 00 63 3F 03 06 3C 00 00 00 63 36 1C 00 00 00 00 00 63 63 3E 00 00 00 00 00 7E 18 18 00 00 00 00 00 30 73 7E 00 00 00 00 00 FF 18 18 00 00 00 00 00 66 66 F3 00 00 00 00 00 18 18 18 D8 70 00 00 00 66 66 3B 00 00 00 00 00 18 18 3C 00 00 00 00 00 63 63 3E 00 00 00 00 00 66 66 3B 00 00 00 00 00 33 33 33 00 00 00 00 00 67 63 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 63 3E 00 00 00 00 00 60 60 00 00 00 00 00 00 03 03 00 00 00 00 00 00 6E C3 06 0C 1F 00 00 00 67 CF 1F 03 03 00 00 00 3C 3C 18 00 00 00 00 00 1B 00 00 00 00 00 00 00 6C 00 00 00 00 00 00 00 11 44 11 44 11 44 00 00 55 AA 55 AA 55 AA 00 00 DD 77 DD 77 DD 77 00 00 18 18 18 18 18 18 00 00 18 18 18 18 18 18 00 00 18 18 18 18 18 18 00 00 36 36 36 36 36 36 00 00 36 36 36 36 36 36 00 00 18 18 18 18 18 18 00 00 36 36 36 36 36 36 00 00 36 36 36 36 36 36 00 00 36 36 36 36 36 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 18 18 18 18 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 18 18 18 18 18 00 00 18 18 18 18 18 18 00 00 00 00 00 00 00 00 00 00 18 18 18 18 18 18 00 00 18 18 18 18 18 18 00 00 36 36 36 36 36 36 00 00 00 00 00 00 00 00 00 00 36 36 36 36 36 36 00 00 00 00 00 00 00 00 00 00 36 36 36 36 36 36 00 00 36 36 36 36 36 36 00 00 00 00 00 00 00 00 00 00 36 36 36 36 36 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 18 18 18 18 18 00 00 36 36 36 36 36 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 18 18 18 18 18 00 00 36 36 36 36 36 36 00 00 36 36 36 36 36 36 00 00 18 18 18 18 18 18 00 00 00 00 00 00 00 00 00 00 18 18 18 18 18 18 00 00 FF FF FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 F0 F0 F0 F0 F0 F0 00 00 0F 0F 0F 0F 0F 0F 00 00 00 00 00 00 00 00 00 00 6C 6E 3B 00 00 00 00 00 63 7E 60 60 20 00 00 00 60 60 60 00 00 00 00 00 36 36 36 00 00 00 00 00 30 63 7F 00 00 00 00 00 6C 6C 38 00 00 00 00 00 3E 30 30 60 00 00 00 00 0C 0C 0C 00 00 00 00 00 3C 18 7E 00 00 00 00 00 63 36 1C 00 00 00 00 00 36 36 77 00 00 00 00 00 66 66 3C 00 00 00 00 00 7E 00 00 00 00 00 00 00 7E 60 C0 00 00 00 00 00 60 30 1C 00 00 00 00 00 63 63 63 00 00 00 00 00 00 7F 00 00 00 00 00 00 18 00 FF 00 00 00 00 00 30 00 7E 00 00 00 00 00 0C 00 7E 00 00 00 00 00 18 18 18 18 18 18 00 00 D8 D8 70 00 00 00 00 00 00 18 18 00 00 00 00 00 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6C 3C 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3E 3E 00 00 00 00 00 00 00 00 00 00 00 00 00 00
\ No newline at end of file
diff --git a/rtl/video/mda.v b/rtl/video/mda.v
new file mode 100644
index 0000000..9eff53a
--- /dev/null
+++ b/rtl/video/mda.v
@@ -0,0 +1,270 @@
+// Graphics Gremlin
+//
+// Copyright (c) 2021 Eric Schlaepfer
+// This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
+// International License. To view a copy of this license, visit
+// http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative
+// Commons, PO Box 1866, Mountain View, CA 94042, USA.
+//
+`default_nettype none
+module mda(
+ // Clocks
+ input clk,
+
+ // ISA bus
+ input[15:0] bus_a,
+ input bus_ior_l,
+ input bus_iow_l,
+ input bus_memr_l,
+ input bus_memw_l,
+ input[7:0] bus_d,
+ output[7:0] bus_out,
+ output bus_dir,
+ input bus_aen,
+ output bus_rdy,
+
+ // RAM
+ output ram_we_l,
+ output[18:0] ram_a,
+ input[7:0] ram_d,
+
+ // Video outputs
+ output hsync,
+ output vsync,
+ output de_o,
+ output video,
+ output intensity
+ );
+
+ parameter MDA_70HZ = 1;
+ parameter BLINK_MAX = 0;
+
+ parameter IO_BASE_ADDR = 16'h3b0; // MDA is 3B0, CGA is 3D0
+ wire crtc_cs;
+ wire status_cs;
+ wire control_cs;
+ wire bus_mem_cs;
+
+ reg[7:0] bus_int_out;
+ wire[7:0] bus_out_crtc;
+ wire[7:0] bus_out_mem;
+ wire[7:0] mda_status_reg;
+ reg[7:0] mda_control_reg = 8'b0010_1000;
+ wire video_enabled;
+ wire blink_enabled;
+
+ wire hsync_int;
+ wire vsync_l;
+ wire cursor;
+// wire video;
+ wire display_enable;
+// wire intensity;
+
+ wire[13:0] crtc_addr;
+ wire[4:0] row_addr;
+
+ wire charrom_read;
+ wire disp_pipeline;
+ wire isa_op_enable;
+ wire vram_read_char;
+ wire vram_read_att;
+ wire vram_read;
+ wire vram_read_a0;
+ wire[4:0] clkdiv;
+ wire crtc_clk;
+ wire[7:0] ram_1_d;
+
+ reg[23:0] blink_counter;
+ reg blink;
+
+ reg bus_memw_synced_l;
+ reg bus_memr_synced_l;
+ reg bus_ior_synced_l;
+ reg bus_iow_synced_l;
+
+ //wire cpu_memsel;
+ //reg[1:0] wait_state = 2'd0;
+ //reg bus_rdy_latch;
+
+ assign de_o = display_enable;
+
+ assign ram_a = {7'b0000000, crtc_addr[10:0],
+ vram_read_a0};
+
+ assign ram_1_d = ram_d;
+ //assign ram_1_d = 8'hFF;
+ assign ram_we_l = vram_read;
+
+
+ // Synchronize ISA bus control lines to our clock
+ always @ (posedge clk)
+ begin
+ //bus_memw_synced_l <= bus_memw_l;
+ //bus_memr_synced_l <= bus_memr_l;
+ bus_ior_synced_l <= bus_ior_l;
+ bus_iow_synced_l <= bus_iow_l;
+ end
+
+ // Some modules need a non-inverted vsync trigger
+ assign vsync = ~vsync_l;
+
+ // Mapped IO
+ assign crtc_cs = (bus_a[15:3] == IO_BASE_ADDR[15:3]) & ~bus_aen; // 3B4/3B5
+ assign status_cs = (bus_a == IO_BASE_ADDR + 20'hA) & ~bus_aen;
+ assign control_cs = (bus_a == IO_BASE_ADDR + 16'h8) & ~bus_aen;
+
+ // Memory-mapped from B0000 to B7FFF
+ // assign bus_mem_cs = (bus_a[19:15] == 5'b10110);
+
+ // Mux ISA bus data from every possible internal source.
+ always @ (*)
+ begin
+// if (bus_mem_cs & ~bus_memr_l) begin
+// bus_int_out <= bus_out_mem;
+ if (status_cs & ~bus_ior_l) begin
+ bus_int_out <= mda_status_reg;
+ end else if (crtc_cs & ~bus_ior_l & (bus_a[0] == 1)) begin
+ bus_int_out <= bus_out_crtc;
+ end else begin
+ bus_int_out <= 8'h00;
+ end
+ end
+
+ // Only for read operations does bus_dir go high.
+ assign bus_dir = (crtc_cs | status_cs) & ~bus_ior_l;
+ // | (bus_mem_cs & ~bus_memr_l);
+ //assign bus_dir = (crtc_cs | status_cs);
+ assign bus_out = bus_int_out;
+
+
+ // MDA status register (read only at 3BA)
+ assign mda_status_reg = {4'b1111, video, 2'b00, hsync_int};
+
+ // MDA mode control register (write only)
+ assign blink_enabled = mda_control_reg[5];
+ assign video_enabled = mda_control_reg[3];
+
+ // Hsync only present when video is enabled
+ assign hsync = video_enabled & hsync_int;
+
+ // Update control register
+ always @ (posedge clk)
+ begin
+ if (control_cs & ~bus_iow_synced_l) begin
+ mda_control_reg <= bus_d;
+ end
+ end
+
+ // CRT controller (MC6845 compatible)
+ crtc6845 crtc (
+ .clk(clk),
+ .divclk(crtc_clk),
+ .cs(crtc_cs),
+ .a0(bus_a[0]),
+ .write(~bus_iow_synced_l),
+ .read(~bus_ior_synced_l),
+ .bus(bus_d),
+ .bus_out(bus_out_crtc),
+ .lock(MDA_70HZ == 1),
+ .hsync(hsync_int),
+ .vsync(vsync_l),
+ .display_enable(display_enable),
+ .cursor(cursor),
+ .mem_addr(crtc_addr),
+ .row_addr(row_addr)
+ );
+
+
+// if (MDA_70HZ) begin
+ defparam crtc.H_TOTAL = 8'd99;
+ defparam crtc.H_DISP = 8'd80;
+ defparam crtc.H_SYNCPOS = 8'd82;
+ defparam crtc.H_SYNCWIDTH = 4'd12;
+ defparam crtc.V_TOTAL = 7'd31;
+ defparam crtc.V_TOTALADJ = 5'd1;
+ defparam crtc.V_DISP = 7'd25;
+ defparam crtc.V_SYNCPOS = 7'd27;
+ defparam crtc.V_MAXSCAN = 5'd13;
+ defparam crtc.C_START = 7'd11;
+ defparam crtc.C_END = 5'd12;
+// end else begin
+ /*
+ defparam crtc.H_TOTAL = 8'd97;
+ defparam crtc.H_DISP = 8'd80;
+ defparam crtc.H_SYNCPOS = 8'd82;
+ defparam crtc.H_SYNCWIDTH = 4'd15;
+ defparam crtc.V_TOTAL = 7'd25;
+ defparam crtc.V_TOTALADJ = 5'd6;
+ defparam crtc.V_DISP = 7'd25;
+ defparam crtc.V_SYNCPOS = 7'd25;
+ defparam crtc.V_MAXSCAN = 5'd13;
+ defparam crtc.C_START = 7'd11;
+ defparam crtc.C_END = 5'd12;
+ //end
+
+ // Interface to video SRAM chip
+ mda_vram video_buffer (
+ .clk(clk),
+ .isa_addr({3'b000, bus_a[15:0]}),
+ .isa_din(bus_d),
+ .isa_dout(bus_out_mem),
+ .isa_read(bus_mem_cs & ~bus_memr_synced_l),
+ .isa_write(bus_mem_cs & ~bus_memw_synced_l),
+ .pixel_addr({7'h00, crtc_addr[10:0], vram_read_a0}),
+ .pixel_data(ram_1_d),
+ .pixel_read(vram_read),
+ .ram_a(ram_a),
+ .ram_d(ram_d),
+ .ram_we_l(ram_we_l),
+ .isa_op_enable(isa_op_enable)
+ );
+
+ defparam video_buffer.MDA_70HZ = MDA_70HZ;
+*/
+ // Sequencer state machine
+ mda_sequencer sequencer (
+ .clk(clk),
+ .clk_seq(clkdiv),
+ .vram_read(vram_read),
+ .vram_read_a0(vram_read_a0),
+ .vram_read_char(vram_read_char),
+ .vram_read_att(vram_read_att),
+ .crtc_clk(crtc_clk),
+ .charrom_read(charrom_read),
+ .disp_pipeline(disp_pipeline),
+ .isa_op_enable(isa_op_enable)
+ );
+
+ defparam sequencer.MDA_70HZ = MDA_70HZ;
+
+ // Pixel pusher
+ mda_pixel pixel (
+ .clk(clk),
+ .clk_seq(clkdiv),
+ .vram_data(ram_1_d),
+ .vram_read_char(vram_read_char),
+ .vram_read_att(vram_read_att),
+ .disp_pipeline(disp_pipeline),
+ .charrom_read(charrom_read),
+ .display_enable(display_enable),
+ .cursor(cursor),
+ .row_addr(row_addr),
+ .blink_enabled(blink_enabled),
+ .blink(blink),
+ .video_enabled(video_enabled),
+ .video(video),
+ .intensity(intensity)
+ );
+
+ // Generate blink signal for cursor and character
+ always @ (posedge clk)
+ begin
+ if (blink_counter == BLINK_MAX) begin
+ blink_counter <= 0;
+ blink <= ~blink;
+ end else begin
+ blink_counter <= blink_counter + 1;
+ end
+ end
+
+endmodule
diff --git a/rtl/video/mda_attrib.v b/rtl/video/mda_attrib.v
new file mode 100644
index 0000000..78559c2
--- /dev/null
+++ b/rtl/video/mda_attrib.v
@@ -0,0 +1,69 @@
+// Graphics Gremlin
+//
+// Copyright (c) 2021 Eric Schlaepfer
+// This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
+// International License. To view a copy of this license, visit
+// http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative
+// Commons, PO Box 1866, Mountain View, CA 94042, USA.
+//
+`default_nettype none
+module mda_attrib(
+ input clk,
+ input[7:0] att_byte,
+ input[4:0] row_addr,
+ input display_enable,
+ input blink_enabled,
+ input blink,
+ input cursor,
+ input pix_in,
+ output pix_out,
+ output intensity_out
+ );
+
+ reg blinkdiv;
+ reg[1:0] blink_old;
+ wire att_inverse;
+ wire att_underline;
+ wire att_blink;
+ wire att_nodisp;
+ wire[2:0] att_fg;
+ wire[2:0] att_bg;
+ wire cursorblink;
+ wire blink_area;
+ wire vid_underline;
+ wire intensity_bg;
+ wire intensity_fg;
+ wire alpha_dots;
+
+ // Extract attributes from the attribute byte
+ assign att_fg = att_byte[2:0];
+ assign att_bg = att_byte[6:4];
+ assign att_underline = (att_fg == 3'b001) & (row_addr==5'd12);
+ assign intensity_bg = att_byte[7] & ~blink_enabled;
+ assign intensity_fg = att_byte[3];
+ assign att_inverse = (att_fg == 3'b000) & (att_bg == 3'b111);
+ assign att_nodisp = (att_fg == 3'b000) & (att_bg == 3'b000);
+ assign att_blink = att_byte[7];
+
+ // Character blink is half the rate of the cursor blink
+ always @ (posedge clk)
+ begin
+ blink_old <= {blink_old[0], blink};
+ if (blink_old == 2'b01) begin
+ blinkdiv <= ~blinkdiv;
+ end
+ end
+
+ // Assemble all the signals to create the final video signal
+ assign cursorblink = cursor & blink;
+ assign blink_area = att_blink & blinkdiv & ~cursor & blink_enabled;
+ assign vid_underline = (pix_in | att_underline);
+ assign alpha_dots = (vid_underline & ~att_nodisp & ~blink_area) | cursorblink;
+ assign pix_out = (alpha_dots ^ att_inverse) & display_enable;
+
+ // Assign intensity signal
+ assign intensity_out = (alpha_dots ? intensity_fg : intensity_bg) & display_enable;
+
+
+endmodule
+
diff --git a/rtl/video/mda_pixel.v b/rtl/video/mda_pixel.v
new file mode 100644
index 0000000..6ae4989
--- /dev/null
+++ b/rtl/video/mda_pixel.v
@@ -0,0 +1,126 @@
+// Graphics Gremlin
+//
+// Copyright (c) 2021 Eric Schlaepfer
+// This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
+// International License. To view a copy of this license, visit
+// http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative
+// Commons, PO Box 1866, Mountain View, CA 94042, USA.
+//
+`default_nettype none
+module mda_pixel(
+ input clk,
+ input[4:0] clk_seq,
+ input[7:0] vram_data,
+ input vram_read_char,
+ input vram_read_att,
+ input disp_pipeline,
+ input charrom_read,
+ input display_enable,
+ input cursor,
+ input[4:0] row_addr,
+ input blink_enabled,
+ input blink,
+ input video_enabled,
+ output video,
+ output intensity
+ );
+
+ reg[7:0] attr_byte;
+ reg[7:0] char_byte;
+ reg[7:0] char_byte_old;
+ reg[7:0] attr_byte_del;
+ reg[7:0] charbits;
+ reg[1:0] cursor_del;
+ reg[1:0] display_enable_del;
+ reg pix;
+ reg pix_delay;
+ reg ninth_column;
+ wire[11:0] rom_addr;
+
+ // Character ROM
+ reg[7:0] char_rom[0:4095];
+ initial $readmemh("mda.hex", char_rom, 0, 4095);
+
+
+ // Latch character and attribute data from VRAM
+ // at appropriate times
+ always @ (posedge clk)
+ begin
+ if (vram_read_char) begin
+ char_byte <= vram_data; //ES testing
+ char_byte_old <= char_byte;
+ end
+ if (vram_read_att) begin
+ attr_byte <= vram_data; //ES testing
+ end
+ end
+
+ // Add a pipeline delay to the attribute byte data, cursor, and display
+ // enable so they line up with the displayed character
+ always @ (posedge clk)
+ begin
+ if (disp_pipeline) begin
+ attr_byte_del <= video_enabled ? attr_byte : 8'd0;
+ display_enable_del <= {display_enable_del[0], display_enable};
+ cursor_del <= {cursor_del[0], cursor};
+ end
+ end
+
+ // Look up character byte in our character ROM table
+ assign rom_addr = {row_addr[3], char_byte, row_addr[2:0]};
+ always @ (posedge clk)
+ begin
+ // Only load character bits at this point
+ if (charrom_read) begin
+ charbits <= char_rom[rom_addr];
+ end
+ end
+
+ // Pixel shifter
+ always @ (*)
+ begin
+ case (clk_seq[4:1])
+ 5'd0: pix <= charbits[0];
+ 5'd1: pix <= ninth_column;
+ 5'd2: pix <= charbits[7];
+ 5'd3: pix <= charbits[6];
+ 5'd4: pix <= charbits[5];
+ 5'd5: pix <= charbits[4];
+ 5'd6: pix <= charbits[3];
+ 5'd7: pix <= charbits[2];
+ 5'd8: pix <= charbits[1];
+ default: pix <= 0;
+ endcase
+ end
+
+ // For some characters, duplicate the 8th column as the 9th column
+ // (Mainly line drawing characters so they span the whole cell)
+ always @ (posedge clk)
+ begin
+ if (charrom_read) begin
+ ninth_column <= (char_byte_old[7:5] == 3'b110) ? charbits[0] : 0;
+ end
+ end
+
+ // Add one clk cycle delay to match up pixel data with attribute byte
+ // data.
+ always @ (posedge clk)
+ begin
+ pix_delay <= pix;
+ end
+
+ // Applies video attributes, generates final video
+ mda_attrib attrib (
+ .clk(clk),
+ .att_byte(attr_byte_del),
+ .row_addr(row_addr),
+ .display_enable(display_enable_del[1]),
+ .blink_enabled(blink_enabled),
+ .blink(blink),
+ .cursor(cursor_del[1]),
+ .pix_in(pix_delay),
+ .pix_out(video),
+ .intensity_out(intensity)
+ );
+
+endmodule
diff --git a/rtl/video/mda_sequencer.v b/rtl/video/mda_sequencer.v
new file mode 100644
index 0000000..0b1b04a
--- /dev/null
+++ b/rtl/video/mda_sequencer.v
@@ -0,0 +1,62 @@
+// Graphics Gremlin
+//
+// Copyright (c) 2021 Eric Schlaepfer
+// This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
+// International License. To view a copy of this license, visit
+// http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative
+// Commons, PO Box 1866, Mountain View, CA 94042, USA.
+//
+`default_nettype none
+module mda_sequencer(
+ input clk,
+ output[4:0] clk_seq,
+ output vram_read,
+ output vram_read_a0,
+ output vram_read_char,
+ output vram_read_att,
+ output crtc_clk,
+ output charrom_read,
+ output disp_pipeline,
+ output isa_op_enable
+ );
+
+ parameter MDA_70HZ = 0;
+
+ reg crtc_clk_int = 1'b0;
+ reg[4:0] clkdiv = 5'b0;
+
+ // Sequencer: times internal operations
+ always @ (posedge clk)
+ begin
+ if (clkdiv == 5'd17) begin
+ clkdiv <= 5'd0;
+ crtc_clk_int <= 1'b1;
+ end else begin
+ clkdiv <= clkdiv + 1;
+ crtc_clk_int <= 1'b0;
+ end
+ end
+
+ // Control signals based on the sequencer state
+ assign vram_read = ((clkdiv == 5'd1) || (clkdiv == 5'd2) || (clkdiv == 5'd3)
+ || (clkdiv == 5'd4));
+ assign vram_read_a0 = (clkdiv == 5'd3);
+ assign vram_read_char = (clkdiv == 5'd3);
+ assign vram_read_att = (clkdiv == 5'd4);
+ assign charrom_read = (clkdiv == 5'd1);
+ assign disp_pipeline = (clkdiv == 5'd4);
+ assign crtc_clk = crtc_clk_int;
+ assign clk_seq = clkdiv;
+ // Leave a gap of at least 2 cycles between the end of ISA operation and
+ // vram_read. This is because an ISA operation takes 3 cycles.
+ // Stupid hack: 70Hz needs an extra cycle. 50Hz can't tolerate
+ // an extra cycle.
+// if (MDA_70HZ) begin
+// assign isa_op_enable = (clkdiv > 5'd6) && (clkdiv < 5'd16);
+// end else begin
+ assign isa_op_enable = (clkdiv > 5'd5) && (clkdiv < 5'd16);
+// end
+
+
+endmodule
+
diff --git a/rtl/video/mda_vgaport.v b/rtl/video/mda_vgaport.v
new file mode 100644
index 0000000..bfabe89
--- /dev/null
+++ b/rtl/video/mda_vgaport.v
@@ -0,0 +1,50 @@
+// Graphics Gremlin
+//
+// Copyright (c) 2021 Eric Schlaepfer
+// This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
+// International License. To view a copy of this license, visit
+// http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative
+// Commons, PO Box 1866, Mountain View, CA 94042, USA.
+//
+module mda_vgaport(
+ input wire clk,
+
+ input wire video,
+ input wire intensity,
+
+ // Analog outputs
+ output reg [5:0] red,
+ output reg [5:0] green,
+ output reg [5:0] blue,
+ input wire [2:0] mda_rgb
+ );
+
+ always @(posedge clk)
+ begin
+ case({video, intensity}) // 1 = green, 2 = amber, 3 = b&w
+ 2'd0: begin
+ red <= 6'd0;
+ green <= 6'd0;
+ blue <= 6'd0;
+ end
+ 2'd1: begin
+ red <= mda_rgb == 0 ? 6'd0 : 6'd16;
+ green <= mda_rgb == 1 ? 6'd12 : 6'd16;
+ blue <= mda_rgb == 2 ? 6'd16 : 6'd0;
+ end
+ 2'd2: begin
+ red <= mda_rgb == 0 ? 6'd0 : 6'd48;
+ green <= mda_rgb == 1 ? 6'd21 : 6'd48;
+ blue <= mda_rgb == 2 ? 6'd48 : 6'd0;
+ end
+ 2'd3: begin
+ red <= mda_rgb == 0 ? 6'd0 : 6'd63;
+ green <= mda_rgb == 1 ? 6'd27 : 6'd63;
+ blue <= mda_rgb == 2 ? 6'd63 : 6'd0;
+ end
+ default: ;
+ endcase
+ end
+endmodule
+
+
diff --git a/rtl/video/splash.hex b/rtl/video/splash.hex
index c6381cc..25e1884 100644
--- a/rtl/video/splash.hex
+++ b/rtl/video/splash.hex
@@ -1 +1 @@
-20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 60 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 28 07 20 07 20 07 20 07 28 07 20 07 2F 07 28 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 29 07 29 07 28 07 20 07 20 07 28 07 20 07 28 07 28 07 29 07 2F 07 28 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 28 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 28 07 28 07 29 07 2F 07 28 07 20 07 20 07 29 07 5C 07 20 07 20 07 29 07 5C 07 28 07 29 07 29 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 28 07 5F 07 29 07 28 07 29 07 5C 07 20 07 29 07 5C 07 20 07 2F 07 28 07 5F 07 29 07 29 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 29 07 29 07 5C 07 20 07 29 07 28 07 20 07 20 07 20 07 20 07 2F 07 28 07 5F 07 29 07 7C 07 28 07 28 07 5F 07 29 07 28 07 28 07 5F 07 29 07 5C 07 20 07 20 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 5F 07 28 07 29 07 28 07 28 07 5F 07 7C 07 28 07 5F 07 7C 07 5F 07 29 07 29 07 20 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 2F 07 28 07 28 07 5F 07 7C 07 28 07 29 07 5C 07 20 07 20 07 28 07 5F 07 29 07 29 07 20 07 29 07 5C 07 5F 07 5F 07 5F 07 5F 07 5F 07 28 07 28 07 5F 07 29 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 20 07 5C 07 2F 07 20 07 20 07 7C 07 28 07 5F 07 29 07 20 07 5F 07 5F 07 7C 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 28 07 5F 07 29 07 29 07 20 07 20 07 28 07 28 07 5F 07 29 07 20 07 7C 07 20 07 5F 07 20 07 28 07 28 07 2F 07 20 07 5F 07 5F 07 5C 07 20 07 5C 07 2F 07 20 07 2F 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 7C 07 5C 07 2F 07 7C 07 20 07 7C 07 7C 07 20 07 5C 07 5F 07 5F 07 20 07 5C 07 20 07 20 07 7C 07 20 07 7C 07 20 07 2F 07 20 07 2D 07 5F 07 29 07 7C 07 20 07 27 07 5F 07 7C 07 20 07 7C 07 20 07 20 07 5F 07 2F 07 7C 07 20 07 28 07 5F 07 5F 07 20 07 3E 07 20 07 20 07 3C 07 20 07 20 07 20 07 7C 07 20 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 7C 07 5F 07 7C 07 7C 07 5F 07 7C 07 5F 07 5F 07 5F 07 2F 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 5C 07 5F 07 5F 07 5F 07 7C 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 5C 07 5F 07 5F 07 5F 07 2F 07 5F 07 2F 07 5C 07 5F 07 5C 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 30 07 37 07 2F 07 30 07 36 07 2F 07 32 07 30 07 32 07 32 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 72 07 74 07 20 07 62 07 79 07 20 07 40 07 73 07 70 07 61 07 72 07 6B 07 32 07 6B 07 30 07 36 07 2C 07 20 07 40 07 6E 07 61 07 65 07 6C 07 6F 07 6F 07 62 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 77 07 65 07 72 07 65 07 64 07 20 07 62 07 79 07 20 07 4B 07 46 07 50 07 43 07 2D 07 58 07 54 07 20 07 26 07 20 07 4D 07 43 07 4C 07 38 07 36 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 43 07 6F 07 6E 07 74 07 72 07 69 07 62 07 75 07 74 07 6F 07 72 07 73 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 40 07 4A 07 61 07 73 07 6F 07 6E 07 41 07 2C 07 20 07 40 07 67 07 79 07 75 07 72 07 63 07 6F 07 2C 07 20 07 40 07 6B 07 69 07 74 07 75 07 6E 07 65 07 2D 07 73 07 61 07 6E 07 2C 07 20 07 40 07 4D 07 69 07 63 07 72 07 6F 07 43 07 6F 07 72 07 65 07 4C 07 61 07 62 07 73 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
\ No newline at end of file
+20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 60 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 28 07 20 07 20 07 20 07 28 07 20 07 2F 07 28 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 29 07 29 07 28 07 20 07 20 07 28 07 20 07 28 07 28 07 29 07 2F 07 28 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 28 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 28 07 28 07 29 07 2F 07 28 07 20 07 20 07 29 07 5C 07 20 07 20 07 29 07 5C 07 28 07 29 07 29 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 28 07 5F 07 29 07 28 07 29 07 5C 07 20 07 29 07 5C 07 20 07 2F 07 28 07 5F 07 29 07 29 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 29 07 29 07 5C 07 20 07 29 07 28 07 20 07 20 07 20 07 20 07 2F 07 28 07 5F 07 29 07 7C 07 28 07 28 07 5F 07 29 07 28 07 28 07 5F 07 29 07 5C 07 20 07 20 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 5F 07 28 07 29 07 28 07 28 07 5F 07 7C 07 28 07 5F 07 7C 07 5F 07 29 07 29 07 20 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 2F 07 28 07 28 07 5F 07 7C 07 28 07 29 07 5C 07 20 07 20 07 28 07 5F 07 29 07 29 07 20 07 29 07 5C 07 5F 07 5F 07 5F 07 5F 07 5F 07 28 07 28 07 5F 07 29 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 20 07 5C 07 2F 07 20 07 20 07 7C 07 28 07 5F 07 29 07 20 07 5F 07 5F 07 7C 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 28 07 5F 07 29 07 29 07 20 07 20 07 28 07 28 07 5F 07 29 07 20 07 7C 07 20 07 5F 07 20 07 28 07 28 07 2F 07 20 07 5F 07 5F 07 5C 07 20 07 5C 07 2F 07 20 07 2F 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 7C 07 5C 07 2F 07 7C 07 20 07 7C 07 7C 07 20 07 5C 07 5F 07 5F 07 20 07 5C 07 20 07 20 07 7C 07 20 07 7C 07 20 07 2F 07 20 07 2D 07 5F 07 29 07 7C 07 20 07 27 07 5F 07 7C 07 20 07 7C 07 20 07 20 07 5F 07 2F 07 7C 07 20 07 28 07 5F 07 5F 07 20 07 3E 07 20 07 20 07 3C 07 20 07 20 07 20 07 7C 07 20 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 7C 07 5F 07 7C 07 7C 07 5F 07 7C 07 5F 07 5F 07 5F 07 2F 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 5C 07 5F 07 5F 07 5F 07 7C 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 5C 07 5F 07 5F 07 5F 07 2F 07 5F 07 2F 07 5C 07 5F 07 5C 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 31 07 33 07 2F 07 30 07 36 07 2F 07 32 07 30 07 32 07 32 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 72 07 74 07 20 07 62 07 79 07 20 07 40 07 73 07 70 07 61 07 72 07 6B 07 32 07 6B 07 30 07 36 07 2C 07 20 07 40 07 6E 07 61 07 65 07 6C 07 6F 07 6F 07 62 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 77 07 65 07 72 07 65 07 64 07 20 07 62 07 79 07 20 07 4B 07 46 07 50 07 43 07 2D 07 58 07 54 07 20 07 26 07 20 07 4D 07 43 07 4C 07 38 07 36 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 43 07 6F 07 6E 07 74 07 72 07 69 07 62 07 75 07 74 07 6F 07 72 07 73 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 40 07 4A 07 61 07 73 07 6F 07 6E 07 41 07 2C 07 20 07 40 07 67 07 79 07 75 07 72 07 63 07 6F 07 2C 07 20 07 40 07 6B 07 69 07 74 07 75 07 6E 07 65 07 2D 07 73 07 61 07 6E 07 2C 07 20 07 40 07 4D 07 69 07 63 07 72 07 6F 07 43 07 6F 07 72 07 65 07 4C 07 61 07 62 07 73 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
\ No newline at end of file
diff --git a/sys/ascal.vhd b/sys/ascal.vhd
index bd4e238..9b3465e 100644
--- a/sys/ascal.vhd
+++ b/sys/ascal.vhd
@@ -113,21 +113,23 @@ USE ieee.numeric_std.ALL;
ENTITY ascal IS
GENERIC (
- MASK : unsigned(7 DOWNTO 0) :=x"FF";
- RAMBASE : unsigned(31 DOWNTO 0);
- RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB
- INTER : boolean := true;
- HEADER : boolean := true;
- DOWNSCALE : boolean := true;
- BYTESWAP : boolean := true;
- PALETTE : boolean := true;
- PALETTE2 : boolean := true;
- FRAC : natural RANGE 4 TO 6 :=4;
- OHRES : natural RANGE 1 TO 4096 :=2048;
- IHRES : natural RANGE 1 TO 2048 :=2048;
- N_DW : natural RANGE 64 TO 128 := 128;
- N_AW : natural RANGE 8 TO 32 := 32;
- N_BURST : natural := 256 -- 256 bytes per burst
+ MASK : unsigned(7 DOWNTO 0) :=x"FF";
+ RAMBASE : unsigned(31 DOWNTO 0);
+ RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB
+ INTER : boolean := true;
+ HEADER : boolean := true;
+ DOWNSCALE : boolean := true;
+ BYTESWAP : boolean := true;
+ PALETTE : boolean := true;
+ PALETTE2 : boolean := true;
+ ADAPTIVE : boolean := true;
+ DOWNSCALE_NN : boolean := false;
+ FRAC : natural RANGE 4 TO 8 :=4;
+ OHRES : natural RANGE 1 TO 4096 :=2048;
+ IHRES : natural RANGE 1 TO 2048 :=2048;
+ N_DW : natural RANGE 64 TO 128 := 128;
+ N_AW : natural RANGE 8 TO 32 := 32;
+ N_BURST : natural := 256 -- 256 bytes per burst
);
PORT (
------------------------------------
@@ -225,12 +227,12 @@ ENTITY ascal IS
------------------------------------
-- Polyphase filter coefficients
-- Order :
- -- [Horizontal] [Vertical]
+ -- [Horizontal] [Vertical] [Horizontal2] [Vertical2]
-- [0]...[2**FRAC-1]
-- [-1][0][1][2]
poly_clk : IN std_logic;
- poly_dw : IN unsigned(8 DOWNTO 0);
- poly_a : IN unsigned(FRAC+2 DOWNTO 0);
+ poly_dw : IN unsigned(9 DOWNTO 0);
+ poly_a : IN unsigned(FRAC+3 DOWNTO 0);
poly_wr : IN std_logic;
------------------------------------
@@ -295,6 +297,7 @@ ARCHITECTURE rtl OF ascal IS
r,g,b : unsigned(7 DOWNTO 0); -- 0.8
END RECORD;
TYPE arr_pix IS ARRAY (natural RANGE <>) OF type_pix;
+ TYPE arr_pixq IS ARRAY(natural RANGE <>) OF arr_pix(0 TO 3);
ATTRIBUTE ramstyle : string;
SUBTYPE uint12 IS natural RANGE 0 TO 4095;
@@ -302,9 +305,11 @@ ARCHITECTURE rtl OF ascal IS
TYPE arr_uv48 IS ARRAY (natural RANGE <>) OF unsigned(47 DOWNTO 0);
TYPE arr_uv24 IS ARRAY (natural RANGE <>) OF unsigned(23 DOWNTO 0);
- TYPE arr_uv36 IS ARRAY (natural RANGE <>) OF unsigned(35 DOWNTO 0);
+ TYPE arr_uv40 IS ARRAY (natural RANGE <>) OF unsigned(39 DOWNTO 0);
TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255;
TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12;
+ TYPE arr_frac IS ARRAY (natural RANGE <>) OF unsigned(11 DOWNTO 0);
+ TYPE arr_div IS ARRAY (natural RANGE <>) OF unsigned(20 DOWNTO 0);
----------------------------------------------------------
-- Input image
@@ -415,7 +420,7 @@ ARCHITECTURE rtl OF ascal IS
ATTRIBUTE ramstyle of pal1_mem : signal is "no_rw_check";
ATTRIBUTE ramstyle of pal2_mem : signal is "no_rw_check";
SIGNAL o_htotal,o_hsstart,o_hsend : uint12;
- SIGNAL o_hmin,o_hmax,o_hdisp : uint12;
+ SIGNAL o_hmin,o_hmax,o_hdisp,o_v_hmin_adj : uint12;
SIGNAL o_hsize,o_vsize : uint12;
SIGNAL o_vtotal,o_vsstart,o_vsend : uint12;
SIGNAL o_vmin,o_vmax,o_vdisp : uint12;
@@ -430,7 +435,7 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_pshift : natural RANGE 0 TO 15;
SIGNAL o_readack,o_readack_sync,o_readack_sync2 : std_logic;
SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic;
- SIGNAL o_copyv : unsigned(0 TO 8);
+ SIGNAL o_copyv : unsigned(0 TO 14);
SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address
SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1;
SIGNAL o_stride : unsigned(13 DOWNTO 0);
@@ -448,16 +453,19 @@ ARCHITECTURE rtl OF ascal IS
ATTRIBUTE ramstyle OF o_line1 : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_line2 : SIGNAL IS "no_rw_check";
ATTRIBUTE ramstyle OF o_line3 : SIGNAL IS "no_rw_check";
- SIGNAL o_wadl,o_radl : natural RANGE 0 TO OHRES-1;
+ SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1;
SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix;
SIGNAL o_wr : unsigned(3 DOWNTO 0);
SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3 : uint12;
SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12;
SIGNAL o_ihsize_temp, o_ihsize_temp2 : natural RANGE 0 TO 32767;
- SIGNAL o_vfrac,o_hfrac,o_hfrac1,o_hfrac2,o_hfrac3,o_hfrac4 : unsigned(11 DOWNTO 0);
+ SIGNAL o_vfrac : unsigned(11 DOWNTO 0);
+ SIGNAL o_hfrac : arr_frac(0 TO 9);
+ ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register
+
SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1;
- SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 5);
+ SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 11);
SIGNAL o_hsp,o_vss : std_logic;
SIGNAL o_vcarrym,o_prim : boolean;
SIGNAL o_read,o_read_pre : std_logic;
@@ -474,14 +482,20 @@ ARCHITECTURE rtl OF ascal IS
TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15;
SIGNAL o_off : arr_uint4(0 TO 2);
SIGNAL o_bibu : std_logic :='0';
- SIGNAL o_dcptv : arr_uint12(1 TO 8);
+ SIGNAL o_dcptv : arr_uint12(1 TO 14);
SIGNAL o_dcpt : uint12;
SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix;
- SIGNAL o_hpixq,o_vpixq,o_vpixq1 : arr_pix(0 TO 3);
-
+ SIGNAL o_hpixq : arr_pixq(2 TO 8);
+ ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register
+ SIGNAL o_vpixq, o_vpixq_pre : arr_pix(0 TO 3);
+ SIGNAL o_vpix_outer : arr_pix(0 TO 2);
+ SIGNAL o_vpix_inner : arr_pix(0 TO 6);
+
+
SIGNAL o_vpe : std_logic;
- SIGNAL o_div,o_div2 : unsigned(18 DOWNTO 0); --uint12;
- SIGNAL o_dir,o_dir2 : unsigned(11 DOWNTO 0);
+ SIGNAL o_div : arr_div(0 TO 2); --uint12;
+ SIGNAL o_dir : arr_frac(0 TO 2);
+ ATTRIBUTE ramstyle OF o_div, o_dir : SIGNAL IS "logic"; -- avoid blockram shift register
SIGNAL o_vdivi : unsigned(12 DOWNTO 0);
SIGNAL o_vdivr : unsigned(24 DOWNTO 0);
SIGNAL o_divstart : std_logic;
@@ -711,8 +725,7 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0);
SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0);
SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix;
- SIGNAL o_h_near_pix,o_v_near_pix : type_pix;
-
+
-----------------------------------------------------------------------------
-- Nearest + Bilinear + Sharp Bilinear
FUNCTION bil_frac(f : unsigned) RETURN unsigned IS
@@ -760,6 +773,7 @@ ARCHITECTURE rtl OF ascal IS
END IF;
RETURN x;
END FUNCTION;
+
SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t;
SIGNAL o_h_near_t,o_v_near_t : type_bil_t;
SIGNAL i_h_bil_t : type_bil_t;
@@ -933,82 +947,160 @@ ARCHITECTURE rtl OF ascal IS
-----------------------------------------------------------------------------
-- Polyphase
-
- CONSTANT POLY16 : arr_int9 := (
- -24,-21,-15,-9,-5,-1,4,8,6,8,5,4,3,1,0,0,
- 176,174,169,160,150,131,115,85,58,27,4,-6,-20,-24,-26,-25,
- -24,-25,-26,-24,-20,-6,4,27,58,85,115,131,150,160,169,174,
- 0,0,0,1,3,4,5,8,6,8,4,-1,-5,-9,-15,-21);
-
- CONSTANT POLY32 : arr_int9 := (
- -24,-22,-20,-18,-16,-13,-11,-8,-6,-3,-1,0,2,3,5,5,6,6,6,5,5,4,4,3,2,1,1,0,0,0,0,0,
- 176,175,174,172,169,164,160,153,147,138,129,119,109,96,84,71,58,40,22,12,3,-4,-12,-16,-20,-22,-25,-25,-26,-25,-25,-25,
- -24,-25,-26,-26,-26,-24,-23,-19,-16,-10,-4,4,11,22,32,45,58,77,96,108,119,129,140,147,154,159,165,168,172,173,175,175,
- 0,0,0,0,1,1,2,2,3,3,4,5,6,7,7,7,6,5,4,3,1,-1,-4,-6,-8,-10,-13,-15,-18,-20,-22,-22);
-
- FUNCTION init_poly RETURN arr_uv36 IS
- VARIABLE m : arr_uv36(0 TO 2**FRAC-1) :=(OTHERS =>x"000000000");
- BEGIN
- IF FRAC=4 THEN
- FOR i IN 0 TO 15 LOOP
- m(i):=unsigned(to_signed(POLY16(i),9) & to_signed(POLY16(i+16),9) &
- to_signed(POLY16(i+32),9) & to_signed(POLY16(i+48),9));
- END LOOP;
- ELSIF FRAC=5 THEN
- FOR i IN 0 TO 31 LOOP
- m(i):=unsigned(to_signed(POLY32(i),9) & to_signed(POLY32(i+32),9) &
- to_signed(POLY32(i+64),9) & to_signed(POLY32(i+96),9));
- END LOOP;
- END IF;
- RETURN m;
- END FUNCTION;
-
- SIGNAL o_h_poly : arr_uv36(0 TO 2**FRAC-1):=init_poly;
- SIGNAL o_v_poly : arr_uv36(0 TO 2**FRAC-1):=init_poly;
- ATTRIBUTE ramstyle OF o_h_poly : SIGNAL IS "no_rw_check";
- ATTRIBUTE ramstyle OF o_v_poly : SIGNAL IS "no_rw_check";
- SIGNAL o_h_poly_a,o_v_poly_a : integer RANGE 0 TO 2**FRAC-1;
- SIGNAL o_h_poly_dr,o_h_poly_dr2,o_v_poly_dr,o_v_poly_dr2 : unsigned(35 DOWNTO 0);
- SIGNAL o_h_poly_pix,o_v_poly_pix : type_pix;
- SIGNAL poly_h_wr,poly_v_wr : std_logic;
- SIGNAL poly_tdw : unsigned(35 DOWNTO 0);
- SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0);
-
- TYPE type_poly_t IS RECORD
- r0,r1,b0,b1,g0,g1 : signed(17 DOWNTO 0);
+ -- 2.7
+ TYPE poly_phase_t IS RECORD
+ t0, t1, t2, t3 : signed(9 DOWNTO 0);
+ END RECORD;
+
+ -- 4.14
+ TYPE poly_phase_interp_t IS RECORD
+ t0, t1, t2, t3 : signed(17 DOWNTO 0);
END RECORD;
- SIGNAL o_h_poly_t,o_v_poly_t : type_poly_t;
+ -- 5.22
+ TYPE type_poly_t IS RECORD
+ r0,r1,b0,b1,g0,g1 : signed(26 DOWNTO 0);
+ END RECORD;
- FUNCTION poly_calc1(fi : unsigned(35 DOWNTO 0);
+
+ SIGNAL o_h_poly_mem : arr_uv40(0 TO 2**FRAC-1);
+ SIGNAL o_v_poly_mem : arr_uv40(0 TO 2**FRAC-1);
+ SIGNAL o_a_poly_mem : arr_uv40(0 TO 2**FRAC-1);
+ ATTRIBUTE ramstyle OF o_h_poly_mem : SIGNAL IS "no_rw_check";
+ ATTRIBUTE ramstyle OF o_v_poly_mem : SIGNAL IS "no_rw_check";
+ ATTRIBUTE ramstyle OF o_a_poly_mem : SIGNAL IS "no_rw_check";
+ SIGNAL o_a_poly_addr, o_v_poly_addr : integer RANGE 0 TO 2**FRAC-1;
+ SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3, o_h_poly_phase_a4, o_h_poly_phase_a5 : poly_phase_t;
+ SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3, o_v_poly_phase_a4, o_v_poly_phase_a5 : poly_phase_t;
+ SIGNAL o_poly_phase_a, o_poly_phase_a2, o_poly_phase_a3 : poly_phase_t;
+ SIGNAL o_poly_phase_b,o_poly_phase_b2,o_poly_phase_b3 : poly_phase_t;
+ SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase, o_poly_phase1 : poly_phase_interp_t;
+ SIGNAL o_v_poly_pix, o_h_poly_pix, o_h_lum_pix, o_v_lum_pix : type_pix;
+ SIGNAL o_poly_lum, o_poly_lum1 : unsigned(7 DOWNTO 0);
+ SIGNAL o_poly_lerp_ta, o_poly_lerp_tb : signed(9 DOWNTO 0);
+ SIGNAL o_h_poly_t,o_h_poly_t2,o_v_poly_t : type_poly_t;
+
+ SIGNAL o_v_poly_adaptive, o_h_poly_adaptive, o_v_poly_use_adaptive, o_h_poly_use_adaptive : std_logic;
+ SIGNAL poly_wr_mode : std_logic_vector(2 DOWNTO 0);
+ SIGNAL poly_tdw : unsigned(39 DOWNTO 0);
+ SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0);
+
+
+ FUNCTION poly_unpack(a : unsigned(39 DOWNTO 0)) RETURN poly_phase_t IS
+ VARIABLE v : poly_phase_t;
+ BEGIN
+ v.t0 := signed(a(39 DOWNTO 30));
+ v.t1 := signed(a(29 DOWNTO 20));
+ v.t2 := signed(a(19 DOWNTO 10));
+ v.t3 := signed(a( 9 DOWNTO 0));
+
+ RETURN v;
+ END FUNCTION;
+
+ -- 6 DSP 18*18 + 18*18
+ FUNCTION poly_calc(fi : poly_phase_interp_t;
p : arr_pix(0 TO 3)) RETURN type_poly_t IS
VARIABLE t : type_poly_t;
BEGIN
- -- 2.7 * 1.8 = 3.15
- t.r0:=(signed(fi(35 DOWNTO 27)) * signed('0' & p(0).r) +
- signed(fi(26 DOWNTO 18)) * signed('0' & p(1).r));
- t.r1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p(2).r) +
- signed(fi( 8 DOWNTO 0)) * signed('0' & p(3).r));
- t.g0:=(signed(fi(35 DOWNTO 27)) * signed('0' & p(0).g) +
- signed(fi(26 DOWNTO 18)) * signed('0' & p(1).g));
- t.g1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p(2).g) +
- signed(fi( 8 DOWNTO 0)) * signed('0' & p(3).g));
- t.b0:=(signed(fi(35 DOWNTO 27)) * signed('0' & p(0).b) +
- signed(fi(26 DOWNTO 18)) * signed('0' & p(1).b));
- t.b1:=(signed(fi(17 DOWNTO 9)) * signed('0' & p(2).b) +
- signed(fi( 8 DOWNTO 0)) * signed('0' & p(3).b));
+ -- 3.15 * 1.8 = 4.23
+ t.r0:=(fi.t0 * signed('0' & p(0).r) +
+ fi.t1 * signed('0' & p(1).r));
+ t.r1:=(fi.t2 * signed('0' & p(2).r) +
+ fi.t3 * signed('0' & p(3).r));
+ t.g0:=(fi.t0 * signed('0' & p(0).g) +
+ fi.t1 * signed('0' & p(1).g));
+ t.g1:=(fi.t2 * signed('0' & p(2).g) +
+ fi.t3 * signed('0' & p(3).g));
+ t.b0:=(fi.t0 * signed('0' & p(0).b) +
+ fi.t1 * signed('0' & p(1).b));
+ t.b1:=(fi.t2 * signed('0' & p(2).b) +
+ fi.t3 * signed('0' & p(3).b));
RETURN t;
END FUNCTION;
- FUNCTION poly_calc2(t : type_poly_t) RETURN type_pix IS
+ FUNCTION poly_final(t : type_poly_t) RETURN type_pix IS
VARIABLE p : type_pix;
BEGIN
- p.r:=bound(unsigned(t.r0+t.r1),15);
- p.g:=bound(unsigned(t.g0+t.g1),15);
- p.b:=bound(unsigned(t.b0+t.b1),15);
+ p.r:=bound(unsigned(t.r0(26 DOWNTO 8)+t.r1(26 DOWNTO 8)),15);
+ p.g:=bound(unsigned(t.g0(26 DOWNTO 8)+t.g1(26 DOWNTO 8)),15);
+ p.b:=bound(unsigned(t.b0(26 DOWNTO 8)+t.b1(26 DOWNTO 8)),15);
RETURN p;
END FUNCTION;
-
+
+ -- 4 DSP 18*18 + 18*18
+ FUNCTION poly_lerp(a : poly_phase_t;
+ b : poly_phase_t;
+ ta : SIGNED(9 DOWNTO 0);
+ tb : SIGNED(9 DOWNTO 0)) RETURN poly_phase_interp_t IS
+ VARIABLE v : poly_phase_interp_t;
+ VARIABLE t0,t1,t2,t3 : signed(19 DOWNTO 0);
+ BEGIN
+ -- 2.8 * 2.8 = 4.16
+ t0 := (a.t0 * ta) + (b.t0 * tb);
+ t1 := (a.t1 * ta) + (b.t1 * tb);
+ t2 := (a.t2 * ta) + (b.t2 * tb);
+ t3 := (a.t3 * ta) + (b.t3 * tb);
+
+ -- 4.16 -> 3.15
+ v.t0 := t0(18 DOWNTO 1);
+ v.t1 := t1(18 DOWNTO 1);
+ v.t2 := t2(18 DOWNTO 1);
+ v.t3 := t3(18 DOWNTO 1);
+
+ RETURN v;
+ END FUNCTION;
+
+ FUNCTION poly_cvt(a : poly_phase_t) RETURN poly_phase_interp_t IS
+ VARIABLE v : poly_phase_interp_t;
+ BEGIN
+ v.t0 := resize(signed( a.t0 & "0000000" ), v.t0'length);
+ v.t1 := resize(signed( a.t1 & "0000000" ), v.t1'length);
+ v.t2 := resize(signed( a.t2 & "0000000" ), v.t2'length);
+ v.t3 := resize(signed( a.t3 & "0000000" ), v.t3'length);
+ RETURN v;
+ END FUNCTION;
+
+ -- Nearest neighbor polyphase ceoffs
+ FUNCTION poly_nn(frac : unsigned(FRAC-1 DOWNTO 0)) RETURN poly_phase_t IS
+ VARIABLE v : poly_phase_t;
+ BEGIN
+ IF frac(frac'left)='0' THEN
+ v := (t1=>to_signed(256, 10), OTHERS=>to_signed(0, 10));
+ ELSE
+ v := (t2=>to_signed(256, 10), OTHERS=>to_signed(0, 10));
+ END IF;
+ RETURN v;
+ END FUNCTION;
+
+
+ FUNCTION poly_lum(p : type_pix) RETURN unsigned IS
+ VARIABLE v : UNSIGNED(7 DOWNTO 0);
+ BEGIN
+ -- 0.375 R + 0.5 G + 0.125 B
+ --v := ("00" & p.r(7 DOWNTO 2)) + ("000" & p.r(7 DOWNTO 3)) + ("0" & p.g(7 DOWNTO 1)) + ("000" & p.b(7 DOWNTO 3));
+
+ -- 0.25 R + 0.5 G + 0.25 B
+ -- v := ( ("00" & p.r(7 DOWNTO 2)) + ("0" & p.g(7 DOWNTO 1)) + ("00" & p.b(7 DOWNTO 2)) );
+
+ -- Just OR them all together
+ --v := (p.r OR p.g OR p.b);
+
+ -- Maximum
+ IF p.r > p.g THEN
+ v := p.r;
+ ELSE
+ v := p.g;
+ END IF;
+
+ IF p.b > v THEN
+ v := p.b;
+ END IF;
+
+ -- 100%
+ -- v := "1111111";
+
+ RETURN v;
+ END FUNCTION;
BEGIN
-----------------------------------------------------------------------------
@@ -1160,7 +1252,7 @@ BEGIN
i_format<=format; --
-- Downscaling : Nearest or bilinear
- i_bil<=to_std_logic(i_mode(2 DOWNTO 0)/="000" AND DOWNSCALE);
+ i_bil<=to_std_logic(i_mode(2 DOWNTO 0)/="000" AND NOT DOWNSCALE_NN);
i_hdown<=to_std_logic(i_hsize>i_ohsize AND DOWNSCALE); --H downscale
i_vdown<=to_std_logic(i_vsize>i_ovsize AND DOWNSCALE); --V downscale
@@ -1272,11 +1364,12 @@ BEGIN
-- C4 : Horizontal Bilinear
IF i_bil='0' THEN
frac_v:=near_frac(i_h_frac);
+ i_h_bil_t<=near_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3));
ELSE
frac_v:=bil_frac(i_h_frac);
+ i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3));
END IF;
- i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3));
i_hpix.r<=bound(i_h_bil_t.r,8+FRAC);
i_hpix.g<=bound(i_h_bil_t.g,8+FRAC);
i_hpix.b<=bound(i_h_bil_t.b,8+FRAC);
@@ -1288,11 +1381,12 @@ BEGIN
-- C5 : Vertical Bilinear
IF i_bil='0' THEN
frac_v:=near_frac(i_v_frac(11 DOWNTO 0));
+ bil_t_v:=near_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm));
ELSE
frac_v:=bil_frac(i_v_frac(11 DOWNTO 0));
+ bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm));
END IF;
- bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm));
i_pix.r<=bound(bil_t_v.r,8+FRAC);
i_pix.g<=bound(bil_t_v.g,8+FRAC);
i_pix.b<=bound(bil_t_v.b,8+FRAC);
@@ -1721,7 +1815,7 @@ BEGIN
VARIABLE hcarry_v,vcarry_v : boolean;
VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1;
VARIABLE off_v : natural RANGE 0 TO 15;
- BEGIN
+ BEGIN
IF o_reset_na='0' THEN
o_copy<=sWAIT;
o_state<=sDISP;
@@ -1822,7 +1916,14 @@ BEGIN
o_vdown<='0';
END IF;
- o_ihsize_temp <= o_ihsize * to_integer(o_format(2 DOWNTO 0) - 2);
+ -- 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
+ CASE o_format(2 DOWNTO 0) IS
+ WHEN "011" => o_ihsize_temp <= o_ihsize;
+ WHEN "100" => o_ihsize_temp <= o_ihsize * 2;
+ WHEN "110" => o_ihsize_temp <= o_ihsize * 4;
+ WHEN OTHERS => o_ihsize_temp <= o_ihsize * 3;
+ END CASE;
+
o_ihsize_temp2 <= (o_ihsize_temp + N_BURST - 1);
o_hburst <= o_ihsize_temp2 / N_BURST;
@@ -2111,7 +2212,7 @@ BEGIN
o_hpix1<=o_hpix0;
o_hpix2<=o_hpix1;
o_hpix3<=o_hpix2;
-
+
IF o_first='1' THEN
-- Left edge. Duplicate first pixel
o_hpix1<=hpix_v;
@@ -2171,13 +2272,87 @@ BEGIN
------------------------------------------------------
END IF;
END PROCESS Scalaire;
-
- o_h_poly_a<=to_integer(o_hfrac1(11 DOWNTO 12-FRAC));
- o_v_poly_a<=to_integer(o_vfrac(11 DOWNTO 12-FRAC));
-
- o_h_poly_dr<=o_h_poly(o_h_poly_a) WHEN rising_edge(o_clk);
- o_v_poly_dr<=o_v_poly(o_v_poly_a) WHEN rising_edge(o_clk);
-
+
+ -- Fetch polyphase coefficients
+ PolyFetch:PROCESS (o_clk) IS
+ VARIABLE hfrac3_v, vfrac_v : unsigned(FRAC-1 DOWNTO 0);
+ BEGIN
+ IF rising_edge(o_clk) THEN
+ hfrac3_v:=o_hfrac(3)(11 DOWNTO 12-FRAC);
+ vfrac_v:=o_vfrac(11 DOWNTO 12-FRAC);
+
+ o_v_poly_use_adaptive <= to_std_logic((o_vmode(2 DOWNTO 0)/="000") AND (o_v_poly_adaptive = '1'));
+ o_h_poly_use_adaptive <= to_std_logic((o_hmode(2 DOWNTO 0)/="000") AND (o_h_poly_adaptive = '1'));
+ o_v_poly_addr<=to_integer(o_vfrac(11 DOWNTO 12-FRAC));
+
+ -- C3 / HC3 / VC4
+ IF o_vmode(2 DOWNTO 0)/="000" THEN
+ o_v_poly_phase_a<=poly_unpack(o_v_poly_mem(o_v_poly_addr));
+ ELSE
+ o_v_poly_phase_a<=poly_nn(vfrac_v);
+ END IF;
+
+ IF o_hmode(2 DOWNTO 0)/="000" THEN
+ o_h_poly_phase_a<=poly_unpack(o_h_poly_mem(to_integer(hfrac3_v)));
+ ELSE
+ o_h_poly_phase_a<=poly_nn(hfrac3_v);
+ END IF;
+
+ IF o_v_poly_use_adaptive='1' THEN
+ o_poly_lum<=poly_lum(o_v_lum_pix);
+ o_a_poly_addr<=o_v_poly_addr;
+ ELSIF o_h_poly_use_adaptive='1' THEN
+ o_poly_lum<=poly_lum(o_h_lum_pix);
+ o_a_poly_addr<=to_integer(hfrac3_v);
+ END IF;
+
+ -- C4 / HC4 / VC5
+ o_poly_phase_b<=poly_unpack(o_a_poly_mem(o_a_poly_addr));
+
+ IF o_v_poly_use_adaptive='1' THEN
+ o_poly_phase_a<=o_v_poly_phase_a;
+ ELSIF o_h_poly_use_adaptive = '1' THEN
+ o_poly_phase_a<=o_h_poly_phase_a;
+ END IF;
+
+ o_h_poly_phase_a2<=o_h_poly_phase_a;
+ o_v_poly_phase_a2<=o_v_poly_phase_a;
+ o_poly_lum1<=o_poly_lum;
+
+ -- C5 / HC5 / VC6
+ o_poly_lerp_ta<=signed(to_unsigned(256,10) - resize(o_poly_lum1,10));
+ o_poly_lerp_tb<=signed(resize(o_poly_lum1,10));
+
+ o_poly_phase_b2<=o_poly_phase_b;
+ o_poly_phase_a2<=o_poly_phase_a;
+
+ o_h_poly_phase_a3<=o_h_poly_phase_a2;
+ o_v_poly_phase_a3<=o_v_poly_phase_a2;
+
+ -- C6 / HC6 / VC7
+ o_poly_phase<=poly_lerp(o_poly_phase_a2, o_poly_phase_b2, o_poly_lerp_ta, o_poly_lerp_tb);
+ o_h_poly_phase_a4<=o_h_poly_phase_a3;
+ o_v_poly_phase_a4<=o_v_poly_phase_a3;
+
+ -- C7 / HC7 / VC8
+ o_h_poly_phase_a5<=o_h_poly_phase_a4;
+ o_v_poly_phase_a5<=o_v_poly_phase_a4;
+ o_poly_phase1<=o_poly_phase;
+
+ -- C8 / HC8 / VC9
+ o_v_poly_phase<=poly_cvt(o_v_poly_phase_a5);
+ o_h_poly_phase<=poly_cvt(o_h_poly_phase_a5);
+
+ IF o_v_poly_use_adaptive = '1' THEN
+ o_v_poly_phase<=o_poly_phase1;
+ ELSIF o_h_poly_use_adaptive = '1' THEN
+ o_h_poly_phase<=o_poly_phase1;
+ END IF;
+
+ END IF;
+ END PROCESS PolyFetch;
+
+
-- Framebuffer palette
GenPal1:IF PALETTE GENERATE
Tempera1:PROCESS(pal1_clk) IS
@@ -2224,172 +2399,197 @@ BEGIN
BEGIN
IF rising_edge(poly_clk) THEN
IF poly_wr='1' THEN
- poly_tdw(8+9*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO
- 9*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw;
+ poly_tdw(9+10*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO
+ 10*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw;
END IF;
- poly_h_wr<=poly_wr AND NOT poly_a(FRAC+2);
- poly_v_wr<=poly_wr AND poly_a(FRAC+2);
+ poly_wr_mode(0)<=poly_wr AND NOT poly_a(FRAC+2);
+ poly_wr_mode(1)<=poly_wr AND poly_a(FRAC+2);
+ poly_wr_mode(2)<=poly_wr AND poly_a(FRAC+3) AND to_std_logic(ADAPTIVE);
poly_a2<=poly_a(FRAC+1 DOWNTO 2);
- IF poly_h_wr='1' THEN
- o_h_poly(to_integer(poly_a2))<=poly_tdw;
- END IF;
- IF poly_v_wr='1' THEN
- o_v_poly(to_integer(poly_a2))<=poly_tdw;
- END IF;
+ CASE poly_wr_mode IS
+ WHEN "001" => -- horiz
+ o_h_poly_mem(to_integer(poly_a2))<=poly_tdw;
+ o_h_poly_adaptive<='0';
+ WHEN "010" => -- vert
+ o_v_poly_mem(to_integer(poly_a2))<=poly_tdw;
+ o_v_poly_adaptive<='0';
+ WHEN "101" => -- horiz adaptive
+ o_a_poly_mem(to_integer(poly_a2))<=poly_tdw;
+ o_h_poly_adaptive<='1';
+ WHEN "110" => -- vert adaptive
+ o_a_poly_mem(to_integer(poly_a2))<=poly_tdw;
+ o_v_poly_adaptive<='1';
+ WHEN OTHERS => NULL;
+ END CASE;
END IF;
END PROCESS Polikarpov;
-----------------------------------------------------------------------------
-- Horizontal Scaler
HSCAL:PROCESS(o_clk) IS
- VARIABLE div_v : unsigned(18 DOWNTO 0);
+ VARIABLE div_v : unsigned(20 DOWNTO 0);
VARIABLE dir_v : unsigned(11 DOWNTO 0);
BEGIN
IF rising_edge(o_clk) THEN
-- Pipeline signals
-----------------------------------
- -- Pipelined 6 bits non-restoring divider. Cycle 1
+ -- Pipelined 8 bits non-restoring divider. Cycle 1
dir_v:=x"000";
- div_v:=to_unsigned(o_hacc * 64,19);
+ div_v:=to_unsigned(o_hacc * 256,21);
- div_v:=div_v-to_unsigned(o_hsize*64,19);
- dir_v(11):=NOT div_v(18);
- IF div_v(18)='0' THEN
- div_v:=div_v-to_unsigned(o_hsize*32,19);
+ div_v:=div_v-to_unsigned(o_hsize*256,21);
+ dir_v(11):=NOT div_v(20);
+ IF div_v(20)='0' THEN
+ div_v:=div_v-to_unsigned(o_hsize*128,21);
ELSE
- div_v:=div_v+to_unsigned(o_hsize*32,19);
+ div_v:=div_v+to_unsigned(o_hsize*128,21);
END IF;
- dir_v(10):=NOT div_v(18);
- o_div<=div_v;
- o_dir<=dir_v;
+ dir_v(10):=NOT div_v(20);
+
+ o_div(0)<=div_v;
+ o_dir(0)<=dir_v;
-- Cycle 2
- div_v:=o_div;
- dir_v:=o_dir;
- IF div_v(18)='0' THEN
- div_v:=div_v-to_unsigned(o_hsize*16,19);
+ div_v:=o_div(0);
+ dir_v:=o_dir(0);
+ IF div_v(20)='0' THEN
+ div_v:=div_v-to_unsigned(o_hsize*64,21);
ELSE
- div_v:=div_v+to_unsigned(o_hsize*16,19);
+ div_v:=div_v+to_unsigned(o_hsize*64,21);
END IF;
- dir_v( 9):=NOT div_v(18);
+ dir_v( 9):=NOT div_v(20);
- IF div_v(18)='0' THEN
- div_v:=div_v-to_unsigned(o_hsize*8,19);
+ IF div_v(20)='0' THEN
+ div_v:=div_v-to_unsigned(o_hsize*32,21);
ELSE
- div_v:=div_v+to_unsigned(o_hsize*8,19);
+ div_v:=div_v+to_unsigned(o_hsize*32,21);
END IF;
- dir_v(8):=NOT div_v(18);
- o_div2<=div_v;
- o_dir2<=dir_v;
-
+ dir_v( 8):=NOT div_v(20);
+
+ o_div(1)<=div_v;
+ o_dir(1)<=dir_v;
+
-- Cycle 3
- div_v:=o_div2;
- dir_v:=o_dir2;
+ div_v:=o_div(1);
+ dir_v:=o_dir(1);
IF FRAC>4 THEN
- IF div_v(18)='0' THEN
- div_v:=div_v-to_unsigned(o_hsize*4,19);
+ IF div_v(20)='0' THEN
+ div_v:=div_v-to_unsigned(o_hsize*16,21);
ELSE
- div_v:=div_v+to_unsigned(o_hsize*4,19);
+ div_v:=div_v+to_unsigned(o_hsize*16,21);
END IF;
- dir_v(7):=NOT div_v(18);
- IF div_v(18)='0' THEN
- div_v:=div_v-to_unsigned(o_hsize*2,19);
+ dir_v(7):=NOT div_v(20);
+
+ IF div_v(20)='0' THEN
+ div_v:=div_v-to_unsigned(o_hsize*8,21);
ELSE
- div_v:=div_v+to_unsigned(o_hsize*2,19);
+ div_v:=div_v+to_unsigned(o_hsize*8,21);
END IF;
- dir_v(6):=NOT div_v(18);
+ dir_v(6):=NOT div_v(20);
+ END IF;
+ o_div(2)<=div_v;
+ o_dir(2)<=dir_v;
+
+ div_v:=o_div(2);
+ dir_v:=o_dir(2);
+ IF FRAC>6 THEN
+ IF div_v(20)='0' THEN
+ div_v:=div_v-to_unsigned(o_hsize*4,21);
+ ELSE
+ div_v:=div_v+to_unsigned(o_hsize*4,21);
+ END IF;
+ dir_v(5):=NOT div_v(20);
+
+ IF div_v(20)='0' THEN
+ div_v:=div_v-to_unsigned(o_hsize*2,21);
+ ELSE
+ div_v:=div_v+to_unsigned(o_hsize*2,21);
+ END IF;
+ dir_v(4):=NOT div_v(20);
END IF;
-----------------------------------
- o_hfrac<=dir_v;
- o_hfrac1<=o_hfrac; o_hfrac2<=o_hfrac1;
- o_hfrac3<=o_hfrac2; o_hfrac4<=o_hfrac3;
+ o_hfrac(1)<=dir_v;
+ o_hfrac(2 TO 9) <= o_hfrac(1 TO 8);
- o_copyv(1 TO 8)<=o_copyv(0 TO 7);
+ o_copyv(1 TO 14)<=o_copyv(0 TO 13);
o_dcptv(1)<=o_dcpt;
IF o_dcptv(1)>=o_hsize THEN
o_copyv(2)<='0';
END IF;
o_dcptv(2)<=o_dcptv(1) MOD OHRES;
- o_dcptv(3 TO 8)<=o_dcptv(2 TO 7);
+ o_dcptv(3 TO 14)<=o_dcptv(2 TO 13);
- o_hpixq<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0);
-
- -- NEAREST -------------------------------------------
-- C2
- o_h_near_frac<=near_frac(o_hfrac2);
-
- -- C3
- o_h_near_t<=near_calc(o_h_near_frac,o_hpixq);
-
- -- C4 : Nearest
- o_h_near_pix.r<=o_h_near_t.r(7+FRAC DOWNTO FRAC);
- o_h_near_pix.g<=o_h_near_t.g(7+FRAC DOWNTO FRAC);
- o_h_near_pix.b<=o_h_near_t.b(7+FRAC DOWNTO FRAC);
+ o_hpixq(2)<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0);
+ o_hpixq(3 TO 8)<=o_hpixq(2 TO 7);
-- BILINEAR / SHARP BILINEAR ---------------
- -- C1 : Pre-calc Sharp Bilinear
- o_h_sbil_t<=sbil_frac1(o_hfrac1);
+ -- C7 : Pre-calc Sharp Bilinear
+ o_h_sbil_t<=sbil_frac1(o_hfrac(6));
- -- C2 : Select
+ -- C8 : Select
o_h_bil_frac<=(OTHERS =>'0');
IF o_hmode(0)='1' THEN -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
- o_h_bil_frac<=bil_frac(o_hfrac2);
+ o_h_bil_frac<=bil_frac(o_hfrac(7));
END IF;
ELSE -- Sharp Bilinear
IF MASK(MASK_SHARP_BILINEAR)='1' THEN
- o_h_bil_frac<=sbil_frac2(o_hfrac2,o_h_sbil_t);
+ o_h_bil_frac<=sbil_frac2(o_hfrac(7),o_h_sbil_t);
END IF;
END IF;
- -- C3 : Opposite frac
- o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq);
+ -- C9 : Opposite frac
+ o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq(8));
- -- C4 : Bilinear / Sharp Bilinear
+ -- C10 : Bilinear / Sharp Bilinear
o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC);
o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC);
o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC);
-- BICUBIC -------------------------------------------
- -- C1 : Bicubic coefficients A,B,C,D
+ -- C8 : Bicubic coefficients A,B,C,D
+ -- C8 : Bicubic calc T1 = X.D + C
+ o_h_bic_abcd1<=bic_calc0(o_hfrac(7),o_hpixq(6));
+ o_h_bic_tt1<=bic_calc1(o_hfrac(7),
+ bic_calc0(o_hfrac(7),o_hpixq(6)));
- -- C2 : Bicubic calc T1 = X.D + C
- o_h_bic_abcd1<=bic_calc0(o_hfrac2,(o_hpix3,o_hpix2,o_hpix1,o_hpix0));
- o_h_bic_tt1<=bic_calc1(o_hfrac2,
- bic_calc0(o_hfrac2,(o_hpix3,o_hpix2,o_hpix1,o_hpix0)));
-
- -- C3 : Bicubic calc T2 = X.T1 + B
+ -- C9 : Bicubic calc T2 = X.T1 + B
o_h_bic_abcd2<=o_h_bic_abcd1;
- o_h_bic_tt2<=bic_calc2(o_hfrac3,o_h_bic_tt1,o_h_bic_abcd1);
+ o_h_bic_tt2<=bic_calc2(o_hfrac(8),o_h_bic_tt1,o_h_bic_abcd1);
- -- C4 : Bicubic final Y = X.T2 + A
- o_h_bic_pix<=bic_calc3(o_hfrac4,o_h_bic_tt2,o_h_bic_abcd2);
+ -- C10 : Bicubic final Y = X.T2 + A
+ o_h_bic_pix<=bic_calc3(o_hfrac(9),o_h_bic_tt2,o_h_bic_abcd2);
-- POLYPHASE -----------------------------------------
- -- C1 : Read memory
+ -- C2
+ IF o_hfrac(2)(o_hfrac(2)'left)='0' THEN
+ o_h_lum_pix<=o_hpix2;
+ ELSE
+ o_h_lum_pix<=o_hpix1;
+ END IF;
+
+ -- C3-C8 in PolyFetch
+
+ -- C9 : Apply Polyphase
+ o_h_poly_t<=poly_calc(o_h_poly_phase,o_hpixq(8));
+
+ -- C10 : Sum and bound
+ o_h_poly_pix<=poly_final(o_h_poly_t);
- -- C2 : Filter calc
- o_h_poly_dr2<=o_h_poly_dr;
-
- -- C3 : Add
- o_h_poly_t<=poly_calc1(o_h_poly_dr2,o_hpixq);
-
- -- C4 : Bounding
- o_h_poly_pix<=poly_calc2(o_h_poly_t);
-
- -- C5 : Select interpoler ----------------------------
- o_wadl<=o_dcptv(8);
- o_wr<=o_altx AND (o_copyv(8) & o_copyv(8) & o_copyv(8) & o_copyv(8));
+ -- C11 : Select interpoler ----------------------------
+ o_wadl<=o_dcptv(14);
+ o_wr<=o_altx AND (o_copyv(14) & o_copyv(14) & o_copyv(14) & o_copyv(14));
o_ldw<=(x"00",x"00",x"00");
CASE o_hmode(2 DOWNTO 0) IS
WHEN "000" => -- Nearest
IF MASK(MASK_NEAREST)='1' THEN
- o_ldw<=o_h_near_pix;
+ o_ldw<=o_h_poly_pix;
END IF;
WHEN "001" | "010" => -- Bilinear | Sharp Bilinear
IF MASK(MASK_BILINEAR)='1' OR
@@ -2421,10 +2621,10 @@ BEGIN
IF o_wr(3)='1' THEN o_line3(o_wadl)<=o_ldw; END IF;
-- READS
- o_ldr0<=o_line0(o_radl);
- o_ldr1<=o_line1(o_radl);
- o_ldr2<=o_line2(o_radl);
- o_ldr3<=o_line3(o_radl);
+ o_ldr0<=o_line0(o_radl0);
+ o_ldr1<=o_line1(o_radl1);
+ o_ldr2<=o_line2(o_radl2);
+ o_ldr3<=o_line3(o_radl3);
END IF;
END PROCESS OLBUF;
@@ -2459,11 +2659,11 @@ BEGIN
(o_vcpt=o_vsend AND o_hcpt=o_vmin AND o_vcpt_pre2<=o_vmax);
- o_hsv(1 TO 5)<=o_hsv(0 TO 4);
- o_vsv(1 TO 5)<=o_vsv(0 TO 4);
- o_dev(1 TO 5)<=o_dev(0 TO 4);
- o_pev(1 TO 5)<=o_pev(0 TO 4);
- o_end(1 TO 5)<=o_end(0 TO 4);
+ o_hsv(1 TO 11)<=o_hsv(0 TO 10);
+ o_vsv(1 TO 11)<=o_vsv(0 TO 10);
+ o_dev(1 TO 11)<=o_dev(0 TO 10);
+ o_pev(1 TO 11)<=o_pev(0 TO 10);
+ o_end(1 TO 11)<=o_end(0 TO 10);
IF o_run='0' THEN
o_hsv(2)<='0';
@@ -2482,13 +2682,41 @@ BEGIN
-- Vertical Scaler
VSCAL:PROCESS(o_clk) IS
VARIABLE pixq_v : arr_pix(0 TO 3);
+ VARIABLE vlumpix_v : type_pix;
+ VARIABLE r1_v, r2_v : natural RANGE 0 TO OHRES-1;
+ VARIABLE fracnn_v : std_logic;
BEGIN
IF rising_edge(o_clk) THEN
IF o_ce='1' THEN
+ o_v_hmin_adj<=o_hmin + 5;
+
+ fracnn_v := o_vfrac(o_vfrac'left);
+ r1_v := (o_hcpt - o_v_hmin_adj + OHRES) MOD OHRES;
+ r2_v := (o_hcpt - o_hmin + OHRES) MOD OHRES;
+
-- CYCLE 1 -----------------------------------------
-- Read mem
- o_radl<=(o_hcpt - o_hmin + OHRES) MOD OHRES;
-
+ o_radl0<=r1_v;
+ o_radl1<=r1_v;
+ o_radl2<=r1_v;
+ o_radl3<=r1_v;
+
+ IF fracnn_v = '0' THEN
+ CASE o_vacptl IS
+ WHEN "10" => o_radl1<=r2_v;
+ WHEN "11" => o_radl2<=r2_v;
+ WHEN "00" => o_radl3<=r2_v;
+ WHEN OTHERS => o_radl0<=r2_v;
+ END CASE;
+ ELSE
+ CASE o_vacptl IS
+ WHEN "10" => o_radl2<=r2_v;
+ WHEN "11" => o_radl3<=r2_v;
+ WHEN "00" => o_radl0<=r2_v;
+ WHEN OTHERS => o_radl1<=r2_v;
+ END CASE;
+ END IF;
+
-- CYCLE 2 -----------------------------------------
-- Lines reordering
CASE o_vacptl IS
@@ -2497,37 +2725,47 @@ BEGIN
WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1);
WHEN OTHERS => pixq_v:=(o_ldr3,o_ldr0,o_ldr1,o_ldr2);
END CASE;
-
- o_vpixq<=pixq_v;
-
- -- Bottom edge : replicate last line
- IF to_integer(o_vacpt)=o_ivsize THEN
- o_vpixq(2)<=pixq_v(2);
+
+ IF fracnn_v = '0' THEN
+ o_vpix_outer<=(pixq_v(0), pixq_v(2), pixq_v(3));
+ o_vpix_inner(0)<=pixq_v(1);
+ ELSE
+ o_vpix_outer<=(pixq_v(0), pixq_v(1), pixq_v(3));
+ o_vpix_inner(0)<=pixq_v(2);
END IF;
- IF to_integer(o_vacpt)>=o_ivsize+1 THEN
- o_vpixq(2)<=pixq_v(1);
- o_vpixq(1)<=pixq_v(1);
+
+ -- CYCLE 3-7
+ o_vpix_inner(1 TO 5)<=o_vpix_inner(0 TO 4);
+
+ -- CYCLE 8
+ IF to_integer(o_vacpt)>o_ivsize THEN
+ IF fracnn_v = '0' THEN
+ o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_inner(5), o_vpix_inner(5));
+ ELSE
+ o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_outer(1), o_vpix_outer(1));
+ END IF;
+ ELSIF to_integer(o_vacpt)=o_ivsize THEN
+ IF fracnn_v = '0' THEN
+ o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(1));
+ ELSE
+ o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_inner(5));
+ END IF;
+ ELSE
+ IF fracnn_v = '0' THEN
+ o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(2));
+ ELSE
+ o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_outer(2));
+ END IF;
END IF;
-
- o_vpixq1<=o_vpixq;
-
- -- NEAREST -----------------------------------------
- -- C4
- o_v_near_frac<=near_frac(o_vfrac);
-
- -- C5
- o_v_near_t<=near_calc(o_v_near_frac,o_vpixq1);
-
- -- C6 : Nearest
- o_v_near_pix.r<=o_v_near_t.r(7+FRAC DOWNTO FRAC);
- o_v_near_pix.g<=o_v_near_t.g(7+FRAC DOWNTO FRAC);
- o_v_near_pix.b<=o_v_near_t.b(7+FRAC DOWNTO FRAC);
+
+ -- CYCLE 9
+ o_vpixq<=o_vpixq_pre;
-- BILINEAR / SHARP BILINEAR -----------------------
- -- C3 : Pre-calc Sharp Bilinear
+ -- C8 : Pre-calc Sharp Bilinear
o_v_sbil_t<=sbil_frac1(o_vfrac);
- -- C4 : Select
+ -- C9 : Select
o_v_bil_frac<=(OTHERS =>'0');
IF o_vmode(0)='1' THEN -- Bilinear
IF MASK(MASK_BILINEAR)='1' THEN
@@ -2538,56 +2776,56 @@ BEGIN
o_v_bil_frac<=sbil_frac2(o_vfrac,o_v_sbil_t);
END IF;
END IF;
+
+ -- C10 :
+ o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq);
- o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq1);
-
- -- C6 : Bilinear / Sharp Bilinear
+ -- C11 : Nearest / Bilinear / Sharp Bilinear
o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC);
o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC);
o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC);
-- BICUBIC -----------------------------------------
- -- C3 : Bicubic coefficients A,B,C,D
-
- -- C4 : Bicubic calc T1 = X.D + C
+ -- C9 : Bicubic coefficients A,B,C,D
+ -- C9 : Bicubic calc T1 = X.D + C
o_v_bic_abcd1<=bic_calc0(o_vfrac,o_vpixq);
o_v_bic_tt1<=bic_calc1(o_vfrac,bic_calc0(o_vfrac,o_vpixq));
- -- C5 : Bicubic calc T2 = X.T1 + B
+ -- C10 : Bicubic calc T2 = X.T1 + B
o_v_bic_abcd2<=o_v_bic_abcd1;
o_v_bic_tt2<=bic_calc2(o_vfrac,o_v_bic_tt1,o_v_bic_abcd1);
- -- C6 : Bicubic final Y = X.T2 + A
+ -- C11 : Bicubic final Y = X.T2 + A
o_v_bic_pix<=bic_calc3(o_vfrac,o_v_bic_tt2,o_v_bic_abcd2);
-- POLYPHASE ---------------------------------------
- -- C3 : Read memory
-
- -- C4 : Filter calc
- o_v_poly_dr2<=o_v_poly_dr;
-
- -- C5 : Add
- o_v_poly_t<=poly_calc1(o_v_poly_dr2,o_vpixq1);
-
- -- C6 : Bounding
- o_v_poly_pix<=poly_calc2(o_v_poly_t);
-
- -- CYCLE 6 -----------------------------------------
- o_hs<=o_hsv(5);
- o_vs<=o_vsv(5);
- o_de<=o_dev(5);
- o_vbl<=o_end(5);
+ -- C3 : Setup luminance
+ o_v_lum_pix<=o_vpix_inner(0);
+
+ -- C4-C9 in PolyFetch
+
+ -- C10 : Apply polyphase
+ o_v_poly_t<=poly_calc(o_v_poly_phase,o_vpixq);
+
+ -- C11 : Bound
+ o_v_poly_pix<=poly_final(o_v_poly_t);
+
+ -- CYCLE 12 -----------------------------------------
+ o_hs<=o_hsv(11);
+ o_vs<=o_vsv(11);
+ o_de<=o_dev(11);
+ o_vbl<=o_end(11);
o_r<=x"00";
o_g<=x"00";
o_b<=x"00";
- o_brd<= not o_pev(5);
+ o_brd<= not o_pev(11);
CASE o_vmode(2 DOWNTO 0) IS
WHEN "000" => -- Nearest
IF MASK(MASK_NEAREST)='1' THEN
- o_r<=o_v_near_pix.r;
- o_g<=o_v_near_pix.g;
- o_b<=o_v_near_pix.b;
+ o_r<=o_v_poly_pix.r;
+ o_g<=o_v_poly_pix.g;
+ o_b<=o_v_poly_pix.b;
END IF;
WHEN "001" | "010" => -- Bilinear | Sharp Bilinear
IF MASK(MASK_BILINEAR)='1' OR
@@ -2611,7 +2849,7 @@ BEGIN
END IF;
END CASE;
- IF o_pev(5)='0' THEN
+ IF o_pev(11)='0' THEN
o_r<=o_border(23 DOWNTO 16); -- Copy border colour
o_g<=o_border(15 DOWNTO 8);
o_b<=o_border(7 DOWNTO 0);
diff --git a/sys/scanlines.v b/sys/scanlines.v
index 59d29bd..43f890f 100644
--- a/sys/scanlines.v
+++ b/sys/scanlines.v
@@ -5,11 +5,11 @@ module scanlines #(parameter v2=0)
input [1:0] scanlines,
input [23:0] din,
input hs_in,vs_in,
- input de_in,
+ input de_in,ce_in,
output reg [23:0] dout,
output reg hs_out,vs_out,
- output reg de_out
+ output reg de_out,ce_out
);
reg [1:0] scanline;
@@ -56,12 +56,13 @@ end
always @(posedge clk) begin
reg [23:0] dout1, dout2;
- reg de1,de2,vs1,vs2,hs1,hs2;
+ reg de1,de2,vs1,vs2,hs1,hs2,ce1,ce2;
dout <= dout2; dout2 <= dout1; dout1 <= d;
vs_out <= vs2; vs2 <= vs1; vs1 <= vs_in;
hs_out <= hs2; hs2 <= hs1; hs1 <= hs_in;
de_out <= de2; de2 <= de1; de1 <= de_in;
+ ce_out <= ce2; ce2 <= ce1; ce1 <= ce_in;
end
endmodule
diff --git a/sys/sys_top.v b/sys/sys_top.v
index 5275d0b..635ae56 100644
--- a/sys/sys_top.v
+++ b/sys/sys_top.v
@@ -295,8 +295,8 @@ reg [31:0] cfg_custom_p2;
reg [4:0] vol_att;
initial vol_att = 5'b11111;
-reg [8:0] coef_addr;
-reg [8:0] coef_data;
+reg [11:0] coef_addr;
+reg [9:0] coef_data;
reg coef_wr = 0;
wire[12:0] ARX, ARY;
@@ -377,14 +377,14 @@ always@(posedge clk_sys) begin
cfg_set <= 0;
if(cnt<8) begin
case(cnt[2:0])
- 0: if(WIDTH != io_din[11:0]) WIDTH <= io_din[11:0];
- 1: if(HFP != io_din[11:0]) HFP <= io_din[11:0];
- 2: if(HS != io_din[11:0]) HS <= io_din[11:0];
- 3: if(HBP != io_din[11:0]) HBP <= io_din[11:0];
- 4: if(HEIGHT != io_din[11:0]) HEIGHT <= io_din[11:0];
- 5: if(VFP != io_din[11:0]) VFP <= io_din[11:0];
- 6: if(VS != io_din[11:0]) VS <= io_din[11:0];
- 7: if(VBP != io_din[11:0]) VBP <= io_din[11:0];
+ 0: WIDTH <= io_din[11:0];
+ 1: HFP <= io_din[11:0];
+ 2: HS <= {io_din[15], io_din[11:0]};
+ 3: HBP <= io_din[11:0];
+ 4: HEIGHT <= io_din[11:0];
+ 5: VFP <= io_din[11:0];
+ 6: VS <= {io_din[15],io_din[11:0]};
+ 7: VBP <= io_din[11:0];
endcase
`ifndef MISTER_DEBUG_NOHDMI
if(cnt == 1) begin
@@ -423,8 +423,8 @@ always@(posedge clk_sys) begin
if(cmd == 'h26) vol_att <= io_din[4:0];
if(cmd == 'h27) VSET <= io_din[11:0];
if(cmd == 'h2A) begin
- if(cnt[0]) {coef_wr,coef_data} <= {1'b1,io_din[8:0]};
- else coef_addr <= io_din[8:0];
+ if(cnt[0]) {coef_wr,coef_data} <= {1'b1,io_din[9:0]};
+ else coef_addr <= io_din[11:0];
end
if(cmd == 'h2B) scaler_flt <= io_din[2:0];
if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]};
@@ -641,7 +641,13 @@ ascal
.PALETTE2("false"),
`endif
`endif
- .FRAC(6),
+`ifdef MISTER_DISABLE_ADAPTIVE
+ .ADAPTIVE("false"),
+`endif
+`ifdef MISTER_DOWNSCALE_NN
+ .DOWNSCALE_NN("true"),
+`endif
+ .FRAC(8),
.N_DW(128),
.N_AW(28)
)
@@ -677,15 +683,15 @@ ascal
.o_vbl (hdmi_vbl),
.o_brd (hdmi_brd),
.o_lltune (lltune),
- .htotal (WIDTH + HFP + HBP + HS),
+ .htotal (WIDTH + HFP + HBP + HS[11:0]),
.hsstart (WIDTH + HFP),
- .hsend (WIDTH + HFP + HS),
+ .hsend (WIDTH + HFP + HS[11:0]),
.hdisp (WIDTH),
.hmin (hmin),
.hmax (hmax),
- .vtotal (HEIGHT + VFP + VBP + VS),
+ .vtotal (HEIGHT + VFP + VBP + VS[11:0]),
.vsstart (HEIGHT + VFP),
- .vsend (HEIGHT + VFP + VS),
+ .vsend (HEIGHT + VFP + VS[11:0]),
.vdisp (HEIGHT),
.vmin (vmin),
.vmax (vmax),
@@ -951,11 +957,11 @@ pll_hdmi pll_hdmi
//1920x1080@60 PCLK=148.5MHz CEA
reg [11:0] WIDTH = 1920;
reg [11:0] HFP = 88;
-reg [11:0] HS = 48;
+reg [12:0] HS = 48;
reg [11:0] HBP = 148;
reg [11:0] HEIGHT = 1080;
reg [11:0] VFP = 4;
-reg [11:0] VS = 5;
+reg [12:0] VS = 5;
reg [11:0] VBP = 36;
wire [63:0] reconfig_to_pll;
@@ -1208,13 +1214,21 @@ reg hdmi_out_de;
reg [23:0] hdmi_out_d;
always @(posedge hdmi_tx_clk) begin
+ reg [23:0] hdmi_dv_data;
+ reg hdmi_dv_hs, hdmi_dv_vs, hdmi_dv_de;
+
reg hs,vs,de;
reg [23:0] d;
- hs <= (~vga_fb & direct_video) ? dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd;
- vs <= (~vga_fb & direct_video) ? dv_vs : hdmi_vs_osd;
- de <= (~vga_fb & direct_video) ? dv_de : hdmi_de_osd;
- d <= (~vga_fb & direct_video) ? dv_data : hdmi_data_osd;
+ hdmi_dv_data <= dv_data;
+ hdmi_dv_hs <= dv_hs;
+ hdmi_dv_vs <= dv_vs;
+ hdmi_dv_de <= dv_de;
+
+ hs <= (~vga_fb & direct_video) ? hdmi_dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd;
+ vs <= (~vga_fb & direct_video) ? hdmi_dv_vs : hdmi_vs_osd;
+ de <= (~vga_fb & direct_video) ? hdmi_dv_de : hdmi_de_osd;
+ d <= (~vga_fb & direct_video) ? hdmi_dv_data : hdmi_data_osd;
hdmi_out_hs <= hs;
hdmi_out_vs <= vs;
@@ -1230,7 +1244,7 @@ assign HDMI_TX_D = hdmi_out_d;
///////////////////////// VGA output //////////////////////////////////
wire [23:0] vga_data_sl;
-wire vga_de_sl, vga_vs_sl, vga_hs_sl;
+wire vga_de_sl, vga_ce_sl, vga_vs_sl, vga_hs_sl;
scanlines #(0) VGA_scanlines
(
.clk(clk_vid),
@@ -1240,11 +1254,13 @@ scanlines #(0) VGA_scanlines
.hs_in(hs_fix),
.vs_in(vs_fix),
.de_in(de_emu),
+ .ce_in(ce_pix),
.dout(vga_data_sl),
.hs_out(vga_hs_sl),
.vs_out(vga_vs_sl),
- .de_out(vga_de_sl)
+ .de_out(vga_de_sl),
+ .ce_out(vga_ce_sl)
);
wire [23:0] vga_data_osd;
@@ -1307,11 +1323,11 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd);
wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs;
- assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ~vgas_vs : ~vga_vs) | csync_en;
- assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : (vga_fb | vga_scaler) ? (csync_en ? ~vgas_cs : ~vgas_hs) : (csync_en ? ~vga_cs : ~vga_hs);
- assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : vga_o[23:18];
- assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : vga_o[15:10];
- assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : vga_o[7:2] ;
+ assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ :((((vga_fb | vga_scaler) ? ~vgas_vs : ~vga_vs) | csync_en) ^ VS[12]);
+ assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (csync_en ? ~vgas_cs : ~vgas_hs) : (csync_en ? ~vga_cs : ~vga_hs)) ^ HS[12]);
+ assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : vga_o[23:18];
+ assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : vga_o[15:10];
+ assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : vga_o[7:2] ;
`endif
reg video_sync = 0;
@@ -1479,7 +1495,7 @@ sync_fix sync_h(clk_vid, hs_emu, hs_fix);
wire [6:0] user_out, user_in;
assign clk_ihdmi= clk_vid;
-assign ce_hpix = ce_pix;
+assign ce_hpix = vga_ce_sl;
assign hr_out = vga_data_sl[23:16];
assign hg_out = vga_data_sl[15:8];
assign hb_out = vga_data_sl[7:0];
@@ -1522,11 +1538,15 @@ wire [13:0] fb_stride;
assign fb_stride = 0;
`endif
+reg [1:0] sl_r;
+wire [1:0] sl = sl_r;
+always @(posedge clk_sys) sl_r <= FB_EN ? 2'b00 : scanlines;
+
emu emu
(
.CLK_50M(FPGA_CLK2_50),
.RESET(reset),
- .HPS_BUS({scanlines,f1, HDMI_TX_VS,
+ .HPS_BUS({fb_en, sl, f1, HDMI_TX_VS,
clk_100m, clk_ihdmi,
ce_hpix, hde_emu, hhs_fix, hvs_fix,
io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}),