diff --git a/PCXT.sdc b/PCXT.sdc index 869f364..43dffd7 100644 --- a/PCXT.sdc +++ b/PCXT.sdc @@ -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[*] }] diff --git a/PCXT.sv b/PCXT.sv index 1a03433..33e536d 100644 --- a/PCXT.sv +++ b/PCXT.sv @@ -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; diff --git a/README.md b/README.md index 0d3d673..a295953 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/SW/ROMs/ide_xtl.rom b/SW/ROMs/ide_xtl.rom index 7ec06b1..9592de5 100644 Binary files a/SW/ROMs/ide_xtl.rom and b/SW/ROMs/ide_xtl.rom differ diff --git a/SW/ROMs/pcxt_micro8088.rom b/SW/ROMs/pcxt_micro8088.rom index ab83107..b2b3b8c 100644 Binary files a/SW/ROMs/pcxt_micro8088.rom and b/SW/ROMs/pcxt_micro8088.rom differ diff --git a/SW/ROMs/pcxt_pcxt31.rom b/SW/ROMs/pcxt_pcxt31.rom index cf4a585..904df01 100644 Binary files a/SW/ROMs/pcxt_pcxt31.rom and b/SW/ROMs/pcxt_pcxt31.rom differ diff --git a/SW/XTCTL/XTCTL.C b/SW/XTCTL/XTCTL.C index ab0a2e2..16d2e0c 100644 --- a/SW/XTCTL/XTCTL.C +++ b/SW/XTCTL/XTCTL.C @@ -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); diff --git a/SW/splash.txt b/SW/splash.txt index bd1d10b..9744fcb 100644 --- a/SW/splash.txt +++ b/SW/splash.txt @@ -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 diff --git a/files.qip b/files.qip index 191e7e2..6c7b4eb 100644 --- a/files.qip +++ b/files.qip @@ -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" diff --git a/hdd/XTCTL.EXE b/hdd/XTCTL.EXE index 4c1f859..98811f1 100644 Binary files a/hdd/XTCTL.EXE and b/hdd/XTCTL.EXE differ diff --git a/releases/PCXT_20221124.rbf b/releases/PCXT_20221124.rbf new file mode 100644 index 0000000..18aa8a7 Binary files /dev/null and b/releases/PCXT_20221124.rbf differ diff --git a/rtl/8088/biu_max.v b/rtl/8088/biu_max.v index 4db5874..f82d398 100644 --- a/rtl/8088/biu_max.v +++ b/rtl/8088/biu_max.v @@ -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) diff --git a/rtl/8088/i8088.v b/rtl/8088/i8088.v index 57dc179..c5f0d78 100644 --- a/rtl/8088/i8088.v +++ b/rtl/8088/i8088.v @@ -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), diff --git a/rtl/8088/mcl86_eu_core.v b/rtl/8088/mcl86_eu_core.v index d3e9128..cde3824 100644 --- a/rtl/8088/mcl86_eu_core.v +++ b/rtl/8088/mcl86_eu_core.v @@ -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 \ No newline at end of file +endmodule // eu.v diff --git a/rtl/KFPC-XT/HDL/Chipset.sv b/rtl/KFPC-XT/HDL/Chipset.sv index 83f5e6e..a656e5d 100644 --- a/rtl/KFPC-XT/HDL/Chipset.sv +++ b/rtl/KFPC-XT/HDL/Chipset.sv @@ -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; diff --git a/rtl/KFPC-XT/HDL/KF8253/HDL/KF8253_Counter.sv b/rtl/KFPC-XT/HDL/KF8253/HDL/KF8253_Counter.sv index 260c1ad..bede67d 100644 --- a/rtl/KFPC-XT/HDL/KF8253/HDL/KF8253_Counter.sv +++ b/rtl/KFPC-XT/HDL/KF8253/HDL/KF8253_Counter.sv @@ -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 diff --git a/rtl/KFPC-XT/HDL/Peripherals.sv b/rtl/KFPC-XT/HDL/Peripherals.sv index d6ef5ea..90623f4 100644 --- a/rtl/KFPC-XT/HDL/Peripherals.sv +++ b/rtl/KFPC-XT/HDL/Peripherals.sv @@ -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; diff --git a/rtl/KFPC-XT/HDL/RAM.sv b/rtl/KFPC-XT/HDL/RAM.sv index 16144e8..051857c 100644 --- a/rtl/KFPC-XT/HDL/RAM.sv +++ b/rtl/KFPC-XT/HDL/RAM.sv @@ -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 diff --git a/rtl/KFPC-XT/HDL/XT2IDE.sv b/rtl/KFPC-XT/HDL/XT2IDE.sv new file mode 100644 index 0000000..858f8e0 --- /dev/null +++ b/rtl/KFPC-XT/HDL/XT2IDE.sv @@ -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 diff --git a/rtl/common/bram.vhd b/rtl/common/bram.vhd new file mode 100644 index 0000000..28abdbd --- /dev/null +++ b/rtl/common/bram.vhd @@ -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; \ No newline at end of file diff --git a/rtl/common/common.qip b/rtl/common/common.qip index 303aecf..8edf94a 100644 --- a/rtl/common/common.qip +++ b/rtl/common/common.qip @@ -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 ] diff --git a/rtl/common/ide.v b/rtl/common/ide.v new file mode 100644 index 0000000..3efe611 --- /dev/null +++ b/rtl/common/ide.v @@ -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 diff --git a/rtl/common/tandy_pcjr_joy.sv b/rtl/common/tandy_pcjr_joy.sv index 747f580..f8ccdfb 100644 --- a/rtl/common/tandy_pcjr_joy.sv +++ b/rtl/common/tandy_pcjr_joy.sv @@ -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 diff --git a/rtl/jt89/LICENSE b/rtl/sound/jt89/LICENSE similarity index 100% rename from rtl/jt89/LICENSE rename to rtl/sound/jt89/LICENSE diff --git a/rtl/jt89/README.md b/rtl/sound/jt89/README.md similarity index 100% rename from rtl/jt89/README.md rename to rtl/sound/jt89/README.md diff --git a/rtl/jt89/doc/SN76489 - Development - SMS Power!.pdf b/rtl/sound/jt89/doc/SN76489 - Development - SMS Power!.pdf similarity index 100% rename from rtl/jt89/doc/SN76489 - Development - SMS Power!.pdf rename to rtl/sound/jt89/doc/SN76489 - Development - SMS Power!.pdf diff --git a/rtl/jt89/doc/filter_notes.ods b/rtl/sound/jt89/doc/filter_notes.ods similarity index 100% rename from rtl/jt89/doc/filter_notes.ods rename to rtl/sound/jt89/doc/filter_notes.ods diff --git a/rtl/jt89/doc/notes.ods b/rtl/sound/jt89/doc/notes.ods similarity index 100% rename from rtl/jt89/doc/notes.ods rename to rtl/sound/jt89/doc/notes.ods diff --git a/rtl/jt89/doc/texas_instruments_sn76489an.pdf b/rtl/sound/jt89/doc/texas_instruments_sn76489an.pdf similarity index 100% rename from rtl/jt89/doc/texas_instruments_sn76489an.pdf rename to rtl/sound/jt89/doc/texas_instruments_sn76489an.pdf diff --git a/rtl/jt89/hdl/jt89.qip b/rtl/sound/jt89/hdl/jt89.qip similarity index 100% rename from rtl/jt89/hdl/jt89.qip rename to rtl/sound/jt89/hdl/jt89.qip diff --git a/rtl/jt89/hdl/jt89.v b/rtl/sound/jt89/hdl/jt89.v similarity index 100% rename from rtl/jt89/hdl/jt89.v rename to rtl/sound/jt89/hdl/jt89.v diff --git a/rtl/jt89/hdl/jt89.vhd b/rtl/sound/jt89/hdl/jt89.vhd similarity index 100% rename from rtl/jt89/hdl/jt89.vhd rename to rtl/sound/jt89/hdl/jt89.vhd diff --git a/rtl/jt89/hdl/jt89.yaml b/rtl/sound/jt89/hdl/jt89.yaml similarity index 100% rename from rtl/jt89/hdl/jt89.yaml rename to rtl/sound/jt89/hdl/jt89.yaml diff --git a/rtl/jt89/hdl/jt89_mixer.v b/rtl/sound/jt89/hdl/jt89_mixer.v similarity index 100% rename from rtl/jt89/hdl/jt89_mixer.v rename to rtl/sound/jt89/hdl/jt89_mixer.v diff --git a/rtl/jt89/hdl/jt89_noise.v b/rtl/sound/jt89/hdl/jt89_noise.v similarity index 100% rename from rtl/jt89/hdl/jt89_noise.v rename to rtl/sound/jt89/hdl/jt89_noise.v diff --git a/rtl/jt89/hdl/jt89_sms.v b/rtl/sound/jt89/hdl/jt89_sms.v similarity index 100% rename from rtl/jt89/hdl/jt89_sms.v rename to rtl/sound/jt89/hdl/jt89_sms.v diff --git a/rtl/jt89/hdl/jt89_sms.vhd b/rtl/sound/jt89/hdl/jt89_sms.vhd similarity index 100% rename from rtl/jt89/hdl/jt89_sms.vhd rename to rtl/sound/jt89/hdl/jt89_sms.vhd diff --git a/rtl/jt89/hdl/jt89_tone.v b/rtl/sound/jt89/hdl/jt89_tone.v similarity index 100% rename from rtl/jt89/hdl/jt89_tone.v rename to rtl/sound/jt89/hdl/jt89_tone.v diff --git a/rtl/jt89/hdl/jt89_vol.v b/rtl/sound/jt89/hdl/jt89_vol.v similarity index 100% rename from rtl/jt89/hdl/jt89_vol.v rename to rtl/sound/jt89/hdl/jt89_vol.v diff --git a/rtl/jt89/hdl/mixer/jt12_comb.v b/rtl/sound/jt89/hdl/mixer/jt12_comb.v similarity index 100% rename from rtl/jt89/hdl/mixer/jt12_comb.v rename to rtl/sound/jt89/hdl/mixer/jt12_comb.v diff --git a/rtl/jt89/hdl/mixer/jt12_dac2.v b/rtl/sound/jt89/hdl/mixer/jt12_dac2.v similarity index 100% rename from rtl/jt89/hdl/mixer/jt12_dac2.v rename to rtl/sound/jt89/hdl/mixer/jt12_dac2.v diff --git a/rtl/jt89/hdl/mixer/jt12_interpol.v b/rtl/sound/jt89/hdl/mixer/jt12_interpol.v similarity index 100% rename from rtl/jt89/hdl/mixer/jt12_interpol.v rename to rtl/sound/jt89/hdl/mixer/jt12_interpol.v diff --git a/rtl/jt89/syn/quartus/jt89.qip b/rtl/sound/jt89/syn/quartus/jt89.qip similarity index 100% rename from rtl/jt89/syn/quartus/jt89.qip rename to rtl/sound/jt89/syn/quartus/jt89.qip diff --git a/rtl/jt89/syn/quartus/jt89_sms.qip b/rtl/sound/jt89/syn/quartus/jt89_sms.qip similarity index 100% rename from rtl/jt89/syn/quartus/jt89_sms.qip rename to rtl/sound/jt89/syn/quartus/jt89_sms.qip diff --git a/rtl/jt89/syn/quartus/jt89_verilog.qip b/rtl/sound/jt89/syn/quartus/jt89_verilog.qip similarity index 100% rename from rtl/jt89/syn/quartus/jt89_verilog.qip rename to rtl/sound/jt89/syn/quartus/jt89_verilog.qip diff --git a/rtl/jt89/ver/jt89_tb/go b/rtl/sound/jt89/ver/jt89_tb/go similarity index 100% rename from rtl/jt89/ver/jt89_tb/go rename to rtl/sound/jt89/ver/jt89_tb/go diff --git a/rtl/jt89/ver/jt89_tb/inputs.cc b/rtl/sound/jt89/ver/jt89_tb/inputs.cc similarity index 100% rename from rtl/jt89/ver/jt89_tb/inputs.cc rename to rtl/sound/jt89/ver/jt89_tb/inputs.cc diff --git a/rtl/jt89/ver/jt89_tb/jt89_tb.v b/rtl/sound/jt89/ver/jt89_tb/jt89_tb.v similarity index 100% rename from rtl/jt89/ver/jt89_tb/jt89_tb.v rename to rtl/sound/jt89/ver/jt89_tb/jt89_tb.v diff --git a/rtl/jt89/ver/verilator/go b/rtl/sound/jt89/ver/verilator/go similarity index 100% rename from rtl/jt89/ver/verilator/go rename to rtl/sound/jt89/ver/verilator/go diff --git a/rtl/jt89/ver/verilator/test.cpp b/rtl/sound/jt89/ver/verilator/test.cpp similarity index 100% rename from rtl/jt89/ver/verilator/test.cpp rename to rtl/sound/jt89/ver/verilator/test.cpp diff --git a/rtl/jt89/ver/verilator/test.gtkw b/rtl/sound/jt89/ver/verilator/test.gtkw similarity index 100% rename from rtl/jt89/ver/verilator/test.gtkw rename to rtl/sound/jt89/ver/verilator/test.gtkw diff --git a/rtl/jt89/ver/verilator/tests/1.jtt b/rtl/sound/jt89/ver/verilator/tests/1.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/1.jtt rename to rtl/sound/jt89/ver/verilator/tests/1.jtt diff --git a/rtl/jt89/ver/verilator/tests/dr.jtt b/rtl/sound/jt89/ver/verilator/tests/dr.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/dr.jtt rename to rtl/sound/jt89/ver/verilator/tests/dr.jtt diff --git a/rtl/jt89/ver/verilator/tests/no-ch2.jtt b/rtl/sound/jt89/ver/verilator/tests/no-ch2.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/no-ch2.jtt rename to rtl/sound/jt89/ver/verilator/tests/no-ch2.jtt diff --git a/rtl/jt89/ver/verilator/tests/vol.jtt b/rtl/sound/jt89/ver/verilator/tests/vol.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/vol.jtt rename to rtl/sound/jt89/ver/verilator/tests/vol.jtt diff --git a/rtl/jt89/ver/verilator/tests/vol2-ch1.jtt b/rtl/sound/jt89/ver/verilator/tests/vol2-ch1.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/vol2-ch1.jtt rename to rtl/sound/jt89/ver/verilator/tests/vol2-ch1.jtt diff --git a/rtl/jt89/ver/verilator/tests/vol2-ch2.jtt b/rtl/sound/jt89/ver/verilator/tests/vol2-ch2.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/vol2-ch2.jtt rename to rtl/sound/jt89/ver/verilator/tests/vol2-ch2.jtt diff --git a/rtl/jt89/ver/verilator/tests/vol2-ch3.jtt b/rtl/sound/jt89/ver/verilator/tests/vol2-ch3.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/vol2-ch3.jtt rename to rtl/sound/jt89/ver/verilator/tests/vol2-ch3.jtt diff --git a/rtl/jt89/ver/verilator/tests/vol2.jtt b/rtl/sound/jt89/ver/verilator/tests/vol2.jtt similarity index 100% rename from rtl/jt89/ver/verilator/tests/vol2.jtt rename to rtl/sound/jt89/ver/verilator/tests/vol2.jtt diff --git a/rtl/jtopl/LICENSE b/rtl/sound/jtopl/LICENSE similarity index 100% rename from rtl/jtopl/LICENSE rename to rtl/sound/jtopl/LICENSE diff --git a/rtl/jtopl/README.md b/rtl/sound/jtopl/README.md similarity index 100% rename from rtl/jtopl/README.md rename to rtl/sound/jtopl/README.md diff --git a/rtl/jtopl/doc/Makefile b/rtl/sound/jtopl/doc/Makefile similarity index 100% rename from rtl/jtopl/doc/Makefile rename to rtl/sound/jtopl/doc/Makefile diff --git a/rtl/jtopl/doc/Y8950 app notes.pdf b/rtl/sound/jtopl/doc/Y8950 app notes.pdf similarity index 100% rename from rtl/jtopl/doc/Y8950 app notes.pdf rename to rtl/sound/jtopl/doc/Y8950 app notes.pdf diff --git a/rtl/jtopl/doc/Y8950 datasheet.pdf b/rtl/sound/jtopl/doc/Y8950 datasheet.pdf similarity index 100% rename from rtl/jtopl/doc/Y8950 datasheet.pdf rename to rtl/sound/jtopl/doc/Y8950 datasheet.pdf diff --git a/rtl/jtopl/doc/YM2413.pdf b/rtl/sound/jtopl/doc/YM2413.pdf similarity index 100% rename from rtl/jtopl/doc/YM2413.pdf rename to rtl/sound/jtopl/doc/YM2413.pdf diff --git a/rtl/jtopl/doc/YM3812 datasheet.pdf b/rtl/sound/jtopl/doc/YM3812 datasheet.pdf similarity index 100% rename from rtl/jtopl/doc/YM3812 datasheet.pdf rename to rtl/sound/jtopl/doc/YM3812 datasheet.pdf diff --git a/rtl/jtopl/doc/Yamaha YM3812 Application Manual.pdf b/rtl/sound/jtopl/doc/Yamaha YM3812 Application Manual.pdf similarity index 100% rename from rtl/jtopl/doc/Yamaha YM3812 Application Manual.pdf rename to rtl/sound/jtopl/doc/Yamaha YM3812 Application Manual.pdf diff --git a/rtl/jtopl/doc/lfo_count.cc b/rtl/sound/jtopl/doc/lfo_count.cc similarity index 100% rename from rtl/jtopl/doc/lfo_count.cc rename to rtl/sound/jtopl/doc/lfo_count.cc diff --git a/rtl/jtopl/doc/notes.ods b/rtl/sound/jtopl/doc/notes.ods similarity index 100% rename from rtl/jtopl/doc/notes.ods rename to rtl/sound/jtopl/doc/notes.ods diff --git a/rtl/jtopl/doc/opl3.c b/rtl/sound/jtopl/doc/opl3.c similarity index 100% rename from rtl/jtopl/doc/opl3.c rename to rtl/sound/jtopl/doc/opl3.c diff --git a/rtl/jtopl/doc/opl3.h b/rtl/sound/jtopl/doc/opl3.h similarity index 100% rename from rtl/jtopl/doc/opl3.h rename to rtl/sound/jtopl/doc/opl3.h diff --git a/rtl/jtopl/doc/opll.c b/rtl/sound/jtopl/doc/opll.c similarity index 100% rename from rtl/jtopl/doc/opll.c rename to rtl/sound/jtopl/doc/opll.c diff --git a/rtl/jtopl/doc/opll.h b/rtl/sound/jtopl/doc/opll.h similarity index 100% rename from rtl/jtopl/doc/opll.h rename to rtl/sound/jtopl/doc/opll.h diff --git a/rtl/jtopl/doc/opll_patches.c b/rtl/sound/jtopl/doc/opll_patches.c similarity index 100% rename from rtl/jtopl/doc/opll_patches.c rename to rtl/sound/jtopl/doc/opll_patches.c diff --git a/rtl/jtopl/doc/ym2413 app notes.pdf b/rtl/sound/jtopl/doc/ym2413 app notes.pdf similarity index 100% rename from rtl/jtopl/doc/ym2413 app notes.pdf rename to rtl/sound/jtopl/doc/ym2413 app notes.pdf diff --git a/rtl/jtopl/hdl/common.yaml b/rtl/sound/jtopl/hdl/common.yaml similarity index 100% rename from rtl/jtopl/hdl/common.yaml rename to rtl/sound/jtopl/hdl/common.yaml diff --git a/rtl/jtopl/hdl/jt2413.v b/rtl/sound/jtopl/hdl/jt2413.v similarity index 100% rename from rtl/jtopl/hdl/jt2413.v rename to rtl/sound/jtopl/hdl/jt2413.v diff --git a/rtl/jtopl/hdl/jt2413.yaml b/rtl/sound/jtopl/hdl/jt2413.yaml similarity index 100% rename from rtl/jtopl/hdl/jt2413.yaml rename to rtl/sound/jtopl/hdl/jt2413.yaml diff --git a/rtl/jtopl/hdl/jt26.qip b/rtl/sound/jtopl/hdl/jt26.qip similarity index 100% rename from rtl/jtopl/hdl/jt26.qip rename to rtl/sound/jtopl/hdl/jt26.qip diff --git a/rtl/jtopl/hdl/jt26.yaml b/rtl/sound/jtopl/hdl/jt26.yaml similarity index 100% rename from rtl/jtopl/hdl/jt26.yaml rename to rtl/sound/jtopl/hdl/jt26.yaml diff --git a/rtl/jtopl/hdl/jtopl.v b/rtl/sound/jtopl/hdl/jtopl.v similarity index 100% rename from rtl/jtopl/hdl/jtopl.v rename to rtl/sound/jtopl/hdl/jtopl.v diff --git a/rtl/jtopl/hdl/jtopl.yaml b/rtl/sound/jtopl/hdl/jtopl.yaml similarity index 100% rename from rtl/jtopl/hdl/jtopl.yaml rename to rtl/sound/jtopl/hdl/jtopl.yaml diff --git a/rtl/jtopl/hdl/jtopl2.qip b/rtl/sound/jtopl/hdl/jtopl2.qip similarity index 100% rename from rtl/jtopl/hdl/jtopl2.qip rename to rtl/sound/jtopl/hdl/jtopl2.qip diff --git a/rtl/jtopl/hdl/jtopl2.v b/rtl/sound/jtopl/hdl/jtopl2.v similarity index 100% rename from rtl/jtopl/hdl/jtopl2.v rename to rtl/sound/jtopl/hdl/jtopl2.v diff --git a/rtl/jtopl/hdl/jtopl2.yaml b/rtl/sound/jtopl/hdl/jtopl2.yaml similarity index 100% rename from rtl/jtopl/hdl/jtopl2.yaml rename to rtl/sound/jtopl/hdl/jtopl2.yaml diff --git a/rtl/jtopl/hdl/jtopl_acc.v b/rtl/sound/jtopl/hdl/jtopl_acc.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_acc.v rename to rtl/sound/jtopl/hdl/jtopl_acc.v diff --git a/rtl/jtopl/hdl/jtopl_csr.v b/rtl/sound/jtopl/hdl/jtopl_csr.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_csr.v rename to rtl/sound/jtopl/hdl/jtopl_csr.v diff --git a/rtl/jtopl/hdl/jtopl_div.v b/rtl/sound/jtopl/hdl/jtopl_div.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_div.v rename to rtl/sound/jtopl/hdl/jtopl_div.v diff --git a/rtl/jtopl/hdl/jtopl_eg.v b/rtl/sound/jtopl/hdl/jtopl_eg.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_eg.v rename to rtl/sound/jtopl/hdl/jtopl_eg.v diff --git a/rtl/jtopl/hdl/jtopl_eg_cnt.v b/rtl/sound/jtopl/hdl/jtopl_eg_cnt.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_eg_cnt.v rename to rtl/sound/jtopl/hdl/jtopl_eg_cnt.v diff --git a/rtl/jtopl/hdl/jtopl_eg_comb.v b/rtl/sound/jtopl/hdl/jtopl_eg_comb.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_eg_comb.v rename to rtl/sound/jtopl/hdl/jtopl_eg_comb.v diff --git a/rtl/jtopl/hdl/jtopl_eg_ctrl.v b/rtl/sound/jtopl/hdl/jtopl_eg_ctrl.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_eg_ctrl.v rename to rtl/sound/jtopl/hdl/jtopl_eg_ctrl.v diff --git a/rtl/jtopl/hdl/jtopl_eg_final.v b/rtl/sound/jtopl/hdl/jtopl_eg_final.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_eg_final.v rename to rtl/sound/jtopl/hdl/jtopl_eg_final.v diff --git a/rtl/jtopl/hdl/jtopl_eg_pure.v b/rtl/sound/jtopl/hdl/jtopl_eg_pure.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_eg_pure.v rename to rtl/sound/jtopl/hdl/jtopl_eg_pure.v diff --git a/rtl/jtopl/hdl/jtopl_eg_step.v b/rtl/sound/jtopl/hdl/jtopl_eg_step.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_eg_step.v rename to rtl/sound/jtopl/hdl/jtopl_eg_step.v diff --git a/rtl/jtopl/hdl/jtopl_exprom.v b/rtl/sound/jtopl/hdl/jtopl_exprom.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_exprom.v rename to rtl/sound/jtopl/hdl/jtopl_exprom.v diff --git a/rtl/jtopl/hdl/jtopl_lfo.v b/rtl/sound/jtopl/hdl/jtopl_lfo.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_lfo.v rename to rtl/sound/jtopl/hdl/jtopl_lfo.v diff --git a/rtl/jtopl/hdl/jtopl_logsin.v b/rtl/sound/jtopl/hdl/jtopl_logsin.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_logsin.v rename to rtl/sound/jtopl/hdl/jtopl_logsin.v diff --git a/rtl/jtopl/hdl/jtopl_mmr.v b/rtl/sound/jtopl/hdl/jtopl_mmr.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_mmr.v rename to rtl/sound/jtopl/hdl/jtopl_mmr.v diff --git a/rtl/jtopl/hdl/jtopl_noise.v b/rtl/sound/jtopl/hdl/jtopl_noise.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_noise.v rename to rtl/sound/jtopl/hdl/jtopl_noise.v diff --git a/rtl/jtopl/hdl/jtopl_op.v b/rtl/sound/jtopl/hdl/jtopl_op.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_op.v rename to rtl/sound/jtopl/hdl/jtopl_op.v diff --git a/rtl/jtopl/hdl/jtopl_pg.v b/rtl/sound/jtopl/hdl/jtopl_pg.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_pg.v rename to rtl/sound/jtopl/hdl/jtopl_pg.v diff --git a/rtl/jtopl/hdl/jtopl_pg_comb.v b/rtl/sound/jtopl/hdl/jtopl_pg_comb.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_pg_comb.v rename to rtl/sound/jtopl/hdl/jtopl_pg_comb.v diff --git a/rtl/jtopl/hdl/jtopl_pg_inc.v b/rtl/sound/jtopl/hdl/jtopl_pg_inc.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_pg_inc.v rename to rtl/sound/jtopl/hdl/jtopl_pg_inc.v diff --git a/rtl/jtopl/hdl/jtopl_pg_rhy.v b/rtl/sound/jtopl/hdl/jtopl_pg_rhy.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_pg_rhy.v rename to rtl/sound/jtopl/hdl/jtopl_pg_rhy.v diff --git a/rtl/jtopl/hdl/jtopl_pg_sum.v b/rtl/sound/jtopl/hdl/jtopl_pg_sum.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_pg_sum.v rename to rtl/sound/jtopl/hdl/jtopl_pg_sum.v diff --git a/rtl/jtopl/hdl/jtopl_pm.v b/rtl/sound/jtopl/hdl/jtopl_pm.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_pm.v rename to rtl/sound/jtopl/hdl/jtopl_pm.v diff --git a/rtl/jtopl/hdl/jtopl_reg.v b/rtl/sound/jtopl/hdl/jtopl_reg.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_reg.v rename to rtl/sound/jtopl/hdl/jtopl_reg.v diff --git a/rtl/jtopl/hdl/jtopl_reg_ch.v b/rtl/sound/jtopl/hdl/jtopl_reg_ch.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_reg_ch.v rename to rtl/sound/jtopl/hdl/jtopl_reg_ch.v diff --git a/rtl/jtopl/hdl/jtopl_sh.v b/rtl/sound/jtopl/hdl/jtopl_sh.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_sh.v rename to rtl/sound/jtopl/hdl/jtopl_sh.v diff --git a/rtl/jtopl/hdl/jtopl_sh_rst.v b/rtl/sound/jtopl/hdl/jtopl_sh_rst.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_sh_rst.v rename to rtl/sound/jtopl/hdl/jtopl_sh_rst.v diff --git a/rtl/jtopl/hdl/jtopl_single_acc.v b/rtl/sound/jtopl/hdl/jtopl_single_acc.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_single_acc.v rename to rtl/sound/jtopl/hdl/jtopl_single_acc.v diff --git a/rtl/jtopl/hdl/jtopl_slot_cnt.v b/rtl/sound/jtopl/hdl/jtopl_slot_cnt.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_slot_cnt.v rename to rtl/sound/jtopl/hdl/jtopl_slot_cnt.v diff --git a/rtl/jtopl/hdl/jtopl_timers.v b/rtl/sound/jtopl/hdl/jtopl_timers.v similarity index 100% rename from rtl/jtopl/hdl/jtopl_timers.v rename to rtl/sound/jtopl/hdl/jtopl_timers.v diff --git a/rtl/jtopl/hdl/jtopll.yaml b/rtl/sound/jtopl/hdl/jtopll.yaml similarity index 100% rename from rtl/jtopl/hdl/jtopll.yaml rename to rtl/sound/jtopl/hdl/jtopll.yaml diff --git a/rtl/jtopl/hdl/jtopll_mmr.v b/rtl/sound/jtopl/hdl/jtopll_mmr.v similarity index 100% rename from rtl/jtopl/hdl/jtopll_mmr.v rename to rtl/sound/jtopl/hdl/jtopll_mmr.v diff --git a/rtl/jtopl/hdl/jtopll_reg.v b/rtl/sound/jtopl/hdl/jtopll_reg.v similarity index 100% rename from rtl/jtopl/hdl/jtopll_reg.v rename to rtl/sound/jtopl/hdl/jtopll_reg.v diff --git a/rtl/jtopl/ver/jtopl_eg/sweep.cpp b/rtl/sound/jtopl/ver/jtopl_eg/sweep.cpp similarity index 100% rename from rtl/jtopl/ver/jtopl_eg/sweep.cpp rename to rtl/sound/jtopl/ver/jtopl_eg/sweep.cpp diff --git a/rtl/jtopl/ver/jtopl_eg/sweep.sh b/rtl/sound/jtopl/ver/jtopl_eg/sweep.sh similarity index 100% rename from rtl/jtopl/ver/jtopl_eg/sweep.sh rename to rtl/sound/jtopl/ver/jtopl_eg/sweep.sh diff --git a/rtl/jtopl/ver/jtopl_eg/sweep.v b/rtl/sound/jtopl/ver/jtopl_eg/sweep.v similarity index 100% rename from rtl/jtopl/ver/jtopl_eg/sweep.v rename to rtl/sound/jtopl/ver/jtopl_eg/sweep.v diff --git a/rtl/jtopl/ver/jtopl_eg_comb_tb/README b/rtl/sound/jtopl/ver/jtopl_eg_comb_tb/README similarity index 100% rename from rtl/jtopl/ver/jtopl_eg_comb_tb/README rename to rtl/sound/jtopl/ver/jtopl_eg_comb_tb/README diff --git a/rtl/jtopl/ver/jtopl_eg_comb_tb/sim.sh b/rtl/sound/jtopl/ver/jtopl_eg_comb_tb/sim.sh similarity index 100% rename from rtl/jtopl/ver/jtopl_eg_comb_tb/sim.sh rename to rtl/sound/jtopl/ver/jtopl_eg_comb_tb/sim.sh diff --git a/rtl/jtopl/ver/jtopl_eg_comb_tb/test.cpp b/rtl/sound/jtopl/ver/jtopl_eg_comb_tb/test.cpp similarity index 100% rename from rtl/jtopl/ver/jtopl_eg_comb_tb/test.cpp rename to rtl/sound/jtopl/ver/jtopl_eg_comb_tb/test.cpp diff --git a/rtl/jtopl/ver/jtopl_eg_comb_tb/test.v b/rtl/sound/jtopl/ver/jtopl_eg_comb_tb/test.v similarity index 100% rename from rtl/jtopl/ver/jtopl_eg_comb_tb/test.v rename to rtl/sound/jtopl/ver/jtopl_eg_comb_tb/test.v diff --git a/rtl/jtopl/ver/jtopl_eg_comb_tb/tests/attack.tst b/rtl/sound/jtopl/ver/jtopl_eg_comb_tb/tests/attack.tst similarity index 100% rename from rtl/jtopl/ver/jtopl_eg_comb_tb/tests/attack.tst rename to rtl/sound/jtopl/ver/jtopl_eg_comb_tb/tests/attack.tst diff --git a/rtl/jtopl/ver/verilator/VGMParser.cpp b/rtl/sound/jtopl/ver/verilator/VGMParser.cpp similarity index 100% rename from rtl/jtopl/ver/verilator/VGMParser.cpp rename to rtl/sound/jtopl/ver/verilator/VGMParser.cpp diff --git a/rtl/jtopl/ver/verilator/VGMParser.hpp b/rtl/sound/jtopl/ver/verilator/VGMParser.hpp similarity index 100% rename from rtl/jtopl/ver/verilator/VGMParser.hpp rename to rtl/sound/jtopl/ver/verilator/VGMParser.hpp diff --git a/rtl/jtopl/ver/verilator/WaveWritter.cpp b/rtl/sound/jtopl/ver/verilator/WaveWritter.cpp similarity index 100% rename from rtl/jtopl/ver/verilator/WaveWritter.cpp rename to rtl/sound/jtopl/ver/verilator/WaveWritter.cpp diff --git a/rtl/jtopl/ver/verilator/WaveWritter.hpp b/rtl/sound/jtopl/ver/verilator/WaveWritter.hpp similarity index 100% rename from rtl/jtopl/ver/verilator/WaveWritter.hpp rename to rtl/sound/jtopl/ver/verilator/WaveWritter.hpp diff --git a/rtl/jtopl/ver/verilator/feature.hpp b/rtl/sound/jtopl/ver/verilator/feature.hpp similarity index 100% rename from rtl/jtopl/ver/verilator/feature.hpp rename to rtl/sound/jtopl/ver/verilator/feature.hpp diff --git a/rtl/jtopl/ver/verilator/mmr.lut b/rtl/sound/jtopl/ver/verilator/mmr.lut similarity index 100% rename from rtl/jtopl/ver/verilator/mmr.lut rename to rtl/sound/jtopl/ver/verilator/mmr.lut diff --git a/rtl/jtopl/ver/verilator/sim.sh b/rtl/sound/jtopl/ver/verilator/sim.sh similarity index 100% rename from rtl/jtopl/ver/verilator/sim.sh rename to rtl/sound/jtopl/ver/verilator/sim.sh diff --git a/rtl/jtopl/ver/verilator/test.cpp b/rtl/sound/jtopl/ver/verilator/test.cpp similarity index 100% rename from rtl/jtopl/ver/verilator/test.cpp rename to rtl/sound/jtopl/ver/verilator/test.cpp diff --git a/rtl/jtopl/ver/verilator/tests/am.jtt b/rtl/sound/jtopl/ver/verilator/tests/am.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/am.jtt rename to rtl/sound/jtopl/ver/verilator/tests/am.jtt diff --git a/rtl/jtopl/ver/verilator/tests/fb.jtt b/rtl/sound/jtopl/ver/verilator/tests/fb.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/fb.jtt rename to rtl/sound/jtopl/ver/verilator/tests/fb.jtt diff --git a/rtl/jtopl/ver/verilator/tests/fnum.jtt b/rtl/sound/jtopl/ver/verilator/tests/fnum.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/fnum.jtt rename to rtl/sound/jtopl/ver/verilator/tests/fnum.jtt diff --git a/rtl/jtopl/ver/verilator/tests/keycode.jtt b/rtl/sound/jtopl/ver/verilator/tests/keycode.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/keycode.jtt rename to rtl/sound/jtopl/ver/verilator/tests/keycode.jtt diff --git a/rtl/jtopl/ver/verilator/tests/ksl1.jtt b/rtl/sound/jtopl/ver/verilator/tests/ksl1.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/ksl1.jtt rename to rtl/sound/jtopl/ver/verilator/tests/ksl1.jtt diff --git a/rtl/jtopl/ver/verilator/tests/ksl2.jtt b/rtl/sound/jtopl/ver/verilator/tests/ksl2.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/ksl2.jtt rename to rtl/sound/jtopl/ver/verilator/tests/ksl2.jtt diff --git a/rtl/jtopl/ver/verilator/tests/ksl3.jtt b/rtl/sound/jtopl/ver/verilator/tests/ksl3.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/ksl3.jtt rename to rtl/sound/jtopl/ver/verilator/tests/ksl3.jtt diff --git a/rtl/jtopl/ver/verilator/tests/mod.jtt b/rtl/sound/jtopl/ver/verilator/tests/mod.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/mod.jtt rename to rtl/sound/jtopl/ver/verilator/tests/mod.jtt diff --git a/rtl/jtopl/ver/verilator/tests/noteG.jtt b/rtl/sound/jtopl/ver/verilator/tests/noteG.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/noteG.jtt rename to rtl/sound/jtopl/ver/verilator/tests/noteG.jtt diff --git a/rtl/jtopl/ver/verilator/tests/perc.jtt b/rtl/sound/jtopl/ver/verilator/tests/perc.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/perc.jtt rename to rtl/sound/jtopl/ver/verilator/tests/perc.jtt diff --git a/rtl/jtopl/ver/verilator/tests/rates.jtt b/rtl/sound/jtopl/ver/verilator/tests/rates.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/rates.jtt rename to rtl/sound/jtopl/ver/verilator/tests/rates.jtt diff --git a/rtl/jtopl/ver/verilator/tests/slots.jtt b/rtl/sound/jtopl/ver/verilator/tests/slots.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/slots.jtt rename to rtl/sound/jtopl/ver/verilator/tests/slots.jtt diff --git a/rtl/jtopl/ver/verilator/tests/slots_mod.jtt b/rtl/sound/jtopl/ver/verilator/tests/slots_mod.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/slots_mod.jtt rename to rtl/sound/jtopl/ver/verilator/tests/slots_mod.jtt diff --git a/rtl/jtopl/ver/verilator/tests/timers.jtt b/rtl/sound/jtopl/ver/verilator/tests/timers.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/timers.jtt rename to rtl/sound/jtopl/ver/verilator/tests/timers.jtt diff --git a/rtl/jtopl/ver/verilator/tests/tl.jtt b/rtl/sound/jtopl/ver/verilator/tests/tl.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/tl.jtt rename to rtl/sound/jtopl/ver/verilator/tests/tl.jtt diff --git a/rtl/jtopl/ver/verilator/tests/tone.jtt b/rtl/sound/jtopl/ver/verilator/tests/tone.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/tone.jtt rename to rtl/sound/jtopl/ver/verilator/tests/tone.jtt diff --git a/rtl/jtopl/ver/verilator/tests/tone_w1.jtt b/rtl/sound/jtopl/ver/verilator/tests/tone_w1.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/tone_w1.jtt rename to rtl/sound/jtopl/ver/verilator/tests/tone_w1.jtt diff --git a/rtl/jtopl/ver/verilator/tests/tone_w2.jtt b/rtl/sound/jtopl/ver/verilator/tests/tone_w2.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/tone_w2.jtt rename to rtl/sound/jtopl/ver/verilator/tests/tone_w2.jtt diff --git a/rtl/jtopl/ver/verilator/tests/tone_w3.jtt b/rtl/sound/jtopl/ver/verilator/tests/tone_w3.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/tone_w3.jtt rename to rtl/sound/jtopl/ver/verilator/tests/tone_w3.jtt diff --git a/rtl/jtopl/ver/verilator/tests/vib.jtt b/rtl/sound/jtopl/ver/verilator/tests/vib.jtt similarity index 100% rename from rtl/jtopl/ver/verilator/tests/vib.jtt rename to rtl/sound/jtopl/ver/verilator/tests/vib.jtt diff --git a/rtl/sound/saa1099.sv b/rtl/sound/saa1099.sv new file mode 100644 index 0000000..065e319 --- /dev/null +++ b/rtl/sound/saa1099.sv @@ -0,0 +1,403 @@ +//============================================================================ +// +// SAA1099 sound generator +// Copyright (C) 2016-2019 Sorgelig +// +// Based on SAA1099.v code from Miguel Angel Rodriguez Jodar +// Based on SAASound code from Dave Hooper +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ +`timescale 1ns / 1ps +//`default_nettype none + + +module saa1099 +( + input clk_sys, + input ce, // 8 MHz + input rst_n, + input cs_n, + input a0, // 0=data, 1=address + input wr_n, + input [7:0] din, + output [7:0] out_l, + output [7:0] out_r +); + +reg [7:0] amplit0, amplit1, amplit2, amplit3, amplit4, amplit5; +reg [7:0] freq0, freq1, freq2, freq3, freq4, freq5; +reg [7:0] oct10, oct32, oct54; +reg [7:0] freqenable; +reg [7:0] noiseenable; +reg [7:0] noisegen; +reg [7:0] envelope0, envelope1; +reg [7:0] ctrl; + +reg [4:0] addr; +wire rst = ~rst_n | ctrl[1]; +reg wr; + +always @(posedge clk_sys) begin + reg old_wr; + old_wr <= wr_n; + + wr <= 0; + if(~rst_n) begin + addr <= 0; + {amplit0, amplit1, amplit2, amplit3, amplit4, amplit5} <= 0; + {freq0, freq1, freq2, freq3, freq4, freq5} <= 0; + {oct10, oct32, oct54} <= 0; + {freqenable, noiseenable, noisegen} <= 0; + {envelope0, envelope1} <= 0; + ctrl <= 0; + end + else begin + if(!cs_n & old_wr & !wr_n) begin + wr <= 1; + if(a0) addr <= din[4:0]; + else begin + case (addr) + 'h00: amplit0 <= din; + 'h01: amplit1 <= din; + 'h02: amplit2 <= din; + 'h03: amplit3 <= din; + 'h04: amplit4 <= din; + 'h05: amplit5 <= din; + + 'h08: freq0 <= din; + 'h09: freq1 <= din; + 'h0A: freq2 <= din; + 'h0B: freq3 <= din; + 'h0C: freq4 <= din; + 'h0D: freq5 <= din; + + 'h10: oct10 <= din; + 'h11: oct32 <= din; + 'h12: oct54 <= din; + + 'h14: freqenable <= din; + 'h15: noiseenable<= din; + 'h16: noisegen <= din; + + 'h18: envelope0 <= din; + 'h19: envelope1 <= din; + + 'h1C: ctrl <= din; + endcase + end + end + end +end + +wire [21:0] out0; +saa1099_triplet top +( + .*, + .vol('{amplit0, amplit1, amplit2}), + .env(envelope0), + + .freq('{freq0, freq1, freq2}), + .octave('{oct10[2:0], oct10[6:4], oct32[2:0]}), + .freq_en(freqenable[2:0]), + + .noise_en(noiseenable[2:0]), + .noise_freq(noisegen[1:0]), + + .wr_addr(wr & a0 & (din[4:0] == 'h18)), + .wr_data(wr & !a0 & (addr == 'h18)), + + .out(out0) +); + +wire [21:0] out1; +saa1099_triplet bottom +( + .*, + .vol('{amplit3, amplit4, amplit5}), + .env(envelope1), + + .freq('{freq3, freq4, freq5}), + .octave('{oct32[6:4], oct54[2:0], oct54[6:4]}), + .freq_en(freqenable[5:3]), + + .noise_en(noiseenable[5:3]), + .noise_freq(noisegen[5:4]), + + .wr_addr(wr & a0 & (din[4:0] == 'h19)), + .wr_data(wr & !a0 & (addr == 'h19)), + + .out(out1) +); + +saa1099_output_mixer outmix_l(.*, .en(ctrl[0]), .in0(out0[10:0]), .in1(out1[10:0]), .out(out_l)); +saa1099_output_mixer outmix_r(.*, .en(ctrl[0]), .in0(out0[21:11]), .in1(out1[21:11]), .out(out_r)); + +endmodule + +///////////////////////////////////////////////////////////////////////////////// +module saa1099_triplet +( + input rst, + input clk_sys, + input ce, + + input [7:0] vol[3], + input [7:0] env, + + input [7:0] freq[3], + input [2:0] octave[3], + input [2:0] freq_en, + + input [2:0] noise_en, + input [1:0] noise_freq, + + input wr_addr, + input wr_data, + + output[21:0] out +); + +wire tone0, tone1, tone2, noise; +wire pulse_noise, pulse_envelope; +wire[17:0] out0, out1, out2; + +saa1099_tone freq_gen0(.*, .out(tone0), .octave(octave[0]), .freq(freq[0]), .pulse(pulse_noise)); +saa1099_tone freq_gen1(.*, .out(tone1), .octave(octave[1]), .freq(freq[1]), .pulse(pulse_envelope)); +saa1099_tone freq_gen2(.*, .out(tone2), .octave(octave[2]), .freq(freq[2]), .pulse()); +saa1099_noise noise_gen(.*, .out(noise)); + +saa1099_amp amp0(.*, .mixmode({noise_en[0], freq_en[0]}), .tone(tone0), .envreg(0), .vol(vol[0]), .out(out0)); +saa1099_amp amp1(.*, .mixmode({noise_en[1], freq_en[1]}), .tone(tone1), .envreg(0), .vol(vol[1]), .out(out1)); +saa1099_amp amp2(.*, .mixmode({noise_en[2], freq_en[2]}), .tone(tone2), .envreg(env), .vol(vol[2]), .out(out2)); + +assign out[10:0] = {2'b00, out0[8:0] } + {2'b00, out1[8:0] } + {2'b00, out2[8:0] }; +assign out[21:11] = {2'b00, out0[17:9]} + {2'b00, out1[17:9]} + {2'b00, out2[17:9]}; + +endmodule + +///////////////////////////////////////////////////////////////////////////////// + +module saa1099_tone +( + input rst, + input clk_sys, + input ce, + input [2:0] octave, + input [7:0] freq, + output reg out, + output reg pulse +); + +wire [16:0] fcount = ((17'd511 - freq) << (4'd8 - octave)) - 1'd1; +always @(posedge clk_sys) begin + reg [16:0] count; + + pulse <= 0; + if(rst) begin + count <= fcount; + out <= 0; + end else if(ce) begin + if(!count) begin + count <= fcount; + pulse <= 1; + out <= ~out; + end else begin + count <= count - 1'd1; + end + end +end + +endmodule + +///////////////////////////////////////////////////////////////////////////////// + +module saa1099_noise +( + input rst, + input clk_sys, + input ce, + input pulse_noise, + input [1:0] noise_freq, + output out +); + +reg [16:0] lfsr = 0; +wire [16:0] new_lfsr = {(lfsr[0] ^ lfsr[2] ^ !lfsr), lfsr[16:1]}; +wire [10:0] fcount = (11'd256 << noise_freq) - 1'b1; + +always @(posedge clk_sys) begin + reg [10:0] count; + + if(rst) begin + count <= fcount; + end else + if(noise_freq != 3) begin + if(ce) begin + if(!count) begin + count <= fcount; + lfsr <= new_lfsr; + end else begin + count <= count - 1'd1; + end + end + end else if(pulse_noise) begin + lfsr <= new_lfsr; + end +end + +assign out = lfsr[0]; + +endmodule + +///////////////////////////////////////////////////////////////////////////////// + +module saa1099_amp +( + input rst, + input clk_sys, + input [7:0] envreg, + input [1:0] mixmode, + input tone, + input noise, + input wr_addr, + input wr_data, + input pulse_envelope, + input [7:0] vol, + output reg [17:0] out +); + +wire phases[8] = '{0,0,0,0,1,1,0,0}; +wire [1:0] env[8][2] = '{'{0,0}, '{1,1}, '{2,0}, '{2,0}, '{3,2}, '{3,2}, '{3,0}, '{3,0}}; +wire [3:0] levels[4][16] = +'{ + '{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + '{15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15}, + '{15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + '{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15} +}; + +reg [2:0] shape; +reg stereo; +wire resolution = envreg[4]; +wire enable = envreg[7]; +reg [3:0] counter; +reg phase; +wire[3:0] mask = {3'b000, resolution}; + +always @(posedge clk_sys) begin + reg clock; + reg new_data; + + if(rst | ~enable) begin + new_data <= 0; + stereo <= envreg[0]; + shape <= envreg[3:1]; + clock <= envreg[5]; + phase <= 0; + counter <= 0; + end + else begin + if(wr_data) new_data <= 1; + if(clock ? wr_addr : pulse_envelope) begin // pulse from internal or external clock? + counter <= counter + resolution + 1'd1; + if((counter | mask) == 15) begin + if(phase >= phases[shape]) begin + if(~shape[0]) counter <= 15; + if(new_data | shape[0]) begin // if we reached one of the designated points (3) or (4) and there is pending data, load it + new_data <= 0; + stereo <= envreg[0]; + shape <= envreg[3:1]; + clock <= envreg[5]; + phase <= 0; + if(new_data) counter <= 0; + end + end else begin + phase <= 1; + end + end + end + end +end + +wire [3:0] env_l = levels[env[shape][phase]][counter] & ~mask; +wire [3:0] env_r = stereo ? (4'd15 & ~mask) - env_l : env_l; // bit 0 of envreg inverts envelope shape + +reg [1:0] outmix; +always_comb begin + case(mixmode) + 0: outmix <= 0; + 1: outmix <= {tone, 1'b0}; + 2: outmix <= {noise, 1'b0}; + 3: outmix <= {tone & ~noise, tone & noise}; + endcase +end + +wire [8:0] vol_mix_l = {vol[3:1], vol[0] & ~enable, 5'b00000} >> outmix[0]; +wire [8:0] vol_mix_r = {vol[7:5], vol[4] & ~enable, 5'b00000} >> outmix[0]; +wire [8:0] env_out_l; +wire [8:0] env_out_r; +saa1099_mul_env mod_l(.vol(vol_mix_l[8:4]), .env(env_l), .out(env_out_l)); +saa1099_mul_env mod_r(.vol(vol_mix_r[8:4]), .env(env_r), .out(env_out_r)); + +always_comb begin + case({enable, outmix}) + 'b100, 'b101: out = {env_out_r, env_out_l}; + 'b001, 'b010: out = {vol_mix_r, vol_mix_l}; + default: out = 0; + endcase +end + +endmodule + +///////////////////////////////////////////////////////////////////////////////// + +module saa1099_mul_env +( + input [4:0] vol, + input [3:0] env, + output [8:0] out +); + +assign out = (env[0] ? vol : 9'd0)+ + (env[1] ? { vol,1'b0} : 9'd0)+ + (env[2] ? { vol,2'b00} : 9'd0)+ + (env[3] ? {vol,3'b000} : 9'd0); + +endmodule + +///////////////////////////////////////////////////////////////////////////////// + +module saa1099_output_mixer +( + input clk_sys, + input ce, + input en, + input [10:0] in0, + input [10:0] in1, + output reg [7:0] out +); + +wire [17:0] o = 18'd91 * ({1'b0,in0} + {1'b0,in1}); + +// Clean the audio. +always @(posedge clk_sys) begin + reg ced; + ced <= ce; + if(ced) out <= ~en ? 8'h00 : o[17:10]; +end + +endmodule diff --git a/rtl/video/cga.v b/rtl/video/cga.v index dbec11d..ec5ca79 100644 --- a/rtl/video/cga.v +++ b/rtl/video/cga.v @@ -35,6 +35,7 @@ module cga( output dbl_hsync, output vsync, output vblank, + output vblank_border, output de_o, output[3:0] video, output[3:0] dbl_video, @@ -44,7 +45,8 @@ module cga( input thin_font, input tandy_video, output grph_mode, - output hres_mode + output hres_mode, + output tandy_color_16 ); parameter MDA_70HZ = 0; @@ -73,7 +75,8 @@ module cga( reg[7:0] cga_color_reg = 8'b0000_0000; reg[7:0] tandy_color_reg = 8'b0000_0000; reg[3:0] tandy_newcolor = 4'b0000; - reg[4:0] tandy_bordercol = 4'b0000; + reg[3:0] tandy_bordercol = 4'b0000; + reg[4:0] tandy_modesel = 5'b00000; reg tandy_palette_set; wire bw_mode; @@ -81,6 +84,9 @@ module cga( wire tandy_16_mode; wire video_enabled; wire blink_enabled; + + wire tandy_border_en; + wire tandy_color_4; wire hsync_int; wire vsync_l; @@ -229,9 +235,12 @@ module cga( assign mode_640 = cga_control_reg[4]; // 1=640x200 mode, 0=others assign blink_enabled = cga_control_reg[5]; + + assign tandy_border_en = tandy_modesel[2]; + assign tandy_color_4 = tandy_modesel[3]; + assign tandy_color_16 = tandy_modesel[4]; - // FIXME: temporary for testing - assign tandy_16_mode = tandy_video; //cga_control_reg[6]; + assign tandy_16_mode = tandy_video; assign hsync = hsync_int; @@ -251,6 +260,8 @@ module cga( tandy_palette_set <= 1'b1; end else if (tandy_newcolorsel_cs && tandy_color_reg[3:0] == 4'b0010) begin // Border Color tandy_bordercol <= bus_d[3:0]; + end else if (tandy_newcolorsel_cs && tandy_color_reg[3:0] == 4'b0011) begin // Mode Select + tandy_modesel <= bus_d[4:0]; end end @@ -271,6 +282,7 @@ module cga( .vsync(vsync_l), .hblank(hblank), .vblank(vblank), + .vblank_border(vblank_border), .display_enable(display_enable), .cursor(cursor), .mem_addr(crtc_addr), @@ -314,7 +326,8 @@ module cga( .isa_op_enable(isa_op_enable), .hclk(hclk), .lclk(lclk), - .tandy_16_gfx(tandy_16_mode & grph_mode & hres_mode) + .tandy_16_gfx(tandy_16_mode & grph_mode & hres_mode), + .tandy_color_16(tandy_color_16) ); // Pixel pusher @@ -345,6 +358,8 @@ module cga( .tandy_newcolor(tandy_newcolor), .tandy_palette_set(tandy_palette_set), .tandy_bordercol(tandy_bordercol), + .tandy_color_4(tandy_color_4), + .tandy_color_16(tandy_color_16), .video(video) ); diff --git a/rtl/video/cga_attrib.v b/rtl/video/cga_attrib.v index 9a7674a..f2cb669 100644 --- a/rtl/video/cga_attrib.v +++ b/rtl/video/cga_attrib.v @@ -27,8 +27,11 @@ module cga_attrib( input c1, input pix_640, input [3:0] pix_tandy, - input [4:0] tandy_bordercol, - output reg[3:0] pix_out + input [3:0] tandy_bordercol, + input tandy_color_4, + input tandy_color_16, + output reg[3:0] pix_out, + output wire overscan ); reg blinkdiv; @@ -68,18 +71,21 @@ module cga_attrib( // Determine mux A and mux B inputs for selecting output colors. assign mux_a = ~display_enable | (grph_mode ? - (tandy_16_mode ? 0 : (~(~mode_640 & (c0 | c1)))) : + ((tandy_16_mode | tandy_color_16) ? 0 : (~(~mode_640 & (c0 | c1)))) : ~alpha_dots); assign mux_b = grph_mode | ~display_enable; // Shutter closes when video is blanked during sync - assign shutter = (hsync | vsync) | (mode_640 ? ~(display_enable & pix_640) : 1'b0); + assign shutter = (hsync | vsync) | ((mode_640 & ~tandy_color_4) ? ~(display_enable & pix_640) : 1'b0); // Blue palette selection bit assign selblue = bw_mode ? c0 : cga_color_reg[5]; - assign active_area = tandy_16_mode ? pix_tandy : {cga_color_reg[4], c1, c0, selblue}; - + assign active_area = tandy_color_4 ? {1'b0, c1, c0, 1'b0} : + (tandy_16_mode | tandy_color_16) ? pix_tandy : {cga_color_reg[4], c1, c0, selblue}; + + assign overscan = (mux_b & mux_a); + always @ (*) begin if (shutter) begin @@ -89,7 +95,7 @@ module cga_attrib( 2'b00: pix_out <= att_fg; // Text foreground 2'b01: pix_out <= att_bg; // Text background 2'b10: pix_out <= active_area; // Graphics - 2'b11: pix_out <= tandy_16_mode ? tandy_bordercol : cga_color_reg[3:0]; // Overscan color + 2'b11: pix_out <= (tandy_16_mode | tandy_color_16) ? tandy_bordercol : cga_color_reg[3:0]; // Overscan color endcase end end diff --git a/rtl/video/cga_pixel.sv b/rtl/video/cga_pixel.sv index ca8df03..4544b54 100644 --- a/rtl/video/cga_pixel.sv +++ b/rtl/video/cga_pixel.sv @@ -33,13 +33,15 @@ module cga_pixel( input[3:0] tandy_palette_color, input[3:0] tandy_newcolor, input tandy_palette_set, - input[4:0] tandy_bordercol, + input[3:0] tandy_bordercol, + input tandy_color_4, + input tandy_color_16, output[3:0] video ); reg[7:0] attr_byte; reg[7:0] char_byte; - reg[7:0] char_byte_old; + reg[7:0] char_byte_del; reg[7:0] attr_byte_del; reg[7:0] charbits; reg[1:0] cursor_del; @@ -49,6 +51,7 @@ module cga_pixel( reg[1:0] pix_bits; reg[1:0] pix_bits_old; reg[3:0] tandy_bits; + reg overscan; reg[3:0] tandy_palette[0:15] = '{ 4'h0, 4'h1, 4'h2, 4'h3, 4'h4, 4'h5, 4'h6, 4'h7, 4'h8, 4'h9, 4'ha, 4'hb, 4'hc, 4'hd, 4'he, 4'hf }; @@ -57,12 +60,26 @@ module cga_pixel( wire load_shifter; wire [2:0] charpix_sel; reg[3:0] video_out; - assign video = tandy_16_mode ? tandy_palette[video_out] : video_out; // Character ROM reg[7:0] char_rom[0:4095]; initial $readmemh("cga.hex", char_rom, 0, 4095); + always_comb + begin + if (tandy_16_mode) begin + if (overscan) + video = tandy_color_4 ? video_out : tandy_palette[video_out]; + else if (tandy_color_4) + video = tandy_palette[{ 2'b00, video_out[2:1] }]; + else if (mode_640) + video = tandy_palette[{ 2'b000, pix_640 }]; + else + video = tandy_palette[video_out]; + end else + video = video_out; + end + // Latch character and attribute data from VRAM // at appropriate times @@ -73,7 +90,6 @@ module cga_pixel( if (vram_read_char) begin char_byte <= vram_data; - char_byte_old <= char_byte; end if (vram_read_att) begin attr_byte <= vram_data; @@ -83,6 +99,10 @@ module cga_pixel( // Fetch pixel data for graphics modes wire [2:0]muxin; assign muxin = hres_mode ? (clk_seq[3:1] + 3'd6) : (clk_seq[4:2] + 3'd7); + + always @ (posedge clk) + char_byte_del <= char_byte; + always @ (*) begin if (video_enabled) begin @@ -91,14 +111,14 @@ module cga_pixel( // Tandy uses "high res" mode for both 320x200x16 // and 640x200x4 color modes case (muxin) - 3'd0: pix_bits <= char_byte[7:6]; - 3'd1: pix_bits <= char_byte[5:4]; - 3'd2: pix_bits <= char_byte[3:2]; - 3'd3: pix_bits <= char_byte[1:0]; - 3'd4: pix_bits <= attr_byte[7:6]; - 3'd5: pix_bits <= attr_byte[5:4]; - 3'd6: pix_bits <= attr_byte[3:2]; - 3'd7: pix_bits <= attr_byte[1:0]; + 3'd0: pix_bits <= tandy_color_4 ? { attr_byte[7], char_byte_del[7] } : char_byte_del[7:6]; + 3'd1: pix_bits <= tandy_color_4 ? { attr_byte[6], char_byte_del[6] } : char_byte_del[5:4]; + 3'd2: pix_bits <= tandy_color_4 ? { attr_byte[5], char_byte_del[5] } : char_byte_del[3:2]; + 3'd3: pix_bits <= tandy_color_4 ? { attr_byte[4], char_byte_del[4] } : char_byte_del[1:0]; + 3'd4: pix_bits <= tandy_color_4 ? { attr_byte[3], char_byte_del[3] } : attr_byte[7:6]; + 3'd5: pix_bits <= tandy_color_4 ? { attr_byte[2], char_byte_del[2] } : attr_byte[5:4]; + 3'd6: pix_bits <= tandy_color_4 ? { attr_byte[1], char_byte_del[1] } : attr_byte[3:2]; + 3'd7: pix_bits <= tandy_color_4 ? { attr_byte[0], char_byte_del[0] } : attr_byte[1:0]; default: pix_bits <= 2'b0; endcase end else begin @@ -119,11 +139,16 @@ module cga_pixel( // Look up character byte in our character ROM table assign rom_addr = {char_byte, row_addr[2:0]}; + wire pattern_chr = (char_byte >= 8'hB0 && char_byte <= 8'hDF); + always @ (posedge clk) begin // Only load character bits at this point if (charrom_read) begin - charbits <= ((row_addr > 5'd7) && tandy_16_mode) ? 8'b0 : char_rom[{~thin_font, 11'b0} | rom_addr]; + if (row_addr > 5'd7) + charbits <= pattern_chr ? char_rom[{~thin_font, 11'b0} | {char_byte, 3'd7}] : 8'b0; + else + charbits <= char_rom[{~thin_font, 11'b0} | rom_addr]; end end @@ -158,14 +183,14 @@ module cga_pixel( wire[2:0] tmp_clk_seq; assign tmp_clk_seq = clk_seq + 3'd7; assign pix_640 = tmp_clk_seq[1] ? pix_bits[0] : pix_bits[1]; - - // In Tandy 320x200x16 mode, concatenate two adjacent pixels + + // In Tandy 320x200x16 and 160x200x16 modes, concatenate two adjacent pixels wire temp; assign temp = clk_seq[1:0] == 2'b00; always @ (posedge clk) begin if (clk_seq[0]) begin - if (clk_seq[1]) begin + if (muxin[0]) begin tandy_bits <= {pix_bits_old, pix_bits}; end else begin pix_bits_old <= pix_bits; @@ -202,7 +227,10 @@ module cga_pixel( .pix_640(pix_640), .pix_tandy(tandy_bits), .tandy_bordercol(tandy_bordercol), - .pix_out(video_out) + .tandy_color_4(tandy_color_4), + .tandy_color_16(tandy_color_16), + .pix_out(video_out), + .overscan(overscan) ); endmodule diff --git a/rtl/video/cga_sequencer.v b/rtl/video/cga_sequencer.v index e2b6cf3..b40f572 100644 --- a/rtl/video/cga_sequencer.v +++ b/rtl/video/cga_sequencer.v @@ -21,7 +21,8 @@ module cga_sequencer( output isa_op_enable, output hclk, output lclk, - input tandy_16_gfx + input tandy_16_gfx, + input tandy_color_16 ); wire crtc_clk_int; @@ -51,8 +52,8 @@ module cga_sequencer( assign vram_read_char = (clkdiv == 5'd2) || (hres_mode ? (clkdiv == 5'd18) : 0); assign vram_read_att = (clkdiv == 5'd3) || (hres_mode ? (clkdiv == 5'd19) : 0); assign charrom_read = (clkdiv == 5'd3) || (hres_mode ? (clkdiv == 5'd19) : 0);// 3 and 19? - assign disp_pipeline = (clkdiv == (tandy_16_gfx ? 5'd7 : 5'd4)) || (hres_mode ? (clkdiv == (tandy_16_gfx ? 5'd23 : 5'd20)) : 0); - //assign disp_pipeline = (clkdiv == 5'd7) || (hres_mode ? (clkdiv == 5'd23) : 0);// 3 and 19? + assign disp_pipeline = (clkdiv == (tandy_color_16 ? 5'd9 : tandy_16_gfx ? 5'd7 : 5'd4)) || (hres_mode ? (clkdiv == (tandy_16_gfx ? 5'd23 : 5'd20)) : 0); + 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 diff --git a/rtl/video/crtc6845.v b/rtl/video/crtc6845.v index 33e8698..330f94a 100644 --- a/rtl/video/crtc6845.v +++ b/rtl/video/crtc6845.v @@ -24,8 +24,9 @@ module crtc6845( // Video control signals output hsync, output vsync, - output hblank, + output hblank, output vblank, + output vblank_border, output display_enable, output cursor, output [13:0] mem_addr, @@ -136,10 +137,12 @@ module crtc6845( wire [13:0] ma = 14'd0; reg [13:0] ma_rst = 14'd0; // Column reset of memory address + reg [1:0] vs_del; reg vs = 1'b0; reg hs = 1'b0; reg hdisp = 1'b1; reg vdisp = 1'b1; + reg vdisp_border = 1'b1; reg [12:0] hdisp_del; wire cur_on; @@ -152,7 +155,8 @@ module crtc6845( assign hsync = hs; assign display_enable = hdisp & vdisp; assign hblank = ~hdisp; - assign vblank = ~vdisp; + assign vblank = ~vdisp; + assign vblank_border = ~vdisp_border; assign row_addr = v_scancount; @@ -194,11 +198,18 @@ module crtc6845( assign v_end = (v_rowcount == v_total) & (v_scancount == v_maxscan + v_totaladj); + // Vertical counter always @ (posedge clk) begin if (divclk & (h_count == h_total)) begin // was h_syncpos + + vs_del <= {vs_del[0], vs}; + // Handle vertical border blanking + if ((v_rowcount + 1 == v_syncpos) && (v_scancount + 1 == v_maxscan)) + vdisp_border <= 1'b0; + if (v_rowcount != v_total) begin // Vertical count event if (v_scancount != v_maxscan) begin @@ -219,9 +230,12 @@ module crtc6845( end end else begin // Pad with vertical adjust + if (v_scancount != v_maxscan + v_totaladj) begin v_scancount <= v_scancount + 1'b1; + end else begin + v_scancount <= 0; v_rowcount <= 0; vdisp <= 1'b1; @@ -240,6 +254,8 @@ module crtc6845( v_synccount <= v_synccount + 1'b1; end end + else if (vs_del == 2'b10) vdisp_border <= 1'b1; + end end diff --git a/rtl/video/splash.hex b/rtl/video/splash.hex index b1c65e5..3409de3 100644 --- a/rtl/video/splash.hex +++ b/rtl/video/splash.hex @@ -1 +1 @@ -20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 60 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 28 07 20 07 20 07 20 07 28 07 20 07 2F 07 28 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 29 07 29 07 28 07 20 07 20 07 28 07 20 07 28 07 28 07 29 07 2F 07 28 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 28 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 28 07 28 07 29 07 2F 07 28 07 20 07 20 07 29 07 5C 07 20 07 20 07 29 07 5C 07 28 07 29 07 29 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 28 07 5F 07 29 07 28 07 29 07 5C 07 20 07 29 07 5C 07 20 07 2F 07 28 07 5F 07 29 07 29 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 29 07 29 07 5C 07 20 07 29 07 28 07 20 07 20 07 20 07 20 07 2F 07 28 07 5F 07 29 07 7C 07 28 07 28 07 5F 07 29 07 28 07 28 07 5F 07 29 07 5C 07 20 07 20 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 5F 07 28 07 29 07 28 07 28 07 5F 07 7C 07 28 07 5F 07 7C 07 5F 07 29 07 29 07 20 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 2F 07 28 07 28 07 5F 07 7C 07 28 07 29 07 5C 07 20 07 20 07 28 07 5F 07 29 07 29 07 20 07 29 07 5C 07 5F 07 5F 07 5F 07 5F 07 5F 07 28 07 28 07 5F 07 29 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 20 07 5C 07 2F 07 20 07 20 07 7C 07 28 07 5F 07 29 07 20 07 5F 07 5F 07 7C 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 28 07 5F 07 29 07 29 07 20 07 20 07 28 07 28 07 5F 07 29 07 20 07 7C 07 20 07 5F 07 20 07 28 07 28 07 2F 07 20 07 5F 07 5F 07 5C 07 20 07 5C 07 2F 07 20 07 2F 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 7C 07 5C 07 2F 07 7C 07 20 07 7C 07 7C 07 20 07 5C 07 5F 07 5F 07 20 07 5C 07 20 07 20 07 7C 07 20 07 7C 07 20 07 2F 07 20 07 2D 07 5F 07 29 07 7C 07 20 07 27 07 5F 07 7C 07 20 07 7C 07 20 07 20 07 5F 07 2F 07 7C 07 20 07 28 07 5F 07 5F 07 20 07 3E 07 20 07 20 07 3C 07 20 07 20 07 20 07 7C 07 20 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 7C 07 5F 07 7C 07 7C 07 5F 07 7C 07 5F 07 5F 07 5F 07 2F 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 5C 07 5F 07 5F 07 5F 07 7C 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 5C 07 5F 07 5F 07 5F 07 2F 07 5F 07 2F 07 5C 07 5F 07 5C 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 30 07 36 07 2F 07 31 07 31 07 2F 07 32 07 30 07 32 07 32 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 72 07 74 07 20 07 62 07 79 07 20 07 40 07 73 07 70 07 61 07 72 07 6B 07 32 07 6B 07 30 07 36 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 77 07 65 07 72 07 65 07 64 07 20 07 62 07 79 07 20 07 4B 07 46 07 50 07 43 07 2D 07 58 07 54 07 20 07 28 07 40 07 6B 07 69 07 74 07 75 07 6E 07 65 07 2D 07 73 07 61 07 6E 07 29 07 20 07 26 07 20 07 4D 07 43 07 4C 07 38 07 36 07 20 07 28 07 40 07 4D 07 69 07 63 07 72 07 6F 07 43 07 6F 07 72 07 65 07 4C 07 61 07 62 07 73 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 43 07 6F 07 6E 07 74 07 72 07 69 07 62 07 75 07 74 07 6F 07 72 07 73 07 20 07 26 07 20 07 53 07 70 07 65 07 63 07 69 07 61 07 6C 07 20 07 54 07 68 07 61 07 6E 07 6B 07 73 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 40 07 6E 07 61 07 65 07 6C 07 6F 07 6F 07 62 07 20 07 2D 07 20 07 40 07 73 07 6F 07 6D 07 68 07 69 07 20 07 2D 07 20 07 40 07 4D 07 69 07 6C 07 6C 07 73 07 20 07 2D 07 20 07 40 07 54 07 68 07 65 07 53 07 6F 07 6E 07 64 07 65 07 72 07 73 07 20 07 2D 07 20 07 40 07 4A 07 61 07 73 07 6F 07 6E 07 41 07 20 07 2D 07 20 07 40 07 67 07 79 07 75 07 72 07 63 07 6F 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 40 07 4E 07 65 07 77 07 73 07 64 07 65 07 65 07 20 07 2D 07 20 07 40 07 62 07 69 07 72 07 64 07 79 07 62 07 72 07 6F 07 20 07 2D 07 20 07 40 07 46 07 6C 07 61 07 6E 07 64 07 61 07 6E 07 67 07 6F 07 20 07 2D 07 20 07 40 07 70 07 67 07 69 07 6D 07 65 07 6E 07 6F 07 20 07 2D 07 20 07 40 07 6A 07 6F 07 72 07 64 07 69 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 40 07 41 07 64 07 72 07 31 07 30 07 34 07 38 07 20 07 2D 07 20 07 54 07 6F 07 6E 07 79 07 45 07 73 07 63 07 6F 07 62 07 61 07 72 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 \ No newline at end of file +20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 20 07 20 07 60 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 20 07 29 07 20 07 20 07 28 07 20 07 20 07 20 07 28 07 20 07 2F 07 28 07 20 07 20 07 20 07 2A 07 20 07 20 07 20 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 29 07 5C 07 29 07 29 07 28 07 20 07 20 07 28 07 20 07 28 07 28 07 29 07 2F 07 28 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 28 07 20 07 20 07 28 07 20 07 20 07 20 07 20 07 28 07 28 07 29 07 2F 07 28 07 20 07 20 07 29 07 5C 07 20 07 20 07 29 07 5C 07 28 07 29 07 29 07 60 07 20 07 29 07 20 07 20 07 2F 07 28 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 28 07 5F 07 29 07 28 07 29 07 5C 07 20 07 29 07 5C 07 20 07 2F 07 28 07 5F 07 29 07 29 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 29 07 29 07 5C 07 20 07 29 07 28 07 20 07 20 07 20 07 20 07 2F 07 28 07 5F 07 29 07 7C 07 28 07 28 07 5F 07 29 07 28 07 28 07 5F 07 29 07 5C 07 20 07 20 07 28 07 20 07 29 07 28 07 5F 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 28 07 5F 07 28 07 29 07 28 07 28 07 5F 07 7C 07 28 07 5F 07 7C 07 5F 07 29 07 29 07 20 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 2F 07 28 07 28 07 5F 07 7C 07 28 07 29 07 5C 07 20 07 20 07 28 07 5F 07 29 07 29 07 20 07 29 07 5C 07 5F 07 5F 07 5F 07 5F 07 5F 07 28 07 28 07 5F 07 29 07 28 07 5F 07 28 07 5F 07 28 07 29 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 20 07 5C 07 2F 07 20 07 20 07 7C 07 28 07 5F 07 29 07 20 07 5F 07 5F 07 7C 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 28 07 5F 07 29 07 29 07 20 07 20 07 28 07 28 07 5F 07 29 07 20 07 7C 07 20 07 5F 07 20 07 28 07 28 07 2F 07 20 07 5F 07 5F 07 5C 07 20 07 5C 07 2F 07 20 07 2F 07 7C 07 5F 07 20 07 20 07 20 07 5F 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 20 07 7C 07 5C 07 2F 07 7C 07 20 07 7C 07 7C 07 20 07 5C 07 5F 07 5F 07 20 07 5C 07 20 07 20 07 7C 07 20 07 7C 07 20 07 2F 07 20 07 2D 07 5F 07 29 07 7C 07 20 07 27 07 5F 07 7C 07 20 07 7C 07 20 07 20 07 5F 07 2F 07 7C 07 20 07 28 07 5F 07 5F 07 20 07 3E 07 20 07 20 07 3C 07 20 07 20 07 20 07 7C 07 20 07 7C 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 7C 07 5F 07 7C 07 7C 07 5F 07 7C 07 5F 07 5F 07 5F 07 2F 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 5C 07 5F 07 5F 07 5F 07 7C 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 20 07 5C 07 5F 07 5F 07 5F 07 2F 07 5F 07 2F 07 5C 07 5F 07 5C 07 20 07 20 07 7C 07 5F 07 7C 07 20 07 20 07 32 07 34 07 2F 07 31 07 31 07 2F 07 32 07 30 07 32 07 32 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 72 07 74 07 20 07 62 07 79 07 20 07 40 07 73 07 70 07 61 07 72 07 6B 07 32 07 6B 07 30 07 36 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 50 07 6F 07 77 07 65 07 72 07 65 07 64 07 20 07 62 07 79 07 20 07 4B 07 46 07 50 07 43 07 2D 07 58 07 54 07 20 07 28 07 40 07 6B 07 69 07 74 07 75 07 6E 07 65 07 2D 07 73 07 61 07 6E 07 29 07 20 07 26 07 20 07 4D 07 43 07 4C 07 38 07 36 07 20 07 28 07 40 07 4D 07 69 07 63 07 72 07 6F 07 43 07 6F 07 72 07 65 07 4C 07 61 07 62 07 73 07 29 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 43 07 6F 07 6E 07 74 07 72 07 69 07 62 07 75 07 74 07 6F 07 72 07 73 07 20 07 26 07 20 07 53 07 70 07 65 07 63 07 69 07 61 07 6C 07 20 07 54 07 68 07 61 07 6E 07 6B 07 73 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 2D 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 6E 07 61 07 65 07 6C 07 6F 07 6F 07 62 07 20 07 2D 07 20 07 73 07 6F 07 6D 07 68 07 69 07 20 07 2D 07 20 07 4D 07 69 07 6C 07 6C 07 73 07 20 07 2D 07 20 07 54 07 68 07 65 07 53 07 6F 07 6E 07 64 07 65 07 72 07 73 07 20 07 2D 07 20 07 4A 07 61 07 73 07 6F 07 6E 07 41 07 20 07 2D 07 20 07 67 07 79 07 75 07 72 07 63 07 6F 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 4E 07 65 07 77 07 73 07 64 07 65 07 65 07 20 07 2D 07 20 07 62 07 69 07 72 07 64 07 79 07 62 07 72 07 6F 07 20 07 2D 07 20 07 46 07 6C 07 61 07 6E 07 64 07 61 07 6E 07 67 07 6F 07 20 07 2D 07 20 07 70 07 67 07 69 07 6D 07 65 07 6E 07 6F 07 20 07 2D 07 20 07 4A 07 6F 07 72 07 64 07 69 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 41 07 64 07 72 07 31 07 30 07 34 07 38 07 20 07 2D 07 20 07 4B 07 61 07 74 07 68 07 6C 07 65 07 65 07 6E 07 20 07 2D 07 20 07 54 07 6F 07 6E 07 79 07 45 07 73 07 63 07 6F 07 62 07 61 07 72 07 20 07 2D 07 20 07 4A 07 6F 07 72 07 64 07 69 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07 \ No newline at end of file