* MDA and CGA/Tandy now work at the same time. It is possible to switch from one to the other from the OSD menu, as well as their monochrome simulation independently.
* Fixed problem with INT0 test failing
* Fixed a bug that caused the timer counter to be cleared on latch.
* PCXT DIP switches and access to MDA memory
* Add port_b[6] to lock PS/2 CLK.
* PS/2 CLK to drop LOW after receiving the key code.
This commit is contained in:
Aitor Gómez
2022-06-13 06:54:27 +02:00
parent 1f43db18bd
commit fc4fbed2cd
19 changed files with 1332 additions and 376 deletions

View File

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

24
PCXT.sv
View File

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

View File

@@ -5,7 +5,7 @@
(_()((_|(_|_)) (_(_())/((_|()\ (_)) )\_____((_)(_(_())
| \/ |(_) __||_ _(_)) ((_) | _ ((/ __\ \/ /|_ _|
| |\/| || \__ \ | | / -_)| '_| | _/| (__ > < | |
|_| |_||_|___/ |_| \___||_| |_| \___/_/\_\ |_| 07/06/2022
|_| |_||_|___/ |_| \___||_| |_| \___/_/\_\ |_| 13/06/2022
Port by @spark2k06, @naeloob

BIN
releases/PCXT_20220613.rbf Normal file

Binary file not shown.

View File

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

View File

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

View File

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

View File

@@ -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: <generic name="gui_dsm_out_sel" value="1st_order" />
// Retrieval info: <generic name="gui_use_locked" value="true" />
// Retrieval info: <generic name="gui_en_adv_params" value="false" />
// Retrieval info: <generic name="gui_number_of_clocks" value="4" />
// Retrieval info: <generic name="gui_number_of_clocks" value="5" />
// Retrieval info: <generic name="gui_multiply_factor" value="1" />
// Retrieval info: <generic name="gui_frac_multiply_factor" value="1" />
// Retrieval info: <generic name="gui_divide_factor_n" value="1" />
@@ -112,7 +114,7 @@ endmodule
// Retrieval info: <generic name="gui_actual_phase_shift3" value="0" />
// Retrieval info: <generic name="gui_duty_cycle3" value="50" />
// Retrieval info: <generic name="gui_cascade_counter4" value="false" />
// Retrieval info: <generic name="gui_output_clock_frequency4" value="4.776" />
// Retrieval info: <generic name="gui_output_clock_frequency4" value="56.875" />
// Retrieval info: <generic name="gui_divide_factor_c4" value="1" />
// Retrieval info: <generic name="gui_actual_output_clock_frequency4" value="0 MHz" />
// Retrieval info: <generic name="gui_ps_units4" value="ps" />

View File

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

1
rtl/video/mda.hex Normal file

File diff suppressed because one or more lines are too long

270
rtl/video/mda.v Normal file
View File

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

69
rtl/video/mda_attrib.v Normal file
View File

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

126
rtl/video/mda_pixel.v Normal file
View File

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

62
rtl/video/mda_sequencer.v Normal file
View File

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

50
rtl/video/mda_vgaport.v Normal file
View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

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

View File

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