Merge pull request #78 from MiSTer-devel/main

MiSTer-devel updates
This commit is contained in:
Aitor Gómez
2022-11-24 15:24:27 +01:00
committed by GitHub
160 changed files with 2152 additions and 415 deletions

129
PCXT.sdc
View File

@@ -3,47 +3,124 @@ derive_clock_uncertainty
# core specific constraints
# Clocks
set CLOCK_CORE {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk}
set CLOCK_CHIP {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[5].output_counter|divclk}
set CLOCK_UART {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[3].output_counter|divclk}
set CLOCK_14_318 {emu|clk_14_318|q}
set CLOCK_4_77 {emu|clk_normal|clk_out|q}
set PCLK {emu|peripheral_clock|q}
set CLOCK_CORE {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk}
set CLOCK_VGA_MDA {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[1].output_counter|divclk}
set CLOCK_VGA_CGA {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[2].output_counter|divclk}
set CLOCK_UART {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[3].output_counter|divclk}
set CLOCK_OPL {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[4].output_counter|divclk}
set CLOCK_CHIP {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[5].output_counter|divclk}
set CLOCK_VIDEO_MDA {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[6].output_counter|divclk}
set CLOCK_14_318 {emu|clk_14_318|q}
set CLOCK_4_77 {emu|clk_normal|clk_out|q}
set PCLK {emu|peripheral_clock|q}
create_generated_clock -name clk_14_318 -source [get_pins {emu|pll|pll_inst|altera_pll_i|cyclonev_pll|counter[1].output_counter|divclk}] -divide_by 2 [get_pins $CLOCK_14_318]
create_generated_clock -name clk_14_318 -source [get_pins $CLOCK_VGA_CGA] -divide_by 2 [get_pins $CLOCK_14_318]
create_generated_clock -name clk_4_77 -source [get_pins $CLOCK_14_318] -divide_by 3 -duty_cycle 33 [get_pins $CLOCK_4_77]
create_generated_clock -name peripheral_clock -source [get_pins $CLOCK_4_77] -divide_by 2 [get_pins $PCLK]
create_generated_clock -name SDRAM_CLK -source [get_pins $CLOCK_CHIP] [get_ports { SDRAM_CLK }]
set_false_path -to [get_registers {emu:emu|clk_cpu_ff_1 emu:emu|pclk_ff_1 emu:emu|clk_opl2_ff_1}]
# SPLASH
set_false_path -to [get_registers {emu:emu|splash_off}]
# status signal
set_false_path -from [get_registers {emu:emu|hps_io:hps_io|status[3] emu:emu|hps_io:hps_io|status[4] emu:emu|hps_io:hps_io|status[7]}]
# AUDIO
set_false_path -to [get_registers {emu:emu|clk_cpu_ff_1 emu:emu|pclk_ff_1 emu:emu|clk_opl2_ff_1}]
# UART
set_false_path -from [get_clocks $CLOCK_CHIP] -to [get_clocks $CLOCK_UART]
set_false_path -from [get_clocks $CLOCK_UART] -to [get_clocks $CLOCK_CHIP]
# VIDEO
set_max_delay -from [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_address[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_data[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_write_n \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_read_n \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_address_enable_n}] \
-to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_io_address_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_io_data_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_io_write_n_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_address_enable_n_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_address_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_data_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_write_n_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_read_n_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_address_enable_n_1}] 10
# NOTE: If the system clock and video clock are synchronous, the following description is not necessary.
set VIDEO_TO_SYSYEM_DELAY 10
set_false_path -to [get_registers {emu:emu|scale_video_ff[*] \
emu:emu|mda_mode_video_ff \
emu:emu|screen_mode_video_ff[*] \
emu:emu|border_video_ff \
emu:emu|VIDEO_ARX[*] \
emu:emu|VIDEO_ARY[*]}]
set_max_delay -from [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_address[*]}] \
-to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_io_address_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_address_1[*]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_data[*]}] \
-to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_io_data_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_data_1[*]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_write_n}] \
-to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_io_write_n_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_write_n_1}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_io_read_n}] \
-to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_io_read_n_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_io_read_n_1}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|video_address_enable_n}] \
-to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|mda_address_enable_n_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|cga_address_enable_n_1}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -to [get_registers {emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|MDA_CRTC_DOUT_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|MDA_CRTC_OE_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|MDA_CRTC_OE_1 \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|CGA_CRTC_DOUT_1[*] \
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|CGA_CRTC_OE_1}] 10
emu:emu|CHIPSET:u_CHIPSET|PERIPHERALS:u_PERIPHERALS|CGA_CRTC_OE_1}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {emu:emu|hps_io:hps_io|video_calc:video_calc|vid_hcnt[*] \
emu:emu|hps_io:hps_io|video_calc:video_calc|vid_nres[*] \
emu:emu|hps_io:hps_io|video_calc:video_calc|vid_vcnt[*]}] \
-to [get_registers {emu:emu|hps_io:hps_io|video_calc:video_calc|dout[*]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {emu:emu|mda_mode_video_ff}] \
-to [get_registers {emu:emu|hps_io:hps_io|io_dout[0]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {emu:emu|scale_video_ff[*]}] \
-to [get_registers {sl_r[*] \
emu:emu|video_mixer:video_mixer_mda|CE_PIXEL}] $VIDEO_TO_SYSYEM_DELAY
#
set_max_delay -from [get_registers {osd:vga_osd|info \
osd:vga_osd|infoh[*] \
osd:vga_osd|osd_h[*] \
osd:vga_osd|osd_w[*]}] \
-to [get_registers {osd:vga_osd|osd_de[*] \
osd:vga_osd|osd_hcnt2[*]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {osd:vga_osd|osd_enable}] \
-to [get_registers {osd:vga_osd|osd_en[*]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {lowlat}] \
-to [get_registers {ascal:ascal|i_mode[*]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {LFB_FLT}] \
-to [get_registers {ascal:ascal|i_mode[2]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {LFB_EN}] \
-to [get_registers {hmaxi[*] \
hmini[*] \
state[0] \
state[1] \
state[2] \
vmaxi[*] \
vmini[*]
ascal:ascal|i_mode[2]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {FREESCALE}] \
-to [get_registers {state[0] \
state[1] \
state[2]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {HDMI_PR}] \
-to [get_registers {videow[*]}] $VIDEO_TO_SYSYEM_DELAY
set_max_delay -from [get_registers {cfg_done}] \
-to [get_registers {pll_hdmi_adj:pll_hdmi_adj|i_delay[*] \
pll_hdmi_adj:pll_hdmi_adj|i_de2 \
pll_hdmi_adj:pll_hdmi_adj|i_line[*] \
pll_hdmi_adj:pll_hdmi_adj|i_linecpt[*] \
pll_hdmi_adj:pll_hdmi_adj|i_vss_delay \
pll_hdmi_adj:pll_hdmi_adj|i_vss2}] $VIDEO_TO_SYSYEM_DELAY
# SDRAM
set_input_delay -clock { SDRAM_CLK } -max 6 [get_ports { SDRAM_DQ[*] }]

307
PCXT.sv
View File

@@ -201,29 +201,23 @@ module emu
// 01234567890123456789012345678901 23456789012345678901234567890123
// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV
// XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX
wire [1:0] ar = status[9:8];
assign VIDEO_ARX = (!ar) ? 12'd4 : (ar - 1'd1);
assign VIDEO_ARY = (!ar) ? 12'd3 : 12'd0;
`include "build_id.v"
localparam CONF_STR = {
"PCXT;;",
"PCXT;UART115200:115200;",
"S0,IMGIMAVFD,Floppy A:;",
"S1,IMGIMAVFD,Floppy B:;",
"OJK,Write Protect,None,A:,B:,A: & B:;",
"-;",
"S2,IMG,HDD Image:;",
"S2,VHD,IDE 0-0;",
"S3,VHD,IDE 0-1;",
"-;",
"OHI,CPU Speed,4.77MHz,7.16MHz,14.318MHz;",
"OHI,CPU Speed,4.77MHz,7.16MHz,9.54MHz,PC/AT 3.5MHz;",
"-;",
"P1,System & BIOS;",
"P1-;",
"P1O3,Model,IBM PCXT,Tandy 1000;",
"P1-;",
"P1OLM,HDD COM Speed,115200,230400,460800,921600;",
"P1-;",
"P1O7,Boot Splash Screen,Yes,No;",
"P1-;",
"P1FC0,ROM,PCXT BIOS:;",
@@ -235,7 +229,9 @@ module emu
"P1-;",
"P2,Audio & Video;",
"P2-;",
"P2OA,Adlib,On,Invisible;",
//"P2OA,Adlib,On,Invisible;", // status[10] is available, remove this line when used
"P2OA,C/MS Audio,Enabled,Disabled;",
"P2oAB,OPL2,Adlib 388h,SB FM 388h/228h, Disabled;",
"P2o01,Speaker Volume,1,2,3,4;",
"P2o23,Tandy Volume,1,2,3,4;",
"P2o45,Audio Boost,No,2x,4x;",
@@ -262,7 +258,7 @@ module emu
"P3-;",
"-;",
"R0,Reset & apply settings;",
"J,Fire 1, Fire 2;",
"J,Fire 1,Fire 2;",
"V,v",`BUILD_DATE
};
@@ -303,9 +299,8 @@ module emu
reg ioctl_wait;
wire [21:0] gamma_bus;
wire adlibhide = status[10] | xtctl[4];
wire [31:0] joy0, joy1;
wire [13:0] joy0, joy1;
wire [15:0] joya0, joya1;
wire [4:0] joy_opts = status[27:23];
@@ -313,9 +308,26 @@ module emu
wire [1:0] scale = status[2:1];
wire mda_mode = status[4] | xtctl[5];
wire [2:0] screen_mode = status[16:14];
wire [1:0] ar = status[9:8];
wire border = status[29] | xtctl[1];
wire a000h = ~status[41] & ~xtctl[6];
reg [1:0] scale_video_ff;
reg mda_mode_video_ff;
reg [2:0] screen_mode_video_ff;
reg border_video_ff;
wire VGA_VBlank_border;
always @(posedge CLK_VIDEO)
begin
scale_video_ff <= scale;
mda_mode_video_ff <= mda_mode;
screen_mode_video_ff <= screen_mode;
border_video_ff <= border;
VIDEO_ARX <= (!ar) ? 12'd4 : (ar - 1'd1);
VIDEO_ARY <= (!ar) ? 12'd3 : 12'd0;
end
hps_io #(.CONF_STR(CONF_STR), .PS2DIV(2000), .PS2WE(1), .WIDE(1)) hps_io
(
@@ -373,7 +385,7 @@ module emu
wire mgmt_rd;
wire mgmt_wr;
wire [7:0] mgmt_req;
assign mgmt_req[5:0] = 6'b000000;
assign mgmt_req[5:3] = 3'b000;
wire [35:0] EXT_BUS;
hps_ext hps_ext
@@ -402,7 +414,9 @@ module emu
wire clk_28_636;
wire clk_56_875;
wire clk_113_750;
reg clk_25 = 1'b0;
reg clk_14_318 = 1'b0;
reg clk_9_54 = 1'b0;
reg clk_7_16 = 1'b0;
wire clk_4_77;
wire clk_cpu;
@@ -440,6 +454,23 @@ module emu
ce_pixel_cga <= clk_14_318; //if outside always block appears an overscan column in CGA mode
end
reg [4:0] clk_9_54_cnt = 1'b0;
always @(posedge clk_chipset)
if (4'd0 == clk_9_54_cnt) begin
if (clk_9_54)
clk_9_54_cnt <= 4'd3 - 4'd1;
else
clk_9_54_cnt <= 4'd2 - 4'd1;
clk_9_54 <= ~clk_9_54;
end
else begin
clk_9_54_cnt <= clk_9_54_cnt - 4'd1;
clk_9_54 <= clk_9_54;
end
always @(posedge clk_chipset)
clk_25 <= ~clk_25;
always @(posedge clk_14_318)
clk_7_16 <= ~clk_7_16; // 7.16Mhz
@@ -458,26 +489,26 @@ module emu
//////////////////////////////////////////////////////////////////
logic biu_done;
logic turbo_mode;
logic [7:0] clock_cycle_counter_division_ratio;
logic [7:0] clock_cycle_counter_decrement_value;
logic shift_read_timing;
logic [1:0] ram_read_wait_cycle;
logic [1:0] ram_write_wait_cycle;
logic cycle_accrate;
logic [1:0] clk_select;
always @(posedge clk_chipset, posedge reset)
begin
if (reset)
begin
turbo_mode <= 1'b0;
clk_select <= 2'b00;
end
else if (biu_done)
begin
turbo_mode <= xtctl[3:2] == 2'b00 ? (status[18:17] == 2'b01 || status[18:17] == 2'b10) : (xtctl[3:2] == 2'b10 || xtctl[3:2] == 2'b11);
clk_select <= xtctl[3:2] == 2'b00 ? status[18:17] : xtctl[3:2] - 2'b01;
end
clk_select <= (xtctl[3:2] == 2'b00 & ~xtctl[7]) ? status[18:17] : xtctl[7] ? 2'b11 : xtctl[3:2] - 2'b01;
else
begin
turbo_mode <= turbo_mode;
clk_select <= clk_select;
end
end
logic clk_cpu_ff_1;
@@ -490,21 +521,65 @@ module emu
begin
if (reset)
begin
clk_cpu_ff_1 <= 1'b0;
clk_cpu_ff_2 <= 1'b0;
clk_cpu <= 1'b0;
pclk_ff_1 <= 1'b0;
pclk_ff_2 <= 1'b0;
pclk <= 1'b0;
clk_cpu_ff_1 <= 1'b0;
clk_cpu_ff_2 <= 1'b0;
clk_cpu <= 1'b0;
pclk_ff_1 <= 1'b0;
pclk_ff_2 <= 1'b0;
pclk <= 1'b0;
cycle_accrate <= 1'b1;
clock_cycle_counter_division_ratio <= 8'd1 - 8'd1;
clock_cycle_counter_decrement_value <= 8'd1;
shift_read_timing <= 1'b0;
ram_read_wait_cycle <= 2'd0;
ram_write_wait_cycle <= 2'd0;
end
else
begin
clk_cpu_ff_1 <= (clk_select == 2'b10) ? clk_14_318 : (clk_select == 2'b01) ? clk_7_16 : clk_4_77;
clk_cpu_ff_2 <= clk_cpu_ff_1;
clk_cpu <= clk_cpu_ff_2;
pclk_ff_1 <= peripheral_clock;
pclk_ff_2 <= pclk_ff_1;
pclk <= pclk_ff_2;
clk_cpu_ff_2 <= clk_cpu_ff_1;
clk_cpu <= clk_cpu_ff_2;
pclk_ff_1 <= peripheral_clock;
pclk_ff_2 <= pclk_ff_1;
pclk <= pclk_ff_2;
casez (clk_select)
2'b00: begin
clk_cpu_ff_1 <= clk_4_77;
clock_cycle_counter_division_ratio <= 8'd1 - 8'd1;
clock_cycle_counter_decrement_value <= 8'd1;
shift_read_timing <= 1'b0;
ram_read_wait_cycle <= 2'd0;
ram_write_wait_cycle <= 2'd0;
cycle_accrate <= 1'b1;
end
2'b01: begin
clk_cpu_ff_1 <= clk_7_16;
clock_cycle_counter_division_ratio <= 8'd2 - 8'd1;
clock_cycle_counter_decrement_value <= 8'd3;
shift_read_timing <= 1'b0;
ram_read_wait_cycle <= 2'd0;
ram_write_wait_cycle <= 2'd0;
cycle_accrate <= 1'b1;
end
2'b10: begin
clk_cpu_ff_1 <= clk_9_54;
clock_cycle_counter_division_ratio <= 8'd10 - 8'd1;
clock_cycle_counter_decrement_value <= 8'd21;
shift_read_timing <= 1'b0;
ram_read_wait_cycle <= 2'd0;
ram_write_wait_cycle <= 2'd0;
cycle_accrate <= 1'b1;
end
2'b11: begin
clk_cpu_ff_1 <= clk_25;
clock_cycle_counter_division_ratio <= 8'd1 - 8'd1;
clock_cycle_counter_decrement_value <= 8'd5;
shift_read_timing <= 1'b1;
ram_read_wait_cycle <= 2'd1;
ram_write_wait_cycle <= 2'd0;
cycle_accrate <= 1'b0;
end
endcase
end
end
@@ -818,16 +893,18 @@ module emu
//
// Splash screen
//
reg splash_off;
reg [24:0] splash_cnt = 0;
reg [3:0] splash_cnt2 = 0;
reg splashscreen = 1;
always @ (posedge clk_14_318)
begin
splash_off <= status[7];
if (splashscreen)
begin
if (status[7])
if (splash_off)
splashscreen <= 0;
else if(splash_cnt2 == 5) // 5 seconds delay
splashscreen <= 0;
@@ -908,7 +985,7 @@ module emu
wire tandy_bios_flag = bios_write_n ? tandy_mode : tandy_bios_write;
always @(posedge clk_100)
always @(posedge clk_chipset)
begin
if (address_latch_enable)
cpu_address <= cpu_ad_out;
@@ -922,7 +999,7 @@ module emu
.cpu_clock (clk_cpu),
.clk_sys (clk_chipset),
.peripheral_clock (pclk),
.turbo_mode (xtctl[3:2] == 2'b00 ? status[18:17] : xtctl[3:2] - 2'b01),
.clk_select (clk_select),
.reset (reset_cpu),
.sdram_reset (reset_sdram),
.cpu_address (cpu_address),
@@ -934,7 +1011,7 @@ module emu
.interrupt_to_cpu (interrupt_to_cpu),
.splashscreen (splashscreen),
.composite (composite),
.video_output (mda_mode),
.video_output (mda_mode_video_ff),
.clk_vga_cga (clk_28_636),
.enable_cga (1'b1),
.clk_vga_mda (clk_56_875),
@@ -946,8 +1023,9 @@ module emu
.VGA_B (b),
.VGA_HSYNC (HSync),
.VGA_VSYNC (VSync),
.VGA_HBlank (HBlank),
.VGA_VBlank (VBlank),
.VGA_HBlank (HBlank),
.VGA_VBlank (VBlank),
.VGA_VBlank_border (VGA_VBlank_border),
// .address (address),
.address_ext (bios_access_address),
.ext_access_request (bios_access_request),
@@ -977,6 +1055,7 @@ module emu
// .terminal_count_n (terminal_count_n)
.port_b_out (port_b_out),
.port_c_in (port_c_in),
.port_b_in (port_b_out),
.speaker_out (speaker_out),
.ps2_clock (device_clock),
.ps2_data (device_data),
@@ -994,19 +1073,22 @@ module emu
.clk_en_opl2 (cen_opl2), // clk_en_opl2
.jtopl2_snd_e (jtopl2_snd_e),
.tandy_snd_e (tandy_snd_e),
.adlibhide (adlibhide),
.opl2_io (xtctl[4] ? 2'b10 : status[43:42]),
.cms_en (~status[10]),
.o_cms_l (cms_l_snd_e),
.o_cms_r (cms_r_snd_e),
.tandy_video (tandy_mode),
.tandy_bios_flag (tandy_bios_flag),
.tandy_16_gfx (tandy_16_gfx),
.clk_uart ((status[22:21] == 2'b00) ? clk_uart : clk_uart_en),
.clk_uart2 (clk_uart2_en),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts_n (uart_cts),
.uart_dcd_n (uart_dcd),
.uart_dsr_n (uart_dsr),
.uart_rts_n (uart_rts),
.uart_dtr_n (uart_dtr),
.tandy_color_16 (tandy_color_16),
.clk_uart (clk_uart2_en),
.uart2_rx (uart_rx),
.uart2_tx (uart_tx),
.uart2_cts_n (uart_cts),
.uart2_dcd_n (uart_dcd),
.uart2_dsr_n (uart_dsr),
.uart2_rts_n (uart_rts),
.uart2_dtr_n (uart_dtr),
.enable_sdram (1'b1),
.initilized_sdram (initilized_sdram),
.sdram_clock (SDRAM_CLK),
@@ -1033,8 +1115,12 @@ module emu
.clock_rate (cur_rate),
.floppy_wp (status[20:19]),
.fdd_request (mgmt_req[7:6]),
.ide0_request (mgmt_req[2:0]),
.xtctl (xtctl),
.enable_a000h (a000h)
.enable_a000h (a000h),
.wait_count_clk_en (~clk_cpu & clk_cpu_ff_2),
.ram_read_wait_cycle (ram_read_wait_cycle),
.ram_write_wait_cycle (ram_write_wait_cycle)
);
wire [15:0] SDRAM_DQ_IN;
@@ -1068,13 +1154,21 @@ module emu
.SEGMENT(SEGMENT),
.biu_done(biu_done),
.turbo_mode(turbo_mode)
.cycle_accrate(cycle_accrate),
.clock_cycle_counter_division_ratio(clock_cycle_counter_division_ratio),
.clock_cycle_counter_decrement_value(clock_cycle_counter_decrement_value),
.shift_read_timing(shift_read_timing)
);
//
//////////////////////////// AUDIO ///////////////////////////////////
//
wire [15:0] cms_l_snd_e;
wire [16:0] cms_l_snd;
wire [15:0] cms_r_snd_e;
wire [16:0] cms_r_snd;
wire [15:0] jtopl2_snd_e;
wire [16:0] jtopl2_snd;
wire [10:0] tandy_snd_e;
@@ -1085,8 +1179,25 @@ module emu
always @(posedge CLK_AUDIO)
begin
reg [15:0] oldj_0, oldj_1;
reg [15:0] oldcl_0, oldcl_1;
reg [15:0] oldcr_0, oldcr_1;
reg [10:0] oldt_0, oldt_1;
oldj_0 <= jtopl2_snd_e;
oldj_1 <= oldj_0;
if(oldj_0 == oldj_1)
jtopl2_snd <= {oldj_1[15],oldj_1};
oldcl_0 <= cms_l_snd_e;
oldcl_1 <= oldcl_0;
if(oldcl_0 == oldcl_1)
cms_l_snd <= {oldcl_1[15],oldcl_1};
oldcr_0 <= cms_r_snd_e;
oldcr_1 <= oldcr_0;
if(oldcr_0 == oldcr_1)
cms_r_snd <= {oldcr_1[15],oldcr_1};
oldj_0 <= jtopl2_snd_e;
oldj_1 <= oldj_0;
if(oldj_0 == oldj_1)
@@ -1122,22 +1233,36 @@ module emu
end
endfunction
reg [15:0] cmp;
reg [15:0] out;
reg [15:0] cmp_l;
reg [15:0] out_l;
always @(posedge CLK_AUDIO)
begin
reg [16:0] tmp;
reg [16:0] tmp_l;
tmp <= jtopl2_snd + tandy_snd + spk_vol;
tmp_l <= jtopl2_snd + cms_l_snd + tandy_snd + spk_vol;
// clamp the output
out <= (^tmp[16:15]) ? {tmp[16], {15{tmp[15]}}} : tmp[15:0];
out_l <= (^tmp_l[16:15]) ? {tmp_l[16], {15{tmp_l[15]}}} : tmp_l[15:0];
cmp <= compr(out);
cmp_l <= compr(out_l);
end
reg [15:0] cmp_r;
reg [15:0] out_r;
always @(posedge CLK_AUDIO)
begin
reg [16:0] tmp_r;
tmp_r <= jtopl2_snd + cms_r_snd + tandy_snd + spk_vol;
// clamp the output
out_r <= (^tmp_r[16:15]) ? {tmp_r[16], {15{tmp_r[15]}}} : tmp_r[15:0];
cmp_r <= compr(out_r);
end
assign AUDIO_L = status[37:36] ? cmp : out;
assign AUDIO_R = status[37:36] ? cmp : out;
assign AUDIO_L = status[37:36] ? cmp_l : out_l;
assign AUDIO_R = status[37:36] ? cmp_r : out_r;
assign AUDIO_S = 1;
assign AUDIO_MIX = status[39:38];
@@ -1271,19 +1396,35 @@ module emu
assign CLK_VIDEO_CGA = clk_56_875;
assign ce_pixel_mda = clk_28_636;
assign VGA_SL = {scale==3, scale==2};
assign VGA_SL = {scale_video_ff==3, scale_video_ff==2};
wire scandoubler = (scale>0); //|| forced_scandoubler);
wire scandoubler = (scale_video_ff>0); //|| forced_scandoubler);
reg [14:0] HBlank_del;
wire tandy_16_gfx;
wire color = (screen_mode == 3'd0);
wire HBlank_VGA = mda_mode ? HBlank_del[color ? 12 : 13] : tandy_16_gfx ? HBlank_del[color ? 9 : 11] : HBlank_del[color ? 5 : 7];
wire color = (screen_mode_video_ff == 3'd0);
wire HBlank_VGA;
reg [10:0] HBlank_counter = 0;
reg HBlank_fixed = 1'b1;
reg [1:0] HSync_del = 1'b11;
always_comb
begin
if (mda_mode_video_ff)
HBlank_VGA = HBlank_del[color ? 12 : 13];
else if (tandy_color_16)
HBlank_VGA = HBlank_del[color ? 11 : 13];
else if (tandy_16_gfx)
HBlank_VGA = HBlank_del[color ? 9 : 11];
else HBlank_VGA = HBlank_del[color ? 5 : 7];
end
always @ (posedge ce_pixel_cga)
begin
@@ -1296,7 +1437,7 @@ module emu
end
else
begin
if (HBlank_counter == 143)
if (HBlank_counter == 120)
HBlank_fixed <= 1'b0;
else
HBlank_counter <= HBlank_counter + 1;
@@ -1313,7 +1454,7 @@ module emu
.G({g, 2'b00}),
.B({b, 2'b00}),
.gfx_mode(screen_mode),
.gfx_mode(screen_mode_video_ff),
.R_OUT(raux_cga),
.G_OUT(gaux_cga),
@@ -1329,7 +1470,7 @@ module emu
.G({g, 2'b00}),
.B({b, 2'b00}),
.gfx_mode(screen_mode),
.gfx_mode(screen_mode_video_ff),
.R_OUT(raux_mda),
.G_OUT(gaux_mda),
@@ -1361,13 +1502,13 @@ module emu
.G(gaux_cga),
.B(baux_cga),
.HBlank(border ? HBlank_fixed : HBlank_VGA),
.VBlank(border ? ~VSync : VBlank),
.HBlank(border_video_ff ? HBlank_fixed : HBlank_VGA),
.VBlank(border_video_ff ? VGA_VBlank_border : VBlank),
.HSync(HSync),
.VSync(VSync),
.scandoubler(scandoubler),
.hq2x(scale==1),
.hq2x(scale_video_ff==1),
.gamma_bus(gamma_bus_cga),
.VGA_R(VGA_R_cga),
@@ -1399,7 +1540,7 @@ module emu
.VSync(VSync),
.scandoubler(scandoubler),
.hq2x(scale==1),
.hq2x(scale_video_ff==1),
.gamma_bus(gamma_bus_mda),
.VGA_R(VGA_R_mda),
@@ -1412,14 +1553,14 @@ module emu
);
assign VGA_R = mda_mode ? VGA_R_mda : VGA_R_cga;
assign VGA_G = mda_mode ? VGA_G_mda : VGA_G_cga;
assign VGA_B = mda_mode ? VGA_B_mda : VGA_B_cga;
assign VGA_HS = mda_mode ? VGA_HS_mda : VGA_HS_cga;
assign VGA_VS = mda_mode ? VGA_VS_mda : VGA_VS_cga;
assign VGA_DE = mda_mode ? VGA_DE_mda : VGA_DE_cga;
assign gamma_bus = mda_mode ? gamma_bus_mda : gamma_bus_cga;
assign CE_PIXEL = mda_mode ? CE_PIXEL_mda : CE_PIXEL_cga;
assign VGA_R = mda_mode_video_ff ? VGA_R_mda : VGA_R_cga;
assign VGA_G = mda_mode_video_ff ? VGA_G_mda : VGA_G_cga;
assign VGA_B = mda_mode_video_ff ? VGA_B_mda : VGA_B_cga;
assign VGA_HS = mda_mode_video_ff ? VGA_HS_mda : VGA_HS_cga;
assign VGA_VS = mda_mode_video_ff ? VGA_VS_mda : VGA_VS_cga;
assign VGA_DE = mda_mode_video_ff ? VGA_DE_mda : VGA_DE_cga;
assign gamma_bus = mda_mode_video_ff ? gamma_bus_mda : gamma_bus_cga;
assign CE_PIXEL = mda_mode_video_ff ? CE_PIXEL_mda : CE_PIXEL_cga;

View File

@@ -2,9 +2,9 @@
PCXT port for MiSTer by [@spark2k06](https://github.com/spark2k06/).
Discussion and evolution of the core in the following misterfpga forum thread:
Discussion and evolution of the core in the following misterfpga forum section:
https://misterfpga.org/viewtopic.php?t=4680&start=1020
https://misterfpga.org/viewforum.php?f=40
## Description
@@ -18,17 +18,18 @@ The [Graphics Gremlin project](https://github.com/schlae/graphics-gremlin) from
## Key features
* CPU Speed 4.77 MHz and turbo modes 7.16 MHz / 14.318 MHz
* 8088 CPU with these speed settings: 4.77 MHz, 7.16 MHz, 9.54 MHz cycle accurate, and PC/AT 286 at 3.5MHz equivalent (max. speed)
* BIOS selectable (Tandy 1000 / PCXT)
* Support for IBM Tandy 1000
* Support for IBM PCXT 5160 and clones (CGA graphics)
* Main memory 640Kb + 384Kb UMB memory
* Simultaneous video MDA
* EMS memory up to 2Mb
* Tandy 320x200x16 graphics with 128Kb of shared RAM + CGA graphics
* XTIDE support
* Tandy graphics with 128Kb of shared RAM + CGA graphics
* Audio: Adlib, Tandy, speaker
* Joystick support
* Mouse support into COM2 serial port, this works like any Microsoft mouse... you just need a driver to configure it, like CTMOUSE 1.9 (available into hdd folder), with the command CTMOUSE /s2
* Mouse support into COM1 serial port, this works like any Microsoft mouse... you just need a driver to configure it, like CTMOUSE 1.9 (available into hdd folder)
## Quick Start
@@ -36,9 +37,8 @@ The [Graphics Gremlin project](https://github.com/schlae/graphics-gremlin) from
* Select the core from Computers/PCXT.
* Press WinKey + F12 on your keyboard.
* Model: IBM PCXT.
* CPU Speed: 14.318MHz.
* CPU Speed: PC/AT 3.5MHz (Max speed)
* FDD & HDD -> HDD Image: FreeDOS_HD.img
* FDD & HDD -> Speed: 921600. NOTE: This speed can only be selected if CPU speed is 14.318 MHz.
* BIOS -> PCXT BIOS: pcxt_micro8088.rom
* Choose Reset & apply model.
@@ -58,7 +58,7 @@ Other Open Source ROMs are available in the same folder:
* `pcxt_micro8088.rom`: This ROM already has the XTIDE BIOS embedded at address F000h. ([Source Code](https://github.com/skiselev/8088_bios))
* `ide_xtl.rom`: This ROM corresponds to the XTIDE BIOS, it must be maintained for some scripts to work, it can also be upgraded to a newer version. ([Source Code](https://www.xtideuniversalbios.org/))
Note: Not all ROMs work with MDA video: (IBM5160, Yuko ST and pcxt31 works), (Tandy, micro8088, full XTIDE BIOS do not work).
Note: Not all ROMs work with MDA video: (IBM5160, Yuko ST and pcxt31 works)
## Other BIOSes
@@ -74,23 +74,6 @@ The floppy disk image size must be compatible with the BIOS, for example:
It is possible to use images smaller than the size supported by the BIOS, but only pre-formatted images, as it will not be possible to format them from MS-Dos.
## Mounting the HDD image
Initially, and until an 8-bit IDE module compatible with XTIDE is available, HDD mounting will be done through the serial port available in the core via the OSD menu. The available transfer speeds are as follows:
* 115200 Kbps
* 230400 Kbps
* 460800 Kbps
* 921600 Kbps (Only works with CPU speed at 14.318MHz)
By default it is set to 115200, but the most suitable speed is 460800. It is also possible to use 921600, but only with the CPU speed at 14.318MHz.
The serial port speed change becomes effective after a BIOS reset, it is not possible to use the HDD drive after a speed change, the BIOS must always be reset after that.
## To-do list and challenges
* 8-bit IDE module implementation
## Developers
Any contribution and pull request, please carry it out on the prerelease branch. Periodically they will be reviewed, moved and merged into the main branch, together with the corresponding release.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -7,6 +7,7 @@
#define ADLIBOFF 0x10
#define MDA 0x20
#define A000HOFF 0x40
#define AT4MHZ 0x80
static int _argc;
static char **_argv;
@@ -28,14 +29,14 @@ int main(int argc, char **argv)
if(argc < 2)
{
printf("XTCTL 1.1\n");
printf("XTCTL 1.2\n");
printf("USAGE:\n");
bs = strrchr(argv[0], '\\');
if(bs == NULL)
argv0 = argv[0];
else
argv0 = ++bs;
printf("%s [menu] [composite border adliboff mda a000hoff 4Mhz/7Mhz/14Mhz]\n", argv0);
printf("%s [menu] [composite border adliboff mda a000hoff 5Mhz/8Mhz/10Mhz/AT4MHz]\n", argv0);
return -1;
}
@@ -61,21 +62,27 @@ int main(int argc, char **argv)
if (chk_arg_opt("a000hoff"))
arg |= A000HOFF;
if (chk_arg_opt("4Mhz") || chk_arg_opt("4"))
if (chk_arg_opt("5Mhz") || chk_arg_opt("5"))
{
arg |= 1 << 2;
arg &= ~(1 << 3);
}
else if (chk_arg_opt("7Mhz") || chk_arg_opt("7"))
else if (chk_arg_opt("8Mhz") || chk_arg_opt("8"))
{
arg &= ~(1 << 2);
arg |= 1 << 3;
}
else if (chk_arg_opt("14Mhz") || chk_arg_opt("14"))
else if (chk_arg_opt("10Mhz") || chk_arg_opt("10"))
{
arg |= 1 << 2;
arg |= 1 << 3;
}
else if (chk_arg_opt("AT4Mhz") || chk_arg_opt("AT4"))
{
arg &= ~(1 << 2);
arg &= ~(1 << 3);
arg |= AT4MHZ;
}
}
outp(0x8888, arg);

View File

@@ -5,7 +5,7 @@
(_()((_|(_|_)) (_(_())/((_|()\ (_)) )\_____((_)(_(_())
| \/ |(_) __||_ _(_)) ((_) | _ ((/ __\ \/ /|_ _|
| |\/| || \__ \ | | / -_)| '_| | _/| (__ > < | |
|_| |_||_|___/ |_| \___||_| |_| \___/_/\_\ |_| 06/11/2022
|_| |_||_|___/ |_| \___||_| |_| \___/_/\_\ |_| 24/11/2022
Port by @spark2k06
@@ -15,9 +15,9 @@
Contributors & Special Thanks
-----------------------------
@naeloob - @somhi - @Mills - @TheSonders - @JasonA - @gyurco
@Newsdee - @birdybro - @Flandango - @pgimeno - @jordi
naeloob - somhi - Mills - TheSonders - JasonA - gyurco
Newsdee - birdybro - Flandango - pgimeno - Jordi
@Adr1048 - TonyEscobar
Adr1048 - Kathleen - TonyEscobar - Jordi

View File

@@ -4,8 +4,9 @@ set_global_assignment -name QIP_FILE rtl/pll.qip
set_global_assignment -name QIP_FILE rtl/common/common.qip
set_global_assignment -name QIP_FILE rtl/video/video.qip
set_global_assignment -name QIP_FILE rtl/uart/uart.qip
set_global_assignment -name QIP_FILE rtl/jt89/hdl/jt89.qip
set_global_assignment -name QIP_FILE rtl/jtopl/hdl/jtopl2.qip
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/sound/saa1099.sv"
set_global_assignment -name QIP_FILE rtl/sound/jt89/hdl/jt89.qip
set_global_assignment -name QIP_FILE rtl/sound/jtopl/hdl/jtopl2.qip
set_global_assignment -name QIP_FILE rtl/8088/8088.qip
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/KFSDRAM/HDL/KFSDRAM.sv"
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/KFPS2KB/HDL/KFPS2KB_Shift_Register.sv"
@@ -34,6 +35,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/KF8237/HDL/KF823
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/KF8237/HDL/KF8237.sv"
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/Ready.sv"
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/RAM.sv"
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/XT2IDE.sv"
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/Peripherals.sv"
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/Chipset.sv"
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/KFPC-XT/HDL/Bus_Arbiter.sv"

Binary file not shown.

BIN
releases/PCXT_20221124.rbf Normal file

Binary file not shown.

View File

@@ -88,7 +88,10 @@ module biu_max
output [15:0] BIU_REGISTER_REG,
output [15:0] BIU_RETURN_DATA,
input turbo_mode
// Turbo mode
input [7:0] clock_cycle_counter_division_ratio,
input [7:0] clock_cycle_counter_decrement_value,
input shift_read_timing
);
@@ -149,6 +152,7 @@ reg [15:0] biu_return_data_int;
reg [15:0] biu_return_data_int_d1;
reg [15:0] biu_return_data_int_d2;
reg [12:0] clock_cycle_counter;
reg [7:0] clock_cycle_counter_div;
reg [15:0] eu_register_r3_d;
reg [7:0] latched_data_in;
reg [15:0] pfq_addr_out;
@@ -418,11 +422,21 @@ else
// Strobe from EU to set the 8088 clock cycle counter
if (eu_biu_strobe==2'b10)
begin
clock_cycle_counter_div <= clock_cycle_counter_division_ratio;
clock_cycle_counter <= EU_BIU_DATAOUT[12:0];
end
else if (clock_cycle_counter!=13'h0000)
else if (8'h00 != clock_cycle_counter_div)
begin
clock_cycle_counter <= clock_cycle_counter - 1;
clock_cycle_counter_div <= clock_cycle_counter_div - 1;
end
else
begin
clock_cycle_counter_div <= clock_cycle_counter_division_ratio;
if (clock_cycle_counter != 13'h0000)
if (clock_cycle_counter > clock_cycle_counter_decrement_value)
clock_cycle_counter <= clock_cycle_counter - clock_cycle_counter_decrement_value;
else
clock_cycle_counter <= 0;
end
@@ -711,7 +725,7 @@ else
// On the next CLK edge, sample the data.
8'h06 : begin
if ((~turbo_mode & clk_posedge) || (turbo_mode & clk_negedge))
if ((~shift_read_timing & clk_posedge) || (shift_read_timing & clk_negedge))
begin
latched_data_in <= ad_in_int;
@@ -750,7 +764,7 @@ else
// The cycle is complete.
8'h0A : begin
if (turbo_mode | clk_negedge)
if (shift_read_timing | clk_negedge)
begin
addr_out_temp_offset[15:0] <= addr_out_temp_offset[15:0] + 1;
if (word_cycle==1'b1 && byte_num==1'b0)

View File

@@ -20,7 +20,10 @@ module i8088
output [2:0] SEGMENT,
output biu_done,
input turbo_mode
input cycle_accrate,
input [7:0] clock_cycle_counter_division_ratio,
input [7:0] clock_cycle_counter_decrement_value,
input shift_read_timing
);
@@ -90,7 +93,10 @@ biu_max BIU_CORE
.BIU_REGISTER_RM (t_biu_register_rm),
.BIU_REGISTER_REG (t_biu_register_reg),
.BIU_RETURN_DATA (t_biu_return_data),
.turbo_mode (turbo_mode)
.clock_cycle_counter_division_ratio (clock_cycle_counter_division_ratio),
.clock_cycle_counter_decrement_value (clock_cycle_counter_decrement_value),
.shift_read_timing (shift_read_timing)
);
//------------------------------------------------------------------------
@@ -101,14 +107,14 @@ mcl86_eu_core EU_CORE
(
.CORE_CLK_INT (CORE_CLK),
.RESET_INT (RESET),
.TEST_N_INT (1'b1),
.TEST_N_INT (1'b0),
.EU_BIU_COMMAND (t_eu_biu_command),
.EU_BIU_DATAOUT (t_eu_biu_dataout),
.EU_REGISTER_R3 (t_eu_register_r3),
.EU_PREFIX_LOCK (t_eu_prefix_lock),
.EU_FLAG_I (t_eu_flag_i),
.BIU_DONE (t_biu_done),
.BIU_CLK_COUNTER_ZERO (~turbo_mode ? t_biu_clk_counter_zero : 1'b1),
.BIU_CLK_COUNTER_ZERO (cycle_accrate ? t_biu_clk_counter_zero : 1'b1),
.BIU_NMI_CAUGHT (t_biu_nmi_caught),
.BIU_NMI_DEBOUNCE (t_biu_nmi_debounce),
.BIU_INTR (t_biu_intr),

View File

@@ -19,6 +19,9 @@
// Revision 1.0 10/8/15
// Initial revision
//
// Revision 2.0 11/6/22
// Changed overflow flag calculation into rtl instead of microcode
//
//
//------------------------------------------------------------------------
//
@@ -99,10 +102,13 @@ reg eu_tr_latched;
reg biu_done_caught;
reg eu_biu_req_d1;
reg intr_enable_delayed;
reg eu_overflow_override;
reg eu_add_overflow8_fixed;
reg eu_add_overflow16_fixed;
wire eu_prefix_rep;
wire eu_prefix_repnz;
wire eu_tf_debounce;
wire eu_prefix_lock ;
wire eu_prefix_lock;
wire eu_biu_req;
wire eu_parity;
wire eu_flag_o;
@@ -155,15 +161,12 @@ wire [15:0] eu_alu_out;
wire [15:0] eu_operand0;
wire [15:0] eu_operand1;
wire [31:0] eu_rom_data;
wire [15:0] add_total;
wire [15:0] sub_total;
wire [15:0] adc_total;
wire [15:0] sbb_total;
reg eu_overflow_fix;
reg eu_add_overflow8_fixed;
reg eu_add_overflow16_fixed;
//------------------------------------------------------------------------
@@ -336,11 +339,13 @@ assign intr_asserted = BIU_INTR & intr_enable_delayed;
assign new_instruction = (eu_rom_address[12:8]==5'h01) ? 1'b1 : 1'b0;
assign add_total = eu_register_r0 + eu_register_r1;
assign adc_total = eu_register_r0 + eu_register_r1 + eu_flag_c;
assign sub_total = eu_register_r0 - eu_register_r1;
assign sbb_total = eu_register_r0 - eu_register_r1 - eu_flag_c;
//------------------------------------------------------------------------------------------
//
// EU Microsequencer
@@ -424,143 +429,147 @@ else
biu_done_caught <= 1'b0;
// ADD - Byte
//
if (eu_rom_address == 16'h09C9)
begin
eu_overflow_fix <= 1'b1;
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b0) && (add_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b1) && (add_total[7]==1'b0) ) )
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
// ADD - Byte
//
if (eu_rom_address == 16'h09C9)
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b0) && (add_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b1) && (add_total[7]==1'b0) ) )
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
// ADC - Byte
//
if (eu_rom_address == 16'h0A03)
begin
eu_overflow_fix <= 1'b1;
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b0) && (adc_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b1) && (adc_total[7]==1'b0) ) )
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
// ADC - Byte
//
if (eu_rom_address == 16'h0A03)
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b0) && (adc_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b1) && (adc_total[7]==1'b0) ) )
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
// SUB - Byte
//
if (eu_rom_address == 16'h0A46)
begin
eu_overflow_fix <= 1'b1;
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b1) && (sub_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b0) && (sub_total[7]==1'b0) ) )
// SUB - Byte
//
if (eu_rom_address == 16'h0A46)
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
// SBB - Byte
//
if (eu_rom_address == 16'h0AAE)
begin
eu_overflow_fix <= 1'b1;
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b1) && (sbb_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b0) && (sbb_total[7]==1'b0) ) )
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
// ADD - Word
//
if (eu_rom_address == 16'h09CC)
begin
eu_overflow_fix <= 1'b1;
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b0) && (add_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b1) && (add_total[15]==1'b0) ) )
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b1) && (sub_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b0) && (sub_total[7]==1'b0) ) )
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
// ADC - Word
//
if (eu_rom_address == 16'h0A12)
begin
eu_overflow_fix <= 1'b1;
// SBB - Byte
//
if (eu_rom_address == 16'h0AAE)
begin
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b0) && (adc_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b1) && (adc_total[15]==1'b0) ) )
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b1) && (sbb_total[7]==1'b1) ) ||
( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b0) && (sbb_total[7]==1'b0) ) )
begin
eu_add_overflow8_fixed <= 1'b1;
end
else
begin
eu_add_overflow8_fixed <= 1'b0;
end
end
// SUB - Word
//
if (eu_rom_address == 16'h0A52)
begin
eu_overflow_fix <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b1) && (sub_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b0) && (sub_total[15]==1'b0) ) )
// ADD - Word
//
if (eu_rom_address == 16'h09CC)
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b0) && (add_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b1) && (add_total[15]==1'b0) ) )
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
// SBB - Word
//
if (eu_rom_address == 16'h0ABA)
begin
eu_overflow_fix <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b1) && (sbb_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b0) && (sbb_total[15]==1'b0) ) )
// ADC - Word
//
if (eu_rom_address == 16'h0A12)
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b0) && (adc_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b1) && (adc_total[15]==1'b0) ) )
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
// SUB - Word
//
if (eu_rom_address == 16'h0A52)
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b1) && (sub_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b0) && (sub_total[15]==1'b0) ) )
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
// SBB - Word
//
if (eu_rom_address == 16'h0ABA)
begin
eu_overflow_override <= 1'b1;
if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b1) && (sbb_total[15]==1'b1) ) ||
( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b0) && (sbb_total[15]==1'b0) ) )
begin
eu_add_overflow16_fixed <= 1'b1;
end
else
begin
eu_add_overflow16_fixed <= 1'b0;
end
end
// Debounce the overflow flag override when microcode returns to the main loop
//
if (eu_rom_address == 16'h0011) eu_overflow_override <= 1'b0;
if (eu_rom_address == 16'h0011) eu_overflow_fix <= 1'b0;
// Generate and store flags for addition
@@ -569,8 +578,8 @@ if (eu_rom_address == 16'h0011) eu_overflow_fix <= 1'b0;
eu_add_carry <= carry[16];
eu_add_carry8 <= carry[8];
eu_add_aux_carry <= carry[4];
eu_add_overflow16 <= (eu_overflow_fix==1'b1) ? eu_add_overflow16_fixed : (carry[16] ^ carry[15]);
eu_add_overflow8 <= (eu_overflow_fix==1'b1) ? eu_add_overflow8_fixed : (carry[8] ^ carry[7]);
eu_add_overflow16 <= (eu_overflow_override==1'b1) ? eu_add_overflow16_fixed : (carry[16] ^ carry[15]);
eu_add_overflow8 <= (eu_overflow_override==1'b1) ? eu_add_overflow8_fixed : (carry[8] ^ carry[7] );
end
@@ -639,4 +648,4 @@ end // EU Microsequencer
endmodule // eu.v
endmodule // eu.v

View File

@@ -1,13 +1,15 @@
//
// KFPC-XT Chipset
// Written by kitune-san
// MiSTer PCXT Chipset
// Ported by @spark2k06
//
// Based on KFPC-XT written by @kitune-san
//
module CHIPSET (
input logic clock,
input logic cpu_clock,
input logic clk_sys,
input logic peripheral_clock,
input logic [1:0] turbo_mode,
input logic [1:0] clk_select,
input logic reset,
input logic sdram_reset,
// CPU
@@ -36,6 +38,7 @@ module CHIPSET (
output logic VGA_VSYNC,
output logic VGA_HBlank,
output logic VGA_VBlank,
output logic VGA_VBlank_border,
// I/O Ports
output logic [19:0] address,
input logic [19:0] address_ext,
@@ -84,29 +87,33 @@ module CHIPSET (
output logic ps2_mouseclk_out,
output logic ps2_mousedat_out,
input logic [4:0] joy_opts,
input logic [31:0] joy0,
input logic [31:0] joy1,
input logic [13:0] joy0,
input logic [13:0] joy1,
input logic [15:0] joya0,
input logic [15:0] joya1,
// JTOPL
input logic clk_en_opl2,
output logic [15:0] jtopl2_snd_e,
input logic adlibhide,
input logic [1:0] opl2_io,
// C/MS Audio
input logic cms_en,
output logic [15:0] o_cms_l,
output logic [15:0] o_cms_r,
// TANDY
input logic tandy_video,
input logic tandy_bios_flag,
output logic [10:0] tandy_snd_e,
output logic tandy_16_gfx,
output logic tandy_color_16,
// UART
input logic clk_uart,
input logic clk_uart2,
input logic uart_rx,
output logic uart_tx,
input logic uart_cts_n,
input logic uart_dcd_n,
input logic uart_dsr_n,
output logic uart_rts_n,
output logic uart_dtr_n,
input logic uart2_rx,
output logic uart2_tx,
input logic uart2_cts_n,
input logic uart2_dcd_n,
input logic uart2_dsr_n,
output logic uart2_rts_n,
output logic uart2_dtr_n,
// SDRAM
input logic enable_sdram,
output logic initilized_sdram,
@@ -137,10 +144,15 @@ module CHIPSET (
input logic [27:0] clock_rate,
input logic [1:0] floppy_wp,
output logic [1:0] fdd_request,
output logic [2:0] ide0_request,
// XTCTL DATA
output logic [7:0] xtctl,
// Optional flags
input logic enable_a000h
// Optional flags
input logic enable_a000h,
// RAM wait mode
input logic wait_count_clk_en,
input logic [1:0] ram_read_wait_cycle,
input logic [1:0] ram_write_wait_cycle
);
logic [19:0] latch_address;
@@ -257,9 +269,8 @@ module CHIPSET (
.clk_sys (clk_sys),
.cpu_clock (cpu_clock),
.clk_uart (clk_uart),
.clk_uart2 (clk_uart2),
.peripheral_clock (peripheral_clock),
.turbo_mode (turbo_mode),
.clk_select (clk_select),
.reset (reset),
.interrupt_to_cpu (interrupt_to_cpu),
.interrupt_acknowledge_n (interrupt_acknowledge_n),
@@ -281,6 +292,7 @@ module CHIPSET (
.VGA_VSYNC (VGA_VSYNC),
.VGA_HBlank (VGA_HBlank),
.VGA_VBlank (VGA_VBlank),
.VGA_VBlank_border (VGA_VBlank_border),
.address (address),
.latch_address (latch_address),
.internal_data_bus (internal_data_bus),
@@ -317,18 +329,22 @@ module CHIPSET (
.ps2_data_out (ps2_data_out),
.clk_en_opl2 (clk_en_opl2),
.jtopl2_snd_e (jtopl2_snd_e),
.adlibhide (adlibhide),
.opl2_io (opl2_io),
.cms_en (cms_en),
.o_cms_l (o_cms_l),
.o_cms_r (o_cms_r),
.tandy_video (tandy_video),
.tandy_snd_e (tandy_snd_e),
.tandy_snd_rdy (tandy_snd_rdy),
.tandy_16_gfx (tandy_16_gfx),
.uart_rx (uart_rx),
.uart_tx (uart_tx),
.uart_cts_n (uart_cts_n),
.uart_dcd_n (uart_dcd_n),
.uart_dsr_n (uart_dsr_n),
.uart_rts_n (uart_rts_n),
.uart_dtr_n (uart_dtr_n),
.tandy_color_16 (tandy_color_16),
.uart2_rx (uart2_rx),
.uart2_tx (uart2_tx),
.uart2_cts_n (uart2_cts_n),
.uart2_dcd_n (uart2_dcd_n),
.uart2_dsr_n (uart2_dsr_n),
.uart2_rts_n (uart2_rts_n),
.uart2_dtr_n (uart2_dtr_n),
.ems_enabled (ems_enabled),
.ems_address (ems_address),
.map_ems (map_ems),
@@ -345,6 +361,7 @@ module CHIPSET (
.clock_rate (clock_rate),
.floppy_wp (floppy_wp),
.fdd_request (fdd_request),
.ide0_request (ide0_request),
.fdd_dma_req (fdd_dma_req),
.fdd_dma_ack (~dma_acknowledge_n[2]),
.terminal_count (terminal_count_n),
@@ -384,7 +401,10 @@ module CHIPSET (
.ems_b4 (ems_b4),
.tandy_bios_flag (tandy_bios_flag),
.bios_protect_flag (bios_protect_flag),
.enable_a000h (enable_a000h)
.enable_a000h (enable_a000h),
.wait_count_clk_en (wait_count_clk_en),
.ram_read_wait_cycle (ram_read_wait_cycle),
.ram_write_wait_cycle (ram_write_wait_cycle)
);
assign data_bus = internal_data_bus;

View File

@@ -53,6 +53,8 @@ module KF8253_Counter (
logic start_counting;
logic first_count_edge;
logic [16:0] count_next;
logic count_period;
logic prev_count_period;
@@ -285,6 +287,18 @@ module KF8253_Counter (
start_counting <= start_counting;
end
// First counte edge signal
always_ff @(posedge clock, posedge reset) begin
if (reset)
first_count_edge <= 1'b0;
else if (start_counting==1'b0)
first_count_edge <= 1'b1;
else if (count_edge == 1'b1)
first_count_edge <= 1'b0;
else
first_count_edge <= first_count_edge;
end
// Decrement counter
function logic [16:0] decrement (input [16:0] count, input is_bcd);
if (count == 17'b0_0000_0000_0000_0000)
@@ -372,7 +386,7 @@ module KF8253_Counter (
count_next = count;
if (count_next == 17'b0_0000_0000_0000_0000) begin
count_period = 1'b1;
count_period = 1'b1 & ~first_count_edge;
count_next = count_preset_load;
end

View File

@@ -1,6 +1,8 @@
//
// KFPC-XT Peripherals
// Written by kitune-san
// MiSTer PCXT Peripherals
// Ported by @spark2k06
//
// Based on KFPC-XT written by @kitune-san
//
module PERIPHERALS #(
parameter ps2_over_time = 16'd1000
@@ -9,7 +11,7 @@ module PERIPHERALS #(
input logic clk_sys,
input logic cpu_clock,
input logic peripheral_clock,
input logic [1:0] turbo_mode,
input logic [1:0] clk_select,
input logic reset,
// CPU
output logic interrupt_to_cpu,
@@ -35,6 +37,7 @@ module PERIPHERALS #(
output logic VGA_VSYNC,
output logic VGA_HBlank,
output logic VGA_VBlank,
output logic VGA_VBlank_border,
// I/O Ports
input logic [19:0] address,
output logic [19:0] latch_address,
@@ -67,29 +70,33 @@ module PERIPHERALS #(
output logic ps2_mouseclk_out,
output logic ps2_mousedat_out,
input logic [4:0] joy_opts,
input logic [31:0] joy0,
input logic [31:0] joy1,
input logic [13:0] joy0,
input logic [13:0] joy1,
input logic [15:0] joya0,
input logic [15:0] joya1,
// JTOPL
input logic clk_en_opl2,
output logic [15:0] jtopl2_snd_e,
input logic adlibhide,
input logic [1:0] opl2_io,
// C/MS Audio
input logic cms_en,
output reg [15:0] o_cms_l,
output reg [15:0] o_cms_r,
// TANDY
input logic tandy_video,
output logic [10:0] tandy_snd_e,
output logic tandy_snd_rdy,
output logic tandy_16_gfx,
output logic tandy_color_16,
// UART
input logic clk_uart,
input logic clk_uart2,
input logic uart_rx,
output logic uart_tx,
input logic uart_cts_n,
input logic uart_dcd_n,
input logic uart_dsr_n,
output logic uart_rts_n,
output logic uart_dtr_n,
input logic uart2_rx,
output logic uart2_tx,
input logic uart2_cts_n,
input logic uart2_dcd_n,
input logic uart2_dsr_n,
output logic uart2_rts_n,
output logic uart2_dtr_n,
// EMS
input logic ems_enabled,
input logic [1:0] ems_address,
@@ -108,6 +115,7 @@ module PERIPHERALS #(
input logic [27:0] clock_rate,
input logic [1:0] floppy_wp,
output logic [1:0] fdd_request,
output logic [2:0] ide0_request,
output logic fdd_dma_req,
input logic fdd_dma_ack,
input logic terminal_count,
@@ -187,8 +195,9 @@ module PERIPHERALS #(
wire nmi_mask_register_n = ~(tandy_video && iorq && ~address_enable_n && address[15:3] == (16'h00a0 >> 3)); // 0xa0 - 0xa7
wire tandy_chip_select_n = ~(iorq && ~address_enable_n && address[15:3] == (16'h00c0 >> 3)); // 0xc0 - 0xc7
wire opl_chip_select_n = ~(iorq && ~address_enable_n && address[15:1] == (16'h0388 >> 1)); // 0x388 .. 0x389
// wire video_chip_select_n = ~((tandy_video & grph_mode & hres_mode) && ~iorq && ~address_enable_n & (address[19:17] == nmi_mask_register_data[3:1])); // 128KB
wire opl_388_select = (iorq && ~address_enable_n && ~opl2_io[1] && address[15:1] == (16'h0388 >> 1)); // 0x388 .. 0x389 (Adlib)
wire opl_228_select = (iorq && ~address_enable_n && (opl2_io == 2'b01) && address[15:1] == (16'h0228 >> 1)); // 0x228 .. 0x229 (Sound Blaster FM)
wire cms_220_select = (iorq && ~address_enable_n && address[15:4] == (16'h0220 >> 4)); // 0x220 .. 0x22F (C/MS Audio)
wire video_chip_select_n = ~(tandy_video && ~iorq && ~address_enable_n & (address[19:17] == nmi_mask_register_data[3:1])); // 128KB
wire cga_chip_select_n = ~(~iorq && ~address_enable_n && enable_cga & (address[19:15] == 5'b10111)); // B8000 - BFFFF (16 KB / 32 KB)
wire mda_chip_select_n = ~(~iorq && ~address_enable_n && enable_mda & (address[19:15] == 6'b10110)); // B0000 - B7FFF (8 repeated blocks of 4Kb)
@@ -205,6 +214,7 @@ module PERIPHERALS #(
assign ems_b3 = (~iorq && ena_ems[2] && (address[19:14] == {ems_page_address, 2'b10})); // C8000h - D8000h - E8000h
assign ems_b4 = (~iorq && ena_ems[3] && (address[19:14] == {ems_page_address, 2'b11})); // CC000h - DC000h - EC000h
wire ide0_cs_n = ~(iorq && ~address_enable_n && ({address[15:4], 4'd0} == 16'h0300));
wire floppy0_select_n = ~(~address_enable_n && (({address[15:2], 2'd0} == 16'h03F0) || ({address[15:1], 1'd0} == 16'h03F4) || ({address[15:0]} == 16'h03F7)));
logic [1:0] ems_access_address;
@@ -472,8 +482,6 @@ module PERIPHERALS #(
wire [7:0] jtopl2_dout;
wire [7:0] opl32_data;
assign opl32_data = adlibhide ? 8'hFF : jtopl2_dout;
jtopl2 jtopl2_inst
(
@@ -483,7 +491,7 @@ module PERIPHERALS #(
.din(internal_data_bus),
.dout(jtopl2_dout),
.addr(address[0]),
.cs_n(opl_chip_select_n),
.cs_n(~(opl_228_select || opl_388_select)),
.wr_n(io_write_n),
.irq_n(),
.snd(jtopl2_snd_e),
@@ -503,6 +511,89 @@ module PERIPHERALS #(
.sound(tandy_snd_e),
.ready(tandy_snd_rdy)
);
//------------------------------------------------------------------------------
reg [27:0] clk_rate;
always @(posedge clock) clk_rate <= clock_rate;
reg ce_1us;
always @(posedge clock) begin
reg [27:0] sum = 0;
ce_1us = 0;
sum = sum + 28'd1000000;
if(sum >= clk_rate) begin
sum = sum - clk_rate;
ce_1us = 1;
end
end
//------------------------------------------------------------------------------ c/ms
wire cms_rd = (address[3:0] == 4'h4 || address[3:0] == 4'hB) && cms_220_select && cms_en;
wire [7:0] data_from_cms = address[3] ? cms_det : 8'h7F;
wire cms_wr = ~address[3] & cms_220_select & cms_en;
reg [7:0] cms_det;
always @(posedge clock) if(~io_write_n && cms_wr && &address[2:1]) cms_det <= internal_data_bus;
reg ce_saa;
always @(posedge clock) begin
reg [27:0] sum = 0;
ce_saa = 0;
sum = sum + 28'd7159090;
if(sum >= clk_rate) begin
sum = sum - clk_rate;
ce_saa = 1;
end
end
wire [7:0] saa1_l,saa1_r;
saa1099 ssa1
(
.clk_sys(clock),
.ce(ce_saa),
.rst_n(~reset & cms_en),
.cs_n(~(cms_wr && (address[2:1] == 0))),
.a0(address[0]),
.wr_n(io_write_n),
.din(internal_data_bus),
.out_l(saa1_l),
.out_r(saa1_r)
);
wire [7:0] saa2_l,saa2_r;
saa1099 ssa2
(
.clk_sys(clock),
.ce(ce_saa),
.rst_n(~reset & cms_en),
.cs_n(~(cms_wr && (address[2:1] == 1))),
.a0(address[0]),
.wr_n(io_write_n),
.din(internal_data_bus),
.out_l(saa2_l),
.out_r(saa2_r)
);
wire [8:0] cms_l = {1'b0, saa1_l} + {1'b0, saa2_l};
wire [8:0] cms_r = {1'b0, saa1_r} + {1'b0, saa2_r};
reg [15:0] sample_pre_l, sample_pre_r;
always @(posedge clock) begin
sample_pre_l <= {2'b0, cms_l, cms_l[8:4]};
sample_pre_r <= {2'b0, cms_r, cms_r[8:4]};
end
always @(posedge clock) begin
o_cms_l <= $signed(sample_pre_l) >>> ~{3'd7};
o_cms_r <= $signed(sample_pre_r) >>> ~{3'd7};
end
//
logic keybord_interrupt_ff;
logic uart_interrupt_ff;
@@ -594,6 +685,9 @@ module PERIPHERALS #(
end
wire iorq_uart = (io_write_n & ~prev_io_write_n) || (~io_read_n & prev_io_read_n);
wire uart_tx;
wire rts_n;
uart uart1
(
.clk (clock),
@@ -606,26 +700,20 @@ module PERIPHERALS #(
.write (io_write_n & ~prev_io_write_n),
.readdata (uart_readdata_1),
.cs (uart_cs & iorq_uart),
.rx (uart_rx),
.tx (uart_tx),
.cts_n (uart_cts_n),
.dcd_n (uart_dcd_n),
.dsr_n (uart_dsr_n),
.rts_n (uart_rts_n),
.dtr_n (uart_dtr_n),
.rx (uart_tx),
.cts_n (0),
.dcd_n (0),
.dsr_n (0),
.ri_n (1),
.rts_n (rts_n),
.irq (uart_irq)
);
wire uart2_tx;
wire rts_n;
uart uart2
(
.clk (clock),
.br_clk (clk_uart2),
.br_clk (clk_uart),
.reset (reset),
.address (address[2:0]),
@@ -634,15 +722,19 @@ module PERIPHERALS #(
.write (io_write_n & ~prev_io_write_n),
.readdata (uart2_readdata_1),
.cs (uart2_cs & iorq_uart),
.rx (uart2_tx),
.cts_n (0),
.dcd_n (0),
.dsr_n (0),
.rx (uart2_rx),
.tx (uart2_tx),
.cts_n (uart2_cts_n),
.dcd_n (uart2_dcd_n),
.dsr_n (uart2_dsr_n),
.rts_n (uart2_rts_n),
.dtr_n (uart2_dtr_n),
.ri_n (1),
.rts_n (rts_n),
.irq (uart2_irq)
);
MSMouseWrapper MSMouseWrapper_inst
(
.clk(clock),
@@ -651,7 +743,7 @@ module PERIPHERALS #(
.ps2dta_out(ps2_mousedat_out),
.ps2clk_out(ps2_mouseclk_out),
.rts(~rts_n),
.rd(uart2_tx)
.rd(uart_tx)
);
// Timing of the readings may need to be reviewed.
@@ -699,10 +791,8 @@ module PERIPHERALS #(
logic [7:0] cga_io_data_2;
logic cga_io_write_n_1;
logic cga_io_write_n_2;
logic cga_io_write_n_3;
logic cga_io_read_n_1;
logic cga_io_read_n_2;
logic cga_io_read_n_3;
logic cga_address_enable_n_1;
logic cga_address_enable_n_2;
@@ -758,10 +848,8 @@ module PERIPHERALS #(
cga_io_data_2 <= cga_io_data_1;
cga_io_write_n_1 <= video_io_write_n;
cga_io_write_n_2 <= cga_io_write_n_1;
cga_io_write_n_3 <= cga_io_write_n_2;
cga_io_read_n_1 <= video_io_read_n;
cga_io_read_n_2 <= cga_io_read_n_1;
cga_io_read_n_3 <= cga_io_read_n_2;
cga_address_enable_n_1 <= video_address_enable_n;
cga_address_enable_n_2 <= cga_address_enable_n_1;
end
@@ -900,8 +988,8 @@ module PERIPHERALS #(
.clk (clk_vga_cga),
.clkdiv (clkdiv),
.bus_a (cga_io_address_2),
.bus_ior_l (cga_io_read_n_3),
.bus_iow_l (cga_io_write_n_3),
.bus_ior_l (cga_io_read_n_2),
.bus_iow_l (cga_io_write_n_2),
.bus_memr_l (1'd0),
.bus_memw_l (1'd0),
.bus_d (cga_io_data_2),
@@ -916,6 +1004,7 @@ module PERIPHERALS #(
.hblank (HBLANK_CGA),
.vsync (VSYNC_CGA),
.vblank (VBLANK_CGA),
.vblank_border (VGA_VBlank_border),
.de_o (de_o_cga),
.video (video_cga), // non scandoubled
// .dbl_video (video_cga), // scandoubled
@@ -923,7 +1012,8 @@ module PERIPHERALS #(
.thin_font (thin_font),
.tandy_video (tandy_video),
.grph_mode (grph_mode),
.hres_mode (hres_mode)
.hres_mode (hres_mode),
.tandy_color_16 (tandy_color_16)
);
always_ff @(posedge clock)
@@ -944,7 +1034,7 @@ module PERIPHERALS #(
(
.clka (clock),
.ena (~cga_chip_select_n_1 || ~video_chip_select_n_1),
.wea (~video_memory_write_n),
.wea (~video_memory_write_n & memory_write_n),
// .addra ((tandy_video & grph_mode & hres_mode) ? ~video_chip_select_n_1 ? video_ram_address : tandy_page_data[3] ? {tandy_page_data[5:3], video_ram_address[13:0]} : {tandy_page_data[5:4], video_ram_address[14:0]} : video_ram_address[13:0]),
.addra (tandy_video ? ~video_chip_select_n_1 ? video_ram_address : tandy_page_data[3] ? {tandy_page_data[5:3], video_ram_address[13:0]} : {tandy_page_data[5:4], video_ram_address[14:0]} : video_ram_address[13:0]),
.dina (video_ram_data),
@@ -976,10 +1066,111 @@ module PERIPHERALS #(
);
//
// XT2IDE
//
logic [7:0] xt2ide0_data_bus_out;
logic ide0_cs1fx;
logic ide0_cs3fx;
logic ide0_io_read_n;
logic ide0_io_write_n;
logic [2:0] ide0_address;
logic [15:0] ide0_data_bus_in;
logic [15:0] ide0_data_bus_out;
XT2IDE xt2ide0 (
.clock (clock),
.reset (reset),
.high_speed (0),
.chip_select_n (ide0_cs_n),
.io_read_n (io_read_n),
.io_write_n (io_write_n),
.address (address[3:0]),
.data_bus_in (internal_data_bus),
.data_bus_out (xt2ide0_data_bus_out),
.ide_cs1fx (ide0_cs1fx),
.ide_cs3fx (ide0_cs3fx),
.ide_io_read_n (ide0_io_read_n),
.ide_io_write_n (ide0_io_write_n),
.ide_address (ide0_address),
.ide_data_bus_in (ide0_data_bus_in),
.ide_data_bus_out (ide0_data_bus_out)
);
//
// IDE
//
logic mgmt_ide0_cs;
logic [15:0] mgmt_ide0_readdata;
logic ide0_command_cs;
logic ide0_control_cs;
logic ide0_comd_ctrl_select;
logic ide0_io_read;
logic ide0_io_read_1;
logic ide0_io_write;
logic prev_ide0_io_read;
logic prev_ide0_io_write;
logic [3:0] ide0_address_1;
logic [15:0] ide0_writedata;
assign mgmt_ide0_cs = (mgmt_address[15:8] == 8'hF0);
assign ide0_command_cs = ~ide0_cs1fx;
assign ide0_control_cs = ~ide0_cs3fx & &ide0_address[2:1];
assign ide0_io_read = ~ide0_io_read_n & (ide0_command_cs | ide0_control_cs);
assign ide0_io_write = ~ide0_io_write_n & (ide0_command_cs | ide0_control_cs);
always_ff @(posedge clock)
begin
ide0_io_read_1 <= ide0_io_read;
prev_ide0_io_read <= ide0_io_read_1;
prev_ide0_io_write <= ide0_io_write;
ide0_address_1 <= ~ide0_control_cs ? {1'b0, ide0_address} : {1'b1, ide0_address};
ide0_writedata <= ide0_data_bus_out;
end
ide ide
(
.clk (clock),
.rst_n (~reset),
// .irq (),
// .drq (),
.use_fast (0),
// .no_data (),
// .drive_en (),
.io_address (ide0_address_1),
.io_read (ide0_io_read & ~prev_ide0_io_read),
.io_readdata (ide0_data_bus_in),
.io_write (~ide0_io_write & prev_ide0_io_write),
.io_writedata (ide0_writedata),
.io_32 (0),
// .io_wait (),
.request (ide0_request),
.mgmt_address (mgmt_address[3:0]),
.mgmt_writedata (mgmt_writedata),
.mgmt_readdata (mgmt_ide0_readdata),
.mgmt_write (mgmt_write & mgmt_ide0_cs),
.mgmt_read (mgmt_read & mgmt_ide0_cs)
);
//
// FDC
//
logic mgmt_fdd_cs;
logic [15:0] mgmt_fdd_readdata;
logic [7:0] write_to_fdd;
logic [2:0] fdd_io_address;
logic fdd_io_read;
@@ -1061,7 +1252,7 @@ module PERIPHERALS #(
.mgmt_write (mgmt_write & mgmt_fdd_cs),
.mgmt_writedata (mgmt_writedata),
.mgmt_read (mgmt_read & mgmt_fdd_cs),
.mgmt_readdata (mgmt_readdata),
.mgmt_readdata (mgmt_fdd_readdata),
.wp (floppy_wp),
@@ -1091,6 +1282,12 @@ module PERIPHERALS #(
end
//
// mgmt_readdata
//
assign mgmt_readdata = mgmt_ide0_cs ? mgmt_ide0_readdata : mgmt_fdd_readdata;
//
// KFTVGA
//
@@ -1131,7 +1328,7 @@ module PERIPHERALS #(
.clk (clock),
.reset (reset),
.en (joystick_select && ~io_write_n),
.turbo_mode (turbo_mode),
.clk_select (clk_select),
.joy_opts (joy_opts),
.joy0 (joy0),
.joy1 (joy1),
@@ -1187,10 +1384,15 @@ module PERIPHERALS #(
data_bus_out_from_chipset <= 1'b1;
data_bus_out <= MDA_CRTC_DOUT_2;
end
else if ((~opl_chip_select_n) && (~io_read_n))
else if ((opl_228_select || opl_388_select) && ~io_read_n)
begin
data_bus_out_from_chipset <= 1'b1;
data_bus_out <= opl32_data;
data_bus_out <= jtopl2_dout;
end
else if (cms_rd)
begin
data_bus_out_from_chipset <= 1'b1;
data_bus_out <= data_from_cms;
end
else if ((uart_cs) && (~io_read_n))
begin
@@ -1227,6 +1429,11 @@ module PERIPHERALS #(
data_bus_out_from_chipset <= 1'b1;
data_bus_out <= joy_data;
end
else if ((~ide0_cs_n) && (~io_read_n))
begin
data_bus_out_from_chipset <= 1'b1;
data_bus_out <= xt2ide0_data_bus_out;
end
else if ((~floppy0_select_n || fdd_dma_read) && (~io_read_n))
begin
data_bus_out_from_chipset <= 1'b1;

View File

@@ -1,6 +1,8 @@
//
// KFPC-XT Peripherals
// Written by kitune-san
// MiSTer PCXT RAM
// Ported by @spark2k06
//
// Based on KFPC-XT written by @kitune-san
//
module RAM (
input logic clock,
@@ -38,8 +40,12 @@ module RAM (
// BIOS
input logic [1:0] bios_protect_flag,
input logic tandy_bios_flag,
// Optional flags
input logic enable_a000h
// Optional flags
input logic enable_a000h,
// Wait mode
input logic wait_count_clk_en,
input logic [1:0] ram_read_wait_cycle,
input logic [1:0] ram_write_wait_cycle
);
typedef enum {IDLE, RAM_WRITE_1, RAM_WRITE_2, RAM_READ_1, RAM_READ_2, COMPLETE_RAM_RW, WAIT} state_t;
@@ -54,6 +60,8 @@ module RAM (
logic enable_refresh;
logic write_protect;
logic [1:0] read_wait_count;
logic [1:0] write_wait_count;
logic access_ready;
//
@@ -327,7 +335,30 @@ module RAM (
access_ready <= access_ready;
end
assign memory_access_ready = ((~ram_address_select_n) && ((~memory_read_n) || (~memory_write_n))) ? access_ready : 1'b1;
always_ff @(posedge clock, posedge reset) begin
if (reset)
read_wait_count <= 0;
else if (~read_command)
read_wait_count <= ram_read_wait_cycle;
else if ((wait_count_clk_en) && (read_wait_count != 0))
read_wait_count <= read_wait_count - 1;
else
read_wait_count <= read_wait_count;
end
always_ff @(posedge clock, posedge reset) begin
if (reset)
write_wait_count <= 0;
else if (~write_command)
write_wait_count <= ram_write_wait_cycle;
else if ((wait_count_clk_en) && (write_wait_count != 0))
write_wait_count <= write_wait_count - 1;
else
write_wait_count <= write_wait_count;
end
assign memory_access_ready = ((~ram_address_select_n) && ((~memory_read_n) || (~memory_write_n)))
? (access_ready & ((read_wait_count==0) || (~read_command)) & ((write_wait_count==0) || (~write_command))) : 1'b1;
endmodule

111
rtl/KFPC-XT/HDL/XT2IDE.sv Normal file
View File

@@ -0,0 +1,111 @@
//
// XT2IDE written by kitune-san
//
module XT2IDE
(
input logic clock,
input logic reset,
input logic high_speed,
input logic chip_select_n,
input logic io_read_n,
input logic io_write_n,
input logic [4:0] address,
input logic [7:0] data_bus_in,
output logic [7:0] data_bus_out,
output logic ide_cs1fx,
output logic ide_cs3fx,
output logic ide_io_read_n,
output logic ide_io_write_n,
output logic [2:0] ide_address,
input logic [15:0] ide_data_bus_in,
output logic [15:0] ide_data_bus_out
);
logic select_1;
logic select_2;
logic latch_high_read_byte;
logic read_high_byte;
logic latch_high_write_byte;
logic [7:0] read_buffer;
//
// Control Signals
//
assign select_1 = high_speed ? address[0] : address[3];
assign select_2 = high_speed ? address[3] : address[0];
always_comb
begin
latch_high_read_byte = 1'b0;
read_high_byte = 1'b0;
latch_high_write_byte = 1'b0;
if (~address[2] & ~address[1] & ~select_2 & ~chip_select_n) begin
casez ({select_1, io_read_n, io_write_n})
3'b001: latch_high_read_byte = 1'b1;
3'b101: read_high_byte = 1'b1;
3'b110: latch_high_write_byte = 1'b1;
endcase
end
end
assign ide_io_read_n = io_read_n;
assign ide_io_write_n = io_write_n;
assign ide_cs1fx = select_1 | chip_select_n;
assign ide_cs3fx = ~select_1 | chip_select_n;
//
// XT Address -> IDE Address
//
assign ide_address = {address[2:1], select_2};
//
// XT Data Bus -> IDE Data Bus
//
always_ff @(posedge clock, posedge reset)
begin
if (reset)
ide_data_bus_out[15:8] <= 8'hFF;
else if (~chip_select_n & latch_high_write_byte)
ide_data_bus_out[15:8] <= data_bus_in;
else
ide_data_bus_out[15:8] <= ide_data_bus_out[15:8];
end
always_comb
begin
if (io_write_n | chip_select_n)
ide_data_bus_out[7:0] = 8'hFF;
else
ide_data_bus_out[7:0] = data_bus_in;
end
//
// IDE Data Bus -> XT Data Bus
//
always_ff @(posedge clock, posedge reset)
begin
if (reset)
read_buffer <= 8'hFF;
else if (~ide_io_read_n & latch_high_read_byte)
read_buffer <= ide_data_bus_in[15:8];
else
read_buffer <= read_buffer;
end
always_comb
begin
if (read_high_byte)
data_bus_out = read_buffer;
else if (~io_read_n & ~chip_select_n)
data_bus_out = ide_data_bus_in[7:0];
else
data_bus_out = 8'hFF;
end
endmodule

330
rtl/common/bram.vhd Normal file
View File

@@ -0,0 +1,330 @@
--------------------------------------------------------------
-- Single port Block RAM
--------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
ENTITY spram IS
generic (
addr_width : integer := 8;
data_width : integer := 8;
mem_init_file : string := " ";
mem_name : string := "MEM" -- for InSystem Memory content editor.
);
PORT
(
clock : in STD_LOGIC;
address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
enable : in STD_LOGIC := '1';
wren : in STD_LOGIC := '0';
q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
cs : in std_logic := '1'
);
END spram;
ARCHITECTURE SYN OF spram IS
BEGIN
spram_sz : work.spram_sz
generic map(addr_width, data_width, 2**addr_width, mem_init_file, mem_name)
port map(clock,address,data,enable,wren,q,cs);
END SYN;
--------------------------------------------------------------
-- Single port Block RAM with specific size
--------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
ENTITY spram_sz IS
generic (
addr_width : integer := 8;
data_width : integer := 8;
numwords : integer := 2**8;
mem_init_file : string := " ";
mem_name : string := "MEM" -- for InSystem Memory content editor.
);
PORT
(
clock : in STD_LOGIC;
address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
enable : in STD_LOGIC := '1';
wren : in STD_LOGIC := '0';
q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
cs : in std_logic := '1'
);
END ENTITY;
ARCHITECTURE SYN OF spram_sz IS
signal q0 : std_logic_vector((data_width - 1) downto 0);
BEGIN
q<= q0 when cs = '1' else (others => '1');
altsyncram_component : altsyncram
GENERIC MAP (
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
intended_device_family => "Cyclone V",
lpm_hint => "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME="&mem_name,
lpm_type => "altsyncram",
numwords_a => numwords,
operation_mode => "SINGLE_PORT",
outdata_aclr_a => "NONE",
outdata_reg_a => "UNREGISTERED",
power_up_uninitialized => "FALSE",
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
init_file => mem_init_file,
widthad_a => addr_width,
width_a => data_width,
width_byteena_a => 1
)
PORT MAP (
address_a => address,
clock0 => clock,
data_a => data,
wren_a => wren and cs,
q_a => q0
);
END SYN;
--------------------------------------------------------------
-- Dual port Block RAM same parameters on both ports
--------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
entity dpram is
generic (
addr_width : integer := 8;
data_width : integer := 8;
mem_init_file : string := " "
);
PORT
(
clock : in STD_LOGIC;
address_a : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
data_a : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
enable_a : in STD_LOGIC := '1';
wren_a : in STD_LOGIC := '0';
q_a : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
cs_a : in std_logic := '1';
address_b : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0) := (others => '0');
data_b : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
enable_b : in STD_LOGIC := '1';
wren_b : in STD_LOGIC := '0';
q_b : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
cs_b : in std_logic := '1'
);
end entity;
ARCHITECTURE SYN OF dpram IS
BEGIN
ram : work.dpram_dif generic map(addr_width,data_width,addr_width,data_width,mem_init_file)
port map(clock,address_a,data_a,enable_a,wren_a,q_a,cs_a,address_b,data_b,enable_b,wren_b,q_b,cs_b);
END SYN;
--------------------------------------------------------------
-- Dual port Block RAM different parameters on ports
--------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
entity dpram_dif is
generic (
addr_width_a : integer := 8;
data_width_a : integer := 8;
addr_width_b : integer := 8;
data_width_b : integer := 8;
mem_init_file : string := " "
);
PORT
(
clock : in STD_LOGIC;
address_a : in STD_LOGIC_VECTOR (addr_width_a-1 DOWNTO 0);
data_a : in STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0) := (others => '0');
enable_a : in STD_LOGIC := '1';
wren_a : in STD_LOGIC := '0';
q_a : out STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0);
cs_a : in std_logic := '1';
address_b : in STD_LOGIC_VECTOR (addr_width_b-1 DOWNTO 0) := (others => '0');
data_b : in STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0) := (others => '0');
enable_b : in STD_LOGIC := '1';
wren_b : in STD_LOGIC := '0';
q_b : out STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0);
cs_b : in std_logic := '1'
);
end entity;
ARCHITECTURE SYN OF dpram_dif IS
signal q0 : std_logic_vector((data_width_a - 1) downto 0);
signal q1 : std_logic_vector((data_width_b - 1) downto 0);
BEGIN
q_a<= q0 when cs_a = '1' else (others => '1');
q_b<= q1 when cs_b = '1' else (others => '1');
altsyncram_component : altsyncram
GENERIC MAP (
address_reg_b => "CLOCK1",
clock_enable_input_a => "NORMAL",
clock_enable_input_b => "NORMAL",
clock_enable_output_a => "BYPASS",
clock_enable_output_b => "BYPASS",
indata_reg_b => "CLOCK1",
intended_device_family => "Cyclone V",
lpm_type => "altsyncram",
numwords_a => 2**addr_width_a,
numwords_b => 2**addr_width_b,
operation_mode => "BIDIR_DUAL_PORT",
outdata_aclr_a => "NONE",
outdata_aclr_b => "NONE",
outdata_reg_a => "UNREGISTERED",
outdata_reg_b => "UNREGISTERED",
power_up_uninitialized => "FALSE",
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
init_file => mem_init_file,
widthad_a => addr_width_a,
widthad_b => addr_width_b,
width_a => data_width_a,
width_b => data_width_b,
width_byteena_a => 1,
width_byteena_b => 1,
wrcontrol_wraddress_reg_b => "CLOCK1"
)
PORT MAP (
address_a => address_a,
address_b => address_b,
clock0 => clock,
clock1 => clock,
clocken0 => enable_a,
clocken1 => enable_b,
data_a => data_a,
data_b => data_b,
wren_a => wren_a and cs_a,
wren_b => wren_b and cs_b,
q_a => q0,
q_b => q1
);
END SYN;
--------------------------------------------------------------
-- Dual port Block RAM different parameters and clocks on ports
--------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
entity dpram_difclk is
generic (
addr_width_a : integer := 8;
data_width_a : integer := 8;
addr_width_b : integer := 8;
data_width_b : integer := 8;
mem_init_file : string := " "
);
PORT
(
clk_a : in STD_LOGIC;
clk_b : in STD_LOGIC;
address_a : in STD_LOGIC_VECTOR (addr_width_a-1 DOWNTO 0);
data_a : in STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0) := (others => '0');
enable_a : in STD_LOGIC := '1';
wren_a : in STD_LOGIC := '0';
q_a : out STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0);
cs_a : in std_logic := '1';
address_b : in STD_LOGIC_VECTOR (addr_width_b-1 DOWNTO 0) := (others => '0');
data_b : in STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0) := (others => '0');
enable_b : in STD_LOGIC := '1';
wren_b : in STD_LOGIC := '0';
q_b : out STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0);
cs_b : in std_logic := '1'
);
end entity;
ARCHITECTURE SYN OF dpram_difclk IS
signal q0 : std_logic_vector((data_width_a - 1) downto 0);
signal q1 : std_logic_vector((data_width_b - 1) downto 0);
BEGIN
q_a<= q0 when cs_a = '1' else (others => '1');
q_b<= q1 when cs_b = '1' else (others => '1');
altsyncram_component : altsyncram
GENERIC MAP (
address_reg_b => "CLOCK1",
clock_enable_input_a => "NORMAL",
clock_enable_input_b => "NORMAL",
clock_enable_output_a => "BYPASS",
clock_enable_output_b => "BYPASS",
indata_reg_b => "CLOCK1",
intended_device_family => "Cyclone V",
lpm_type => "altsyncram",
numwords_a => 2**addr_width_a,
numwords_b => 2**addr_width_b,
operation_mode => "BIDIR_DUAL_PORT",
outdata_aclr_a => "NONE",
outdata_aclr_b => "NONE",
outdata_reg_a => "UNREGISTERED",
outdata_reg_b => "UNREGISTERED",
power_up_uninitialized => "FALSE",
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
init_file => mem_init_file,
widthad_a => addr_width_a,
widthad_b => addr_width_b,
width_a => data_width_a,
width_b => data_width_b,
width_byteena_a => 1,
width_byteena_b => 1,
wrcontrol_wraddress_reg_b => "CLOCK1"
)
PORT MAP (
address_a => address_a,
address_b => address_b,
clock0 => clk_a,
clock1 => clk_b,
clocken0 => enable_a,
clocken1 => enable_b,
data_a => data_a,
data_b => data_b,
wren_a => wren_a and cs_a,
wren_b => wren_b and cs_b,
q_a => q0,
q_b => q1
);
END SYN;

View File

@@ -4,4 +4,6 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) bios.v
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) floppy.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) simple_fifo.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) MSMouseWrapper.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ide.v ]
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) bram.vhd ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) tandy_pcjr_joy.sv ]

314
rtl/common/ide.v Normal file
View File

@@ -0,0 +1,314 @@
/*
* Copyright (c) 2020, Alexey Melnikov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
module ide
(
input clk,
input rst_n,
output reg irq,
output drq,
input use_fast, // 1 - supports fast read mode
output no_data, // pause for system when no data is available in fast mode
output [1:0] drive_en,
input [3:0] io_address,
input io_read,
output reg [31:0] io_readdata,
input io_write,
input [31:0] io_writedata,
input io_32,
output reg io_wait,
output reg [2:0] request,
input [3:0] mgmt_address,
input mgmt_write,
input [15:0] mgmt_writedata,
input mgmt_read,
output reg [15:0] mgmt_readdata
);
assign drq = status[3];
assign drive_en = present;
//------------------------------------------------------------------------------
wire io_wr = io_write & |present;
//------------------------------------------------------------------------------
always @(posedge clk) if(io_read) begin
if(!present) io_readdata <= 32'hFFFFFFFF;
else begin
case(io_address)
0: io_readdata <= status[3] ? {buf_q[31:16], (~io_32 & io_cnt[0]) ? buf_q[31:16] : buf_q[15:0]} : 32'd0;
1: io_readdata <= error;
2: io_readdata <= (hob ? sector_count[15:8] : sector_count[7:0] );
3: io_readdata <= (hob ? sector[15:8] : sector[7:0] );
4: io_readdata <= (hob ? cylinder[23:16] : cylinder[7:0] );
5: io_readdata <= (hob ? cylinder[31:24] : cylinder[15:8] );
6: io_readdata <= drv_addr;
7: io_readdata <= status;
14: io_readdata <= status;
15: io_readdata <= { 2'b10, ~drv_addr[3:0], ~drv_addr[4], drv_addr[4]};
default: io_readdata <= 0;
endcase
end
end
//------------------------------------------------------------------------------
reg [7:0] features;
always @(posedge clk) begin
if(~rst_n) features <= 8'h00;
else if(io_wr && io_address == 1) features <= io_writedata[7:0];
end
reg [15:0] blk_size;
always @(posedge clk) begin
if(~rst_n) blk_size <= 16'h0000;
else if(mgmt_write && mgmt_address == 0) blk_size <= {mgmt_writedata[7:0], 8'h00};
else if(mgmt_write && mgmt_address == 4 && blk_size[15]) blk_size <= mgmt_writedata[15:0];
end
reg [7:0] error;
always @(posedge clk) begin
if(~rst_n) error <= 8'h00;
else if(mgmt_write && mgmt_address == 0) error <= mgmt_writedata[15:8];
end
reg [15:0] sector_count;
always @(posedge clk) begin
if(~rst_n) sector_count <= 16'd1;
else if(mgmt_write && mgmt_address == 1) sector_count[7:0] <= mgmt_writedata[7:0];
else if(mgmt_write && mgmt_address == 3) sector_count[15:8] <= mgmt_writedata[7:0];
else if(io_wr && io_address == 2) sector_count <= {sector_count[7:0], io_writedata[7:0]};
end
reg [15:0] sector;
always @(posedge clk) begin
if(~rst_n) sector <= 16'd1;
else if(mgmt_write && mgmt_address == 1) sector[7:0] <= mgmt_writedata[15:8];
else if(mgmt_write && mgmt_address == 3) sector[15:8] <= mgmt_writedata[15:8];
else if(io_wr && io_address == 3) sector <= {sector[7:0],io_writedata[7:0]};
end
reg [31:0] cylinder;
always @(posedge clk) begin
if(~rst_n) cylinder <= 32'hFFFFFFFF;
else if(mgmt_write && mgmt_address == 2) cylinder[15:0] <= mgmt_writedata[15:0];
else if(mgmt_write && mgmt_address == 4) cylinder[31:16] <= mgmt_writedata[15:0];
else if(io_wr && io_address == 4) {cylinder[23:16], cylinder[7:0] } <= {cylinder[7:0], io_writedata[7:0]};
else if(io_wr && io_address == 5) {cylinder[31:24], cylinder[15:8]} <= {cylinder[15:8], io_writedata[7:0]};
end
reg [7:0] drv_addr;
always @(posedge clk) begin
if(~rst_n) drv_addr <= 8'd0;
else if(mgmt_write && mgmt_address == 5) drv_addr <= mgmt_writedata[7:0];
else if(io_wr && io_address == 6) drv_addr <= io_writedata[7:0];
end
reg [7:0] cmd;
always @(posedge clk) begin
if(~rst_n) cmd <= 8'd0;
else if(io_wr && io_address == 7) cmd <= io_writedata[7:0];
end
reg [7:0] status = 0;
always @(posedge clk) begin
if(reset) status <= 8'h80;
else if(mgmt_write && mgmt_address == 5) status <= {mgmt_writedata[15:14],1'b0,mgmt_writedata[12:11],2'b00,mgmt_writedata[8]};
else if(io_wr && io_address == 7) status <= 8'h80;
else if(io_done & drq & last_read) status <= 8'h40;
else if(io_done & drq) status <= 8'h80;
end
reg last_read = 0;
always @(posedge clk) begin
if(reset) last_read <= 0;
else if(mgmt_write && mgmt_address == 5) last_read <= mgmt_writedata[9];
else if(io_done & drq) last_read <= 0;
end
reg fast_read = 0;
always @(posedge clk) begin
if(reset) fast_read <= 0;
else if(mgmt_write && mgmt_address == 5) fast_read <= mgmt_writedata[13];
else if(io_done & drq) fast_read <= 0;
end
always @(posedge clk) begin
if(~rst_n) io_wait <= 1'd0;
else if(sw_reset) io_wait <= use_wait;
else if(mgmt_write && mgmt_address == 5) io_wait <= 1'd0;
else if(io_wr && io_address == 7) io_wait <= use_wait;
else if(io_done & drq) io_wait <= use_wait;
end
always @(posedge clk) begin
if(reset) request <= 3'b110; // reset
else if(mgmt_write && mgmt_address == 5) request <= 3'b000;
else if(io_wr && io_address == 7) request <= 3'b100; // new command
else if(io_done & drq & ~last_read) request <= 3'b101; // data send/recv
end
always @(posedge clk) begin
if(reset) irq <= 1'b0;
else if(mgmt_write && mgmt_address == 5 && mgmt_writedata[10] && ~disable_irq) irq <= 1'b1;
else if((io_read | io_wr) && io_address == 7) irq <= 1'b0;
end
always @(posedge clk) begin
case(mgmt_address)
0: mgmt_readdata <= {features, 6'd0, use_fast, io_done};
1: mgmt_readdata <= {sector[7:0], sector_count[7:0]};
2: mgmt_readdata <= {cylinder[15:0]};
3: mgmt_readdata <= {sector[15:8], sector_count[15:8]};
4: mgmt_readdata <= {cylinder[31:16]};
5: mgmt_readdata <= {cmd, drv_addr};
default: mgmt_readdata <= (mgmt_cnt[0]) ? buf_readdata[31:16] : buf_readdata[15:0];
endcase
end
//------------------------------------------------------------------------------
reg [1:0] hob_ena = 0;
reg [1:0] present = 0;
always @(posedge clk) begin
if(mgmt_write && mgmt_address == 6 && mgmt_writedata[3]) {hob_ena[0], present[0]} <= mgmt_writedata[1:0];
if(mgmt_write && mgmt_address == 6 && mgmt_writedata[7]) {hob_ena[1], present[1]} <= mgmt_writedata[5:4];
end
reg use_wait = 0;
always @(posedge clk) begin
if(mgmt_write && mgmt_address == 6 && mgmt_writedata[9]) use_wait <= mgmt_writedata[8];
end
//------------------------------------------------------------------------------
wire reset = ~rst_n | sw_reset;
reg disable_irq;
always @(posedge clk) begin
if(reset) disable_irq <= 1'b0;
else if(io_wr && io_address == 14) disable_irq <= io_writedata[1];
end
reg sw_reset;
always @(posedge clk) begin
if(~rst_n) sw_reset <= 1'b0;
else if(io_wr && io_address == 14) sw_reset <= io_writedata[2];
end
reg hob_pre;
always @(posedge clk) begin
if(reset) hob_pre <= 1'b0;
else if(io_wr && io_address == 14) hob_pre <= io_writedata[7];
end
reg hob;
always @(posedge clk) hob <= hob_pre & hob_ena[drv_addr[4]];
//------------------------------------------------------------------------------
wire write_data_io = io_wr && io_address == 0 && drq;
wire read_data_io = io_read && io_address == 0 && drq;
wire io_done = (blk_size && io_cnt >= blk_size);
reg [13:0] io_cnt;
wire io_stb = read_data_io | write_data_io;
always @(posedge clk) begin
reg old_stb, r_32;
old_stb <= io_stb;
if(io_stb) r_32 <= io_32;
if(reset) io_cnt <= 0;
else if(mgmt_write && mgmt_address == 5) io_cnt <= 0;
else if(old_stb & ~io_stb) io_cnt <= io_cnt + 1'd1 + r_32;
end
reg [13:0] mgmt_cnt;
always @(posedge clk) begin
reg old_wr, old_rd;
old_wr <= mgmt_write;
old_rd <= mgmt_read;
if((old_wr & ~mgmt_write) | (old_rd & ~mgmt_read)) begin
if(&mgmt_address) mgmt_cnt <= mgmt_cnt + 1'd1;
else mgmt_cnt <= 0;
end
if(~rst_n) mgmt_cnt <= 0;
end
wire n_data = (mgmt_cnt[13:1] <= io_cnt[13:1]) && drq && fast_read;
reg [1:0] n_data_r;
assign no_data = n_data || n_data_r;
always @(posedge clk) n_data_r <= {n_data_r[0], n_data};
wire [31:0] buf_readdata;
wire [31:0] buf_q;
dpram #(12,16) io_buf0
(
.clock(clk),
.address_a(mgmt_cnt[12:1]),
.data_a(mgmt_writedata),
.wren_a(mgmt_write & &mgmt_address & ~mgmt_cnt[0]),
.q_a(buf_readdata[15:0]),
.address_b(io_cnt[12:1]),
.data_b(io_writedata[15:0]),
.wren_b(write_data_io & (io_32 | ~io_cnt[0])),
.q_b(buf_q[15:0])
);
dpram #(12,16) io_buf1
(
.clock(clk),
.address_a(mgmt_cnt[12:1]),
.data_a(mgmt_writedata),
.wren_a(mgmt_write & &mgmt_address & mgmt_cnt[0]),
.q_a(buf_readdata[31:16]),
.address_b(io_cnt[12:1]),
.data_b(io_32 ? io_writedata[31:16] : io_writedata[15:0]),
.wren_b(write_data_io & (io_32 | io_cnt[0])),
.q_b(buf_q[31:16])
);
//------------------------------------------------------------------------------
endmodule

View File

@@ -6,10 +6,10 @@ module tandy_pcjr_joy
input logic clk, //50Mhz Anything else and the pulse_div values must be adjusted
input logic reset,
input logic en, //Active High. Triggers reading of joystics and generates pulse
input logic [1:0] turbo_mode, //0 - 4.77Mhz 1 - 7.16Mhz 2 - 14.38Mhz
input logic [1:0] clk_select, //0 - 4.77Mhz 1 - 7.16Mhz 2 - 9.54Mhz 3 - PC/AT 286 3.5MHz
input logic [4:0] joy_opts, //bits: 4 - Adjust timing for Turbo, 3 - Disable P2, 2 - P2 Analog/Digital, 1 - Disable P1, 0 - P1 Analog/Digital
input logic [31:0] joy0,
input logic [31:0] joy1,
input logic [13:0] joy0,
input logic [13:0] joy1,
input logic [15:0] joya0,
input logic [15:0] joya1,
output logic [7:0] d_out //Format Bit 7 down to 0: P2Btn2, P2Btn1, P1Btn2, P1Btn1, P2-Y_Axis, P2-X_Axis, P1-Y_Axis, P1-X_Axis
@@ -23,9 +23,9 @@ module tandy_pcjr_joy
logic [9:0] joy1_x;
logic [9:0] joy0_y;
logic [9:0] joy1_y;
logic [7:0] counter; //Clock cycle counter
logic [7:0] pulse_div; //# of clock cycles in each pulse segment according to cpu freq (turbo_mode).
// 4.77Mhz ~ 220, 7.16Mhz ~ 106 and 14.38Mhz ~ 70.
logic [8:0] counter; //Clock cycle counter
logic [8:0] pulse_div; //# of clock cycles in each pulse segment according to cpu freq and clk_select.
// 4.77Mhz ~ 265, 7.16Mhz ~ 200, 9.54Mhz ~ 170 and PC/AT 286 3.5MHz ~ 90.
// These values may need some tweaking to keep joysticks centered.
// The Frogger games has a decent joystick calibration test
@@ -35,27 +35,27 @@ module tandy_pcjr_joy
assign joy1_y = joy_opts[2] ? (joy1[2] ? 8'hFF : joy1[3] ? 8'h00 : 8'h80 ) : 8'd128 + joya1[15:8];
assign pulse_div = joy_opts[4] ? (turbo_mode == 1 ? 8'd106 : turbo_mode == 2 ? 8'd70 : 8'd220) : 8'd220;
assign pulse_div = joy_opts[4] ? (clk_select == 1 ? 9'd200 : clk_select == 2 ? 9'd170 : clk_select == 3 ? 9'd90 : 9'd265) : 9'd265;
always @(posedge clk) begin
reg en_d;
en_d <= en;
if(reset) begin
counter <= 8'h0;
counter <= 9'h0;
end
else if (en && ~en_d) begin
joy0_x_r <= joy0_x[7:0] < 8'h70 || joy0_x[7:0] > 8'h90 ? joy0_x[7:0] : 8'h80;
joy1_x_r <= joy1_x[7:0] < 8'h70 || joy1_x[7:0] > 8'h90 ? joy1_x[7:0] : 8'h80;
joy0_y_r <= joy0_y[7:0] < 8'h70 || joy0_y[7:0] > 8'h90 ? joy0_y[7:0] : 8'h80;
joy1_y_r <= joy1_y[7:0] < 8'h70 || joy1_y[7:0] > 8'h90 ? joy1_y[7:0] : 8'h80;
counter <= 8'h0;
counter <= 9'h0;
end
else if(counter == pulse_div) begin // 8 (185) - 4.77 4 (106) - 7.16 (70) - 14.318
else if(counter == pulse_div) begin
if(joy0_x_r != 0) joy0_x_r <= joy0_x_r - 1'b1;
if(joy1_x_r != 0) joy1_x_r <= joy1_x_r - 1'b1;
if(joy0_y_r != 0) joy0_y_r <= joy0_y_r - 1'b1;
if(joy1_y_r != 0) joy1_y_r <= joy1_y_r - 1'b1;
counter <= 8'h0;
counter <= 9'h0;
end
else counter <= counter + 1'b1;
end

Some files were not shown because too many files have changed in this diff Show More