mirror of
https://github.com/MiSTer-devel/PCXT_MiSTer.git
synced 2026-04-19 03:04:47 +00:00
Replace the derived XT pseudo-clocks with a synchronous clock-enable scheduler on clk_chipset so the XT side runs from a single base clock without changing the mature 8088/BIU clocking model. - generate exact CPU and peripheral enables from clk_chipset - update the XT chipset and peripheral path to consume enables instead of reconstructed pseudo-clock edges - keep the 8088 CLK pin as a local compatibility signal - refresh SYSTEM.sdc so pll_system video clocks and clk_14_318 resolve cleanly in TimeQuest
1910 lines
61 KiB
Systemverilog
1910 lines
61 KiB
Systemverilog
//============================================================================
|
|
//
|
|
// 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.
|
|
//
|
|
//============================================================================
|
|
|
|
`ifndef SYSTEM_VARIANT_TANDY
|
|
`define SYSTEM_VARIANT_TANDY 0
|
|
`endif
|
|
`ifndef ROM_VARIANT_TANDY
|
|
`define ROM_VARIANT_TANDY `SYSTEM_VARIANT_TANDY
|
|
`endif
|
|
`ifndef ROM_IS_TANDY
|
|
`define ROM_IS_TANDY `ROM_VARIANT_TANDY
|
|
`endif
|
|
`ifndef CONF_STR_SYSTEM
|
|
`define CONF_STR_SYSTEM (`SYSTEM_VARIANT_TANDY ? "Tandy1000;UART115200:115200;" : "PCXT;UART115200:115200;")
|
|
`endif
|
|
`ifndef ENABLE_TANDY_VIDEO
|
|
`define ENABLE_TANDY_VIDEO 0
|
|
`endif
|
|
`ifndef ENABLE_TANDY_AUDIO
|
|
`define ENABLE_TANDY_AUDIO 0
|
|
`endif
|
|
`ifndef ENABLE_TANDY_KBD
|
|
`define ENABLE_TANDY_KBD 0
|
|
`endif
|
|
`ifndef ENABLE_A000_UMB
|
|
`define ENABLE_A000_UMB 0
|
|
`endif
|
|
`ifndef ENABLE_CGA
|
|
`define ENABLE_CGA 1
|
|
`endif
|
|
`ifndef ENABLE_HGC
|
|
`define ENABLE_HGC 0
|
|
`endif
|
|
`ifndef ENABLE_OPL2
|
|
`define ENABLE_OPL2 0
|
|
`endif
|
|
`ifndef ENABLE_CMS
|
|
`define ENABLE_CMS 0
|
|
`endif
|
|
`ifndef ENABLE_EMS
|
|
`define ENABLE_EMS 0
|
|
`endif
|
|
|
|
module emu
|
|
(
|
|
//Master input clock
|
|
input CLK_50M,
|
|
|
|
//Async reset from top-level module.
|
|
//Can be used as initial reset.
|
|
input RESET,
|
|
|
|
//Must be passed to hps_io module
|
|
inout [48:0] HPS_BUS,
|
|
|
|
//Base video clock. Usually equals to CLK_SYS.
|
|
output CLK_VIDEO,
|
|
|
|
//Multiple resolutions are supported using different CE_PIXEL rates.
|
|
//Must be based on CLK_VIDEO
|
|
output CE_PIXEL,
|
|
|
|
//Video aspect ratio for HDMI. Most retro systems have ratio 4:3.
|
|
//if VIDEO_ARX[12] or VIDEO_ARY[12] is set then [11:0] contains scaled size instead of aspect ratio.
|
|
output [12:0] VIDEO_ARX,
|
|
output [12:0] VIDEO_ARY,
|
|
|
|
output [7:0] VGA_R,
|
|
output [7:0] VGA_G,
|
|
output [7:0] VGA_B,
|
|
output VGA_HS,
|
|
output VGA_VS,
|
|
output VGA_DE, // = ~(VBlank | HBlank)
|
|
output VGA_F1,
|
|
output [1:0] VGA_SL,
|
|
output VGA_SCALER, // Force VGA scaler
|
|
output VGA_DISABLE,
|
|
|
|
input [11:0] HDMI_WIDTH,
|
|
input [11:0] HDMI_HEIGHT,
|
|
output HDMI_FREEZE,
|
|
output HDMI_BLACKOUT,
|
|
output HDMI_BOB_DEINT,
|
|
|
|
`ifdef MISTER_FB
|
|
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
|
|
// FB_FORMAT:
|
|
// [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
|
|
// [3] : 0=16bits 565 1=16bits 1555
|
|
// [4] : 0=RGB 1=BGR (for 16/24/32 modes)
|
|
//
|
|
// FB_STRIDE either 0 (rounded to 256 bytes) or multiple of pixel size (in bytes)
|
|
output FB_EN,
|
|
output [4:0] FB_FORMAT,
|
|
output [11:0] FB_WIDTH,
|
|
output [11:0] FB_HEIGHT,
|
|
output [31:0] FB_BASE,
|
|
output [13:0] FB_STRIDE,
|
|
input FB_VBL,
|
|
input FB_LL,
|
|
output FB_FORCE_BLANK,
|
|
|
|
`ifdef MISTER_FB_PALETTE
|
|
// Palette control for 8bit modes.
|
|
// Ignored for other video modes.
|
|
output FB_PAL_CLK,
|
|
output [7:0] FB_PAL_ADDR,
|
|
output [23:0] FB_PAL_DOUT,
|
|
input [23:0] FB_PAL_DIN,
|
|
output FB_PAL_WR,
|
|
`endif
|
|
`endif
|
|
|
|
output LED_USER, // 1 - ON, 0 - OFF.
|
|
|
|
// b[1]: 0 - LED status is system status OR'd with b[0]
|
|
// 1 - LED status is controled solely by b[0]
|
|
// hint: supply 2'b00 to let the system control the LED.
|
|
output [1:0] LED_POWER,
|
|
output [1:0] LED_DISK,
|
|
|
|
// I/O board button press simulation (active high)
|
|
// b[1]: user button
|
|
// b[0]: osd button
|
|
output [1:0] BUTTONS,
|
|
|
|
input CLK_AUDIO, // 24.576 MHz
|
|
output [15:0] AUDIO_L,
|
|
output [15:0] AUDIO_R,
|
|
output AUDIO_S, // 1 - signed audio samples, 0 - unsigned
|
|
output [1:0] AUDIO_MIX, // 0 - no mix, 1 - 25%, 2 - 50%, 3 - 100% (mono)
|
|
|
|
//ADC
|
|
inout [3:0] ADC_BUS,
|
|
|
|
//SD-SPI
|
|
output SD_SCK,
|
|
output SD_MOSI,
|
|
input SD_MISO,
|
|
output SD_CS,
|
|
input SD_CD,
|
|
|
|
//High latency DDR3 RAM interface
|
|
//Use for non-critical time purposes
|
|
output DDRAM_CLK,
|
|
input DDRAM_BUSY,
|
|
output [7:0] DDRAM_BURSTCNT,
|
|
output [28:0] DDRAM_ADDR,
|
|
input [63:0] DDRAM_DOUT,
|
|
input DDRAM_DOUT_READY,
|
|
output DDRAM_RD,
|
|
output [63:0] DDRAM_DIN,
|
|
output [7:0] DDRAM_BE,
|
|
output DDRAM_WE,
|
|
|
|
//SDRAM interface with lower latency
|
|
output SDRAM_CLK,
|
|
output SDRAM_CKE,
|
|
output [12:0] SDRAM_A,
|
|
output [1:0] SDRAM_BA,
|
|
inout [15:0] SDRAM_DQ,
|
|
output SDRAM_DQML,
|
|
output SDRAM_DQMH,
|
|
output SDRAM_nCS,
|
|
output SDRAM_nCAS,
|
|
output SDRAM_nRAS,
|
|
output SDRAM_nWE,
|
|
|
|
`ifdef MISTER_DUAL_SDRAM
|
|
//Secondary SDRAM
|
|
//Set all output SDRAM_* signals to Z ASAP if SDRAM2_EN is 0
|
|
input SDRAM2_EN,
|
|
output SDRAM2_CLK,
|
|
output [12:0] SDRAM2_A,
|
|
output [1:0] SDRAM2_BA,
|
|
inout [15:0] SDRAM2_DQ,
|
|
output SDRAM2_nCS,
|
|
output SDRAM2_nCAS,
|
|
output SDRAM2_nRAS,
|
|
output SDRAM2_nWE,
|
|
`endif
|
|
|
|
input UART_CTS,
|
|
output UART_RTS,
|
|
input UART_RXD,
|
|
output UART_TXD,
|
|
output UART_DTR,
|
|
input UART_DSR,
|
|
|
|
// Open-drain User port.
|
|
// 0 - D+/RX
|
|
// 1 - D-/TX
|
|
// 2..6 - USR2..USR6
|
|
// Set USER_OUT to 1 to read from USER_IN.
|
|
input [6:0] USER_IN,
|
|
output [6:0] USER_OUT,
|
|
|
|
input OSD_STATUS
|
|
);
|
|
|
|
///////// Default values for ports not used in this core /////////
|
|
|
|
assign ADC_BUS = 'Z;
|
|
//assign USER_OUT = '1;
|
|
//assign {UART_RTS, UART_TXD, UART_DTR} = 0;
|
|
assign {SD_SCK, SD_MOSI, SD_CS} = 'Z;
|
|
//assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = 'Z;
|
|
assign SDRAM_CLK = clk_chipset;
|
|
assign {DDRAM_CLK, DDRAM_BURSTCNT, DDRAM_ADDR, DDRAM_DIN, DDRAM_BE, DDRAM_RD, DDRAM_WE} = '0;
|
|
|
|
assign VGA_F1 = 0;
|
|
assign VGA_SCALER = 0;
|
|
assign VGA_DISABLE = 0;
|
|
assign HDMI_FREEZE = 0;
|
|
assign HDMI_BLACKOUT = 0;
|
|
assign HDMI_BOB_DEINT = 0;
|
|
|
|
assign LED_DISK = 0;
|
|
assign LED_POWER = 0;
|
|
assign BUTTONS = 0;
|
|
|
|
assign LED_USER = 0;
|
|
//led fdd_led(clk_cpu, |mgmt_req[7:6], LED_USER);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Status Bit Map:
|
|
// Upper Lower
|
|
// 0 1 2 3 4 5 6
|
|
// 01234567890123456789012345678901 23456789012345678901234567890123
|
|
// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV
|
|
// XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX
|
|
|
|
`include "build_id.v"
|
|
|
|
localparam CONF_STR_HGC = ((`ENABLE_HGC && `ENABLE_CGA) ? "P1oC,PCXT CGA Graphics,Yes,No;P1oD,PCXT Hercules Graphics,Yes,No;P1O4,PCXT 1st Video,CGA,Hercules;P1-;" : "");
|
|
localparam CONF_STR_ROM = (`ROM_IS_TANDY ? "P1FC1,ROM,Tandy BIOS:;P1-;" : "P1FC0,ROM,PCXT BIOS:;");
|
|
localparam CONF_STR_CMS = (`ENABLE_CMS ? "P2OA,C/MS Audio,Enabled,Disabled;" : "");
|
|
localparam CONF_STR_OPL2 = (`ENABLE_OPL2 ? "P2oAB,OPL2,Adlib 388h,SB FM 388h/228h, Disabled;" : "");
|
|
localparam CONF_STR_TANDY_AUDIO = (`ENABLE_TANDY_AUDIO ? "P2o23,Tandy Volume,1,2,3,4;" : "");
|
|
localparam CONF_STR_EMS = (`ENABLE_EMS ? "P3OB,Lo-tech 2MB EMS,Enabled,Disabled;P3OCD,EMS Frame,C000,D000,E000;P3-;" : "");
|
|
localparam CONF_STR_A000 = (`ENABLE_A000_UMB ? "P3o9,A000 UMB,Enabled,Disabled;P3-;" : "");
|
|
|
|
localparam CONF_STR = {
|
|
`CONF_STR_SYSTEM,
|
|
"S0,IMGIMAVFD,Floppy A:;",
|
|
"S1,IMGIMAVFD,Floppy B:;",
|
|
"OJK,Write Protect,None,A:,B:,A: & B:;",
|
|
"-;",
|
|
"S2,VHD,IDE 0-0;",
|
|
"S3,VHD,IDE 0-1;",
|
|
"OLM,2nd SD card,Disable,IDE 0-0,IDE 0-1;",
|
|
"-;",
|
|
"OHI,CPU Speed,4.77MHz,7.16MHz,9.54MHz,PC/AT 3.5MHz;",
|
|
"-;",
|
|
"P1,System & BIOS;",
|
|
"P1-;",
|
|
CONF_STR_HGC,
|
|
"P1O7,Boot Splash Screen,Yes,No;",
|
|
"P1-;",
|
|
CONF_STR_ROM,
|
|
"P1FC2,ROM,EC00 BIOS:;",
|
|
"P1-;",
|
|
"P1OUV,BIOS Writable,None,EC00,Main,All;",
|
|
"P1-;",
|
|
"P2,Audio & Video;",
|
|
"P2-;",
|
|
CONF_STR_CMS,
|
|
CONF_STR_OPL2,
|
|
"P2o01,Speaker Volume,1,2,3,4;",
|
|
CONF_STR_TANDY_AUDIO,
|
|
"P2o45,Audio Boost,No,2x,4x;",
|
|
"P2o67,Stereo Mix,none,25%,50%,100%;",
|
|
"P2-;",
|
|
"P2oEH,CRT H offset,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15;",
|
|
"P2oIK,CRT V offset,0,1,2,3,4,5,6,7;",
|
|
"P2oMO,VSync Width,Auto,1,2,3,4,5,6,7;",
|
|
"P2oPR,HSync Width,Auto,1,2,3,4,5,6,7;",
|
|
"P2-;",
|
|
"P2O12,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
|
"P2O89,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];",
|
|
"P2OT,Border,No,Yes;",
|
|
"P2o8,Composite video,Off,On;",
|
|
"P2OEG,Display,Full Color,Green,Amber,B&W,Red,Blue,Fuchsia,Purple;",
|
|
"P2-;",
|
|
"P3,Hardware;",
|
|
"P3-;",
|
|
CONF_STR_EMS,
|
|
CONF_STR_A000,
|
|
"P3ONO,Joystick 1, Analog, Digital, Disabled;",
|
|
"P3OPQ,Joystick 2, Analog, Digital, Disabled;",
|
|
"P3OR,Sync Joy to CPU Speed,No,Yes;",
|
|
"P3OS,Swap Joysticks,No,Yes;",
|
|
"P3-;",
|
|
"-;",
|
|
"R0,Reset & apply settings;",
|
|
"J,Fire 1,Fire 2;",
|
|
"V,v",`BUILD_DATE
|
|
};
|
|
|
|
wire forced_scandoubler;
|
|
wire [1:0] buttons;
|
|
wire [63:0] status;
|
|
wire [7:0] xtctl;
|
|
|
|
//Keyboard Ps2
|
|
wire ps2_kbd_clk_out;
|
|
wire ps2_kbd_data_out;
|
|
wire ps2_kbd_clk_in;
|
|
wire ps2_kbd_data_in;
|
|
|
|
//Mouse PS2
|
|
wire ps2_mouse_clk_out;
|
|
wire ps2_mouse_data_out;
|
|
wire ps2_mouse_clk_in;
|
|
wire ps2_mouse_data_in;
|
|
|
|
wire ioctl_download;
|
|
wire [7:0] ioctl_index;
|
|
wire ioctl_wr;
|
|
wire [24:0] ioctl_addr;
|
|
wire [15:0] ioctl_data;
|
|
reg ioctl_wait;
|
|
|
|
wire [21:0] gamma_bus;
|
|
|
|
wire [13:0] joy0, joy1;
|
|
wire [15:0] joya0, joya1;
|
|
wire [4:0] joy_opts = status[27:23];
|
|
|
|
wire composite = status[40] | xtctl[0];
|
|
wire [1:0] scale = status[2:1];
|
|
wire [2:0] screen_mode = status[16:14];
|
|
wire [1:0] ar = status[9:8];
|
|
wire border = status[29] | xtctl[1];
|
|
wire a000h = `ENABLE_A000_UMB ? (~status[41] & ~xtctl[6]) : 1'b0;
|
|
wire [2:0] vsync_width_osd = status[56:54]; // 0=Auto (use register), 1-7=override
|
|
wire [2:0] hsync_width_osd = status[59:57]; // 0=Auto, 1-7=fixed width (Nx16 pixel clocks)
|
|
|
|
reg [1:0] scale_video_ff;
|
|
reg hgc_mode_video_ff;
|
|
reg [2:0] screen_mode_video_ff;
|
|
reg border_video_ff;
|
|
reg cga_hw;
|
|
wire video_scandoubler_en = (scale_video_ff > 0) || forced_scandoubler;
|
|
wire cga_scandouble_en = video_scandoubler_en;
|
|
reg hercules_hw;
|
|
|
|
wire VGA_VBlank_border;
|
|
wire std_hsyncwidth;
|
|
wire pause_core;
|
|
wire swap_video;
|
|
wire swap_video_eff = `ENABLE_HGC ? (`ENABLE_CGA ? swap_video : (`ENABLE_TANDY_VIDEO ? 1'b0 : 1'b1)) : 1'b0;
|
|
|
|
always @(posedge clk_57_272)
|
|
begin
|
|
scale_video_ff <= scale;
|
|
screen_mode_video_ff <= screen_mode;
|
|
border_video_ff <= border;
|
|
cga_hw <= `ENABLE_CGA ? (~status[44] | tandy_video_mode) : 1'b0;
|
|
hercules_hw <= `ENABLE_HGC ? (`ENABLE_CGA ? ~status[45] : 1'b1) : 1'b0;
|
|
VIDEO_ARX <= (!ar) ? 12'd4 : (ar - 1'd1);
|
|
VIDEO_ARY <= (!ar) ? 12'd3 : 12'd0;
|
|
end
|
|
|
|
always @(posedge clk_chipset)
|
|
hgc_mode_video_ff <= `ENABLE_HGC ? hgc_mode : 1'b0;
|
|
|
|
hps_io #(.CONF_STR(CONF_STR), .PS2DIV(2000), .PS2WE(1), .WIDE(1)) hps_io
|
|
(
|
|
.clk_sys(clk_chipset),
|
|
.HPS_BUS(HPS_BUS),
|
|
.EXT_BUS(EXT_BUS),
|
|
.gamma_bus(gamma_bus),
|
|
|
|
.forced_scandoubler(forced_scandoubler),
|
|
|
|
.buttons(buttons),
|
|
.status(status),
|
|
.status_menumask({status[5]}),
|
|
|
|
.ps2_kbd_clk_in (ps2_kbd_clk_out),
|
|
.ps2_kbd_data_in (ps2_kbd_data_out),
|
|
.ps2_kbd_clk_out (ps2_kbd_clk_in),
|
|
.ps2_kbd_data_out (ps2_kbd_data_in),
|
|
|
|
.ps2_mouse_clk_out (ps2_mouse_clk_out),
|
|
.ps2_mouse_data_out (ps2_mouse_data_out),
|
|
.ps2_mouse_clk_in (ps2_mouse_clk_in),
|
|
.ps2_mouse_data_in (ps2_mouse_data_in),
|
|
|
|
.joystick_0(joy0),
|
|
.joystick_1(joy1),
|
|
.joystick_l_analog_0(joya0),
|
|
.joystick_l_analog_1(joya1),
|
|
|
|
//ioctl
|
|
.ioctl_download(ioctl_download),
|
|
.ioctl_index(ioctl_index),
|
|
.ioctl_wr(ioctl_wr),
|
|
.ioctl_addr(ioctl_addr),
|
|
.ioctl_dout(ioctl_data),
|
|
.ioctl_wait(ioctl_wait)
|
|
);
|
|
|
|
|
|
wire [15:0] mgmt_din;
|
|
wire [15:0] mgmt_dout;
|
|
wire [15:0] mgmt_addr;
|
|
wire mgmt_rd;
|
|
wire mgmt_wr;
|
|
wire [7:0] mgmt_req;
|
|
assign mgmt_req[5:3] = 3'b000;
|
|
|
|
wire [35:0] EXT_BUS;
|
|
hps_ext hps_ext
|
|
(
|
|
.clk_sys(clk_chipset),
|
|
.EXT_BUS(EXT_BUS),
|
|
|
|
.ext_din(mgmt_din),
|
|
.ext_dout(mgmt_dout),
|
|
.ext_addr(mgmt_addr),
|
|
.ext_rd(mgmt_rd),
|
|
.ext_wr(mgmt_wr),
|
|
|
|
.ext_req(mgmt_req),
|
|
.ext_hotswap(2'b00)
|
|
);
|
|
|
|
//
|
|
/////////////////////// CLOCKS /////////////////////////////
|
|
//
|
|
|
|
wire clk_sys;
|
|
wire pll_locked;
|
|
|
|
wire clk_100;
|
|
wire clk_28_636;
|
|
wire clk_57_272;
|
|
wire clk_114_544;
|
|
wire clk_video_out_ps;
|
|
reg clk_14_318 = 1'b0;
|
|
wire clk_cpu;
|
|
logic cpu_ce_posedge;
|
|
logic cpu_ce_negedge;
|
|
logic peripheral_ce;
|
|
wire clk_chipset;
|
|
|
|
localparam [27:0] cur_rate = 28'd50000000;
|
|
|
|
pll pll
|
|
(
|
|
.refclk(CLK_50M),
|
|
.rst(0),
|
|
.outclk_0(clk_100),
|
|
.outclk_1(clk_chipset),
|
|
.locked(pll_locked)
|
|
);
|
|
|
|
wire pll_system_locked;
|
|
|
|
pll_system pll_system_inst (
|
|
.refclk(CLK_50M),
|
|
.rst(0),
|
|
.outclk_0(clk_28_636),
|
|
.outclk_1(clk_57_272),
|
|
.outclk_2(clk_114_544),
|
|
.outclk_3(clk_video_out_ps),
|
|
.locked(pll_system_locked)
|
|
);
|
|
|
|
wire reset_wire = RESET | status[0] | buttons[1] | !pll_locked | !pll_system_locked | splashscreen | splash_reset_hold | splash_pending;
|
|
wire video_retime_reset = RESET | status[0] | buttons[1] | !pll_locked | !pll_system_locked | splash_pending;
|
|
wire reset_sdram_wire = RESET | !pll_locked;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
// TODO: messy, use a single clock domain at least
|
|
always @(posedge clk_28_636)
|
|
begin
|
|
HBlank_del <= {HBlank_del[13], HBlank_del[12], HBlank_del[11], HBlank_del[10], HBlank_del[9],
|
|
HBlank_del[8], HBlank_del[7], HBlank_del[6], HBlank_del[5], HBlank_del[4],
|
|
HBlank_del[3], HBlank_del[2], HBlank_del[1], HBlank_del[0], HBlank};
|
|
clk_14_318 <= ~clk_14_318; // 14.318Mhz
|
|
ce_pixel_cga <= clk_14_318; //if outside always block appears an overscan column in CGA mode
|
|
end
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
logic biu_done;
|
|
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;
|
|
wire [1:0] clk_select_next = ((xtctl[3:2] == 2'b00) && ~xtctl[7]) ? status[18:17] :
|
|
(xtctl[7] ? 2'b11 : xtctl[3:2] - 2'b01);
|
|
|
|
always @(posedge clk_chipset, posedge reset)
|
|
begin
|
|
if (reset)
|
|
clk_select <= 2'b00;
|
|
else if (biu_done)
|
|
clk_select <= clk_select_next;
|
|
end
|
|
|
|
XT_CE_Generator u_XT_CE_Generator
|
|
(
|
|
.clock (clk_chipset),
|
|
.reset (reset),
|
|
.clk_select_load (biu_done),
|
|
.clk_select (clk_select_next),
|
|
.cpu_clk_pin (clk_cpu),
|
|
.cpu_ce_posedge (cpu_ce_posedge),
|
|
.cpu_ce_negedge (cpu_ce_negedge),
|
|
.peripheral_ce (peripheral_ce),
|
|
.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),
|
|
.ram_read_wait_cycle (ram_read_wait_cycle),
|
|
.ram_write_wait_cycle (ram_write_wait_cycle)
|
|
);
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
logic reset = 1'b1;
|
|
logic [15:0] reset_count = 16'h0000;
|
|
logic reset_sdram = 1'b1;
|
|
logic [15:0] reset_sdram_count = 16'h0000;
|
|
|
|
always @(posedge clk_chipset, posedge reset_wire)
|
|
begin
|
|
if (reset_wire)
|
|
begin
|
|
reset <= 1'b1;
|
|
reset_count <= 16'h0000;
|
|
end
|
|
else if (reset)
|
|
begin
|
|
if (reset_count != 16'hffff)
|
|
begin
|
|
reset <= 1'b1;
|
|
reset_count <= reset_count + 16'h0001;
|
|
end
|
|
else
|
|
begin
|
|
reset <= 1'b0;
|
|
reset_count <= reset_count;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
reset <= 1'b0;
|
|
reset_count <= reset_count;
|
|
end
|
|
end
|
|
|
|
logic reset_cpu_ff = 1'b1;
|
|
logic reset_cpu = 1'b1;
|
|
logic [15:0] reset_cpu_count = 16'h0000;
|
|
|
|
always @(negedge clk_chipset, posedge reset)
|
|
begin
|
|
if (reset)
|
|
reset_cpu_ff <= 1'b1;
|
|
else
|
|
reset_cpu_ff <= reset;
|
|
end
|
|
|
|
localparam tandy_video_mode = `ENABLE_TANDY_VIDEO;
|
|
reg hgc_mode = 0;
|
|
|
|
always @(negedge clk_chipset, posedge reset)
|
|
begin
|
|
if (reset)
|
|
begin
|
|
hgc_mode <= `ENABLE_HGC ? (`ENABLE_CGA ? status[4] : 1'b1) : 1'b0;
|
|
reset_cpu <= 1'b1;
|
|
reset_cpu_count <= 16'h0000;
|
|
end
|
|
else if (reset_cpu)
|
|
begin
|
|
reset_cpu <= reset_cpu_ff;
|
|
reset_cpu_count <= 16'h0000;
|
|
end
|
|
else
|
|
begin
|
|
if (reset_cpu_count != 16'h002A)
|
|
begin
|
|
reset_cpu <= reset_cpu_ff;
|
|
reset_cpu_count <= reset_cpu_count + 16'h0001;
|
|
end
|
|
else
|
|
begin
|
|
reset_cpu <= 1'b0;
|
|
reset_cpu_count <= reset_cpu_count;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge clk_chipset, posedge reset_sdram_wire)
|
|
begin
|
|
if (reset_sdram_wire)
|
|
begin
|
|
reset_sdram <= 1'b1;
|
|
reset_sdram_count <= 16'h0000;
|
|
end
|
|
else if (reset_sdram)
|
|
begin
|
|
if (reset_sdram_count != 16'hffff)
|
|
begin
|
|
reset_sdram <= 1'b1;
|
|
reset_sdram_count <= reset_sdram_count + 16'h0001;
|
|
end
|
|
else
|
|
begin
|
|
reset_sdram <= 1'b0;
|
|
reset_sdram_count <= reset_sdram_count;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
reset_sdram <= 1'b0;
|
|
reset_sdram_count <= reset_sdram_count;
|
|
end
|
|
end
|
|
|
|
//
|
|
/////////////////////// BIOS LOADER ////////////////////////////
|
|
//
|
|
|
|
reg [4:0] bios_load_state = 4'h0;
|
|
reg [1:0] bios_protect_flag;
|
|
reg bios_access_request;
|
|
reg [19:0] bios_access_address;
|
|
reg [15:0] bios_write_data;
|
|
reg bios_write_n;
|
|
reg [7:0] bios_write_wait_cnt;
|
|
reg bios_write_byte_cnt;
|
|
reg tandy_bios_write;
|
|
wire select_pcxt = (ioctl_index[5:0] == 0) && (ioctl_addr[24:16] == 9'b000000000);
|
|
wire select_tandy = `ROM_IS_TANDY ? (ioctl_index[5:0] == 1) && (ioctl_addr[24:16] == 9'b000000000) : 1'b0;
|
|
wire select_xtide = ioctl_index == 2;
|
|
|
|
wire [19:0] bios_access_address_wire = select_pcxt ? { 4'b1111, ioctl_addr[15:0]} :
|
|
select_tandy ? { 4'b1111, ioctl_addr[15:0]} :
|
|
select_xtide ? { 6'b111011, ioctl_addr[13:0]} :
|
|
20'hFFFFF;
|
|
|
|
wire bios_load_n = ~(ioctl_download & (select_pcxt | select_tandy | select_xtide));
|
|
|
|
always @(posedge clk_chipset, posedge reset_sdram)
|
|
begin
|
|
if (reset_sdram)
|
|
begin
|
|
bios_protect_flag <= 2'b11;
|
|
bios_access_request <= 1'b0;
|
|
bios_access_address <= 20'hFFFFF;
|
|
bios_write_data <= 16'hFFFF;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
bios_write_byte_cnt <= 1'h0;
|
|
tandy_bios_write <= 1'b0;
|
|
ioctl_wait <= 1'b1;
|
|
bios_load_state <= 4'h00;
|
|
end
|
|
else if (~initilized_sdram)
|
|
begin
|
|
bios_protect_flag <= 2'b11;
|
|
bios_access_request <= 1'b0;
|
|
bios_access_address <= 20'hFFFFF;
|
|
bios_write_data <= 16'hFFFF;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
bios_write_byte_cnt <= 1'h0;
|
|
ioctl_wait <= 1'b1;
|
|
bios_load_state <= 4'h00;
|
|
end
|
|
else
|
|
begin
|
|
casez (bios_load_state)
|
|
4'h00:
|
|
begin
|
|
bios_protect_flag <= ~status[31:30]; // bios_writable
|
|
bios_access_address <= 20'hFFFFF;
|
|
bios_write_data <= 16'hFFFF;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
bios_write_byte_cnt <= 1'h0;
|
|
tandy_bios_write <= 1'b0;
|
|
if (~ioctl_download)
|
|
begin
|
|
bios_access_request <= 1'b0;
|
|
ioctl_wait <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
bios_access_request <= 1'b1;
|
|
ioctl_wait <= 1'b1;
|
|
end
|
|
|
|
if ((ioctl_download) && (~processor_ready) && (address_direction))
|
|
bios_load_state <= 4'h01;
|
|
else
|
|
bios_load_state <= 4'h00;
|
|
end
|
|
4'h01:
|
|
begin
|
|
bios_protect_flag <= 2'b00;
|
|
bios_access_request <= 1'b1;
|
|
bios_write_byte_cnt <= 1'h0;
|
|
tandy_bios_write <= select_tandy;
|
|
if (~ioctl_download)
|
|
begin
|
|
bios_access_address <= 20'hFFFFF;
|
|
bios_write_data <= 16'hFFFF;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
ioctl_wait <= 1'b0;
|
|
bios_load_state <= 4'h00;
|
|
end
|
|
else if ((~ioctl_wr) || (bios_load_n))
|
|
begin
|
|
bios_access_address <= 20'hFFFFF;
|
|
bios_write_data <= 16'hFFFF;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
ioctl_wait <= 1'b0;
|
|
bios_load_state <= 4'h01;
|
|
end
|
|
else
|
|
begin
|
|
bios_access_address <= bios_access_address_wire;
|
|
bios_write_data <= ioctl_data;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
ioctl_wait <= 1'b1;
|
|
bios_load_state <= 4'h02;
|
|
end
|
|
end
|
|
4'h02:
|
|
begin
|
|
bios_protect_flag <= 2'b00;
|
|
bios_access_request <= 1'b1;
|
|
bios_access_address <= bios_access_address;
|
|
bios_write_data <= bios_write_data;
|
|
bios_write_byte_cnt <= bios_write_byte_cnt;
|
|
tandy_bios_write <= select_tandy;
|
|
ioctl_wait <= 1'b1;
|
|
bios_write_wait_cnt <= bios_write_wait_cnt + 'h1;
|
|
|
|
if (bios_write_wait_cnt != 'd20)
|
|
begin
|
|
bios_write_n <= 1'b0;
|
|
bios_load_state <= 4'h02;
|
|
end
|
|
else
|
|
begin
|
|
bios_write_n <= 1'b1;
|
|
bios_load_state <= 4'h03;
|
|
end
|
|
end
|
|
4'h03:
|
|
begin
|
|
bios_protect_flag <= 2'b00;
|
|
bios_access_request <= 1'b1;
|
|
bios_access_address <= bios_access_address;
|
|
bios_write_data <= bios_write_data;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_byte_cnt <= bios_write_byte_cnt;
|
|
tandy_bios_write <= 1'b0;
|
|
ioctl_wait <= 1'b1;
|
|
bios_write_wait_cnt <= bios_write_wait_cnt + 'h1;
|
|
|
|
if (bios_write_wait_cnt != 'h40)
|
|
bios_load_state <= 4'h03;
|
|
else
|
|
bios_load_state <= 4'h04;
|
|
end
|
|
4'h04:
|
|
begin
|
|
bios_protect_flag <= 2'b00;
|
|
bios_access_request <= 1'b1;
|
|
bios_access_address <= bios_access_address + 'h1;
|
|
bios_write_data <= {8'hFF, bios_write_data[15:8]};
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
bios_write_byte_cnt <= ~bios_write_byte_cnt;
|
|
tandy_bios_write <= 1'b0;
|
|
ioctl_wait <= 1'b1;
|
|
if (bios_write_byte_cnt == 1'b0)
|
|
bios_load_state <= 4'h02;
|
|
else
|
|
bios_load_state <= 4'h01;
|
|
end
|
|
default:
|
|
begin
|
|
bios_protect_flag <= 2'b11;
|
|
bios_access_request <= 1'b0;
|
|
bios_access_address <= 20'hFFFFF;
|
|
bios_write_data <= 16'hFFFF;
|
|
bios_write_n <= 1'b1;
|
|
bios_write_wait_cnt <= 'h0;
|
|
bios_write_byte_cnt <= 1'h0;
|
|
tandy_bios_write <= 1'b0;
|
|
ioctl_wait <= 1'b0;
|
|
bios_load_state <= 4'h00;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Splash screen
|
|
//
|
|
reg splash_off = 1'b1;
|
|
reg [24:0] splash_cnt = 0;
|
|
reg [3:0] splash_cnt2 = 0;
|
|
reg splashscreen = 1'b0;
|
|
reg splash_pending = 1'b1;
|
|
reg [23:0] splash_boot_cnt = 24'd0;
|
|
reg splashscreen_sync1 = 0;
|
|
reg splashscreen_sync2 = 0;
|
|
reg splashscreen_sync_prev = 0;
|
|
reg status0_sync1 = 0;
|
|
reg status0_sync2 = 0;
|
|
reg status0_sync_prev = 0;
|
|
wire status0_clear_pulse = status0_sync2 & ~status0_sync_prev;
|
|
reg splash_reset_hold = 0;
|
|
reg [16:0] splash_reset_cnt = 17'd0;
|
|
localparam [16:0] SPLASH_RESET_HOLD = 17'd131072;
|
|
reg phys_reset_hold = 0;
|
|
reg [23:0] phys_reset_cnt = 24'd0;
|
|
localparam [23:0] PHYS_RESET_HOLD = 24'd2863600;
|
|
localparam [23:0] SPLASH_BOOT_WAIT = 24'd14318000;
|
|
|
|
always @ (posedge clk_14_318)
|
|
begin
|
|
splash_off <= status[7];
|
|
if (RESET || buttons[1])
|
|
begin
|
|
phys_reset_hold <= 1'b1;
|
|
phys_reset_cnt <= 24'd0;
|
|
end
|
|
else if (phys_reset_hold)
|
|
begin
|
|
if (phys_reset_cnt == PHYS_RESET_HOLD)
|
|
phys_reset_hold <= 1'b0;
|
|
else
|
|
phys_reset_cnt <= phys_reset_cnt + 24'd1;
|
|
end
|
|
|
|
if (splash_pending)
|
|
begin
|
|
if (~splash_off)
|
|
begin
|
|
splashscreen <= 1'b1;
|
|
splash_cnt <= 0;
|
|
splash_cnt2 <= 0;
|
|
splash_pending <= 1'b0;
|
|
splash_boot_cnt <= 24'd0;
|
|
end
|
|
else if (splash_boot_cnt == SPLASH_BOOT_WAIT)
|
|
begin
|
|
splash_pending <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
splash_boot_cnt <= splash_boot_cnt + 24'd1;
|
|
end
|
|
end
|
|
else if (splashscreen)
|
|
begin
|
|
if (splash_off)
|
|
begin
|
|
splashscreen <= 0;
|
|
end
|
|
else if(splash_cnt2 == 5) // 5 seconds delay
|
|
begin
|
|
splashscreen <= 0;
|
|
end
|
|
else if (splash_cnt == 14318000)
|
|
begin // 1 second at 14.318Mhz
|
|
splash_cnt2 <= splash_cnt2 + 1;
|
|
splash_cnt <= 0;
|
|
end
|
|
else
|
|
splash_cnt <= splash_cnt + 1;
|
|
end
|
|
|
|
end
|
|
|
|
always @(posedge clk_chipset)
|
|
begin
|
|
splashscreen_sync1 <= splashscreen;
|
|
splashscreen_sync2 <= splashscreen_sync1;
|
|
splashscreen_sync_prev <= splashscreen_sync2;
|
|
status0_sync1 <= status[0];
|
|
status0_sync2 <= status0_sync1;
|
|
status0_sync_prev <= status0_sync2;
|
|
|
|
if (splashscreen_sync_prev && ~splashscreen_sync2)
|
|
begin
|
|
splash_reset_hold <= 1'b1;
|
|
splash_reset_cnt <= 17'd0;
|
|
end
|
|
else if (splash_reset_hold)
|
|
begin
|
|
if (splash_reset_cnt == SPLASH_RESET_HOLD)
|
|
splash_reset_hold <= 1'b0;
|
|
else
|
|
splash_reset_cnt <= splash_reset_cnt + 17'd1;
|
|
end
|
|
end
|
|
|
|
//
|
|
// Input F/F PS2_CLK
|
|
//
|
|
logic device_clock_ff;
|
|
logic device_clock;
|
|
|
|
always_ff @(negedge clk_chipset, posedge reset)
|
|
begin
|
|
if (reset)
|
|
begin
|
|
device_clock_ff <= 1'b0;
|
|
device_clock <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
device_clock_ff <= ps2_kbd_clk_in;
|
|
device_clock <= device_clock_ff ;
|
|
end
|
|
end
|
|
|
|
|
|
//
|
|
// Input F/F PS2_DAT
|
|
//
|
|
logic device_data_ff;
|
|
logic device_data;
|
|
|
|
always_ff @(negedge clk_chipset, posedge reset)
|
|
begin
|
|
if (reset)
|
|
begin
|
|
device_data_ff <= 1'b0;
|
|
device_data <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
device_data_ff <= ps2_kbd_data_in;
|
|
device_data <= device_data_ff;
|
|
end
|
|
end
|
|
|
|
|
|
wire [7:0] data_bus;
|
|
wire INTA_n;
|
|
wire [19:0] cpu_ad_out;
|
|
reg [19:0] cpu_address;
|
|
wire [7:0] cpu_data_bus;
|
|
wire processor_ready;
|
|
wire interrupt_to_cpu;
|
|
wire address_latch_enable;
|
|
wire address_direction;
|
|
|
|
wire lock_n;
|
|
wire [2:0]processor_status;
|
|
|
|
wire [3:0] dma_acknowledge_n;
|
|
|
|
logic [7:0] port_b_out;
|
|
logic [7:0] port_c_in;
|
|
wire [1:0] fdd_present;
|
|
reg [7:0] sw;
|
|
|
|
wire [5:0] sw_base;
|
|
wire [1:0] sw_floppy;
|
|
|
|
assign sw_base = `ENABLE_HGC ? (hgc_mode ? 6'b111101 : 6'b101101) : 6'b101101;
|
|
assign sw_floppy = fdd_present[1] ? 2'b01 : 2'b00;
|
|
assign sw = {sw_floppy, sw_base}; // DIP switches (CGA and floppy count)
|
|
assign port_c_in[3:0] = port_b_out[3] ? sw[7:4] : sw[3:0];
|
|
|
|
wire tandy_bios_flag = bios_write_n ? `ROM_IS_TANDY : tandy_bios_write;
|
|
|
|
wire video_output_sel = `ENABLE_HGC ? hgc_mode_video_ff : 1'b0;
|
|
wire enable_hgc_sel = `ENABLE_HGC ? 1'b1 : 1'b0;
|
|
wire [1:0] hgc_rgb_sel = `ENABLE_HGC ? 2'b10 : 2'b00;
|
|
wire hercules_hw_sel = `ENABLE_HGC ? hercules_hw : 1'b0;
|
|
wire ems_enabled_sel = `ENABLE_EMS ? ~status[11] : 1'b0;
|
|
wire [1:0] ems_address_sel = `ENABLE_EMS ? status[13:12] : 2'b00;
|
|
|
|
always @(posedge clk_chipset)
|
|
begin
|
|
if (address_latch_enable)
|
|
cpu_address <= cpu_ad_out;
|
|
else
|
|
cpu_address <= cpu_address;
|
|
end
|
|
|
|
CHIPSET #(.clk_rate(cur_rate)) u_CHIPSET
|
|
(
|
|
.clock (clk_chipset),
|
|
.cpu_ce_posedge (cpu_ce_posedge),
|
|
.cpu_ce_negedge (cpu_ce_negedge),
|
|
.clk_sys (clk_chipset),
|
|
.peripheral_ce (peripheral_ce),
|
|
.clk_select (clk_select),
|
|
.reset (reset_cpu),
|
|
.sdram_reset (reset_sdram),
|
|
.cpu_address (cpu_address),
|
|
.cpu_data_bus (cpu_data_bus),
|
|
.processor_status (processor_status),
|
|
.processor_lock_n (lock_n),
|
|
// .processor_transmit_or_receive_n (processor_transmit_or_receive_n),
|
|
.processor_ready (processor_ready),
|
|
.interrupt_to_cpu (interrupt_to_cpu),
|
|
.splashscreen (splashscreen),
|
|
.status0_clear (status0_clear_pulse),
|
|
.std_hsyncwidth (std_hsyncwidth),
|
|
.composite (composite),
|
|
.video_output (video_output_sel),
|
|
.clk_vga_cga (clk_28_636),
|
|
.enable_cga (`ENABLE_CGA),
|
|
.clk_vga_hgc (clk_57_272),
|
|
.enable_hgc (enable_hgc_sel),
|
|
.hgc_rgb (hgc_rgb_sel),
|
|
// .de_o (VGA_DE),
|
|
.VGA_R (r),
|
|
.VGA_G (g),
|
|
.VGA_B (b),
|
|
.VGA_HSYNC (HSync),
|
|
.VGA_VSYNC (VSync),
|
|
.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),
|
|
.address_direction (address_direction),
|
|
.data_bus (data_bus),
|
|
.data_bus_ext (bios_write_data[7:0]),
|
|
// .data_bus_direction (data_bus_direction),
|
|
.address_latch_enable (address_latch_enable),
|
|
// .io_channel_check (),
|
|
.io_channel_ready (1'b1),
|
|
.interrupt_request (0), // use? -> It does not seem to be necessary.
|
|
// .io_read_n (io_read_n),
|
|
.io_read_n_ext (1'b1),
|
|
// .io_read_n_direction (io_read_n_direction),
|
|
// .io_write_n (io_write_n),
|
|
.io_write_n_ext (1'b1),
|
|
// .io_write_n_direction (io_write_n_direction),
|
|
// .memory_read_n (memory_read_n),
|
|
.memory_read_n_ext (1'b1),
|
|
// .memory_read_n_direction (memory_read_n_direction),
|
|
// .memory_write_n (memory_write_n),
|
|
.memory_write_n_ext (bios_write_n),
|
|
// .memory_write_n_direction (memory_write_n_direction),
|
|
.dma_request (0), // use? -> I don't know if it will ever be necessary, at least not during testing.
|
|
.dma_acknowledge_n (dma_acknowledge_n),
|
|
// .address_enable_n (address_enable_n),
|
|
// .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),
|
|
.ps2_clock_out (ps2_kbd_clk_out),
|
|
.ps2_data_out (ps2_kbd_data_out),
|
|
.ps2_mouseclk_in (ps2_mouse_clk_out),
|
|
.ps2_mousedat_in (ps2_mouse_data_out),
|
|
.ps2_mouseclk_out (ps2_mouse_clk_in),
|
|
.ps2_mousedat_out (ps2_mouse_data_in),
|
|
.joy_opts (joy_opts), //Joy0-Disabled, Joy0-Type, Joy1-Disabled, Joy1-Type, turbo_sync
|
|
.joy0 (status[28] ? joy1 : joy0),
|
|
.joy1 (status[28] ? joy0 : joy1),
|
|
.joya0 (status[28] ? joya1 : joya0),
|
|
.joya1 (status[28] ? joya0 : joya1),
|
|
.jtopl2_snd_e (jtopl2_snd_e),
|
|
.tandy_snd_e (tandy_snd_e),
|
|
.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_video_mode),
|
|
.tandy_bios_flag (tandy_bios_flag),
|
|
.tandy_16_gfx (tandy_16_gfx),
|
|
.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),
|
|
.sdram_address (SDRAM_A),
|
|
.sdram_cke (SDRAM_CKE),
|
|
.sdram_cs (SDRAM_nCS),
|
|
.sdram_ras (SDRAM_nRAS),
|
|
.sdram_cas (SDRAM_nCAS),
|
|
.sdram_we (SDRAM_nWE),
|
|
.sdram_ba (SDRAM_BA),
|
|
.sdram_dq_in (SDRAM_DQ_IN),
|
|
.sdram_dq_out (SDRAM_DQ_OUT),
|
|
.sdram_dq_io (SDRAM_DQ_IO),
|
|
.sdram_ldqm (SDRAM_DQML),
|
|
.sdram_udqm (SDRAM_DQMH),
|
|
.ems_enabled (ems_enabled_sel),
|
|
.ems_address (ems_address_sel),
|
|
.bios_protect_flag (bios_protect_flag),
|
|
.use_mmc (use_mmc),
|
|
.spi_clk (spi_clk),
|
|
.spi_cs (spi_cs),
|
|
.spi_mosi (spi_mosi),
|
|
.spi_miso (spi_miso),
|
|
.mgmt_readdata (mgmt_din),
|
|
.mgmt_writedata (mgmt_dout),
|
|
.mgmt_address (mgmt_addr),
|
|
.mgmt_write (mgmt_wr),
|
|
.mgmt_read (mgmt_rd),
|
|
.floppy_wp (status[20:19]),
|
|
.fdd_present (fdd_present),
|
|
.fdd_request (mgmt_req[7:6]),
|
|
.ide0_request (mgmt_req[2:0]),
|
|
.xtctl (xtctl),
|
|
.enable_a000h (a000h),
|
|
.wait_count_clk_en (cpu_ce_negedge),
|
|
.ram_read_wait_cycle (ram_read_wait_cycle),
|
|
.ram_write_wait_cycle (ram_write_wait_cycle),
|
|
.pause_core (pause_core),
|
|
.cga_hw (cga_hw),
|
|
.cga_scandouble_en (cga_scandouble_en),
|
|
.hercules_hw (hercules_hw_sel),
|
|
.swap_video (swap_video),
|
|
.crt_h_offset (status[49:46]),
|
|
.crt_v_offset (status[52:50]),
|
|
.vsync_width_osd (vsync_width_osd),
|
|
.hsync_width_osd (hsync_width_osd)
|
|
);
|
|
|
|
wire [15:0] SDRAM_DQ_IN;
|
|
wire [15:0] SDRAM_DQ_OUT;
|
|
wire SDRAM_DQ_IO;
|
|
wire initilized_sdram;
|
|
|
|
assign SDRAM_DQ_IN = SDRAM_DQ;
|
|
assign SDRAM_DQ = ~SDRAM_DQ_IO ? SDRAM_DQ_OUT : 16'hZZZZ;
|
|
|
|
wire s6_3_mux;
|
|
wire [2:0] SEGMENT;
|
|
|
|
i8088 B1
|
|
(
|
|
.CORE_CLK(clk_100),
|
|
.CLK(clk_cpu),
|
|
|
|
.RESET(reset_cpu),
|
|
.READY(processor_ready && ~pause_core),
|
|
.NMI(1'b0),
|
|
.INTR(interrupt_to_cpu),
|
|
|
|
.ad_out(cpu_ad_out),
|
|
.dout(cpu_data_bus),
|
|
.din(data_bus),
|
|
|
|
.lock_n(lock_n),
|
|
.s6_3_mux(s6_3_mux),
|
|
.s2_s0_out(processor_status),
|
|
.SEGMENT(SEGMENT),
|
|
|
|
.biu_done(biu_done),
|
|
.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 = {cms_l_snd_e[15],cms_l_snd_e};
|
|
wire [15:0] cms_r_snd_e;
|
|
wire [16:0] cms_r_snd = {cms_r_snd_e[15],cms_r_snd_e};
|
|
|
|
wire [15:0] jtopl2_snd_e;
|
|
wire [16:0] jtopl2_snd = {jtopl2_snd_e[15], jtopl2_snd_e};
|
|
wire [10:0] tandy_snd_e;
|
|
wire [16:0] tandy_snd = `ENABLE_TANDY_AUDIO ? {{{2{tandy_snd_e[10]}}, {4{tandy_snd_e[10]}}, tandy_snd_e} << status[35:34], 2'b00} : 17'd0;
|
|
wire [16:0] spk_vol = {2'b00, {3'b000,~speaker_out} << status[33:32], 11'd0};
|
|
wire speaker_out;
|
|
|
|
localparam [3:0] comp_f1 = 4;
|
|
localparam [3:0] comp_a1 = 2;
|
|
localparam comp_x1 = ((32767 * (comp_f1 - 1)) / ((comp_f1 * comp_a1) - 1)) + 1; // +1 to make sure it won't overflow
|
|
localparam comp_b1 = comp_x1 * comp_a1;
|
|
|
|
localparam [3:0] comp_f2 = 8;
|
|
localparam [3:0] comp_a2 = 4;
|
|
localparam comp_x2 = ((32767 * (comp_f2 - 1)) / ((comp_f2 * comp_a2) - 1)) + 1; // +1 to make sure it won't overflow
|
|
localparam comp_b2 = comp_x2 * comp_a2;
|
|
|
|
function [15:0] compr;
|
|
input [15:0] inp;
|
|
reg [15:0] v, v1, v2;
|
|
begin
|
|
v = inp[15] ? (~inp) + 1'd1 : inp;
|
|
v1 = (v < comp_x1[15:0]) ? (v * comp_a1) : (((v - comp_x1[15:0])/comp_f1) + comp_b1[15:0]);
|
|
v2 = (v < comp_x2[15:0]) ? (v * comp_a2) : (((v - comp_x2[15:0])/comp_f2) + comp_b2[15:0]);
|
|
v = status[37] ? v2 : v1;
|
|
compr = inp[15] ? ~(v-1'd1) : v;
|
|
end
|
|
endfunction
|
|
|
|
reg [15:0] cmp_l;
|
|
reg [15:0] out_l;
|
|
always @(posedge clk_chipset)
|
|
begin
|
|
reg [16:0] tmp_l;
|
|
|
|
tmp_l <= jtopl2_snd + cms_l_snd + tandy_snd + spk_vol;
|
|
|
|
// clamp the output
|
|
out_l <= (^tmp_l[16:15]) ? {tmp_l[16], {15{tmp_l[15]}}} : tmp_l[15:0];
|
|
|
|
cmp_l <= compr(out_l);
|
|
end
|
|
|
|
reg [15:0] cmp_r;
|
|
reg [15:0] out_r;
|
|
always @(posedge clk_chipset)
|
|
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 = pause_core ? 1'b0 : status[37:36] ? cmp_l : out_l;
|
|
assign AUDIO_R = pause_core ? 1'b0 : status[37:36] ? cmp_r : out_r;
|
|
assign AUDIO_S = 1;
|
|
assign AUDIO_MIX = status[39:38];
|
|
|
|
//
|
|
//////////////////////////// UART ///////////////////////////////////
|
|
//
|
|
|
|
//assign USER_OUT = {1'b1, 1'b1, uart_dtr, 1'b1, uart_rts, uart_tx, 1'b1};
|
|
|
|
//
|
|
// Pin | USB Name | |Signal
|
|
// ----+----------+---+-------------
|
|
// 0 | D+ | I |RX
|
|
// 1 | D- | O |TX
|
|
// 2 | TX- | O |RTS
|
|
// 3 | GND_d | I |CTS
|
|
// 4 | RX+ | O |DTR
|
|
// 5 | RX- | I |DSR
|
|
// 6 | TX+ | I |DCD
|
|
//
|
|
|
|
logic clk_uart_ff_1;
|
|
logic clk_uart_ff_2;
|
|
logic clk_uart_ff_3;
|
|
logic clk_uart_en;
|
|
logic clk_uart2_en;
|
|
logic [2:0] clk_uart2_counter;
|
|
|
|
always @(posedge clk_chipset)
|
|
begin
|
|
clk_uart_ff_1 <= clk_14_318;
|
|
clk_uart_ff_2 <= clk_uart_ff_1;
|
|
clk_uart_ff_3 <= clk_uart_ff_2;
|
|
clk_uart_en <= ~clk_uart_ff_3 & clk_uart_ff_2;
|
|
end
|
|
|
|
always @(posedge clk_chipset)
|
|
begin
|
|
if (clk_uart_en)
|
|
begin
|
|
if (3'd7 != clk_uart2_counter)
|
|
begin
|
|
clk_uart2_counter <= clk_uart2_counter +3'd1;
|
|
clk_uart2_en <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
clk_uart2_counter <= 3'd0;
|
|
clk_uart2_en <= 1'b1;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
clk_uart2_counter <= clk_uart2_counter;
|
|
clk_uart2_en <= 1'b0;
|
|
end
|
|
end
|
|
|
|
wire uart_tx, uart_rts, uart_dtr;
|
|
|
|
assign UART_TXD = uart_tx;
|
|
assign UART_RTS = uart_rts;
|
|
assign UART_DTR = uart_dtr;
|
|
|
|
wire uart_rx = UART_RXD;
|
|
wire uart_cts = UART_CTS;
|
|
wire uart_dsr = UART_DSR;
|
|
wire uart_dcd = UART_DTR;
|
|
|
|
|
|
/// UART2
|
|
|
|
assign USER_OUT = {1'b1, 1'b1, uart2_dtr, 1'b1, uart2_rts, uart2_tx, 1'b1};
|
|
|
|
//
|
|
// Pin | USB Name | |Signal
|
|
// ----+----------+---+-------------
|
|
// 0 | D+ | I |RX
|
|
// 1 | D- | O |TX
|
|
// 2 | TX- | O |RTS
|
|
// 3 | GND_d | I |CTS
|
|
// 4 | RX+ | O |DTR
|
|
// 5 | RX- | I |DSR
|
|
// 6 | TX+ | I |DCD
|
|
//
|
|
|
|
wire uart2_tx, uart2_rts, uart2_dtr;
|
|
|
|
wire uart2_rx = USER_IN[0];
|
|
wire uart2_cts = USER_IN[3];
|
|
wire uart2_dsr = USER_IN[5];
|
|
wire uart2_dcd = USER_IN[6];
|
|
|
|
//
|
|
/////////////////////// MMC ///////////////////////
|
|
//
|
|
logic [1:0] use_mmc;
|
|
logic spi_clk;
|
|
logic spi_cs;
|
|
logic spi_mosi;
|
|
logic spi_miso;
|
|
|
|
always @(posedge clk_chipset)
|
|
if (reset)
|
|
use_mmc <= status[22:21];
|
|
else
|
|
use_mmc <= use_mmc;
|
|
|
|
assign SD_SCK = spi_clk;
|
|
assign SD_MOSI = spi_mosi;
|
|
assign spi_miso = SD_MISO;
|
|
assign SD_CS = spi_cs;
|
|
|
|
//
|
|
/////////////////////// VIDEO ///////////////////////
|
|
//
|
|
|
|
wire HBlank;
|
|
wire HSync;
|
|
wire VBlank;
|
|
wire VSync;
|
|
reg ce_pixel_cga = 1'b0;
|
|
wire ce_pixel_hgc_raw;
|
|
wire de_o;
|
|
wire [5:0] r, g, b;
|
|
reg [7:0] raux_cga, gaux_cga, baux_cga;
|
|
reg [7:0] raux_hgc, gaux_hgc, baux_hgc;
|
|
wire [7:0] VGA_R_AUX, VGA_G_AUX, VGA_B_AUX;
|
|
wire CLK_VIDEO_HGC;
|
|
wire CLK_VIDEO_CGA;
|
|
wire CE_PIXEL_CREDITS;
|
|
|
|
wire [7:0] VGA_R_cga;
|
|
wire [7:0] VGA_G_cga;
|
|
wire [7:0] VGA_B_cga;
|
|
wire VGA_HS_cga;
|
|
wire VGA_VS_cga;
|
|
wire VGA_DE_cga;
|
|
wire [21:0] gamma_bus_cga;
|
|
wire CE_PIXEL_cga;
|
|
reg ce_pixel_cga_2x = 1'b0;
|
|
wire ce_pixel_cga_vid = cga_scandouble_en ? ce_pixel_cga_2x : ce_pixel_cga;
|
|
|
|
wire [7:0] VGA_R_hgc;
|
|
wire [7:0] VGA_G_hgc;
|
|
wire [7:0] VGA_B_hgc;
|
|
wire VGA_HS_hgc;
|
|
wire VGA_VS_hgc;
|
|
wire VGA_DE_hgc;
|
|
wire [21:0] gamma_bus_hgc;
|
|
wire CE_PIXEL_hgc;
|
|
reg [1:0] ce_pixel_hgc_div = 2'b0;
|
|
reg [5:0] hgc_r_meta, hgc_g_meta, hgc_b_meta;
|
|
reg [5:0] hgc_r_sync, hgc_g_sync, hgc_b_sync;
|
|
reg hgc_hs_meta, hgc_vs_meta;
|
|
reg hgc_hs_sync, hgc_vs_sync;
|
|
reg hgc_hb_meta, hgc_vb_meta;
|
|
reg hgc_hb_sync, hgc_vb_sync;
|
|
|
|
reg [7:0] VGA_R_cga_src = 8'd0;
|
|
reg [7:0] VGA_G_cga_src = 8'd0;
|
|
reg [7:0] VGA_B_cga_src = 8'd0;
|
|
reg VGA_HS_cga_src = 1'b0;
|
|
reg VGA_VS_cga_src = 1'b0;
|
|
reg VGA_DE_cga_src = 1'b0;
|
|
reg LHBL_cga_src = 1'b1;
|
|
reg LVBL_cga_src = 1'b1;
|
|
reg CE_PIXEL_cga_src = 1'b0;
|
|
reg [7:0] VGA_R_cga_ps = 8'd0;
|
|
reg [7:0] VGA_G_cga_ps = 8'd0;
|
|
reg [7:0] VGA_B_cga_ps = 8'd0;
|
|
reg VGA_HS_cga_ps = 1'b0;
|
|
reg VGA_VS_cga_ps = 1'b0;
|
|
reg VGA_DE_cga_ps = 1'b0;
|
|
reg LHBL_cga_ps = 1'b1;
|
|
reg LVBL_cga_ps = 1'b1;
|
|
reg CE_PIXEL_cga_ps = 1'b0;
|
|
reg CE_PIXEL_cga_ps_d = 1'b0;
|
|
reg [7:0] VGA_R_cga_hdmi, VGA_G_cga_hdmi, VGA_B_cga_hdmi;
|
|
reg VGA_HS_cga_hdmi, VGA_VS_cga_hdmi, VGA_DE_cga_hdmi;
|
|
reg LHBL_cga_hdmi, LVBL_cga_hdmi;
|
|
reg CE_PIXEL_cga_hdmi = 1'b0;
|
|
|
|
reg [7:0] VGA_R_hgc_src = 8'd0;
|
|
reg [7:0] VGA_G_hgc_src = 8'd0;
|
|
reg [7:0] VGA_B_hgc_src = 8'd0;
|
|
reg VGA_HS_hgc_src = 1'b0;
|
|
reg VGA_VS_hgc_src = 1'b0;
|
|
reg VGA_DE_hgc_src = 1'b0;
|
|
reg LHBL_hgc_src = 1'b1;
|
|
reg credits_vb_hgc_src = 1'b1;
|
|
reg CE_PIXEL_hgc_src = 1'b0;
|
|
reg [7:0] VGA_R_hgc_ps = 8'd0;
|
|
reg [7:0] VGA_G_hgc_ps = 8'd0;
|
|
reg [7:0] VGA_B_hgc_ps = 8'd0;
|
|
reg VGA_HS_hgc_ps = 1'b0;
|
|
reg VGA_VS_hgc_ps = 1'b0;
|
|
reg VGA_DE_hgc_ps = 1'b0;
|
|
reg LHBL_hgc_ps = 1'b1;
|
|
reg credits_vb_hgc_ps = 1'b1;
|
|
reg CE_PIXEL_hgc_ps = 1'b0;
|
|
reg ce_pixel_hgc_prev = 1'b0;
|
|
reg ce_pixel_hgc_tog = 1'b0;
|
|
reg ce_pixel_hgc_tog_1 = 1'b0;
|
|
reg ce_pixel_hgc_tog_2 = 1'b0;
|
|
wire CE_PIXEL_hgc_sync;
|
|
reg [7:0] VGA_R_hgc_56 = 8'd0, VGA_G_hgc_56 = 8'd0, VGA_B_hgc_56 = 8'd0;
|
|
reg VGA_HS_hgc_56 = 1'b0, VGA_VS_hgc_56 = 1'b0, VGA_DE_hgc_56 = 1'b0;
|
|
reg LHBL_hgc_56 = 1'b1, credits_vb_hgc_56 = 1'b1;
|
|
reg CE_PIXEL_hgc_hdmi = 1'b0;
|
|
|
|
assign CLK_VIDEO = clk_video_out_ps;
|
|
assign CLK_VIDEO_HGC = clk_114_544;
|
|
assign CLK_VIDEO_CGA = clk_57_272;
|
|
assign ce_pixel_hgc_raw = ce_pixel_hgc_div[1];
|
|
|
|
always @(posedge clk_114_544)
|
|
if (`ENABLE_HGC)
|
|
ce_pixel_hgc_div <= ce_pixel_hgc_div + 2'd1;
|
|
else
|
|
ce_pixel_hgc_div <= 2'd0;
|
|
|
|
always @(posedge clk_57_272)
|
|
ce_pixel_cga_2x <= ~ce_pixel_cga_2x;
|
|
|
|
assign VGA_SL = {scale_video_ff==3, scale_video_ff==2};
|
|
|
|
wire scandoubler = video_scandoubler_en;
|
|
|
|
reg [14:0] HBlank_del;
|
|
reg [24:0] HBlank_del_hgc;
|
|
wire tandy_16_gfx;
|
|
wire tandy_color_16;
|
|
wire color = (screen_mode_video_ff == 3'd0);
|
|
|
|
wire HBlank_VGA;
|
|
|
|
reg [10:0] HBlank_counter = 0;
|
|
reg [10:0] HBlank_counter_hgc = 0;
|
|
reg HBlank_fixed = 1'b1;
|
|
reg HBlank_fixed_hgc = 1'b1;
|
|
reg [1:0] HSync_del = 1'b11;
|
|
reg [1:0] HSync_del_hgc = 1'b11;
|
|
localparam integer MDA_VSYNC_DELAY = 19;
|
|
reg [MDA_VSYNC_DELAY:0] VSync_line;
|
|
reg video_pause_core_buf;
|
|
reg video_pause_core;
|
|
|
|
always_comb
|
|
begin
|
|
if (swap_video_eff)
|
|
HBlank_VGA = HBlank_del_hgc[24];
|
|
else if (tandy_color_16)
|
|
HBlank_VGA = HBlank_del[11];
|
|
else if (tandy_16_gfx)
|
|
HBlank_VGA = HBlank_del[9];
|
|
else
|
|
HBlank_VGA = HBlank_del[5];
|
|
end
|
|
|
|
always @ (posedge ce_pixel_cga)
|
|
begin
|
|
|
|
HSync_del <= {HSync_del[0], HSync};
|
|
|
|
if (HSync_del == 2'b01)
|
|
begin
|
|
HBlank_counter <= 0;
|
|
HBlank_fixed <= 1'b1;
|
|
end
|
|
else
|
|
begin
|
|
if (HBlank_counter == (std_hsyncwidth ? 120 : 143))
|
|
HBlank_fixed <= 1'b0;
|
|
else
|
|
HBlank_counter <= HBlank_counter + 1;
|
|
end
|
|
end
|
|
|
|
always @(posedge clk_57_272)
|
|
begin
|
|
if (swap_video_eff)
|
|
begin
|
|
HBlank_del_hgc <= {HBlank_del_hgc[23:0], HBlank};
|
|
HSync_del_hgc <= {HSync_del_hgc[0], HSync};
|
|
if (HSync_del_hgc == 2'b01)
|
|
begin
|
|
VSync_line <= {VSync_line[MDA_VSYNC_DELAY-1:0], VSync};
|
|
HBlank_counter_hgc <= 0;
|
|
HBlank_fixed_hgc <= 1'b1;
|
|
end
|
|
else
|
|
begin
|
|
if (HBlank_counter_hgc == (std_hsyncwidth ? 120 : 143))
|
|
HBlank_fixed_hgc <= 1'b0;
|
|
else
|
|
HBlank_counter_hgc <= HBlank_counter_hgc + 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @ (posedge clk_video_out_ps) begin
|
|
video_pause_core_buf <= pause_core;
|
|
video_pause_core <= video_pause_core_buf;
|
|
end
|
|
|
|
video_monochrome_converter video_mono_cga
|
|
(
|
|
.clk_vid(CLK_VIDEO_CGA),
|
|
.ce_pix(ce_pixel_cga_vid),
|
|
|
|
.R({r, 2'b00}),
|
|
.G({g, 2'b00}),
|
|
.B({b, 2'b00}),
|
|
|
|
.gfx_mode(screen_mode_video_ff),
|
|
|
|
.R_OUT(raux_cga),
|
|
.G_OUT(gaux_cga),
|
|
.B_OUT(baux_cga)
|
|
);
|
|
|
|
video_monochrome_converter video_mono_hgc
|
|
(
|
|
.clk_vid(CLK_VIDEO_HGC),
|
|
.ce_pix(ce_pixel_hgc_raw),
|
|
|
|
.R({hgc_r_sync, 2'b00}),
|
|
.G({hgc_g_sync, 2'b00}),
|
|
.B({hgc_b_sync, 2'b00}),
|
|
|
|
.gfx_mode(screen_mode_video_ff),
|
|
|
|
.R_OUT(raux_hgc),
|
|
.G_OUT(gaux_hgc),
|
|
.B_OUT(baux_hgc)
|
|
);
|
|
|
|
/*
|
|
assign VGA_R = raux;
|
|
assign VGA_G = gaux;
|
|
assign VGA_B = baux;
|
|
assign VGA_HS = HSync;
|
|
assign VGA_VS = VSync;
|
|
assign VGA_DE = ~(HBlank | VBlank);
|
|
assign CE_PIXEL = ce_pixel;
|
|
*/
|
|
|
|
wire LHBL = cga_scandouble_en ? HBlank :
|
|
((border_video_ff) ? (swap_video_eff ? HBlank_fixed_hgc : HBlank_fixed) : HBlank_VGA);
|
|
wire LVBL = cga_scandouble_en ? VBlank :
|
|
((border_video_ff) ? (std_hsyncwidth ? VGA_VBlank_border : VBlank) : VBlank);
|
|
wire VSync_hgc = VSync_line[MDA_VSYNC_DELAY];
|
|
|
|
wire pre2x_LHBL, pre2x_LVBL;
|
|
wire [7:0] pre2x_r, pre2x_g, pre2x_b;
|
|
|
|
|
|
video_mixer #(.GAMMA(1)) video_mixer_cga
|
|
(
|
|
.*,
|
|
|
|
.CLK_VIDEO(CLK_VIDEO_CGA),
|
|
.CE_PIXEL(CE_PIXEL_cga),
|
|
.ce_pix(ce_pixel_cga_vid),
|
|
|
|
.freeze_sync(),
|
|
|
|
.R(raux_cga),
|
|
.G(gaux_cga),
|
|
.B(baux_cga),
|
|
|
|
.HBlank(LHBL),
|
|
.VBlank(LVBL),
|
|
.HSync(HSync),
|
|
.VSync(VSync),
|
|
|
|
.scandoubler(1'b0),
|
|
.hq2x(scale_video_ff==1),
|
|
.gamma_bus(gamma_bus_cga),
|
|
|
|
.VGA_R(VGA_R_cga),
|
|
.VGA_G(VGA_G_cga),
|
|
.VGA_B(VGA_B_cga),
|
|
.VGA_VS(VGA_VS_cga),
|
|
.VGA_HS(VGA_HS_cga),
|
|
.VGA_DE(VGA_DE_cga)
|
|
|
|
);
|
|
|
|
always @(posedge clk_57_272)
|
|
begin
|
|
VGA_R_cga_src <= VGA_R_cga;
|
|
VGA_G_cga_src <= VGA_G_cga;
|
|
VGA_B_cga_src <= VGA_B_cga;
|
|
VGA_HS_cga_src <= VGA_HS_cga;
|
|
VGA_VS_cga_src <= VGA_VS_cga;
|
|
VGA_DE_cga_src <= VGA_DE_cga;
|
|
LHBL_cga_src <= LHBL;
|
|
LVBL_cga_src <= LVBL;
|
|
CE_PIXEL_cga_src <= CE_PIXEL_cga;
|
|
end
|
|
|
|
// Retimes the exact-frequency CGA output onto a phase-shifted sibling clock.
|
|
always @(posedge clk_video_out_ps or posedge video_retime_reset)
|
|
begin
|
|
if (video_retime_reset)
|
|
begin
|
|
VGA_R_cga_ps <= 8'd0;
|
|
VGA_G_cga_ps <= 8'd0;
|
|
VGA_B_cga_ps <= 8'd0;
|
|
VGA_HS_cga_ps <= 1'b0;
|
|
VGA_VS_cga_ps <= 1'b0;
|
|
VGA_DE_cga_ps <= 1'b0;
|
|
LHBL_cga_ps <= 1'b1;
|
|
LVBL_cga_ps <= 1'b1;
|
|
CE_PIXEL_cga_ps <= 1'b0;
|
|
CE_PIXEL_cga_ps_d <= 1'b0;
|
|
VGA_R_cga_hdmi <= 8'd0;
|
|
VGA_G_cga_hdmi <= 8'd0;
|
|
VGA_B_cga_hdmi <= 8'd0;
|
|
VGA_HS_cga_hdmi <= 1'b0;
|
|
VGA_VS_cga_hdmi <= 1'b0;
|
|
VGA_DE_cga_hdmi <= 1'b0;
|
|
LHBL_cga_hdmi <= 1'b1;
|
|
LVBL_cga_hdmi <= 1'b1;
|
|
CE_PIXEL_cga_hdmi <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
CE_PIXEL_cga_hdmi <= CE_PIXEL_cga_ps & ~CE_PIXEL_cga_ps_d;
|
|
if (CE_PIXEL_cga_ps & ~CE_PIXEL_cga_ps_d)
|
|
begin
|
|
VGA_R_cga_hdmi <= VGA_R_cga_ps;
|
|
VGA_G_cga_hdmi <= VGA_G_cga_ps;
|
|
VGA_B_cga_hdmi <= VGA_B_cga_ps;
|
|
VGA_HS_cga_hdmi <= VGA_HS_cga_ps;
|
|
VGA_VS_cga_hdmi <= VGA_VS_cga_ps;
|
|
VGA_DE_cga_hdmi <= VGA_DE_cga_ps;
|
|
LHBL_cga_hdmi <= LHBL_cga_ps;
|
|
LVBL_cga_hdmi <= LVBL_cga_ps;
|
|
end
|
|
|
|
CE_PIXEL_cga_ps_d <= CE_PIXEL_cga_ps;
|
|
CE_PIXEL_cga_ps <= CE_PIXEL_cga_src;
|
|
VGA_R_cga_ps <= VGA_R_cga_src;
|
|
VGA_G_cga_ps <= VGA_G_cga_src;
|
|
VGA_B_cga_ps <= VGA_B_cga_src;
|
|
VGA_HS_cga_ps <= VGA_HS_cga_src;
|
|
VGA_VS_cga_ps <= VGA_VS_cga_src;
|
|
VGA_DE_cga_ps <= VGA_DE_cga_src;
|
|
LHBL_cga_ps <= LHBL_cga_src;
|
|
LVBL_cga_ps <= LVBL_cga_src;
|
|
end
|
|
end
|
|
|
|
always @(posedge clk_114_544)
|
|
begin
|
|
if (ce_pixel_hgc_raw)
|
|
begin
|
|
hgc_r_meta <= r;
|
|
hgc_g_meta <= g;
|
|
hgc_b_meta <= b;
|
|
hgc_hs_meta <= HSync;
|
|
hgc_vs_meta <= VSync_hgc;
|
|
hgc_hb_meta <= HBlank;
|
|
hgc_vb_meta <= VBlank;
|
|
|
|
hgc_r_sync <= hgc_r_meta;
|
|
hgc_g_sync <= hgc_g_meta;
|
|
hgc_b_sync <= hgc_b_meta;
|
|
hgc_hs_sync <= hgc_hs_meta;
|
|
hgc_vs_sync <= hgc_vs_meta;
|
|
hgc_hb_sync <= hgc_hb_meta;
|
|
hgc_vb_sync <= hgc_vb_meta;
|
|
end
|
|
end
|
|
|
|
video_mixer #(.GAMMA(0)) video_mixer_hgc
|
|
(
|
|
.*,
|
|
|
|
.CLK_VIDEO(CLK_VIDEO_HGC),
|
|
.CE_PIXEL(CE_PIXEL_hgc),
|
|
.ce_pix(ce_pixel_hgc_raw),
|
|
|
|
.freeze_sync(),
|
|
|
|
.R(raux_hgc),
|
|
.G(gaux_hgc),
|
|
.B(baux_hgc),
|
|
|
|
.HBlank(hgc_hb_sync),
|
|
.VBlank(hgc_vb_sync),
|
|
.HSync(hgc_hs_sync),
|
|
.VSync(hgc_vs_sync),
|
|
|
|
.scandoubler(scandoubler),
|
|
.hq2x(scale_video_ff==1),
|
|
.gamma_bus(gamma_bus_hgc),
|
|
|
|
.VGA_R(VGA_R_hgc),
|
|
.VGA_G(VGA_G_hgc),
|
|
.VGA_B(VGA_B_hgc),
|
|
.VGA_VS(VGA_VS_hgc),
|
|
.VGA_HS(VGA_HS_hgc),
|
|
.VGA_DE(VGA_DE_hgc)
|
|
|
|
);
|
|
|
|
always @(posedge clk_114_544)
|
|
begin
|
|
ce_pixel_hgc_prev <= CE_PIXEL_hgc;
|
|
if (CE_PIXEL_hgc && ~ce_pixel_hgc_prev)
|
|
ce_pixel_hgc_tog <= ~ce_pixel_hgc_tog;
|
|
end
|
|
|
|
always @(posedge clk_57_272)
|
|
begin
|
|
ce_pixel_hgc_tog_1 <= ce_pixel_hgc_tog;
|
|
ce_pixel_hgc_tog_2 <= ce_pixel_hgc_tog_1;
|
|
CE_PIXEL_hgc_src <= CE_PIXEL_hgc_sync;
|
|
|
|
if (CE_PIXEL_hgc_sync)
|
|
begin
|
|
VGA_R_hgc_src <= VGA_R_hgc;
|
|
VGA_G_hgc_src <= VGA_G_hgc;
|
|
VGA_B_hgc_src <= VGA_B_hgc;
|
|
VGA_HS_hgc_src <= VGA_HS_hgc;
|
|
VGA_VS_hgc_src <= VGA_VS_hgc;
|
|
VGA_DE_hgc_src <= VGA_DE_hgc;
|
|
LHBL_hgc_src <= hgc_hb_sync;
|
|
credits_vb_hgc_src <= hgc_vb_sync;
|
|
end
|
|
end
|
|
|
|
assign CE_PIXEL_hgc_sync = ce_pixel_hgc_tog_1 ^ ce_pixel_hgc_tog_2;
|
|
|
|
// Retimes the HGC mixer output by exploiting the exact 2:1 relation between
|
|
// clk_114_544 and the phase-shifted clk_video_out_ps.
|
|
always @(posedge clk_video_out_ps or posedge video_retime_reset)
|
|
begin
|
|
if (video_retime_reset)
|
|
begin
|
|
VGA_R_hgc_ps <= 8'd0;
|
|
VGA_G_hgc_ps <= 8'd0;
|
|
VGA_B_hgc_ps <= 8'd0;
|
|
VGA_HS_hgc_ps <= 1'b0;
|
|
VGA_VS_hgc_ps <= 1'b0;
|
|
VGA_DE_hgc_ps <= 1'b0;
|
|
LHBL_hgc_ps <= 1'b1;
|
|
credits_vb_hgc_ps <= 1'b1;
|
|
CE_PIXEL_hgc_ps <= 1'b0;
|
|
VGA_R_hgc_56 <= 8'd0;
|
|
VGA_G_hgc_56 <= 8'd0;
|
|
VGA_B_hgc_56 <= 8'd0;
|
|
VGA_HS_hgc_56 <= 1'b0;
|
|
VGA_VS_hgc_56 <= 1'b0;
|
|
VGA_DE_hgc_56 <= 1'b0;
|
|
LHBL_hgc_56 <= 1'b1;
|
|
credits_vb_hgc_56 <= 1'b1;
|
|
CE_PIXEL_hgc_hdmi <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
CE_PIXEL_hgc_hdmi <= CE_PIXEL_hgc_ps;
|
|
if (CE_PIXEL_hgc_ps)
|
|
begin
|
|
VGA_R_hgc_56 <= VGA_R_hgc_ps;
|
|
VGA_G_hgc_56 <= VGA_G_hgc_ps;
|
|
VGA_B_hgc_56 <= VGA_B_hgc_ps;
|
|
VGA_HS_hgc_56 <= VGA_HS_hgc_ps;
|
|
VGA_VS_hgc_56 <= VGA_VS_hgc_ps;
|
|
VGA_DE_hgc_56 <= VGA_DE_hgc_ps;
|
|
LHBL_hgc_56 <= LHBL_hgc_ps;
|
|
credits_vb_hgc_56 <= credits_vb_hgc_ps;
|
|
end
|
|
|
|
CE_PIXEL_hgc_ps <= CE_PIXEL_hgc_src;
|
|
VGA_R_hgc_ps <= VGA_R_hgc_src;
|
|
VGA_G_hgc_ps <= VGA_G_hgc_src;
|
|
VGA_B_hgc_ps <= VGA_B_hgc_src;
|
|
VGA_HS_hgc_ps <= VGA_HS_hgc_src;
|
|
VGA_VS_hgc_ps <= VGA_VS_hgc_src;
|
|
VGA_DE_hgc_ps <= VGA_DE_hgc_src;
|
|
LHBL_hgc_ps <= LHBL_hgc_src;
|
|
credits_vb_hgc_ps <= credits_vb_hgc_src;
|
|
end
|
|
end
|
|
|
|
assign VGA_R_AUX = swap_video_eff ? VGA_R_hgc_56 : VGA_R_cga_hdmi;
|
|
assign VGA_G_AUX = swap_video_eff ? VGA_G_hgc_56 : VGA_G_cga_hdmi;
|
|
assign VGA_B_AUX = swap_video_eff ? VGA_B_hgc_56 : VGA_B_cga_hdmi;
|
|
assign VGA_HS = swap_video_eff ? VGA_HS_hgc_56 : VGA_HS_cga_hdmi;
|
|
assign VGA_VS = swap_video_eff ? VGA_VS_hgc_56 : VGA_VS_cga_hdmi;
|
|
assign VGA_DE = swap_video_eff ? VGA_DE_hgc_56 : VGA_DE_cga_hdmi;
|
|
assign gamma_bus = swap_video_eff ? gamma_bus_hgc : gamma_bus_cga;
|
|
assign CE_PIXEL = swap_video_eff ? CE_PIXEL_hgc_hdmi : CE_PIXEL_cga_hdmi;
|
|
assign CE_PIXEL_CREDITS = swap_video_eff ? CE_PIXEL_hgc_hdmi : CE_PIXEL_cga_hdmi;
|
|
wire credits_hb = swap_video_eff ? LHBL_hgc_56 : LHBL_cga_hdmi;
|
|
wire credits_vb = swap_video_eff ? credits_vb_hgc_56 : LVBL_cga_hdmi;
|
|
wire credits_border = swap_video_eff ? 1'b0 : border_video_ff;
|
|
jtframe_credits #(
|
|
.PAGES (4),
|
|
.COLW (8),
|
|
.BLKPOL (1)
|
|
) u_credits(
|
|
.rst ( reset ),
|
|
.clk ( clk_video_out_ps ),
|
|
.pxl_cen ( CE_PIXEL_CREDITS ),
|
|
|
|
// input image
|
|
.HB ( credits_hb ),
|
|
.VB ( credits_vb ),
|
|
.rgb_in ( { VGA_R_AUX, VGA_G_AUX, VGA_B_AUX } ),
|
|
.rotate ( 2'd0 ),
|
|
.toggle ( 1'b0 ),
|
|
.fast_scroll( 1'b0 ),
|
|
.border ( credits_border ),
|
|
|
|
.vram_din ( 8'h0 ),
|
|
.vram_dout ( ),
|
|
.vram_addr ( 8'h0 ),
|
|
.vram_we ( 1'b0 ),
|
|
.vram_ctrl ( 3'b0 ),
|
|
.enable ( video_pause_core ),
|
|
|
|
// output image
|
|
.HB_out ( pre2x_LHBL ),
|
|
.VB_out ( pre2x_LVBL ),
|
|
.rgb_out ( {VGA_R, VGA_G, VGA_B } )
|
|
);
|
|
|
|
|
|
endmodule
|